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(¶m->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, ¶m->tmmbrParams);
216 }
217
218 delete param;
219 }
220 }
221 break;
222 }
223
224 return ret;
225 }