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 <TextStreamGraphRtcp.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 <TextConfig.h>
25
TextStreamGraphRtcp(BaseSessionCallback * callback,int localFd)26 TextStreamGraphRtcp::TextStreamGraphRtcp(BaseSessionCallback* callback, int localFd) :
27 TextStreamGraph(callback, localFd)
28 {
29 }
30
~TextStreamGraphRtcp()31 TextStreamGraphRtcp::~TextStreamGraphRtcp() {}
32
create(RtpConfig * config)33 ImsMediaResult TextStreamGraphRtcp::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 TextConfig(reinterpret_cast<TextConfig*>(config));
43 BaseNode* pNodeRtcpEncoder = new RtcpEncoderNode(mCallback);
44 pNodeRtcpEncoder->SetMediaType(IMS_MEDIA_TEXT);
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_TEXT);
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_TEXT);
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_TEXT);
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 TextStreamGraphRtcp::update(RtpConfig* config)
85 {
86 IMLOGI1("[update] state[%d]", mGraphState);
87
88 if (config == nullptr)
89 {
90 return RESULT_INVALID_PARAM;
91 }
92
93 TextConfig* pConfig = reinterpret_cast<TextConfig*>(config);
94
95 if (*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 TextConfig(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
128 if (ret != RESULT_SUCCESS)
129 {
130 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
131 }
132 }
133 }
134
135 if (mGraphState == kStreamStateCreated &&
136 mConfig->getMediaDirection() != RtpConfig::MEDIA_DIRECTION_NO_FLOW)
137 {
138 IMLOGI0("[update] resume RTCP");
139 return start();
140 }
141
142 // restart scheduler
143 if (mGraphState == kStreamStateRunning)
144 {
145 mScheduler->Start();
146 }
147
148 return ret;
149 }
150
start()151 ImsMediaResult TextStreamGraphRtcp::start()
152 {
153 IMLOGI1("[start] state[%d]", mGraphState);
154
155 if (mConfig == nullptr)
156 {
157 return RESULT_INVALID_PARAM;
158 }
159
160 if (mConfig->getMediaDirection() != RtpConfig::MEDIA_DIRECTION_NO_FLOW)
161 {
162 return BaseStreamGraph::start();
163 }
164
165 // not started
166 return RESULT_SUCCESS;
167 }
168
setMediaQualityThreshold(MediaQualityThreshold * threshold)169 bool TextStreamGraphRtcp::setMediaQualityThreshold(MediaQualityThreshold* threshold)
170 {
171 if (threshold != nullptr)
172 {
173 BaseNode* node = findNode(kNodeIdRtcpDecoder);
174
175 if (node != nullptr)
176 {
177 RtcpDecoderNode* decoder = reinterpret_cast<RtcpDecoderNode*>(node);
178 decoder->SetInactivityTimerSec(threshold->getRtcpInactivityTimerMillis() / 1000);
179 return true;
180 }
181 }
182
183 return false;
184 }