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, &timestamp, &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 }