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 <VideoStreamGraphRtcp.h>
18 #include <RtcpEncoderNode.h>
19 #include <RtcpDecoderNode.h>
20 #include <SocketReaderNode.h>
21 #include <SocketWriterNode.h>
22 #include <ImsMediaNetworkUtil.h>
23 #include <ImsMediaTrace.h>
24 #include <VideoConfig.h>
25 
VideoStreamGraphRtcp(BaseSessionCallback * callback,int localFd)26 VideoStreamGraphRtcp::VideoStreamGraphRtcp(BaseSessionCallback* callback, int localFd) :
27         VideoStreamGraph(callback, localFd)
28 {
29 }
30 
~VideoStreamGraphRtcp()31 VideoStreamGraphRtcp::~VideoStreamGraphRtcp() {}
32 
create(RtpConfig * config)33 ImsMediaResult VideoStreamGraphRtcp::create(RtpConfig* config)
34 {
35     IMLOGI1("[create] state[%d]", mGraphState);
36 
37     if (config == nullptr)
38     {
39         return RESULT_INVALID_PARAM;
40     }
41 
42     mConfig = new VideoConfig(reinterpret_cast<VideoConfig*>(config));
43     BaseNode* pNodeRtcpEncoder = new RtcpEncoderNode(mCallback);
44     pNodeRtcpEncoder->SetMediaType(IMS_MEDIA_VIDEO);
45 
46     char localIp[MAX_IP_LEN];
47     uint32_t localPort = 0;
48     ImsMediaNetworkUtil::getLocalIpPortFromSocket(mLocalFd, localIp, MAX_IP_LEN, localPort);
49     RtpAddress localAddress(localIp, localPort - 1);
50     (static_cast<RtcpEncoderNode*>(pNodeRtcpEncoder))->SetLocalAddress(localAddress);
51     pNodeRtcpEncoder->SetConfig(config);
52     AddNode(pNodeRtcpEncoder);
53 
54     BaseNode* pNodeSocketWriter = new SocketWriterNode(mCallback);
55     pNodeSocketWriter->SetMediaType(IMS_MEDIA_VIDEO);
56     (static_cast<SocketWriterNode*>(pNodeSocketWriter))->SetLocalFd(mLocalFd);
57     (static_cast<SocketWriterNode*>(pNodeSocketWriter))
58             ->SetLocalAddress(RtpAddress(localIp, localPort));
59     (static_cast<SocketWriterNode*>(pNodeSocketWriter))->SetProtocolType(kProtocolRtcp);
60     pNodeSocketWriter->SetConfig(config);
61     AddNode(pNodeSocketWriter);
62     pNodeRtcpEncoder->ConnectRearNode(pNodeSocketWriter);
63 
64     BaseNode* pNodeSocketReader = new SocketReaderNode(mCallback);
65     pNodeSocketReader->SetMediaType(IMS_MEDIA_VIDEO);
66     (static_cast<SocketReaderNode*>(pNodeSocketReader))->SetLocalFd(mLocalFd);
67     (static_cast<SocketReaderNode*>(pNodeSocketReader))
68             ->SetLocalAddress(RtpAddress(localIp, localPort));
69     (static_cast<SocketReaderNode*>(pNodeSocketReader))->SetProtocolType(kProtocolRtcp);
70     pNodeSocketReader->SetConfig(config);
71     AddNode(pNodeSocketReader);
72 
73     BaseNode* pNodeRtcpDecoder = new RtcpDecoderNode(mCallback);
74     pNodeRtcpDecoder->SetMediaType(IMS_MEDIA_VIDEO);
75     (static_cast<RtcpDecoderNode*>(pNodeRtcpDecoder))->SetLocalAddress(localAddress);
76     pNodeRtcpDecoder->SetConfig(config);
77     AddNode(pNodeRtcpDecoder);
78     pNodeSocketReader->ConnectRearNode(pNodeRtcpDecoder);
79 
80     setState(StreamState::kStreamStateCreated);
81     return ImsMediaResult::RESULT_SUCCESS;
82 }
83 
update(RtpConfig * config)84 ImsMediaResult VideoStreamGraphRtcp::update(RtpConfig* config)
85 {
86     IMLOGI1("[update] state[%d]", mGraphState);
87 
88     if (config == nullptr)
89     {
90         return RESULT_INVALID_PARAM;
91     }
92 
93     VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(config);
94 
95     if (*reinterpret_cast<VideoConfig*>(mConfig) == *pConfig)
96     {
97         IMLOGI0("[update] no update");
98         return RESULT_SUCCESS;
99     }
100 
101     if (mConfig != nullptr)
102     {
103         delete mConfig;
104     }
105 
106     mConfig = new VideoConfig(pConfig);
107 
108     if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW)
109     {
110         IMLOGI0("[update] pause RTCP");
111         return stop();
112     }
113 
114     ImsMediaResult ret = ImsMediaResult::RESULT_NOT_READY;
115     // stop scheduler
116     if (mGraphState == kStreamStateRunning)
117     {
118         mScheduler->Stop();
119     }
120 
121     for (auto& node : mListNodeStarted)
122     {
123         if (node != nullptr)
124         {
125             IMLOGD1("[update] update node[%s]", node->GetNodeName());
126             ret = node->UpdateConfig(pConfig);
127             if (ret != RESULT_SUCCESS)
128             {
129                 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
130             }
131         }
132     }
133 
134     if (mGraphState == kStreamStateCreated &&
135             mConfig->getMediaDirection() != RtpConfig::MEDIA_DIRECTION_NO_FLOW)
136     {
137         IMLOGI0("[update] resume RTCP");
138         return start();
139     }
140 
141     // restart scheduler
142     if (mGraphState == kStreamStateRunning)
143     {
144         mScheduler->Start();
145     }
146 
147     return ret;
148 }
149 
start()150 ImsMediaResult VideoStreamGraphRtcp::start()
151 {
152     IMLOGI1("[start] state[%d]", mGraphState);
153 
154     if (mConfig == nullptr)
155     {
156         return RESULT_INVALID_PARAM;
157     }
158 
159     if (mConfig->getMediaDirection() != RtpConfig::MEDIA_DIRECTION_NO_FLOW)
160     {
161         return BaseStreamGraph::start();
162     }
163 
164     // not started
165     return RESULT_SUCCESS;
166 }
167 
setMediaQualityThreshold(MediaQualityThreshold * threshold)168 bool VideoStreamGraphRtcp::setMediaQualityThreshold(MediaQualityThreshold* threshold)
169 {
170     if (threshold != nullptr)
171     {
172         BaseNode* node = findNode(kNodeIdRtcpDecoder);
173 
174         if (node != nullptr)
175         {
176             RtcpDecoderNode* decoder = reinterpret_cast<RtcpDecoderNode*>(node);
177             decoder->SetInactivityTimerSec(threshold->getRtcpInactivityTimerMillis() / 1000);
178             return true;
179         }
180     }
181 
182     return false;
183 }
184 
OnEvent(int32_t type,uint64_t param1,uint64_t param2)185 bool VideoStreamGraphRtcp::OnEvent(int32_t type, uint64_t param1, uint64_t param2)
186 {
187     IMLOGI3("[OnEvent] type[%d], param1[%d], param2[%d]", type, param1, param2);
188 
189     bool ret = false;
190 
191     switch (type)
192     {
193         case kRequestVideoSendNack:
194         case kRequestVideoSendPictureLost:
195         case kRequestVideoSendTmmbr:
196         case kRequestVideoSendTmmbn:
197         {
198             BaseNode* node = findNode(kNodeIdRtcpEncoder);
199             InternalRequestEventParam* param = reinterpret_cast<InternalRequestEventParam*>(param1);
200 
201             if (node != nullptr && param != nullptr)
202             {
203                 RtcpEncoderNode* encoder = reinterpret_cast<RtcpEncoderNode*>(node);
204 
205                 if (type == kRequestVideoSendNack)
206                 {
207                     ret = encoder->SendNack(&param->nackParams);
208                 }
209                 else if (type == kRequestVideoSendPictureLost)
210                 {
211                     ret = encoder->SendPictureLost(param->value);
212                 }
213                 else if (type == kRequestVideoSendTmmbr || type == kRequestVideoSendTmmbn)
214                 {
215                     ret = encoder->SendTmmbrn(param->type, &param->tmmbrParams);
216                 }
217 
218                 delete param;
219             }
220         }
221         break;
222     }
223 
224     return ret;
225 }