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 "avcodec_errors.h"
20 #include "common/common_macro.h"
21 #include "common/const_def.h"
22 #include "common/event_channel.h"
23 #include "common/media_log.h"
24 #include "configuration/include/config.h"
25 #include "magic_enum.hpp"
26 #include "media_controller.h"
27 #include "protocol/frame/h264_frame.h"
28 #include "surface.h"
29 #include "utils/data_buffer.h"
30
31 using namespace OHOS::MediaAVCodec;
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 if (bufferReceiver_) {
74 bufferReceiver_->SetBufferReceiverListener(shared_from_this());
75 }
76 return true;
77 }
78
SetSurface(sptr<Surface> surface,bool keyFrame)79 bool VideoPlayController::SetSurface(sptr<Surface> surface, bool keyFrame)
80 {
81 SHARING_LOGD("trace.");
82 RETURN_FALSE_IF_NULL(surface);
83 if (isVideoRunning_) {
84 SHARING_LOGE("video play is running, cann't set surface.");
85 return false;
86 }
87
88 if (videoSinkDecoder_ == nullptr) {
89 SHARING_LOGE("cann't set surface if the decoder not init.");
90 return false;
91 }
92
93 if (forceSWDecoder_) {
94 if ((nullptr != videoSinkDecoder_)) {
95 bool isVaild = true;
96 if (isSurfaceNoCopy_) {
97 isVaild = videoSinkDecoder_->SetSurface(surface);
98 }
99 if (isVaild) {
100 enableSurface_ = true;
101 surface_ = surface;
102 SHARING_LOGD("set surface success.");
103 return true;
104 } else {
105 SHARING_LOGD("set surface failed.");
106 return false;
107 }
108 }
109 } else {
110 if ((nullptr != videoSinkDecoder_) && (videoSinkDecoder_->SetSurface(surface))) {
111 surface_ = surface;
112 isKeyMode_ = keyFrame;
113 enableSurface_ = true;
114 SHARING_LOGD("set surface success.");
115 return true;
116 }
117 }
118
119 return false;
120 }
121
Start(BufferDispatcher::Ptr & dispatcher)122 bool VideoPlayController::Start(BufferDispatcher::Ptr &dispatcher)
123 {
124 SHARING_LOGD("trace.");
125 if (isVideoRunning_) {
126 SHARING_LOGW("video play is running.");
127 return true;
128 }
129
130 if (enableSurface_ && (nullptr != videoSinkDecoder_)) {
131 if (videoSinkDecoder_->Start()) {
132 isVideoRunning_ = true;
133 dispatcher->AttachReceiver(bufferReceiver_);
134 SetKeyMode(isKeyMode_);
135 StartVideoThread();
136 return true;
137 }
138 }
139 SHARING_LOGE("video play start failed, mediachannelId: %{public}u!", mediachannelId_);
140 return false;
141 }
142
Stop(BufferDispatcher::Ptr & dispatcher)143 void VideoPlayController::Stop(BufferDispatcher::Ptr &dispatcher)
144 {
145 SHARING_LOGD("trace.");
146 RETURN_IF_NULL(dispatcher);
147 SHARING_LOGI("video play stop, mediachannelId: %{public}u.", mediachannelId_);
148 if (bufferReceiver_) {
149 dispatcher->DetachReceiver(bufferReceiver_);
150 }
151
152 if (isVideoRunning_ && (nullptr != videoSinkDecoder_)) {
153 videoSinkDecoder_->Stop();
154 isVideoRunning_ = false;
155 if (bufferReceiver_) {
156 bufferReceiver_->NotifyReadStop();
157 }
158 StopVideoThread();
159 }
160
161 SHARING_LOGI("media play stop done, mediachannelId: %{public}u.", mediachannelId_);
162 }
163
Release()164 void VideoPlayController::Release()
165 {
166 SHARING_LOGD("trace.");
167 if (nullptr != videoSinkDecoder_) {
168 videoSinkDecoder_->Release();
169 videoSinkDecoder_.reset();
170 }
171 }
172
StartVideoThread()173 void VideoPlayController::StartVideoThread()
174 {
175 SHARING_LOGD("trace.");
176 if (videoPlayThread_ != nullptr) {
177 SHARING_LOGD("play start thread already exist, mediachannelId: %{public}u.", mediachannelId_);
178 return;
179 }
180
181 videoPlayThread_ = std::make_shared<std::thread>(&VideoPlayController::VideoPlayThread, this);
182 if (videoPlayThread_ == nullptr) {
183 SHARING_LOGE("play start create thread error, mediachannelId: %{public}u!", mediachannelId_);
184 return;
185 }
186 std::string name = "videoplay";
187 pthread_setname_np(videoPlayThread_->native_handle(), name.c_str());
188 }
189
StopVideoThread()190 void VideoPlayController::StopVideoThread()
191 {
192 SHARING_LOGD("trace.");
193 if (videoPlayThread_) {
194 if (videoPlayThread_->joinable()) {
195 videoPlayThread_->join();
196 }
197 videoPlayThread_ = nullptr;
198 }
199 SHARING_LOGD("stop video thread exit, mediachannelId: %{public}u.", mediachannelId_);
200 }
201
VideoPlayThread()202 void VideoPlayController::VideoPlayThread()
203 {
204 SHARING_LOGD("video play thread start mediaChannelId: %{public}u tid: %{public}d.", mediachannelId_, gettid());
205 while (isVideoRunning_) {
206 MediaData::Ptr outData = std::make_shared<MediaData>();
207 outData->buff = std::make_shared<DataBuffer>();
208 int32_t ret = 0;
209 if (bufferReceiver_) {
210 ret = bufferReceiver_->RequestRead(MediaType::MEDIA_TYPE_VIDEO, [&outData](const MediaData::Ptr &data) {
211 if (data == nullptr) {
212 return;
213 }
214 outData->buff->ReplaceData(data->buff->Peek(), data->buff->Size());
215 outData->keyFrame = data->keyFrame;
216 outData->mediaType = data->mediaType;
217 outData->pts = data->pts;
218 outData->isRaw = data->isRaw;
219 outData->ssrc = data->ssrc;
220 });
221 }
222 if (ret != 0) {
223 continue;
224 }
225 if (videoSinkDecoder_) {
226 if (outData->keyFrame) {
227 MEDIA_LOGD("get key frame.");
228 auto sps = bufferReceiver_->GetSPS();
229 if (sps != nullptr && sps->buff != nullptr) {
230 MEDIA_LOGD("get sps from dispatcher.");
231 ProcessVideoData(sps->buff->Peek(), sps->buff->Size());
232 }
233 auto pps = bufferReceiver_->GetPPS();
234 if (pps != nullptr && pps->buff != nullptr) {
235 MEDIA_LOGD("get pps from dispatcher.");
236 ProcessVideoData(pps->buff->Peek(), pps->buff->Size());
237 }
238 }
239 MEDIA_LOGD("process video data, size: %{public}d, keyFrame: %{public}d.", outData->buff->Size(),
240 outData->keyFrame);
241 ProcessVideoData(outData->buff->Peek(), outData->buff->Size());
242 }
243 }
244
245 SHARING_LOGD("play thread exit, mediachannelId: %{public}u tid: %{public}d.", mediachannelId_, gettid());
246 }
247
ProcessVideoData(const char * data,int32_t size)248 void VideoPlayController::ProcessVideoData(const char *data, int32_t size)
249 {
250 MEDIA_LOGD("trace.");
251 if (data == nullptr || size <= 0) {
252 SHARING_LOGD("data is null, mediachannelId: %{public}u.", mediachannelId_);
253 return;
254 }
255
256 {
257 std::unique_lock<std::mutex> lock(videoSinkDecoder_->inMutex_);
258 if (videoSinkDecoder_->inQueue_.empty()) {
259 while (isVideoRunning_) {
260 SHARING_LOGD("try wait, mediachannelId: %{public}u.", mediachannelId_);
261 videoSinkDecoder_->inCond_.wait_for(lock, std::chrono::milliseconds(DECODE_WAIT_MILLISECONDS),
262 [this]() { return (!videoSinkDecoder_->inQueue_.empty()); });
263
264 if (videoSinkDecoder_->inQueue_.empty()) {
265 SHARING_LOGD("index queue empty, mediachannelId: %{public}u.", mediachannelId_);
266 continue;
267 }
268 break;
269 }
270 }
271 }
272
273 if (!isVideoRunning_) {
274 SHARING_LOGD("stop return, mediachannelId: %{public}u.", mediachannelId_);
275 return;
276 }
277
278 bool ret = videoSinkDecoder_->DecodeVideoData(data, size);
279 if (ret == false) {
280 SHARING_LOGE("sink decode data failed.");
281 }
282 }
283
OnVideoDataDecoded(DataBuffer::Ptr decodedData)284 void VideoPlayController::OnVideoDataDecoded(DataBuffer::Ptr decodedData)
285 {
286 MEDIA_LOGD("trace.");
287 if (forceSWDecoder_) {
288 if (!isSurfaceNoCopy_) {
289 RenderInCopyMode(decodedData);
290 }
291 }
292 }
293
OnError(int32_t errorCode)294 void VideoPlayController::OnError(int32_t errorCode)
295 {
296 SHARING_LOGW("trace mediachannelId: %{public}u.", mediachannelId_);
297 auto mediaController = mediaController_.lock();
298 RETURN_IF_NULL(mediaController);
299
300 auto msg = std::make_shared<EventMsg>();
301 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
302 statusMsg->eventMsg = msg;
303 statusMsg->errorCode = ERR_OK;
304 if (surface_) {
305 statusMsg->surfaceId = surface_->GetUniqueId();
306 }
307
308 switch (errorCode) {
309 case MediaAVCodec::AVCS_ERR_SERVICE_DIED:
310 SHARING_LOGE("media service died: %{public}u.", mediachannelId_);
311 statusMsg->status = CONNTROLLER_NOTIFY_DECODER_DIED;
312 statusMsg->errorCode = ERR_SURFACE_FAILURE;
313 break;
314 default:
315 break;
316 }
317
318 mediaController->OnPlayControllerNotify(statusMsg);
319 }
320
RenderInCopyMode(DataBuffer::Ptr decodedData)321 int32_t VideoPlayController::RenderInCopyMode(DataBuffer::Ptr decodedData)
322 {
323 SHARING_LOGD("Render begin.");
324 sptr<SurfaceBuffer> buffer;
325 int32_t releaseFence = -1;
326 int32_t renderWidth = static_cast<int32_t>(videoTrack_.width == 0 ? DEFAULT_VIDEO_WIDTH : videoTrack_.width);
327 int32_t renderHeight = static_cast<int32_t>(videoTrack_.height == 0 ?
328 DEFAULT_CAPTURE_VIDEO_HEIGHT : videoTrack_.height);
329
330 BufferRequestConfig requestConfig = {
331 .width = renderWidth, .height = renderHeight, .strideAlignment = 8,
332 // .format = PIXEL_FMT_RGBA_8888,
333 // .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
334 .format = GRAPHIC_PIXEL_FMT_YCRCB_420_SP,
335 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
336 .timeout = 0,
337 };
338
339 if (surface_ == nullptr) {
340 return -1;
341 }
342
343 SurfaceError error = surface_->RequestBuffer(buffer, releaseFence, requestConfig);
344 if (error != SURFACE_ERROR_OK) {
345 return -1;
346 }
347
348 void *bufferVirAddr = buffer->GetVirAddr();
349 SHARING_LOGD("buffer size is %{public}d.", decodedData->Size());
350 if (firstFrame_ == true) {
351 firstFrame_ = false;
352 SHARING_LOGD("first frame.");
353 }
354
355 int32_t dataSize = renderWidth * renderHeight * 3 / 2;
356 auto ret = memcpy_s(bufferVirAddr, dataSize, decodedData->Peek(), dataSize);
357 if (ret != EOK) {
358 SHARING_LOGE("copy data failed !");
359 return -1;
360 }
361
362 if (bufferVirAddr == nullptr) {
363 SHARING_LOGD("bufferVirAddr is nullptr.");
364 return -1;
365 }
366
367 BufferFlushConfig flushConfig = {
368 .damage = {
369 .x = 0, .y = 0, .w = renderWidth, .h = renderHeight,
370 },
371 .timestamp = 0,
372 };
373
374 surface_->FlushBuffer(buffer, -1, flushConfig);
375 SHARING_LOGD("Render End.");
376 return 0;
377 }
378
OnAccelerationDoneNotify()379 void VideoPlayController::OnAccelerationDoneNotify()
380 {
381 SHARING_LOGW("mediachannelId: %{public}u!", mediachannelId_);
382 auto mediaController = mediaController_.lock();
383 RETURN_IF_NULL(mediaController);
384
385 auto msg = std::make_shared<EventMsg>();
386 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
387 statusMsg->eventMsg = msg;
388 statusMsg->errorCode = ERR_DECODE_DISABLE_ACCELERATION;
389 statusMsg->status = CONNTROLLER_NOTIFY_ACCELERATION;
390
391 if (surface_) {
392 statusMsg->surfaceId = surface_->GetUniqueId();
393 }
394
395 mediaController->OnPlayControllerNotify(statusMsg);
396 }
397
OnKeyModeNotify(bool enable)398 void VideoPlayController::OnKeyModeNotify(bool enable)
399 {
400 SHARING_LOGW("enable: %{public}d, mediachannelId: %{public}u!", enable, mediachannelId_);
401 auto mediaController = mediaController_.lock();
402 RETURN_IF_NULL(mediaController);
403
404 auto msg = std::make_shared<EventMsg>();
405 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
406 statusMsg->eventMsg = msg;
407 statusMsg->errorCode = ERR_OK;
408
409 if (surface_) {
410 statusMsg->surfaceId = surface_->GetUniqueId();
411 }
412
413 if (enable) {
414 statusMsg->status = CONNTROLLER_NOTIFY_KEYMOD_START;
415 } else {
416 statusMsg->status = CONNTROLLER_NOTIFY_KEYMOD_STOP;
417 }
418
419 mediaController->OnPlayControllerNotify(statusMsg);
420 }
421
422 } // namespace Sharing
423 } // namespace OHOS