1 /**
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <VideoStreamGraphRtpRx.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaNetworkUtil.h>
20 #include <VideoConfig.h>
21 #include <RtpDecoderNode.h>
22 #include <SocketReaderNode.h>
23 #include <VideoRtpPayloadDecoderNode.h>
24 #include <IVideoRendererNode.h>
25
VideoStreamGraphRtpRx(BaseSessionCallback * callback,int localFd)26 VideoStreamGraphRtpRx::VideoStreamGraphRtpRx(BaseSessionCallback* callback, int localFd) :
27 VideoStreamGraph(callback, localFd)
28 {
29 mSurface = nullptr;
30 }
31
~VideoStreamGraphRtpRx()32 VideoStreamGraphRtpRx::~VideoStreamGraphRtpRx() {}
33
create(RtpConfig * config)34 ImsMediaResult VideoStreamGraphRtpRx::create(RtpConfig* config)
35 {
36 IMLOGI1("[create] state[%d]", mGraphState);
37
38 if (config == nullptr)
39 {
40 return RESULT_INVALID_PARAM;
41 }
42
43 mConfig = new VideoConfig(reinterpret_cast<VideoConfig*>(config));
44
45 char localIp[MAX_IP_LEN];
46 uint32_t localPort = 0;
47 ImsMediaNetworkUtil::getLocalIpPortFromSocket(mLocalFd, localIp, MAX_IP_LEN, localPort);
48 RtpAddress localAddress(localIp, localPort);
49
50 BaseNode* pNodeSocketReader = new SocketReaderNode(mCallback);
51 pNodeSocketReader->SetMediaType(IMS_MEDIA_VIDEO);
52 (static_cast<SocketReaderNode*>(pNodeSocketReader))->SetLocalFd(mLocalFd);
53 (static_cast<SocketReaderNode*>(pNodeSocketReader))->SetLocalAddress(localAddress);
54 (static_cast<SocketReaderNode*>(pNodeSocketReader))->SetProtocolType(kProtocolRtp);
55 pNodeSocketReader->SetConfig(config);
56 AddNode(pNodeSocketReader);
57
58 BaseNode* pNodeRtpDecoder = new RtpDecoderNode(mCallback);
59 pNodeRtpDecoder->SetMediaType(IMS_MEDIA_VIDEO);
60 pNodeRtpDecoder->SetConfig(mConfig);
61 (static_cast<RtpDecoderNode*>(pNodeRtpDecoder))->SetLocalAddress(localAddress);
62 AddNode(pNodeRtpDecoder);
63 pNodeSocketReader->ConnectRearNode(pNodeRtpDecoder);
64
65 BaseNode* pNodeRtpPayloadDecoder = new VideoRtpPayloadDecoderNode(mCallback);
66 pNodeRtpPayloadDecoder->SetMediaType(IMS_MEDIA_VIDEO);
67 pNodeRtpPayloadDecoder->SetConfig(mConfig);
68 AddNode(pNodeRtpPayloadDecoder);
69 pNodeRtpDecoder->ConnectRearNode(pNodeRtpPayloadDecoder);
70
71 BaseNode* pNodeRenderer = new IVideoRendererNode(mCallback);
72 pNodeRenderer->SetMediaType(IMS_MEDIA_VIDEO);
73 pNodeRenderer->SetConfig(mConfig);
74 AddNode(pNodeRenderer);
75 pNodeRtpPayloadDecoder->ConnectRearNode(pNodeRenderer);
76 setState(StreamState::kStreamStateCreated);
77 return RESULT_SUCCESS;
78 }
79
update(RtpConfig * config)80 ImsMediaResult VideoStreamGraphRtpRx::update(RtpConfig* config)
81 {
82 IMLOGI1("[update] state[%d]", mGraphState);
83
84 if (config == nullptr)
85 {
86 return RESULT_INVALID_PARAM;
87 }
88
89 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(config);
90
91 if (*reinterpret_cast<VideoConfig*>(mConfig) == *pConfig)
92 {
93 IMLOGI0("[update] no update");
94 return RESULT_SUCCESS;
95 }
96
97 if (mGraphState == kStreamStateWaitSurface)
98 {
99 setState(StreamState::kStreamStateCreated);
100 }
101
102 if (mConfig != nullptr)
103 {
104 delete mConfig;
105 mConfig = nullptr;
106 }
107
108 mConfig = new VideoConfig(pConfig);
109
110 if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW ||
111 mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY ||
112 mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_INACTIVE)
113 {
114 IMLOGI0("[update] pause RX");
115 return stop();
116 }
117
118 ImsMediaResult ret = RESULT_NOT_READY;
119
120 if (mGraphState == kStreamStateRunning)
121 {
122 mScheduler->Stop();
123
124 for (auto& node : mListNodeStarted)
125 {
126 if (node != nullptr)
127 {
128 IMLOGD1("[update] update node[%s]", node->GetNodeName());
129 ret = node->UpdateConfig(mConfig);
130 if (ret != RESULT_SUCCESS)
131 {
132 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
133 }
134 }
135 }
136
137 mScheduler->Start();
138 }
139 else if (mGraphState == kStreamStateCreated)
140 {
141 for (auto& node : mListNodeToStart)
142 {
143 if (node != nullptr)
144 {
145 IMLOGD1("[update] update node[%s]", node->GetNodeName());
146 ret = node->UpdateConfig(mConfig);
147
148 if (ret != RESULT_SUCCESS)
149 {
150 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
151 }
152 }
153 }
154 }
155
156 if (mGraphState == kStreamStateCreated &&
157 (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY ||
158 pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE))
159 {
160 IMLOGI0("[update] resume RX");
161 return start();
162 }
163
164 return ret;
165 }
166
start()167 ImsMediaResult VideoStreamGraphRtpRx::start()
168 {
169 IMLOGI1("[start] state[%d]", mGraphState);
170
171 if (mConfig == nullptr)
172 {
173 return RESULT_INVALID_PARAM;
174 }
175
176 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(mConfig);
177
178 if (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW ||
179 pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY ||
180 mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_INACTIVE)
181 {
182 IMLOGI1("[start] direction[%d] no need to start", pConfig->getMediaDirection());
183 return RESULT_SUCCESS;
184 }
185
186 if (mSurface == nullptr)
187 {
188 IMLOGI2("[start] direction[%d], mode[%d], surface is not ready, wait",
189 pConfig->getMediaDirection(), pConfig->getVideoMode());
190 setState(StreamState::kStreamStateWaitSurface);
191 return RESULT_SUCCESS;
192 }
193
194 ImsMediaResult result = startNodes();
195
196 if (result != RESULT_SUCCESS)
197 {
198 setState(StreamState::kStreamStateCreated);
199 mCallback->SendEvent(kImsMediaEventNotifyError, result, kStreamModeRtpRx);
200 return result;
201 }
202
203 setState(StreamState::kStreamStateRunning);
204 return RESULT_SUCCESS;
205 }
206
setMediaQualityThreshold(MediaQualityThreshold * threshold)207 bool VideoStreamGraphRtpRx::setMediaQualityThreshold(MediaQualityThreshold* threshold)
208 {
209 if (threshold != nullptr)
210 {
211 BaseNode* node = findNode(kNodeIdRtpDecoder);
212
213 if (node != nullptr)
214 {
215 RtpDecoderNode* decoder = reinterpret_cast<RtpDecoderNode*>(node);
216 decoder->SetInactivityTimerSec(threshold->getRtpInactivityTimerMillis().empty()
217 ? 0
218 : threshold->getRtpInactivityTimerMillis().front() / 1000);
219 return true;
220 }
221
222 node = findNode(kNodeIdVideoRenderer);
223
224 if (node != nullptr)
225 {
226 IVideoRendererNode* decoder = reinterpret_cast<IVideoRendererNode*>(node);
227 decoder->SetPacketLossParam(threshold->getRtpPacketLossDurationMillis(),
228 threshold->getRtpPacketLossRate().empty()
229 ? 0
230 : threshold->getRtpPacketLossRate().front());
231 return true;
232 }
233 }
234
235 return false;
236 }
237
setSurface(ANativeWindow * surface)238 void VideoStreamGraphRtpRx::setSurface(ANativeWindow* surface)
239 {
240 IMLOGD0("[setSurface]");
241
242 if (surface != nullptr)
243 {
244 mSurface = surface;
245
246 BaseNode* node = findNode(kNodeIdVideoRenderer);
247
248 if (node != nullptr)
249 {
250 IVideoRendererNode* renderer = reinterpret_cast<IVideoRendererNode*>(node);
251 renderer->UpdateSurface(surface);
252
253 if (getState() == StreamState::kStreamStateWaitSurface)
254 {
255 setState(StreamState::kStreamStateCreated);
256 start();
257 }
258 }
259 }
260 }
261
OnEvent(int32_t type,uint64_t param1,uint64_t param2)262 bool VideoStreamGraphRtpRx::OnEvent(int32_t type, uint64_t param1, uint64_t param2)
263 {
264 IMLOGI3("[OnEvent] type[%d], param1[%d], param2[%d]", type, param1, param2);
265
266 switch (type)
267 {
268 case kRequestRoundTripTimeDelayUpdate:
269 {
270 BaseNode* node = findNode(kNodeIdVideoRenderer);
271
272 if (node != nullptr)
273 {
274 IVideoRendererNode* pNode = reinterpret_cast<IVideoRendererNode*>(node);
275 pNode->UpdateRoundTripTimeDelay(param1);
276 return true;
277 }
278 }
279 break;
280 default:
281 break;
282 }
283
284 return false;
285 }