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 <AudioStreamGraphRtcp.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
AudioStreamGraphRtcp(BaseSessionCallback * callback,int localFd)25 AudioStreamGraphRtcp::AudioStreamGraphRtcp(BaseSessionCallback* callback, int localFd) :
26 AudioStreamGraph(callback, localFd)
27 {
28 mConfig = nullptr;
29 }
30
~AudioStreamGraphRtcp()31 AudioStreamGraphRtcp::~AudioStreamGraphRtcp() {}
32
create(RtpConfig * config)33 ImsMediaResult AudioStreamGraphRtcp::create(RtpConfig* config)
34 {
35 IMLOGD1("[create] state[%d]", mGraphState);
36
37 if (config == nullptr)
38 {
39 return RESULT_INVALID_PARAM;
40 }
41
42 mConfig = new AudioConfig(reinterpret_cast<AudioConfig*>(config));
43 BaseNode* pNodeRtcpEncoder = new RtcpEncoderNode(mCallback);
44 pNodeRtcpEncoder->SetMediaType(IMS_MEDIA_AUDIO);
45 char localIp[MAX_IP_LEN];
46 uint32_t localPort = 0;
47 ImsMediaNetworkUtil::getLocalIpPortFromSocket(mLocalFd, localIp, MAX_IP_LEN, localPort);
48 RtpAddress localAddress(localIp, localPort - 1);
49 (static_cast<RtcpEncoderNode*>(pNodeRtcpEncoder))->SetLocalAddress(localAddress);
50 pNodeRtcpEncoder->SetConfig(config);
51 AddNode(pNodeRtcpEncoder);
52
53 BaseNode* pNodeSocketWriter = new SocketWriterNode(mCallback);
54 pNodeSocketWriter->SetMediaType(IMS_MEDIA_AUDIO);
55 (static_cast<SocketWriterNode*>(pNodeSocketWriter))->SetLocalFd(mLocalFd);
56 (static_cast<SocketWriterNode*>(pNodeSocketWriter))
57 ->SetLocalAddress(RtpAddress(localIp, localPort));
58 (static_cast<SocketWriterNode*>(pNodeSocketWriter))->SetProtocolType(kProtocolRtcp);
59 pNodeSocketWriter->SetConfig(config);
60 AddNode(pNodeSocketWriter);
61 pNodeRtcpEncoder->ConnectRearNode(pNodeSocketWriter);
62 setState(StreamState::kStreamStateCreated);
63
64 BaseNode* pNodeSocketReader = new SocketReaderNode(mCallback);
65 pNodeSocketReader->SetMediaType(IMS_MEDIA_AUDIO);
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_AUDIO);
75 (static_cast<RtcpDecoderNode*>(pNodeRtcpDecoder))->SetLocalAddress(localAddress);
76 pNodeRtcpDecoder->SetConfig(config);
77 AddNode(pNodeRtcpDecoder);
78 pNodeSocketReader->ConnectRearNode(pNodeRtcpDecoder);
79 return ImsMediaResult::RESULT_SUCCESS;
80 }
81
update(RtpConfig * config)82 ImsMediaResult AudioStreamGraphRtcp::update(RtpConfig* config)
83 {
84 IMLOGD1("[update] state[%d]", mGraphState);
85
86 if (config == nullptr)
87 {
88 return RESULT_INVALID_PARAM;
89 }
90
91 AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
92
93 if (*reinterpret_cast<AudioConfig*>(mConfig) == *pConfig)
94 {
95 IMLOGI0("[update] no update");
96 return RESULT_SUCCESS;
97 }
98
99 if (mConfig != nullptr)
100 {
101 delete mConfig;
102 mConfig = new AudioConfig(pConfig);
103 }
104
105 if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW)
106 {
107 IMLOGI0("[update] pause RTCP");
108 return stop();
109 }
110
111 ImsMediaResult ret = ImsMediaResult::RESULT_NOT_READY;
112
113 // update in running state
114 if (mGraphState == kStreamStateRunning)
115 {
116 mScheduler->Stop();
117
118 for (auto& node : mListNodeStarted)
119 {
120 IMLOGD1("[update] update node[%s]", node->GetNodeName());
121 ret = node->UpdateConfig(pConfig);
122 if (ret != RESULT_SUCCESS)
123 {
124 IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
125 }
126 }
127
128 mScheduler->Start();
129 }
130
131 if (mGraphState == kStreamStateCreated &&
132 mConfig->getMediaDirection() != RtpConfig::MEDIA_DIRECTION_NO_FLOW)
133 {
134 IMLOGI0("[update] resume RTCP");
135 return start();
136 }
137
138 return ret;
139 }
140
start()141 ImsMediaResult AudioStreamGraphRtcp::start()
142 {
143 if (mConfig == nullptr)
144 {
145 return RESULT_NOT_READY;
146 }
147
148 if (mConfig->getMediaDirection() != RtpConfig::MEDIA_DIRECTION_NO_FLOW)
149 {
150 return BaseStreamGraph::start();
151 }
152
153 // not started
154 return RESULT_SUCCESS;
155 }
156
OnEvent(int32_t type,uint64_t param1,uint64_t param2)157 bool AudioStreamGraphRtcp::OnEvent(int32_t type, uint64_t param1, uint64_t param2)
158 {
159 IMLOGI3("[onEvent] type[%d], param1[%d], param2[%d]", type, param1, param2);
160
161 switch (type)
162 {
163 case kRequestSendRtcpXrReport:
164 {
165 BaseNode* node = findNode(kNodeIdRtcpEncoder);
166
167 if (node != nullptr)
168 {
169 RtcpEncoderNode* encoder = reinterpret_cast<RtcpEncoderNode*>(node);
170 encoder->SendRtcpXr(
171 reinterpret_cast<uint8_t*>(param1), static_cast<uint32_t>(param2));
172 return true;
173 }
174 }
175 break;
176 default:
177 break;
178 }
179
180 return false;
181 }