• 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 <AudioStreamGraphRtpTx.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaNetworkUtil.h>
20 #include <AudioConfig.h>
21 #include <IAudioSourceNode.h>
22 #include <DtmfEncoderNode.h>
23 #include <AudioRtpPayloadEncoderNode.h>
24 #include <RtpEncoderNode.h>
25 #include <SocketWriterNode.h>
26 
AudioStreamGraphRtpTx(BaseSessionCallback * callback,int localFd)27 AudioStreamGraphRtpTx::AudioStreamGraphRtpTx(BaseSessionCallback* callback, int localFd) :
28         AudioStreamGraph(callback, localFd)
29 {
30 }
31 
~AudioStreamGraphRtpTx()32 AudioStreamGraphRtpTx::~AudioStreamGraphRtpTx() {}
33 
create(RtpConfig * config)34 ImsMediaResult AudioStreamGraphRtpTx::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 AudioConfig(reinterpret_cast<AudioConfig*>(config));
44 
45     BaseNode* pNodeSource = new IAudioSourceNode(mCallback);
46     pNodeSource->SetMediaType(IMS_MEDIA_AUDIO);
47     pNodeSource->SetConfig(mConfig);
48     AddNode(pNodeSource);
49 
50     BaseNode* pNodeRtpPayloadEncoder = new AudioRtpPayloadEncoderNode(mCallback);
51     pNodeRtpPayloadEncoder->SetMediaType(IMS_MEDIA_AUDIO);
52     pNodeRtpPayloadEncoder->SetConfig(mConfig);
53     AddNode(pNodeRtpPayloadEncoder);
54     pNodeSource->ConnectRearNode(pNodeRtpPayloadEncoder);
55 
56     BaseNode* pNodeRtpEncoder = new RtpEncoderNode(mCallback);
57     pNodeRtpEncoder->SetMediaType(IMS_MEDIA_AUDIO);
58     char localIp[MAX_IP_LEN];
59     uint32_t localPort = 0;
60     ImsMediaNetworkUtil::getLocalIpPortFromSocket(mLocalFd, localIp, MAX_IP_LEN, localPort);
61     RtpAddress localAddress(localIp, localPort);
62     pNodeRtpEncoder->SetConfig(mConfig);
63     (static_cast<RtpEncoderNode*>(pNodeRtpEncoder))->SetLocalAddress(localAddress);
64     AddNode(pNodeRtpEncoder);
65     pNodeRtpPayloadEncoder->ConnectRearNode(pNodeRtpEncoder);
66 
67     BaseNode* pNodeSocketWriter = new SocketWriterNode(mCallback);
68     pNodeSocketWriter->SetMediaType(IMS_MEDIA_AUDIO);
69     (static_cast<SocketWriterNode*>(pNodeSocketWriter))->SetLocalFd(mLocalFd);
70     (static_cast<SocketWriterNode*>(pNodeSocketWriter))->SetLocalAddress(localAddress);
71     (static_cast<SocketWriterNode*>(pNodeSocketWriter))->SetProtocolType(kProtocolRtp);
72     pNodeSocketWriter->SetConfig(config);
73     AddNode(pNodeSocketWriter);
74     pNodeRtpEncoder->ConnectRearNode(pNodeSocketWriter);
75     setState(StreamState::kStreamStateCreated);
76 
77     if (!createDtmfGraph(mConfig, pNodeRtpEncoder))
78     {
79         IMLOGE0("[create] fail to create dtmf graph");
80     }
81 
82     return RESULT_SUCCESS;
83 }
84 
update(RtpConfig * config)85 ImsMediaResult AudioStreamGraphRtpTx::update(RtpConfig* config)
86 {
87     IMLOGI1("[update] state[%d]", mGraphState);
88 
89     if (config == nullptr)
90     {
91         return RESULT_INVALID_PARAM;
92     }
93 
94     AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
95 
96     if (*reinterpret_cast<AudioConfig*>(mConfig) == *pConfig)
97     {
98         IMLOGI0("[update] no update");
99         return RESULT_SUCCESS;
100     }
101 
102     if (mConfig != nullptr)
103     {
104         delete mConfig;
105     }
106 
107     mConfig = new AudioConfig(pConfig);
108 
109     if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW ||
110             mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY ||
111             mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_INACTIVE)
112     {
113         IMLOGI0("[update] pause TX");
114         return stop();
115     }
116 
117     ImsMediaResult ret = RESULT_NOT_READY;
118 
119     if (mGraphState == kStreamStateRunning)
120     {
121         mScheduler->Stop();
122         for (auto& node : mListNodeStarted)
123         {
124             IMLOGD1("[update] update node[%s]", node->GetNodeName());
125             ret = node->UpdateConfig(mConfig);
126             if (ret != RESULT_SUCCESS)
127             {
128                 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
129             }
130         }
131         mScheduler->Start();
132     }
133     else if (mGraphState == kStreamStateCreated)
134     {
135         for (auto& node : mListNodeToStart)
136         {
137             IMLOGD1("[update] update node[%s]", node->GetNodeName());
138             ret = node->UpdateConfig(mConfig);
139             if (ret != RESULT_SUCCESS)
140             {
141                 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
142             }
143         }
144     }
145 
146     if (mGraphState == kStreamStateCreated &&
147             (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY ||
148                     pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE))
149     {
150         IMLOGI0("[update] resume TX");
151         return start();
152     }
153 
154     return ret;
155 }
156 
start()157 ImsMediaResult AudioStreamGraphRtpTx::start()
158 {
159     if (mConfig == nullptr)
160     {
161         return RESULT_NOT_READY;
162     }
163 
164     if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY ||
165             mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE)
166     {
167         return BaseStreamGraph::start();
168     }
169 
170     // not started
171     return RESULT_SUCCESS;
172 }
173 
createDtmfGraph(RtpConfig * config,BaseNode * rtpEncoderNode)174 bool AudioStreamGraphRtpTx::createDtmfGraph(RtpConfig* config, BaseNode* rtpEncoderNode)
175 {
176     if (config == nullptr)
177     {
178         return false;
179     }
180 
181     AudioConfig* audioConfig = reinterpret_cast<AudioConfig*>(config);
182 
183     if (audioConfig->getTxDtmfPayloadTypeNumber() == 0)
184     {
185         return false;
186     }
187 
188     if (mConfig == nullptr)
189     {
190         mConfig = new AudioConfig(*audioConfig);
191     }
192 
193     BaseNode* pDtmfEncoderNode = new DtmfEncoderNode(mCallback);
194     pDtmfEncoderNode->SetMediaType(IMS_MEDIA_AUDIO);
195     pDtmfEncoderNode->SetConfig(audioConfig);
196     AddNode(pDtmfEncoderNode);
197     mListDtmfNodes.push_back(pDtmfEncoderNode);
198 
199     if (rtpEncoderNode != nullptr)
200     {
201         pDtmfEncoderNode->ConnectRearNode(rtpEncoderNode);
202     }
203 
204     return true;
205 }
206 
sendDtmf(char digit,int duration)207 bool AudioStreamGraphRtpTx::sendDtmf(char digit, int duration)
208 {
209     IMLOGD1("[sendDtmf], state[%d]", mGraphState);
210     BaseNode* pDTMFNode = nullptr;
211     if (!mListDtmfNodes.empty())
212     {
213         pDTMFNode = mListDtmfNodes.front();
214     }
215 
216     if (pDTMFNode != nullptr && pDTMFNode->GetNodeId() == kNodeIdDtmfEncoder)
217     {
218         IMLOGD2("[sendDtmf] %c, duration[%d]", digit, duration);
219         ImsMediaSubType subtype = MEDIASUBTYPE_DTMF_PAYLOAD;
220 
221         // TODO(249734476): add implementation of continuous DTMF operation
222         if (duration == 0)
223         {
224             subtype = MEDIASUBTYPE_DTMFSTART;
225         }
226 
227         pDTMFNode->OnDataFromFrontNode(subtype, (uint8_t*)&digit, 1, 0, 0, duration);
228         return true;
229     }
230     else
231     {
232         IMLOGE0("[sendDtmf] DTMF is not enabled");
233     }
234 
235     return false;
236 }
237 
processCmr(const uint32_t cmrType,const uint32_t cmrDefine)238 void AudioStreamGraphRtpTx::processCmr(const uint32_t cmrType, const uint32_t cmrDefine)
239 {
240     BaseNode* node = findNode(kNodeIdAudioSource);
241 
242     if (node != nullptr)
243     {
244         (reinterpret_cast<IAudioSourceNode*>(node))->ProcessCmr(cmrType, cmrDefine);
245     }
246 }
247 
sendRtpHeaderExtension(std::list<RtpHeaderExtension> * listExtension)248 void AudioStreamGraphRtpTx::sendRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension)
249 {
250     BaseNode* node = findNode(kNodeIdRtpEncoder);
251 
252     if (node != nullptr)
253     {
254         (reinterpret_cast<RtpEncoderNode*>(node))->SetRtpHeaderExtension(listExtension);
255     }
256 }