• 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_sink_decoder.h"
17 #include <securec.h>
18 #include "avcodec_codec_name.h"
19 #include "avcodec_errors.h"
20 #include "avcodec_mime_type.h"
21 #include "buffer/avsharedmemory.h"
22 #include "common/common_macro.h"
23 #include "common/media_log.h"
24 #include "configuration/include/config.h"
25 #include "common/sharing_sink_hisysevent.h"
26 #include "utils/utils.h"
27 
28 namespace OHOS {
29 namespace Sharing {
VideoSinkDecoder(uint32_t controlId,bool forceSWDecoder)30 VideoSinkDecoder::VideoSinkDecoder(uint32_t controlId, bool forceSWDecoder)
31 {
32     SHARING_LOGD("trace.");
33     controlId_ = controlId;
34     forceSWDecoder_ = forceSWDecoder;
35 }
36 
~VideoSinkDecoder()37 VideoSinkDecoder::~VideoSinkDecoder()
38 {
39     SHARING_LOGD("trace.");
40     Release();
41 }
42 
Init(CodecId videoCodecId)43 bool VideoSinkDecoder::Init(CodecId videoCodecId)
44 {
45     SHARING_LOGD("trace.");
46     videoCodecId_ = videoCodecId;
47     return InitDecoder() && SetVideoCallback();
48 }
49 
InitDecoder()50 bool VideoSinkDecoder::InitDecoder()
51 {
52     SHARING_LOGD("trace.");
53     if (videoDecoder_ != nullptr) {
54         SHARING_LOGD("start video decoder already init.");
55         return true;
56     }
57     if (forceSWDecoder_) {
58         SHARING_LOGD("begin create software video decoder.");
59         videoDecoder_ = OHOS::MediaAVCodec::VideoDecoderFactory::CreateByName(
60             (MediaAVCodec::AVCodecCodecName::VIDEO_DECODER_AVC_NAME).data());
61     } else {
62         SHARING_LOGD("begin create hardware video decoder.");
63         videoDecoder_ = OHOS::MediaAVCodec::VideoDecoderFactory::CreateByMime(
64             (MediaAVCodec::AVCodecMimeType::MEDIA_MIMETYPE_VIDEO_AVC).data());
65     }
66 
67     if (videoDecoder_ == nullptr) {
68         SHARING_LOGE("create video decoder failed!");
69         WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::VIDEO_DECODE,
70                                                      SinkErrorCode::WIFI_DISPLAY_VIDEO_DECODE_FAILED);
71         return false;
72     }
73     SHARING_LOGD("init video decoder success.");
74     return true;
75 }
76 
SetDecoderFormat(const VideoTrack & track)77 bool VideoSinkDecoder::SetDecoderFormat(const VideoTrack &track)
78 {
79     SHARING_LOGD("trace.");
80     RETURN_FALSE_IF_NULL(videoDecoder_);
81     videoTrack_ = track;
82     MediaAVCodec::Format format;
83     format.PutIntValue("width", track.width);
84     format.PutIntValue("height", track.height);
85     format.PutDoubleValue("frame_rate", track.frameRate);
86 
87     auto ret = videoDecoder_->Configure(format);
88     if (ret != MediaAVCodec::AVCS_ERR_OK) {
89         SHARING_LOGE("configure decoder format param failed!");
90         WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::VIDEO_DECODE,
91                                                      SinkErrorCode::WIFI_DISPLAY_VIDEO_DECODE_FAILED);
92         return false;
93     }
94     SHARING_LOGD("configure video decoder format success.");
95     return true;
96 }
97 
SetVideoCallback()98 bool VideoSinkDecoder::SetVideoCallback()
99 {
100     SHARING_LOGD("trace.");
101     RETURN_FALSE_IF_NULL(videoDecoder_);
102     auto ret = videoDecoder_->SetCallback(shared_from_this());
103     if (ret != MediaAVCodec::AVCS_ERR_OK) {
104         SHARING_LOGE("set video decoder callback failed!");
105         return false;
106     }
107     SHARING_LOGD("set video decoder callback success.");
108     return true;
109 }
110 
SetVideoDecoderListener(VideoSinkDecoderListener::Ptr listener)111 void VideoSinkDecoder::SetVideoDecoderListener(VideoSinkDecoderListener::Ptr listener)
112 {
113     SHARING_LOGD("trace.");
114     videoDecoderListener_ = listener;
115 }
116 
SetVideoAudioSync(std::shared_ptr<VideoAudioSync> videoAudioSync)117 void VideoSinkDecoder::SetVideoAudioSync(std::shared_ptr<VideoAudioSync> videoAudioSync)
118 {
119     SHARING_LOGD("trace.");
120     videoAudioSync_ = videoAudioSync;
121 }
122 
Start()123 bool VideoSinkDecoder::Start()
124 {
125     SHARING_LOGD("trace.");
126     if (isRunning_) {
127         MEDIA_LOGD("decoder is running!");
128         return true;
129     }
130     if (StartDecoder()) {
131         isRunning_ = true;
132         return true;
133     } else {
134         WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::VIDEO_DECODE,
135                                                      SinkErrorCode::WIFI_DISPLAY_VIDEO_DECODE_FAILED);
136         return false;
137     }
138 }
139 
Stop()140 void VideoSinkDecoder::Stop()
141 {
142     SHARING_LOGD("trace.");
143     if (!isRunning_) {
144         SHARING_LOGD("decoder is not running.");
145         return;
146     }
147 
148     if (StopDecoder()) {
149         SHARING_LOGD("stop success.");
150         isRunning_ = false;
151         std::lock_guard<std::mutex> lock(inMutex_);
152         std::queue<int32_t> temp;
153         std::swap(temp, inQueue_);
154     }
155 }
156 
Release()157 void VideoSinkDecoder::Release()
158 {
159     SHARING_LOGD("trace.");
160     if (videoDecoder_ != nullptr) {
161         videoDecoder_->Release();
162         videoDecoder_.reset();
163     }
164 }
165 
StartDecoder()166 bool VideoSinkDecoder::StartDecoder()
167 {
168     SHARING_LOGD("trace.");
169     RETURN_FALSE_IF_NULL(videoDecoder_);
170     auto ret = videoDecoder_->Prepare();
171     if (ret != MediaAVCodec::AVCS_ERR_OK) {
172         SHARING_LOGE("prepare decoder failed!");
173         return false;
174     }
175 
176     ret = videoDecoder_->Start();
177     if (ret != MediaAVCodec::AVCS_ERR_OK) {
178         SHARING_LOGE("start decoder failed!");
179         return false;
180     }
181     SHARING_LOGD("start video decoder success.");
182     return true;
183 }
184 
StopDecoder()185 bool VideoSinkDecoder::StopDecoder()
186 {
187     SHARING_LOGD("trace.");
188     if (videoDecoder_ == nullptr) {
189         SHARING_LOGD("StopDecoder no need.");
190         return true;
191     }
192 
193     SHARING_LOGD("before Stop.");
194     auto ret = videoDecoder_->Stop();
195     if (ret != MediaAVCodec::AVCS_ERR_OK) {
196         SHARING_LOGE("stop decoder failed!");
197         return false;
198     }
199 
200     SHARING_LOGD("before Reset.");
201     ret = videoDecoder_->Reset();
202     if (ret != MediaAVCodec::AVCS_ERR_OK) {
203         SHARING_LOGE("Reset decoder failed!");
204         return false;
205     }
206 
207     SHARING_LOGD("try set decoder formt for next play.");
208     if (SetDecoderFormat(videoTrack_)) {
209         if (enableSurface_ && (nullptr != surface_)) {
210             videoDecoder_->SetOutputSurface(surface_);
211         }
212     } else {
213         SHARING_LOGE("set decoder formt failed!");
214         return false;
215     }
216 
217     SHARING_LOGD("StopDecoder success.");
218     return true;
219 }
220 
DecodeVideoData(const char * data,int32_t size,uint64_t pts)221 bool VideoSinkDecoder::DecodeVideoData(const char *data, int32_t size, uint64_t pts)
222 {
223     MEDIA_LOGD("decode data controlId: %{public}u.", controlId_);
224     RETURN_FALSE_IF_NULL(videoDecoder_);
225 
226     std::unique_lock<std::mutex> lock(inMutex_);
227     auto inputIndex = inQueue_.front();
228     MEDIA_LOGD("inQueue front: %{public}d.", inputIndex);
229     auto inputBuffer = inBufferQueue_.front();
230     if (inputBuffer == nullptr || (inputBuffer->GetSize() < size)) {
231         MEDIA_LOGE("GetInputBuffer failed or bufferSize invalid, controlId: %{public}u.", controlId_);
232         return false;
233     }
234     lock.unlock();
235     MEDIA_LOGD("try copy data dest size: %{public}d data size: %{public}d.", inputBuffer->GetSize(), size);
236 
237     auto ret = memcpy_s(inputBuffer->GetBase(), inputBuffer->GetSize(), data, size);
238     if (ret != EOK) {
239         MEDIA_LOGE("copy data failed controlId: %{public}u.", controlId_);
240         return false;
241     }
242 
243     MediaAVCodec::AVCodecBufferInfo bufferInfo;
244     bufferInfo.presentationTimeUs = static_cast<int64_t>(pts);
245     bufferInfo.size = size;
246     bufferInfo.offset = 0;
247     WfdSinkHiSysEvent::GetInstance().RecordMediaDecodeStartTime(MediaReportType::VIDEO, bufferInfo.presentationTimeUs);
248 
249     auto p = data;
250     p = *(p + 2) == 0x01 ? p + 3 : p + 4; // 2: offset, 3: offset, 4: offset
251     if ((p[0] & 0x1f) == 0x06 || (p[0] & 0x1f) == 0x07 || (p[0] & 0x1f) == 0x08) {
252         MEDIA_LOGD("media flag codec data controlId: %{public}u.", controlId_);
253         ret = videoDecoder_->QueueInputBuffer(inputIndex, bufferInfo, MediaAVCodec::AVCODEC_BUFFER_FLAG_CODEC_DATA);
254     } else {
255         MEDIA_LOGD("media flag none controlId: %{public}u.", controlId_);
256         ret = videoDecoder_->QueueInputBuffer(inputIndex, bufferInfo, MediaAVCodec::AVCODEC_BUFFER_FLAG_NONE);
257     }
258 
259     if (ret != MediaAVCodec::AVCS_ERR_OK) {
260         MEDIA_LOGE("QueueInputBuffer failed error: %{public}d controlId: %{public}u.", ret, controlId_);
261         return false;
262     }
263 
264     lock.lock();
265     inQueue_.pop();
266     inBufferQueue_.pop();
267 
268     MEDIA_LOGD("process data success controlId: %{public}u.", controlId_);
269     return true;
270 }
271 
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)272 void VideoSinkDecoder::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
273 {
274     SHARING_LOGE("controlId: %{public}u.", controlId_);
275     auto listener = videoDecoderListener_.lock();
276     if (listener) {
277         listener->OnError(errorCode);
278     }
279     WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::VIDEO_DECODE,
280                                                  SinkErrorCode::WIFI_DISPLAY_VIDEO_DECODE_FAILED);
281 }
282 
OnOutputBufferAvailable(uint32_t index,MediaAVCodec::AVCodecBufferInfo info,MediaAVCodec::AVCodecBufferFlag flag,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)283 void VideoSinkDecoder::OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info,
284     MediaAVCodec::AVCodecBufferFlag flag, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
285 {
286     MEDIA_LOGD("OnOutputBufferAvailable index: %{public}u controlId: %{public}u.", index, controlId_);
287     if (!videoDecoder_) {
288         MEDIA_LOGW("decoder is null!");
289         return;
290     }
291     WfdSinkHiSysEvent::GetInstance().MediaDecodeTimProc(MediaReportType::VIDEO, info.presentationTimeUs);
292 
293     if (forceSWDecoder_) {
294         MEDIA_LOGD("forceSWDecoder_ is true.");
295     }
296     if (forceSWDecoder_) {
297         if (buffer == nullptr || buffer->GetBase() == nullptr) {
298             MEDIA_LOGW("OnOutputBufferAvailable buffer null!");
299             return;
300         }
301         size_t dataSize = static_cast<size_t>(info.size);
302         SHARING_LOGD("OnOutputBufferAvailable size: %{public}zu.", dataSize);
303         auto dataBuf = std::make_shared<DataBuffer>(dataSize);
304         if (dataBuf != nullptr) {
305             dataBuf->PushData((char *)buffer->GetBase(), dataSize);
306             auto listerner = videoDecoderListener_.lock();
307             if (listerner) {
308                 listerner->OnVideoDataDecoded(dataBuf);
309             }
310         } else {
311             MEDIA_LOGE("get databuffer failed!");
312         }
313     }
314 
315     if (videoAudioSync_ && videoAudioSync_->IsNeedDrop(info.presentationTimeUs)) {
316         SHARING_LOGI("ReleaseOutputBuffer drop one frame.");
317         if (videoDecoder_->ReleaseOutputBuffer(index, false) != MediaAVCodec::AVCS_ERR_OK) {
318             MEDIA_LOGW("ReleaseOutputBuffer failed!");
319         }
320     } else {
321         if (videoDecoder_->ReleaseOutputBuffer(index, true) != MediaAVCodec::AVCS_ERR_OK) {
322             MEDIA_LOGW("ReleaseOutputBuffer failed!");
323         }
324     }
325 }
326 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)327 void VideoSinkDecoder::OnInputBufferAvailable(uint32_t index, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
328 {
329     MEDIA_LOGD("OnInputBufferAvailable index: %{public}u controlId: %{public}u.", index, controlId_);
330     {
331         std::lock_guard<std::mutex> lock(inMutex_);
332         if (buffer == nullptr) {
333             return;
334         }
335         inQueue_.push(index);
336         inBufferQueue_.push(buffer);
337     }
338     inCond_.notify_all();
339     MEDIA_LOGD("OnInputBufferAvailable notify.");
340 }
341 
OnOutputFormatChanged(const MediaAVCodec::Format & format)342 void VideoSinkDecoder::OnOutputFormatChanged(const MediaAVCodec::Format &format)
343 {
344     SHARING_LOGD("controlId: %{public}u.", controlId_);
345 }
346 
SetSurface(sptr<Surface> surface)347 bool VideoSinkDecoder::SetSurface(sptr<Surface> surface)
348 {
349     SHARING_LOGD("trace.");
350     RETURN_FALSE_IF_NULL(surface);
351     RETURN_FALSE_IF_NULL(videoDecoder_);
352     if (isRunning_) {
353         SHARING_LOGW("decoder is running, cann't set surface!");
354         return false;
355     }
356 
357     auto ret = videoDecoder_->SetOutputSurface(surface);
358     if (ret != MediaAVCodec::AVCS_ERR_OK) {
359         SHARING_LOGE("decoder set surface error, ret code:  %{public}u.", ret);
360         return false;
361     }
362     enableSurface_ = true;
363     surface_ = surface;
364     return true;
365 }
366 
367 } // namespace Sharing
368 } // namespace OHOS