1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "video_play_controller.h"
17 #include <chrono>
18 #include <securec.h>
19 #include "common/common_macro.h"
20 #include "common/const_def.h"
21 #include "common/event_channel.h"
22 #include "common/media_log.h"
23 #include "configuration/include/config.h"
24 #include "magic_enum.hpp"
25 #include "media_controller.h"
26 #include "media_errors.h"
27 #include "protocol/frame/h264_frame.h"
28 #include "surface.h"
29 #include "utils/data_buffer.h"
30
31 using namespace OHOS::Media;
32
33 namespace OHOS {
34 namespace Sharing {
35
VideoPlayController(uint32_t mediaChannelId)36 VideoPlayController::VideoPlayController(uint32_t mediaChannelId)
37 {
38 SHARING_LOGD("trace.");
39 bufferReceiver_ = std::make_shared<BufferReceiver>();
40 mediachannelId_ = mediaChannelId;
41 }
42
~VideoPlayController()43 VideoPlayController::~VideoPlayController()
44 {
45 SHARING_LOGD("delete video play controller, mediachannelId: %{public}u.", mediachannelId_);
46 }
47
Init(VideoTrack & videoTrack)48 bool VideoPlayController::Init(VideoTrack &videoTrack)
49 {
50 SHARING_LOGD("trace.");
51 if (CODEC_NONE == videoTrack.codecId) {
52 SHARING_LOGW("no need to play.");
53 return false;
54 }
55 videoTrack_ = videoTrack;
56 SHARING_LOGI("videoWidth: %{public}d, videoHeight: %{public}d.", videoTrack.width, videoTrack.height);
57
58 SharingValue::Ptr values = nullptr;
59 auto ret = Config::GetInstance().GetConfig("codec", "forceSWDecoder", "isEnable", values);
60 if (ret == CONFIGURE_ERROR_NONE) {
61 bool value;
62 values->GetValue<bool>(value);
63 forceSWDecoder_ = static_cast<bool>(value);
64 }
65
66 videoSinkDecoder_ = std::make_shared<VideoSinkDecoder>(mediachannelId_, forceSWDecoder_);
67 if (!videoSinkDecoder_->Init(videoTrack.codecId) || !videoSinkDecoder_->SetDecoderFormat(videoTrack)) {
68 SHARING_LOGE("video play init error.");
69 return false;
70 }
71
72 videoSinkDecoder_->SetVideoDecoderListener(shared_from_this());
73 bufferReceiver_->SetBufferReceiverListener(shared_from_this());
74 return true;
75 }
76
SetSurface(sptr<Surface> surface,bool keyFrame)77 bool VideoPlayController::SetSurface(sptr<Surface> surface, bool keyFrame)
78 {
79 SHARING_LOGD("trace.");
80 RETURN_FALSE_IF_NULL(surface);
81 if (isVideoRunning_) {
82 SHARING_LOGE("video play is running, cann't set surface.");
83 return false;
84 }
85
86 if (videoSinkDecoder_ == nullptr) {
87 SHARING_LOGE("cann't set surface if the decoder not init.");
88 return false;
89 }
90
91 if (forceSWDecoder_) {
92 if ((nullptr != videoSinkDecoder_)) {
93 bool isVaild = true;
94 if (isSurfaceNoCopy_) {
95 isVaild = videoSinkDecoder_->SetSurface(surface);
96 }
97 if (isVaild) {
98 enableSurface_ = true;
99 surface_ = surface;
100 SHARING_LOGD("set surface success.");
101 return true;
102 } else {
103 SHARING_LOGD("set surface failed.");
104 return false;
105 }
106 }
107 } else {
108 if ((nullptr != videoSinkDecoder_) && (videoSinkDecoder_->SetSurface(surface))) {
109 surface_ = surface;
110 isKeyMode_ = keyFrame;
111 enableSurface_ = true;
112 SHARING_LOGD("set surface success.");
113 return true;
114 }
115 }
116
117 return false;
118 }
119
Start(BufferDispatcher::Ptr & dispatcher)120 bool VideoPlayController::Start(BufferDispatcher::Ptr &dispatcher)
121 {
122 SHARING_LOGD("trace.");
123 if (isVideoRunning_) {
124 SHARING_LOGW("video play is running.");
125 return true;
126 }
127
128 if (enableSurface_ && (nullptr != videoSinkDecoder_)) {
129 if (videoSinkDecoder_->Start()) {
130 isVideoRunning_ = true;
131 dispatcher->AttachReceiver(bufferReceiver_);
132 SetKeyMode(isKeyMode_);
133 StartVideoThread();
134 return true;
135 }
136 }
137 SHARING_LOGE("video play start failed, mediachannelId: %{public}u!", mediachannelId_);
138 return false;
139 }
140
Stop(BufferDispatcher::Ptr & dispatcher)141 void VideoPlayController::Stop(BufferDispatcher::Ptr &dispatcher)
142 {
143 SHARING_LOGD("trace.");
144 RETURN_IF_NULL(dispatcher);
145 SHARING_LOGI("video play stop, mediachannelId: %{public}u.", mediachannelId_);
146 if (bufferReceiver_) {
147 dispatcher->DetachReceiver(bufferReceiver_);
148 }
149
150 if (isVideoRunning_ && (nullptr != videoSinkDecoder_)) {
151 videoSinkDecoder_->Stop();
152 isVideoRunning_ = false;
153 if (bufferReceiver_) {
154 bufferReceiver_->NotifyReadStop();
155 }
156 StopVideoThread();
157 }
158
159 SHARING_LOGI("media play stop done, mediachannelId: %{public}u.", mediachannelId_);
160 }
161
Release()162 void VideoPlayController::Release()
163 {
164 SHARING_LOGD("trace.");
165 if (nullptr != videoSinkDecoder_) {
166 videoSinkDecoder_->Release();
167 videoSinkDecoder_.reset();
168 }
169 }
170
StartVideoThread()171 void VideoPlayController::StartVideoThread()
172 {
173 SHARING_LOGD("trace.");
174 if (videoPlayThread_ != nullptr) {
175 SHARING_LOGD("play start thread already exist, mediachannelId: %{public}u.", mediachannelId_);
176 return;
177 }
178
179 videoPlayThread_ = std::make_shared<std::thread>(&VideoPlayController::VideoPlayThread, this);
180 std::string name = "videoplay";
181 pthread_setname_np(videoPlayThread_->native_handle(), name.c_str());
182 if (videoPlayThread_ == nullptr) {
183 SHARING_LOGE("play start create thread error, mediachannelId: %{public}u!", mediachannelId_);
184 }
185 }
186
StopVideoThread()187 void VideoPlayController::StopVideoThread()
188 {
189 SHARING_LOGD("trace.");
190 if (videoPlayThread_) {
191 if (videoPlayThread_->joinable()) {
192 videoPlayThread_->join();
193 }
194 videoPlayThread_ = nullptr;
195 }
196 SHARING_LOGD("stop video thread exit, mediachannelId: %{public}u.", mediachannelId_);
197 }
198
VideoPlayThread()199 void VideoPlayController::VideoPlayThread()
200 {
201 SHARING_LOGD("video play thread start mediaChannelId: %{public}u tid: %{public}d.", mediachannelId_, gettid());
202 while (isVideoRunning_) {
203 MediaData::Ptr outData = std::make_shared<MediaData>();
204 outData->buff = std::make_shared<DataBuffer>();
205 int32_t ret = 0;
206 if (bufferReceiver_) {
207 ret = bufferReceiver_->RequestRead(MediaType::MEDIA_TYPE_VIDEO, [&outData](const MediaData::Ptr &data) {
208 if (data == nullptr) {
209 return;
210 }
211 outData->buff->ReplaceData(data->buff->Peek(), data->buff->Size());
212 outData->keyFrame = data->keyFrame;
213 outData->mediaType = data->mediaType;
214 outData->pts = data->pts;
215 outData->isRaw = data->isRaw;
216 outData->ssrc = data->ssrc;
217 });
218 }
219 if (ret != 0) {
220 continue;
221 }
222 if (videoSinkDecoder_) {
223 if (outData->keyFrame) {
224 MEDIA_LOGD("get key frame.");
225 auto sps = bufferReceiver_->GetSPS();
226 if (sps != nullptr && sps->buff != nullptr) {
227 MEDIA_LOGD("get sps from dispatcher.");
228 ProcessVideoData(sps->buff->Peek(), sps->buff->Size());
229 }
230 auto pps = bufferReceiver_->GetPPS();
231 if (pps != nullptr && pps->buff != nullptr) {
232 MEDIA_LOGD("get pps from dispatcher.");
233 ProcessVideoData(pps->buff->Peek(), pps->buff->Size());
234 }
235 }
236 MEDIA_LOGD("process video data, size: %{public}d, keyFrame: %{public}d.", outData->buff->Size(),
237 outData->keyFrame);
238 ProcessVideoData(outData->buff->Peek(), outData->buff->Size());
239 }
240 }
241
242 SHARING_LOGD("play thread exit, mediachannelId: %{public}u tid: %{public}d.", mediachannelId_, gettid());
243 }
244
ProcessVideoData(const char * data,int32_t size)245 void VideoPlayController::ProcessVideoData(const char *data, int32_t size)
246 {
247 MEDIA_LOGD("trace.");
248 if (data == nullptr || size <= 0) {
249 SHARING_LOGD("data is null, mediachannelId: %{public}u.", mediachannelId_);
250 return;
251 }
252
253 int32_t bufferIndex = -1;
254 {
255 std::unique_lock<std::mutex> lock(videoSinkDecoder_->inMutex_);
256 if (videoSinkDecoder_->inQueue_.empty()) {
257 while (isVideoRunning_) {
258 MEDIA_LOGD("try wait, mediachannelId: %{public}u.", mediachannelId_);
259 videoSinkDecoder_->inCond_.wait_for(lock, std::chrono::milliseconds(DECODE_WAIT_MILLISECONDS),
260 [this]() { return (!videoSinkDecoder_->inQueue_.empty()); });
261
262 if (videoSinkDecoder_->inQueue_.empty()) {
263 SHARING_LOGD("index queue empty, mediachannelId: %{public}u.", mediachannelId_);
264 continue;
265 }
266 break;
267 }
268 }
269 if (!videoSinkDecoder_->inQueue_.empty()) {
270 bufferIndex = videoSinkDecoder_->inQueue_.front();
271 videoSinkDecoder_->inQueue_.pop();
272 }
273 }
274
275 if (!isVideoRunning_) {
276 SHARING_LOGD("stop return, mediachannelId: %{public}u.", mediachannelId_);
277 return;
278 }
279
280 if (bufferIndex == -1) {
281 SHARING_LOGD("stop no process video data, mediachannelId: %{public}u.", mediachannelId_);
282 } else {
283 videoSinkDecoder_->DecodeVideoData(data, size, bufferIndex);
284 }
285 }
286
OnVideoDataDecoded(DataBuffer::Ptr decodedData)287 void VideoPlayController::OnVideoDataDecoded(DataBuffer::Ptr decodedData)
288 {
289 MEDIA_LOGD("trace.");
290 if (forceSWDecoder_) {
291 if (!isSurfaceNoCopy_) {
292 RenderInCopyMode(decodedData);
293 }
294 }
295 }
296
OnError(int32_t errorCode)297 void VideoPlayController::OnError(int32_t errorCode)
298 {
299 SHARING_LOGW("trace mediachannelId: %{public}u.", mediachannelId_);
300 auto mediaController = mediaController_.lock();
301 RETURN_IF_NULL(mediaController);
302
303 auto msg = std::make_shared<EventMsg>();
304 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
305 statusMsg->eventMsg = msg;
306 statusMsg->errorCode = ERR_OK;
307 if (surface_) {
308 statusMsg->surfaceId = surface_->GetUniqueId();
309 }
310
311 switch (errorCode) {
312 case Media::MSERR_SERVICE_DIED:
313 SHARING_LOGE("media service died: %{public}u.", mediachannelId_);
314 statusMsg->status = CONNTROLLER_NOTIFY_DECODER_DIED;
315 statusMsg->errorCode = ERR_SURFACE_FAILURE;
316 break;
317 default:
318 break;
319 }
320
321 mediaController->OnPlayControllerNotify(statusMsg);
322 }
323
RenderInCopyMode(DataBuffer::Ptr decodedData)324 int32_t VideoPlayController::RenderInCopyMode(DataBuffer::Ptr decodedData)
325 {
326 SHARING_LOGD("Render begin.");
327 sptr<SurfaceBuffer> buffer;
328 int32_t releaseFence = -1;
329 int32_t renderWidth = videoTrack_.width == 0 ? DEFAULT_VIDEO_WIDTH : videoTrack_.width;
330 int32_t renderHeight = videoTrack_.height == 0 ? DEFAULT_CAPTURE_VIDEO_HEIGHT : videoTrack_.height;
331
332 BufferRequestConfig requestConfig = {
333 .width = renderWidth,
334 .height = renderHeight,
335 .strideAlignment = 8,
336 // .format = PIXEL_FMT_RGBA_8888,
337 // .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
338 .format = GRAPHIC_PIXEL_FMT_YCRCB_420_SP,
339 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
340 .timeout = 0,
341 };
342
343 if (surface_ == nullptr) {
344 return -1;
345 }
346
347 SurfaceError error = surface_->RequestBuffer(buffer, releaseFence, requestConfig);
348 if (error != SURFACE_ERROR_OK) {
349 return -1;
350 }
351
352 void *bufferVirAddr = buffer->GetVirAddr();
353 SHARING_LOGD("buffer size is %{public}d.", decodedData->Size());
354 if (firstFrame_ == true) {
355 firstFrame_ = false;
356 SHARING_LOGD("first frame.");
357 }
358
359 uint32_t dataSize = renderWidth * renderHeight * 3 / 2;
360 auto ret = memcpy_s(bufferVirAddr, dataSize, decodedData->Peek(), dataSize);
361 if (ret != EOK) {
362 SHARING_LOGE("copy data failed !");
363 return -1;
364 }
365
366 if (bufferVirAddr == nullptr) {
367 SHARING_LOGD("bufferVirAddr is nullptr.");
368 return -1;
369 }
370
371 BufferFlushConfig flushConfig = {
372 .damage =
373 {
374 .x = 0,
375 .y = 0,
376 .w = renderWidth,
377 .h = renderHeight,
378 },
379 .timestamp = 0,
380 };
381
382 surface_->FlushBuffer(buffer, -1, flushConfig);
383 SHARING_LOGD("Render End.");
384 return 0;
385 }
386
OnAccelerationDoneNotify()387 void VideoPlayController::OnAccelerationDoneNotify()
388 {
389 SHARING_LOGW("mediachannelId: %{public}u!", mediachannelId_);
390 auto mediaController = mediaController_.lock();
391 RETURN_IF_NULL(mediaController);
392
393 auto msg = std::make_shared<EventMsg>();
394 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
395 statusMsg->eventMsg = msg;
396 statusMsg->errorCode = ERR_DECODE_DISABLE_ACCELERATION;
397 statusMsg->status = CONNTROLLER_NOTIFY_ACCELERATION;
398
399 if (surface_) {
400 statusMsg->surfaceId = surface_->GetUniqueId();
401 }
402
403 mediaController->OnPlayControllerNotify(statusMsg);
404 }
405
OnKeyModeNotify(bool enable)406 void VideoPlayController::OnKeyModeNotify(bool enable)
407 {
408 SHARING_LOGW("enable: %{public}d, mediachannelId: %{public}u!", enable, mediachannelId_);
409 auto mediaController = mediaController_.lock();
410 RETURN_IF_NULL(mediaController);
411
412 auto msg = std::make_shared<EventMsg>();
413 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
414 statusMsg->eventMsg = msg;
415 statusMsg->errorCode = ERR_OK;
416
417 if (surface_) {
418 statusMsg->surfaceId = surface_->GetUniqueId();
419 }
420
421 if (enable) {
422 statusMsg->status = CONNTROLLER_NOTIFY_KEYMOD_START;
423 } else {
424 statusMsg->status = CONNTROLLER_NOTIFY_KEYMOD_STOP;
425 }
426
427 mediaController->OnPlayControllerNotify(statusMsg);
428 }
429
430 } // namespace Sharing
431 } // namespace OHOS