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 }