• 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 "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