• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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