• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }