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 #include "common/sharing_sink_hisysevent.h"
31
32 using namespace OHOS::MediaAVCodec;
33
34 namespace OHOS {
35 namespace Sharing {
36
VideoPlayController(uint32_t mediaChannelId)37 VideoPlayController::VideoPlayController(uint32_t mediaChannelId)
38 {
39 SHARING_LOGD("trace.");
40 bufferReceiver_ = std::make_shared<BufferReceiver>();
41 mediachannelId_ = mediaChannelId;
42 }
43
~VideoPlayController()44 VideoPlayController::~VideoPlayController()
45 {
46 SHARING_LOGD("delete video play controller, mediachannelId: %{public}u.", mediachannelId_);
47 Release();
48 }
49
Init(VideoTrack & videoTrack)50 bool VideoPlayController::Init(VideoTrack &videoTrack)
51 {
52 SHARING_LOGD("trace.");
53 if (CODEC_NONE == videoTrack.codecId) {
54 SHARING_LOGW("no need to play.");
55 return false;
56 }
57 videoTrack_ = videoTrack;
58 SHARING_LOGI("videoWidth: %{public}d, videoHeight: %{public}d.", videoTrack.width, videoTrack.height);
59
60 SharingValue::Ptr values = nullptr;
61 auto ret = Config::GetInstance().GetConfig("codec", "forceSWDecoder", "isEnable", values);
62 if (ret == CONFIGURE_ERROR_NONE) {
63 bool value;
64 values->GetValue<bool>(value);
65 forceSWDecoder_ = static_cast<bool>(value);
66 }
67
68 videoSinkDecoder_ = std::make_shared<VideoSinkDecoder>(mediachannelId_, forceSWDecoder_);
69 if (!videoSinkDecoder_->Init(videoTrack.codecId) || !videoSinkDecoder_->SetDecoderFormat(videoTrack)) {
70 SHARING_LOGE("video play init error.");
71 return false;
72 }
73
74 videoSinkDecoder_->SetVideoDecoderListener(shared_from_this());
75 if (bufferReceiver_) {
76 bufferReceiver_->SetBufferReceiverListener(shared_from_this());
77 }
78 return true;
79 }
80
SetSurface(sptr<Surface> surface,bool keyFrame)81 bool VideoPlayController::SetSurface(sptr<Surface> surface, bool keyFrame)
82 {
83 SHARING_LOGD("trace.");
84 RETURN_FALSE_IF_NULL(surface);
85 if (isVideoRunning_) {
86 SHARING_LOGE("video play is running, cann't set surface.");
87 return false;
88 }
89
90 if (videoSinkDecoder_ == nullptr) {
91 SHARING_LOGE("cann't set surface if the decoder not init.");
92 return false;
93 }
94
95 if (forceSWDecoder_) {
96 bool isValid = true;
97 if (isSurfaceNoCopy_) {
98 isValid = videoSinkDecoder_->SetSurface(surface);
99 }
100 if (isValid) {
101 enableSurface_ = true;
102 surface_ = surface;
103 SHARING_LOGD("set surface success.");
104 return true;
105 } else {
106 SHARING_LOGD("set surface failed.");
107 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::SEND_M7_MSG,
108 SinkErrorCode::WIFI_DISPLAY_ADD_SURFACE_ERROR);
109 return false;
110 }
111 } else {
112 if (videoSinkDecoder_->SetSurface(surface)) {
113 surface_ = surface;
114 isKeyMode_ = keyFrame;
115 enableSurface_ = true;
116 SHARING_LOGD("set surface success.");
117 return true;
118 }
119 }
120
121 return false;
122 }
123
Start(BufferDispatcher::Ptr & dispatcher)124 bool VideoPlayController::Start(BufferDispatcher::Ptr &dispatcher)
125 {
126 SHARING_LOGD("trace.");
127 if (isVideoRunning_) {
128 SHARING_LOGW("video play is running.");
129 return true;
130 }
131
132 if (enableSurface_ && (nullptr != videoSinkDecoder_)) {
133 if (videoSinkDecoder_->Start()) {
134 isVideoRunning_ = true;
135 dispatcher->AttachReceiver(bufferReceiver_);
136 SetKeyMode(isKeyMode_);
137 StartVideoThread();
138 return true;
139 }
140 }
141 SHARING_LOGE("video play start failed, mediachannelId: %{public}u!", mediachannelId_);
142 return false;
143 }
144
Stop(BufferDispatcher::Ptr & dispatcher)145 void VideoPlayController::Stop(BufferDispatcher::Ptr &dispatcher)
146 {
147 SHARING_LOGD("trace.");
148 RETURN_IF_NULL(dispatcher);
149 SHARING_LOGI("video play stop, mediachannelId: %{public}u.", mediachannelId_);
150 if (bufferReceiver_) {
151 dispatcher->DetachReceiver(bufferReceiver_);
152 }
153
154 if (isVideoRunning_ && (nullptr != videoSinkDecoder_)) {
155 videoSinkDecoder_->Stop();
156 isVideoRunning_ = false;
157 if (bufferReceiver_) {
158 bufferReceiver_->NotifyReadStop();
159 }
160 StopVideoThread();
161 }
162
163 SHARING_LOGI("media play stop done, mediachannelId: %{public}u.", mediachannelId_);
164 }
165
Release()166 void VideoPlayController::Release()
167 {
168 SHARING_LOGD("trace.");
169 if (nullptr != videoSinkDecoder_) {
170 videoSinkDecoder_->Release();
171 videoSinkDecoder_.reset();
172 }
173 }
174
StartVideoThread()175 void VideoPlayController::StartVideoThread()
176 {
177 SHARING_LOGD("trace.");
178 if (videoPlayThread_ != nullptr) {
179 SHARING_LOGD("play start thread already exist, mediachannelId: %{public}u.", mediachannelId_);
180 return;
181 }
182
183 videoPlayThread_ = std::make_shared<std::thread>(&VideoPlayController::VideoPlayThread, this);
184 if (videoPlayThread_ == nullptr) {
185 SHARING_LOGE("play start create thread error, mediachannelId: %{public}u!", mediachannelId_);
186 return;
187 }
188 std::string name = "videoplay";
189 pthread_setname_np(videoPlayThread_->native_handle(), name.c_str());
190 }
191
StopVideoThread()192 void VideoPlayController::StopVideoThread()
193 {
194 SHARING_LOGD("trace.");
195 if (videoPlayThread_) {
196 if (videoPlayThread_->joinable()) {
197 videoPlayThread_->join();
198 }
199 videoPlayThread_ = nullptr;
200 }
201 SHARING_LOGD("stop video thread exit, mediachannelId: %{public}u.", mediachannelId_);
202 }
203
VideoPlayThread()204 void VideoPlayController::VideoPlayThread()
205 {
206 SHARING_LOGD("video play thread start mediaChannelId: %{public}u tid: %{public}d.", mediachannelId_, gettid());
207 while (isVideoRunning_) {
208 MediaData::Ptr outData = std::make_shared<MediaData>();
209 outData->buff = std::make_shared<DataBuffer>();
210 int32_t ret = 0;
211 if (bufferReceiver_) {
212 ret = bufferReceiver_->RequestRead(MediaType::MEDIA_TYPE_VIDEO, [&outData](const MediaData::Ptr &data) {
213 if (data == nullptr) {
214 return;
215 }
216 outData->buff->ReplaceData(data->buff->Peek(), data->buff->Size());
217 outData->keyFrame = data->keyFrame;
218 outData->mediaType = data->mediaType;
219 outData->pts = data->pts;
220 outData->isRaw = data->isRaw;
221 outData->ssrc = data->ssrc;
222 });
223 }
224 if (ret != 0) {
225 continue;
226 }
227 if (videoSinkDecoder_) {
228 if (outData->keyFrame) {
229 MEDIA_LOGD("get key frame.");
230 auto sps = bufferReceiver_->GetSPS();
231 if (sps != nullptr && sps->buff != nullptr) {
232 MEDIA_LOGD("get sps from dispatcher.");
233 ProcessVideoData(sps->buff->Peek(), sps->buff->Size(), outData->pts);
234 }
235 auto pps = bufferReceiver_->GetPPS();
236 if (pps != nullptr && pps->buff != nullptr) {
237 MEDIA_LOGD("get pps from dispatcher.");
238 ProcessVideoData(pps->buff->Peek(), pps->buff->Size(), outData->pts);
239 }
240 }
241 MEDIA_LOGD("process video data, size: %{public}d, keyFrame: %{public}d.", outData->buff->Size(),
242 outData->keyFrame);
243 ProcessVideoData(outData->buff->Peek(), outData->buff->Size(), outData->pts);
244 }
245 }
246
247 SHARING_LOGD("play thread exit, mediachannelId: %{public}u tid: %{public}d.", mediachannelId_, gettid());
248 }
249
ProcessVideoData(const char * data,int32_t size,uint64_t pts)250 void VideoPlayController::ProcessVideoData(const char *data, int32_t size, uint64_t pts)
251 {
252 MEDIA_LOGD("trace.");
253 if (data == nullptr || size <= 0) {
254 SHARING_LOGD("data is null, mediachannelId: %{public}u.", mediachannelId_);
255 return;
256 }
257
258 {
259 std::unique_lock<std::mutex> lock(videoSinkDecoder_->inMutex_);
260 if (videoSinkDecoder_->inQueue_.empty()) {
261 while (isVideoRunning_) {
262 SHARING_LOGD("try wait, mediachannelId: %{public}u.", mediachannelId_);
263 videoSinkDecoder_->inCond_.wait_for(lock, std::chrono::milliseconds(DECODE_WAIT_MILLISECONDS),
264 [this]() { return (!videoSinkDecoder_->inQueue_.empty()); });
265
266 if (videoSinkDecoder_->inQueue_.empty()) {
267 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::VIDEO_DECODE,
268 SinkErrorCode::WIFI_DISPLAY_VIDEO_DECODE_TIMEOUT);
269 SHARING_LOGD("index queue empty, mediachannelId: %{public}u.", mediachannelId_);
270 continue;
271 }
272 break;
273 }
274 }
275 }
276
277 if (!isVideoRunning_) {
278 SHARING_LOGD("stop return, mediachannelId: %{public}u.", mediachannelId_);
279 return;
280 }
281
282 bool ret = videoSinkDecoder_->DecodeVideoData(data, size, pts);
283 if (ret == false) {
284 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::VIDEO_DECODE,
285 SinkErrorCode::WIFI_DISPLAY_VIDEO_DECODE_FAILED);
286 SHARING_LOGE("sink decode data failed.");
287 }
288 }
289
OnVideoDataDecoded(DataBuffer::Ptr decodedData)290 void VideoPlayController::OnVideoDataDecoded(DataBuffer::Ptr decodedData)
291 {
292 MEDIA_LOGD("trace.");
293 if (forceSWDecoder_) {
294 if (!isSurfaceNoCopy_) {
295 RenderInCopyMode(decodedData);
296 }
297 }
298 }
299
OnError(int32_t errorCode)300 void VideoPlayController::OnError(int32_t errorCode)
301 {
302 SHARING_LOGW("trace mediachannelId: %{public}u.", mediachannelId_);
303 auto mediaController = mediaController_.lock();
304 RETURN_IF_NULL(mediaController);
305
306 auto msg = std::make_shared<EventMsg>();
307 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
308 statusMsg->eventMsg = msg;
309 statusMsg->errorCode = ERR_OK;
310 if (surface_) {
311 statusMsg->surfaceId = surface_->GetUniqueId();
312 }
313
314 switch (errorCode) {
315 case MediaAVCodec::AVCS_ERR_SERVICE_DIED:
316 SHARING_LOGE("media service died: %{public}u.", mediachannelId_);
317 statusMsg->status = CONNTROLLER_NOTIFY_DECODER_DIED;
318 statusMsg->errorCode = ERR_SURFACE_FAILURE;
319 break;
320 default:
321 break;
322 }
323
324 mediaController->OnPlayControllerNotify(statusMsg);
325 }
326
RenderInCopyMode(DataBuffer::Ptr decodedData)327 int32_t VideoPlayController::RenderInCopyMode(DataBuffer::Ptr decodedData)
328 {
329 SHARING_LOGD("Render begin.");
330 sptr<SurfaceBuffer> buffer;
331 int32_t releaseFence = -1;
332 int32_t renderWidth = static_cast<int32_t>(videoTrack_.width == 0 ? DEFAULT_VIDEO_WIDTH : videoTrack_.width);
333 int32_t renderHeight = static_cast<int32_t>(videoTrack_.height == 0 ?
334 DEFAULT_CAPTURE_VIDEO_HEIGHT : videoTrack_.height);
335
336 BufferRequestConfig requestConfig = {
337 .width = renderWidth, .height = renderHeight, .strideAlignment = 8,
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 if (bufferVirAddr == nullptr) {
354 SHARING_LOGD("bufferVirAddr is nullptr.");
355 return -1;
356 }
357
358 SHARING_LOGD("buffer size is %{public}d.", decodedData->Size());
359 int32_t dataSize = renderWidth * renderHeight * 3 / 2;
360 if (dataSize < 0){
361 SHARING_LOGE("dataSize < 0");
362 return -1;
363 }
364 uint32_t dataSizeUint = static_cast<uint32_t>(dataSize);
365 if (dataSizeUint > static_cast<uint32_t>(decodedData->Size()) || (dataSizeUint > buffer->GetSize())) {
366 SHARING_LOGE("invalid data size");
367 return -1;
368 }
369 auto ret = memcpy_s(bufferVirAddr, dataSize, decodedData->Peek(), dataSize);
370 if (ret != EOK) {
371 SHARING_LOGE("copy data failed !");
372 return -1;
373 }
374
375 BufferFlushConfig flushConfig = {
376 .damage = {
377 .x = 0, .y = 0, .w = renderWidth, .h = renderHeight,
378 },
379 .timestamp = 0,
380 };
381
382 if (firstFrame_ == true) {
383 firstFrame_ = false;
384 SHARING_LOGD("first frame.");
385 }
386
387 surface_->FlushBuffer(buffer, -1, flushConfig);
388 SHARING_LOGD("Render End.");
389 return 0;
390 }
391
OnAccelerationDoneNotify()392 void VideoPlayController::OnAccelerationDoneNotify()
393 {
394 SHARING_LOGW("mediachannelId: %{public}u!", mediachannelId_);
395 auto mediaController = mediaController_.lock();
396 RETURN_IF_NULL(mediaController);
397
398 auto msg = std::make_shared<EventMsg>();
399 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
400 statusMsg->eventMsg = msg;
401 statusMsg->errorCode = ERR_DECODE_DISABLE_ACCELERATION;
402 statusMsg->status = CONNTROLLER_NOTIFY_ACCELERATION;
403
404 if (surface_) {
405 statusMsg->surfaceId = surface_->GetUniqueId();
406 }
407
408 mediaController->OnPlayControllerNotify(statusMsg);
409 }
410
OnKeyModeNotify(bool enable)411 void VideoPlayController::OnKeyModeNotify(bool enable)
412 {
413 SHARING_LOGW("enable: %{public}d, mediachannelId: %{public}u!", enable, mediachannelId_);
414 auto mediaController = mediaController_.lock();
415 RETURN_IF_NULL(mediaController);
416
417 auto msg = std::make_shared<EventMsg>();
418 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
419 statusMsg->eventMsg = msg;
420 statusMsg->errorCode = ERR_OK;
421
422 if (surface_) {
423 statusMsg->surfaceId = surface_->GetUniqueId();
424 }
425
426 if (enable) {
427 statusMsg->status = CONNTROLLER_NOTIFY_KEYMOD_START;
428 } else {
429 statusMsg->status = CONNTROLLER_NOTIFY_KEYMOD_STOP;
430 }
431
432 mediaController->OnPlayControllerNotify(statusMsg);
433 }
434
SetVideoAudioSync(std::shared_ptr<VideoAudioSync> videoAudioSync)435 void VideoPlayController::SetVideoAudioSync(std::shared_ptr<VideoAudioSync> videoAudioSync)
436 {
437 if (videoSinkDecoder_ != nullptr) {
438 videoSinkDecoder_->SetVideoAudioSync(videoAudioSync);
439 }
440 }
441
442 } // namespace Sharing
443 } // namespace OHOS