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 <IVideoSourceNode.h>
18 #include <ImsMediaVideoSource.h>
19 #include <ImsMediaTrace.h>
20 #include <VideoConfig.h>
21 #include <string.h>
22
23 using namespace android::telephony::imsmedia;
24
25 #define DEFAULT_UNDEFINE (-1)
26
IVideoSourceNode(BaseSessionCallback * callback)27 IVideoSourceNode::IVideoSourceNode(BaseSessionCallback* callback) :
28 BaseNode(callback)
29 {
30 std::unique_ptr<ImsMediaVideoSource> source(new ImsMediaVideoSource());
31 mVideoSource = std::move(source);
32 mVideoSource->SetListener(this);
33 mCodecType = DEFAULT_UNDEFINE;
34 mVideoMode = DEFAULT_UNDEFINE;
35 mCodecProfile = VideoConfig::CODEC_PROFILE_NONE;
36 mCodecLevel = VideoConfig::CODEC_LEVEL_NONE;
37 mCameraId = 0;
38 mCameraZoom = 0;
39 mWidth = 0;
40 mHeight = 0;
41 mFramerate = DEFAULT_FRAMERATE;
42 mBitrate = DEFAULT_BITRATE;
43 mSamplingRate = 0;
44 mIntraInterval = 1;
45 mImagePath = "";
46 mDeviceOrientation = 0;
47 mWindow = nullptr;
48 mMinBitrateThreshold = 0;
49 mBitrateNotified = false;
50 }
51
~IVideoSourceNode()52 IVideoSourceNode::~IVideoSourceNode() {}
53
GetNodeId()54 kBaseNodeId IVideoSourceNode::GetNodeId()
55 {
56 return kNodeIdVideoSource;
57 }
58
Start()59 ImsMediaResult IVideoSourceNode::Start()
60 {
61 IMLOGD3("[Start] codec[%d], mode[%d], cameraId[%d]", mCodecType, mVideoMode, mCameraId);
62
63 if (mVideoSource)
64 {
65 mVideoSource->SetCodecConfig(
66 mCodecType, mCodecProfile, mCodecLevel, mBitrate, mFramerate, mIntraInterval);
67 mVideoSource->SetVideoMode(mVideoMode);
68 mVideoSource->SetResolution(mWidth, mHeight);
69
70 if (mVideoMode == VideoConfig::VIDEO_MODE_PREVIEW ||
71 mVideoMode == VideoConfig::VIDEO_MODE_RECORDING)
72 {
73 mVideoSource->SetCameraConfig(mCameraId, mCameraZoom);
74
75 if (mWindow == nullptr)
76 {
77 IMLOGE0("[Start] surface is not ready");
78 return RESULT_NOT_READY;
79 }
80 }
81 else
82 {
83 mVideoSource->SetImagePath(mImagePath);
84 }
85
86 mVideoSource->SetSurface(mWindow);
87
88 if (!mVideoSource->Start())
89 {
90 return RESULT_NOT_READY;
91 }
92
93 mVideoSource->SetDeviceOrientation(mDeviceOrientation);
94 mBitrateNotified = false;
95 }
96
97 mNodeState = kNodeStateRunning;
98 return RESULT_SUCCESS;
99 }
100
Stop()101 void IVideoSourceNode::Stop()
102 {
103 IMLOGD0("[Stop]");
104
105 if (mVideoSource)
106 {
107 mVideoSource->Stop();
108 }
109
110 ClearDataQueue();
111 mNodeState = kNodeStateStopped;
112 }
113
IsRunTime()114 bool IVideoSourceNode::IsRunTime()
115 {
116 return false;
117 }
118
IsSourceNode()119 bool IVideoSourceNode::IsSourceNode()
120 {
121 return true;
122 }
123
SetConfig(void * config)124 void IVideoSourceNode::SetConfig(void* config)
125 {
126 if (config == nullptr)
127 {
128 return;
129 }
130
131 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(config);
132 mCodecType = ImsMediaVideoUtil::ConvertCodecType(pConfig->getCodecType());
133 mVideoMode = pConfig->getVideoMode();
134 mSamplingRate = pConfig->getSamplingRateKHz();
135 mCodecProfile = pConfig->getCodecProfile();
136 mCodecLevel = pConfig->getCodecLevel();
137 mFramerate = pConfig->getFramerate();
138 mBitrate = pConfig->getBitrate();
139 mWidth = pConfig->getResolutionWidth();
140 mHeight = pConfig->getResolutionHeight();
141 mIntraInterval = pConfig->getIntraFrameInterval();
142
143 if (mVideoMode == VideoConfig::VIDEO_MODE_PREVIEW ||
144 mVideoMode == VideoConfig::VIDEO_MODE_RECORDING)
145 {
146 mCameraId = pConfig->getCameraId();
147 mCameraZoom = pConfig->getCameraZoom();
148 }
149 else
150 {
151 mImagePath = pConfig->getPauseImagePath();
152 }
153
154 mDeviceOrientation = pConfig->getDeviceOrientationDegree();
155 }
156
IsSameConfig(void * config)157 bool IVideoSourceNode::IsSameConfig(void* config)
158 {
159 if (config == nullptr)
160 {
161 return true;
162 }
163
164 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(config);
165
166 return (mCodecType == ImsMediaVideoUtil::ConvertCodecType(pConfig->getCodecType()) &&
167 mVideoMode == pConfig->getVideoMode() &&
168 mSamplingRate == pConfig->getSamplingRateKHz() &&
169 mCodecProfile == pConfig->getCodecProfile() &&
170 mCodecLevel == pConfig->getCodecLevel() && mFramerate == pConfig->getFramerate() &&
171 mBitrate == pConfig->getBitrate() && mCameraId == pConfig->getCameraId() &&
172 mCameraZoom == pConfig->getCameraZoom() && mWidth == pConfig->getResolutionWidth() &&
173 mHeight == pConfig->getResolutionHeight() &&
174 mDeviceOrientation == pConfig->getDeviceOrientationDegree());
175 }
176
UpdateConfig(void * config)177 ImsMediaResult IVideoSourceNode::UpdateConfig(void* config)
178 {
179 IMLOGD1("[UpdateConfig] current mode[%d]", mVideoMode);
180
181 if (config == nullptr)
182 {
183 return RESULT_INVALID_PARAM;
184 }
185
186 bool isRestart = false;
187
188 if (IsSameConfig(config))
189 {
190 IMLOGD0("[UpdateConfig] no update");
191 return RESULT_SUCCESS;
192 }
193
194 VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(config);
195
196 if (mCodecType != ImsMediaVideoUtil::ConvertCodecType(pConfig->getCodecType()) ||
197 mVideoMode != pConfig->getVideoMode() || mCodecProfile != pConfig->getCodecProfile() ||
198 mCodecLevel != pConfig->getCodecLevel() || mFramerate != pConfig->getFramerate() ||
199 mCameraId != pConfig->getCameraId() || mWidth != pConfig->getResolutionWidth() ||
200 mHeight != pConfig->getResolutionHeight())
201 {
202 isRestart = true;
203 }
204 else
205 {
206 if (mBitrate != pConfig->getBitrate())
207 {
208 /** TODO: bitrate change */
209 }
210
211 if (mDeviceOrientation != pConfig->getDeviceOrientationDegree())
212 {
213 mDeviceOrientation = pConfig->getDeviceOrientationDegree();
214 mVideoSource->SetDeviceOrientation(mDeviceOrientation);
215 }
216
217 return RESULT_SUCCESS;
218 }
219
220 if (isRestart)
221 {
222 kBaseNodeState prevState = mNodeState;
223 if (mNodeState == kNodeStateRunning)
224 {
225 Stop();
226 }
227
228 // reset the parameters
229 SetConfig(config);
230
231 if (prevState == kNodeStateRunning)
232 {
233 return Start();
234 }
235 }
236
237 return RESULT_SUCCESS;
238 }
239
ProcessData()240 void IVideoSourceNode::ProcessData()
241 {
242 std::lock_guard<std::mutex> guard(mMutex);
243 uint8_t* data = nullptr;
244 uint32_t dataSize = 0;
245 uint32_t timestamp = 0;
246 bool mark = false;
247 uint32_t seq = 0;
248 ImsMediaSubType subtype;
249 ImsMediaSubType dataType;
250
251 while (GetData(&subtype, &data, &dataSize, ×tamp, &mark, &seq, &dataType))
252 {
253 IMLOGD_PACKET1(IM_PACKET_LOG_VIDEO, "[ProcessData] size[%d]", dataSize);
254
255 SendDataToRearNode(
256 MEDIASUBTYPE_UNDEFINED, data, dataSize, timestamp, true, MEDIASUBTYPE_UNDEFINED);
257 DeleteData();
258 }
259 }
260
UpdateSurface(ANativeWindow * window)261 void IVideoSourceNode::UpdateSurface(ANativeWindow* window)
262 {
263 IMLOGD1("[UpdateSurface] surface[%p]", window);
264 mWindow = window;
265 }
266
OnUplinkEvent(uint8_t * data,uint32_t size,int64_t timestamp,uint32_t)267 void IVideoSourceNode::OnUplinkEvent(
268 uint8_t* data, uint32_t size, int64_t timestamp, uint32_t /*flag*/)
269 {
270 IMLOGD_PACKET2(
271 IM_PACKET_LOG_VIDEO, "[OnUplinkEvent] size[%zu], timestamp[%ld]", size, timestamp);
272 std::lock_guard<std::mutex> guard(mMutex);
273
274 if (size > 0)
275 {
276 OnDataFromFrontNode(
277 MEDIASUBTYPE_UNDEFINED, data, size, timestamp, true, MEDIASUBTYPE_UNDEFINED);
278 }
279 }
280
SetBitrateThreshold(int32_t bitrate)281 void IVideoSourceNode::SetBitrateThreshold(int32_t bitrate)
282 {
283 IMLOGD1("[SetBitrateThreshold] bitrate[%d]", bitrate);
284 mMinBitrateThreshold = bitrate;
285 }
286
OnEvent(int32_t type,int32_t param1,int32_t param2)287 void IVideoSourceNode::OnEvent(int32_t type, int32_t param1, int32_t param2)
288 {
289 IMLOGD3("[OnEvent] type[%d], param1[%d], param2[%d]", type, param1, param2);
290
291 switch (type)
292 {
293 case kVideoSourceEventUpdateOrientation:
294 if (mCallback != nullptr)
295 {
296 mCallback->SendEvent(kRequestVideoCvoUpdate, param1, param2);
297 }
298 break;
299 case kVideoSourceEventCameraError:
300 if (mCallback != nullptr)
301 {
302 mCallback->SendEvent(kImsMediaEventNotifyError, param1, param2);
303 }
304 break;
305 case kRequestVideoBitrateChange:
306 if (mVideoSource != nullptr)
307 {
308 if (mVideoSource->changeBitrate(param1))
309 {
310 if (mMinBitrateThreshold != 0 && param1 <= mMinBitrateThreshold &&
311 mCallback != nullptr && !mBitrateNotified)
312 {
313 mCallback->SendEvent(kImsMediaEventNotifyVideoLowestBitrate, param1);
314 mBitrateNotified = true;
315 }
316 }
317 }
318 break;
319 case kRequestVideoIdrFrame:
320 if (mVideoSource != nullptr)
321 {
322 mVideoSource->requestIdrFrame();
323 }
324 break;
325 default:
326 break;
327 }
328 }