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 }