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