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* nodeSocketReader = new SocketReaderNode(mCallback);
51 nodeSocketReader->SetMediaType(IMS_MEDIA_VIDEO);
52 (static_cast<SocketReaderNode*>(nodeSocketReader))->SetLocalFd(mLocalFd);
53 (static_cast<SocketReaderNode*>(nodeSocketReader))->SetLocalAddress(localAddress);
54 (static_cast<SocketReaderNode*>(nodeSocketReader))->SetProtocolType(kProtocolRtp);
55 nodeSocketReader->SetConfig(config);
56 AddNode(nodeSocketReader);
57
58 BaseNode* nodeRtpDecoder = new RtpDecoderNode(mCallback);
59 nodeRtpDecoder->SetMediaType(IMS_MEDIA_VIDEO);
60 nodeRtpDecoder->SetConfig(mConfig);
61 (static_cast<RtpDecoderNode*>(nodeRtpDecoder))->SetLocalAddress(localAddress);
62 AddNode(nodeRtpDecoder);
63 nodeSocketReader->ConnectRearNode(nodeRtpDecoder);
64
65 BaseNode* rtpPayloadDecoder = new VideoRtpPayloadDecoderNode(mCallback);
66 rtpPayloadDecoder->SetMediaType(IMS_MEDIA_VIDEO);
67 rtpPayloadDecoder->SetConfig(mConfig);
68 rtpPayloadDecoder->SetSchedulerCallback(
69 std::static_pointer_cast<StreamSchedulerCallback>(mScheduler));
70 AddNode(rtpPayloadDecoder);
71 nodeRtpDecoder->ConnectRearNode(rtpPayloadDecoder);
72
73 BaseNode* renderer = new IVideoRendererNode(mCallback);
74 renderer->SetMediaType(IMS_MEDIA_VIDEO);
75 renderer->SetConfig(mConfig);
76 renderer->SetSchedulerCallback(std::static_pointer_cast<StreamSchedulerCallback>(mScheduler));
77 AddNode(renderer);
78 rtpPayloadDecoder->ConnectRearNode(renderer);
79 setState(StreamState::kStreamStateCreated);
80 return RESULT_SUCCESS;
81 }
82
update(RtpConfig * config)83 ImsMediaResult VideoStreamGraphRtpRx::update(RtpConfig* config)
84 {
85 IMLOGI1("[update] state[%d]", mGraphState);
86
87 if (config == nullptr)
88 {
89 return RESULT_INVALID_PARAM;
90 }
91
92 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(config);
93
94 if (*reinterpret_cast<VideoConfig*>(mConfig) == *pConfig)
95 {
96 IMLOGI0("[update] no update");
97 return RESULT_SUCCESS;
98 }
99
100 if (mGraphState == kStreamStateWaitSurface)
101 {
102 setState(StreamState::kStreamStateCreated);
103 }
104
105 if (mConfig != nullptr)
106 {
107 delete mConfig;
108 mConfig = nullptr;
109 }
110
111 mConfig = new VideoConfig(pConfig);
112
113 if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW ||
114 mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY ||
115 mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_INACTIVE)
116 {
117 IMLOGI0("[update] pause RX");
118 return stop();
119 }
120
121 ImsMediaResult ret = RESULT_NOT_READY;
122
123 if (mGraphState == kStreamStateRunning)
124 {
125 mScheduler->Stop();
126
127 for (auto& node : mListNodeStarted)
128 {
129 if (node != nullptr)
130 {
131 IMLOGD1("[update] update node[%s]", node->GetNodeName());
132 ret = node->UpdateConfig(mConfig);
133 if (ret != RESULT_SUCCESS)
134 {
135 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
136 }
137 }
138 }
139
140 mScheduler->Start();
141 }
142 else if (mGraphState == kStreamStateCreated)
143 {
144 for (auto& node : mListNodeToStart)
145 {
146 if (node != nullptr)
147 {
148 IMLOGD1("[update] update node[%s]", node->GetNodeName());
149 ret = node->UpdateConfig(mConfig);
150
151 if (ret != RESULT_SUCCESS)
152 {
153 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
154 }
155 }
156 }
157 }
158
159 if (mGraphState == kStreamStateCreated &&
160 (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY ||
161 pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE))
162 {
163 IMLOGI0("[update] resume RX");
164 return start();
165 }
166
167 return ret;
168 }
169
start()170 ImsMediaResult VideoStreamGraphRtpRx::start()
171 {
172 IMLOGI1("[start] state[%d]", mGraphState);
173
174 if (mConfig == nullptr)
175 {
176 return RESULT_INVALID_PARAM;
177 }
178
179 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(mConfig);
180
181 if (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW ||
182 pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY ||
183 mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_INACTIVE)
184 {
185 IMLOGI1("[start] direction[%d] no need to start", pConfig->getMediaDirection());
186 return RESULT_SUCCESS;
187 }
188
189 if (mSurface == nullptr)
190 {
191 IMLOGI2("[start] direction[%d], mode[%d], surface is not ready, wait",
192 pConfig->getMediaDirection(), pConfig->getVideoMode());
193 setState(StreamState::kStreamStateWaitSurface);
194 return RESULT_SUCCESS;
195 }
196
197 ImsMediaResult result = startNodes();
198
199 if (result != RESULT_SUCCESS)
200 {
201 setState(StreamState::kStreamStateCreated);
202 mCallback->SendEvent(kImsMediaEventNotifyError, result, kStreamModeRtpRx);
203 return result;
204 }
205
206 setState(StreamState::kStreamStateRunning);
207 return RESULT_SUCCESS;
208 }
209
setMediaQualityThreshold(MediaQualityThreshold * threshold)210 bool VideoStreamGraphRtpRx::setMediaQualityThreshold(MediaQualityThreshold* threshold)
211 {
212 if (threshold != nullptr)
213 {
214 BaseNode* node = findNode(kNodeIdRtpDecoder);
215
216 if (node != nullptr)
217 {
218 RtpDecoderNode* decoder = reinterpret_cast<RtpDecoderNode*>(node);
219 decoder->SetInactivityTimerSec(threshold->getRtpInactivityTimerMillis().empty()
220 ? 0
221 : threshold->getRtpInactivityTimerMillis().front() / 1000);
222 return true;
223 }
224
225 node = findNode(kNodeIdVideoRenderer);
226
227 if (node != nullptr)
228 {
229 IVideoRendererNode* decoder = reinterpret_cast<IVideoRendererNode*>(node);
230 decoder->SetPacketLossParam(threshold->getRtpPacketLossDurationMillis(),
231 threshold->getRtpPacketLossRate().empty()
232 ? 0
233 : threshold->getRtpPacketLossRate().front());
234 return true;
235 }
236 }
237
238 return false;
239 }
240
setSurface(ANativeWindow * surface)241 void VideoStreamGraphRtpRx::setSurface(ANativeWindow* surface)
242 {
243 IMLOGD0("[setSurface]");
244
245 if (surface != nullptr)
246 {
247 mSurface = surface;
248
249 BaseNode* node = findNode(kNodeIdVideoRenderer);
250
251 if (node != nullptr)
252 {
253 IVideoRendererNode* renderer = reinterpret_cast<IVideoRendererNode*>(node);
254 renderer->UpdateSurface(surface);
255
256 if (getState() == StreamState::kStreamStateWaitSurface)
257 {
258 setState(StreamState::kStreamStateCreated);
259 start();
260 }
261 }
262 }
263 }
264
OnEvent(int32_t type,uint64_t param1,uint64_t param2)265 bool VideoStreamGraphRtpRx::OnEvent(int32_t type, uint64_t param1, uint64_t param2)
266 {
267 IMLOGI3("[OnEvent] type[%d], param1[%d], param2[%d]", type, param1, param2);
268
269 switch (type)
270 {
271 case kRequestRoundTripTimeDelayUpdate:
272 {
273 BaseNode* node = findNode(kNodeIdVideoRenderer);
274
275 if (node != nullptr)
276 {
277 IVideoRendererNode* pNode = reinterpret_cast<IVideoRendererNode*>(node);
278 pNode->UpdateRoundTripTimeDelay(param1);
279 return true;
280 }
281 }
282 break;
283 default:
284 break;
285 }
286
287 return false;
288 }