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