1 /*
2 * Copyright (c) 2023 Huawei Device 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 "media_codec_decoder_adapter_impl.h"
17 #include "buffer_info_adapter_impl.h"
18 #include <cstddef>
19 #include <cstdint>
20 #include <memory>
21 #include <system_error>
22 #include <unordered_map>
23 #include <utility>
24
25 #include "foundation/graphic/graphic_surface/interfaces/inner_api/surface/window.h"
26 #include "native_window.h"
27 #include "nweb_log.h"
28 #include "ohos_buffer_adapter_impl.h"
29 #include "avcodec_list.h"
30
31 using namespace OHOS::NWeb;
32 using namespace std;
33 namespace {
34 const std::unordered_map<OHOS::MediaAVCodec::AVCodecErrorType, ErrorType> ERROR_TYPE_MAP = {
35 { OHOS::MediaAVCodec::AVCodecErrorType::AVCODEC_ERROR_INTERNAL, ErrorType::CODEC_ERROR_INTERNAL },
36 { OHOS::MediaAVCodec::AVCodecErrorType::AVCODEC_ERROR_EXTEND_START, ErrorType::CODEC_ERROR_EXTEND_START }
37 };
38
39 const std::unordered_map<OHOS::MediaAVCodec::AVCodecBufferFlag, BufferFlag> BUFFER_FLAG_MAP = {
40 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_NONE, BufferFlag::CODEC_BUFFER_FLAG_NONE },
41 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_EOS, BufferFlag::CODEC_BUFFER_FLAG_EOS },
42 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_SYNC_FRAME, BufferFlag::CODEC_BUFFER_FLAG_SYNC_FRAME },
43 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_PARTIAL_FRAME,
44 BufferFlag::CODEC_BUFFER_FLAG_PARTIAL_FRAME },
45 { OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_CODEC_DATA, BufferFlag::CODEC_BUFFER_FLAG_CODEC_DATA }
46 };
47
48 const std::unordered_map<BufferFlag, OHOS::MediaAVCodec::AVCodecBufferFlag> AV_BUFFER_FLAG_MAP = {
49 { BufferFlag::CODEC_BUFFER_FLAG_NONE, OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_NONE },
50 { BufferFlag::CODEC_BUFFER_FLAG_EOS, OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_EOS },
51 { BufferFlag::CODEC_BUFFER_FLAG_SYNC_FRAME, OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_SYNC_FRAME },
52 { BufferFlag::CODEC_BUFFER_FLAG_PARTIAL_FRAME,
53 OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_PARTIAL_FRAME },
54 { BufferFlag::CODEC_BUFFER_FLAG_CODEC_DATA, OHOS::MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_CODEC_DATA }
55 };
56 } // namespace
57
DecoderCallbackImpl(std::shared_ptr<DecoderCallbackAdapter> cb)58 DecoderCallbackImpl::DecoderCallbackImpl(std::shared_ptr<DecoderCallbackAdapter> cb) : cb_(cb) {};
59
CreateVideoDecoderByMime(const std::string & mimetype)60 DecoderAdapterCode MediaCodecDecoderAdapterImpl::CreateVideoDecoderByMime(const std::string& mimetype)
61 {
62 decoder_ = VideoDecoderFactory::CreateByMime(mimetype);
63 if (decoder_ == nullptr) {
64 WVLOG_E("MediaCodecDecoder create failed.");
65 return DecoderAdapterCode::DECODER_ERROR;
66 }
67
68 return DecoderAdapterCode::DECODER_OK;
69 }
70
CreateVideoDecoderByName(const std::string & name)71 DecoderAdapterCode MediaCodecDecoderAdapterImpl::CreateVideoDecoderByName(const std::string& name)
72 {
73 std::shared_ptr<OHOS::MediaAVCodec::AVCodecList> codecCapability = AVCodecListFactory::CreateAVCodecList();
74 if (codecCapability == nullptr) {
75 WVLOG_E("MediaCodecDecoder CreateAVCodecList failed.");
76 return DecoderAdapterCode::DECODER_ERROR;
77 }
78
79 capabilityData_ = codecCapability->GetCapability(name, false, AVCodecCategory::AVCODEC_HARDWARE);
80 if (capabilityData_ != nullptr) {
81 decoder_ = VideoDecoderFactory::CreateByName(capabilityData_->codecName);
82 if (decoder_ != nullptr) {
83 isHardwareDecode_ = true;
84 WVLOG_I("MediaCodecDecoder create hardware decoder.");
85 return DecoderAdapterCode::DECODER_OK;
86 }
87 }
88
89 capabilityData_ = codecCapability->GetCapability(name, false, AVCodecCategory::AVCODEC_SOFTWARE);
90 if (capabilityData_ != nullptr) {
91 decoder_ = VideoDecoderFactory::CreateByName(capabilityData_->codecName);
92 if (decoder_ != nullptr) {
93 isHardwareDecode_ = false;
94 WVLOG_I("MediaCodecDecoder create software decoder.");
95 return DecoderAdapterCode::DECODER_OK;
96 }
97 }
98
99 WVLOG_E("MediaCodecDecoder create decoder failed.");
100 return DecoderAdapterCode::DECODER_ERROR;
101 }
102
ConfigureDecoder(const std::shared_ptr<DecoderFormatAdapter> format)103 DecoderAdapterCode MediaCodecDecoderAdapterImpl::ConfigureDecoder(const std::shared_ptr<DecoderFormatAdapter> format)
104 {
105 if (decoder_ == nullptr) {
106 WVLOG_E("MediaCodecDecoder is nullptr.");
107 return DecoderAdapterCode::DECODER_ERROR;
108 }
109
110 if (format == nullptr) {
111 WVLOG_E("format is nullptr.");
112 return DecoderAdapterCode::DECODER_ERROR;
113 }
114
115 if (capabilityData_ != nullptr) {
116 OHOS::MediaAVCodec::VideoCaps videoCaps(capabilityData_);
117 if (!videoCaps.IsSizeSupported(format->GetWidth(), format->GetHeight())) {
118 WVLOG_E("MediaCodecDecoder video size is not supported.");
119 return DecoderAdapterCode::DECODER_ERROR;
120 }
121 }
122
123 OHOS::Media::Format codecFormat;
124
125 codecFormat.PutIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_WIDTH, format->GetWidth());
126 codecFormat.PutIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_HEIGHT, format->GetHeight());
127
128 int32_t ret = decoder_->Configure(codecFormat);
129 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
130 return DecoderAdapterCode::DECODER_ERROR;
131 }
132 return DecoderAdapterCode::DECODER_OK;
133 }
134
SetParameterDecoder(const std::shared_ptr<DecoderFormatAdapter> format)135 DecoderAdapterCode MediaCodecDecoderAdapterImpl::SetParameterDecoder(const std::shared_ptr<DecoderFormatAdapter> format)
136 {
137 if (decoder_ == nullptr) {
138 WVLOG_E("MediaCodecDecoder is nullptr.");
139 return DecoderAdapterCode::DECODER_ERROR;
140 }
141
142 if (format == nullptr) {
143 WVLOG_E("format is nullptr.");
144 return DecoderAdapterCode::DECODER_ERROR;
145 }
146
147 OHOS::Media::Format codecFormat;
148
149 codecFormat.PutIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_WIDTH, format->GetWidth());
150 codecFormat.PutIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_HEIGHT, format->GetHeight());
151
152 int32_t ret = decoder_->SetParameter(codecFormat);
153 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
154 return DecoderAdapterCode::DECODER_ERROR;
155 }
156 return DecoderAdapterCode::DECODER_OK;
157 }
158
SetOutputSurface(void * window)159 DecoderAdapterCode MediaCodecDecoderAdapterImpl::SetOutputSurface(void* window)
160 {
161 if (decoder_ == nullptr) {
162 WVLOG_E("MediaCodecDecoder is nullptr.");
163 return DecoderAdapterCode::DECODER_ERROR;
164 }
165
166 OHNativeWindow* window_ = reinterpret_cast<OHNativeWindow*>(window);
167 if (window_ == nullptr || window_->surface == nullptr) {
168 WVLOG_E("Window is nullptr.");
169 return DecoderAdapterCode::DECODER_ERROR;
170 }
171
172 if (isHardwareDecode_) {
173 uint64_t usage = BUFFER_USAGE_MEM_DMA;
174 NativeWindowHandleOpt(window_, SET_USAGE, usage);
175 WVLOG_I("MediaCodecDecoder default to opening Hebc.");
176 }
177
178 int32_t ret = decoder_->SetOutputSurface(window_->surface);
179 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
180 return DecoderAdapterCode::DECODER_ERROR;
181 }
182 return DecoderAdapterCode::DECODER_OK;
183 }
184
PrepareDecoder()185 DecoderAdapterCode MediaCodecDecoderAdapterImpl::PrepareDecoder()
186 {
187 if (decoder_ == nullptr) {
188 WVLOG_E("MediaCodecDecoder is nullptr.");
189 return DecoderAdapterCode::DECODER_ERROR;
190 }
191
192 int32_t ret = decoder_->Prepare();
193 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
194 return DecoderAdapterCode::DECODER_ERROR;
195 }
196 return DecoderAdapterCode::DECODER_OK;
197 }
198
StartDecoder()199 DecoderAdapterCode MediaCodecDecoderAdapterImpl::StartDecoder()
200 {
201 if (decoder_ == nullptr) {
202 WVLOG_E("MediaCodecDecoder is nullptr.");
203 return DecoderAdapterCode::DECODER_ERROR;
204 }
205 int32_t ret = decoder_->Start();
206 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
207 return DecoderAdapterCode::DECODER_ERROR;
208 }
209 return DecoderAdapterCode::DECODER_OK;
210 }
211
StopDecoder()212 DecoderAdapterCode MediaCodecDecoderAdapterImpl::StopDecoder()
213 {
214 if (decoder_ == nullptr) {
215 WVLOG_E("MediaCodecDecoder is nullptr.");
216 return DecoderAdapterCode::DECODER_ERROR;
217 }
218 int32_t ret = decoder_->Stop();
219 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
220 return DecoderAdapterCode::DECODER_ERROR;
221 }
222 return DecoderAdapterCode::DECODER_OK;
223 }
224
FlushDecoder()225 DecoderAdapterCode MediaCodecDecoderAdapterImpl::FlushDecoder()
226 {
227 if (decoder_ == nullptr) {
228 WVLOG_E("MediaCodecDecoder is nullptr.");
229 return DecoderAdapterCode::DECODER_ERROR;
230 }
231 int32_t ret = decoder_->Flush();
232 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
233 return DecoderAdapterCode::DECODER_ERROR;
234 }
235 return DecoderAdapterCode::DECODER_OK;
236 }
237
ResetDecoder()238 DecoderAdapterCode MediaCodecDecoderAdapterImpl::ResetDecoder()
239 {
240 if (decoder_ == nullptr) {
241 WVLOG_E("MediaCodecDecoder is nullptr.");
242 return DecoderAdapterCode::DECODER_ERROR;
243 }
244 int32_t ret = decoder_->Reset();
245 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
246 return DecoderAdapterCode::DECODER_ERROR;
247 }
248 return DecoderAdapterCode::DECODER_OK;
249 }
250
ReleaseDecoder()251 DecoderAdapterCode MediaCodecDecoderAdapterImpl::ReleaseDecoder()
252 {
253 if (decoder_ == nullptr) {
254 WVLOG_E("MediaCodecDecoder is nullptr.");
255 return DecoderAdapterCode::DECODER_ERROR;
256 }
257 int32_t ret = decoder_->Release();
258 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
259 return DecoderAdapterCode::DECODER_ERROR;
260 }
261 return DecoderAdapterCode::DECODER_OK;
262 }
263
QueueInputBufferDec(uint32_t index,int64_t presentationTimeUs,int32_t size,int32_t offset,BufferFlag flag)264 DecoderAdapterCode MediaCodecDecoderAdapterImpl::QueueInputBufferDec(
265 uint32_t index, int64_t presentationTimeUs, int32_t size, int32_t offset, BufferFlag flag)
266 {
267 struct OHOS::MediaAVCodec::AVCodecBufferInfo bufferInfo;
268
269 bufferInfo.presentationTimeUs = presentationTimeUs;
270 bufferInfo.size = size;
271 bufferInfo.offset = offset;
272
273 AVCodecBufferFlag bufferFlag = MediaCodecDecoderAdapterImpl::GetAVBufferFlag(flag);
274
275 if (decoder_ == nullptr) {
276 WVLOG_E("MediaCodecDecoder is nullptr.");
277 return DecoderAdapterCode::DECODER_ERROR;
278 }
279
280 int32_t ret = decoder_->QueueInputBuffer(index, bufferInfo, bufferFlag);
281 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
282 return DecoderAdapterCode::DECODER_ERROR;
283 }
284 return DecoderAdapterCode::DECODER_OK;
285 }
286
GetOutputFormatDec(std::shared_ptr<DecoderFormatAdapter> format)287 DecoderAdapterCode MediaCodecDecoderAdapterImpl::GetOutputFormatDec(std::shared_ptr<DecoderFormatAdapter> format)
288 {
289 OHOS::Media::Format codecFormat;
290
291 if (decoder_ == nullptr) {
292 WVLOG_E("MediaCodecDecoder is nullptr.");
293 return DecoderAdapterCode::DECODER_ERROR;
294 }
295
296 if (format == nullptr) {
297 WVLOG_E("format is nullptr.");
298 return DecoderAdapterCode::DECODER_ERROR;
299 }
300
301 int32_t ret = decoder_->GetOutputFormat(codecFormat);
302 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
303 return DecoderAdapterCode::DECODER_ERROR;
304 }
305
306 int32_t width = 0;
307 int32_t height = 0;
308 codecFormat.GetIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width);
309 codecFormat.GetIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height);
310 format->SetWidth(width);
311 format->SetHeight(height);
312
313 return DecoderAdapterCode::DECODER_OK;
314 }
315
ReleaseOutputBufferDec(uint32_t index,bool isRender)316 DecoderAdapterCode MediaCodecDecoderAdapterImpl::ReleaseOutputBufferDec(uint32_t index, bool isRender)
317 {
318 if (decoder_ == nullptr) {
319 WVLOG_E("MediaCodecDecoder is nullptr.");
320 return DecoderAdapterCode::DECODER_ERROR;
321 }
322
323 int32_t ret = decoder_->ReleaseOutputBuffer(index, isRender);
324 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
325 return DecoderAdapterCode::DECODER_ERROR;
326 }
327 return DecoderAdapterCode::DECODER_OK;
328 }
329
SetCallbackDec(const std::shared_ptr<DecoderCallbackAdapter> callback)330 DecoderAdapterCode MediaCodecDecoderAdapterImpl::SetCallbackDec(const std::shared_ptr<DecoderCallbackAdapter> callback)
331 {
332 if (callback == nullptr) {
333 WVLOG_E("Media Callback is NULL.");
334 return DecoderAdapterCode::DECODER_ERROR;
335 }
336
337 callback_ = std::make_shared<DecoderCallbackImpl>(callback);
338 if (callback_ == nullptr) {
339 WVLOG_E("Create Callback failed.");
340 return DecoderAdapterCode::DECODER_ERROR;
341 }
342
343 if (decoder_ == nullptr) {
344 WVLOG_E("MediaCodecDecoder is nullptr.");
345 return DecoderAdapterCode::DECODER_ERROR;
346 }
347
348 int32_t ret = decoder_->SetCallback(callback_);
349 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
350 return DecoderAdapterCode::DECODER_ERROR;
351 }
352 return DecoderAdapterCode::DECODER_OK;
353 }
354
GetErrorType(AVCodecErrorType codecErrorType)355 ErrorType MediaCodecDecoderAdapterImpl::GetErrorType(AVCodecErrorType codecErrorType)
356 {
357 auto type = ERROR_TYPE_MAP.find(codecErrorType);
358 if (type == ERROR_TYPE_MAP.end()) {
359 WVLOG_E("error type not found.");
360 return ErrorType::CODEC_ERROR_INTERNAL;
361 }
362 return type->second;
363 }
364
GetBufferFlag(AVCodecBufferFlag codecBufferFlag)365 BufferFlag MediaCodecDecoderAdapterImpl::GetBufferFlag(AVCodecBufferFlag codecBufferFlag)
366 {
367 auto flag = BUFFER_FLAG_MAP.find(codecBufferFlag);
368 if (flag == BUFFER_FLAG_MAP.end()) {
369 WVLOG_E("buffer flag not found.");
370 return BufferFlag::CODEC_BUFFER_FLAG_NONE;
371 }
372 return flag->second;
373 }
374
GetAVBufferFlag(BufferFlag bufferFlag)375 AVCodecBufferFlag MediaCodecDecoderAdapterImpl::GetAVBufferFlag(BufferFlag bufferFlag)
376 {
377 auto flag = AV_BUFFER_FLAG_MAP.find(bufferFlag);
378 if (flag == AV_BUFFER_FLAG_MAP.end()) {
379 WVLOG_E("buffer flag not found.");
380 return AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_NONE;
381 }
382 return flag->second;
383 }
384
OnError(AVCodecErrorType errorType,int32_t errorCode)385 void DecoderCallbackImpl::OnError(AVCodecErrorType errorType, int32_t errorCode)
386 {
387 if (!cb_) {
388 WVLOG_E("callback is NULL.");
389 return;
390 }
391
392 ErrorType errType = MediaCodecDecoderAdapterImpl::GetErrorType(errorType);
393
394 cb_->OnError(errType, errorCode);
395 }
396
OnOutputFormatChanged(const Media::Format & format)397 void DecoderCallbackImpl::OnOutputFormatChanged(const Media::Format& format)
398 {
399 if (!cb_) {
400 WVLOG_E("callback is NULL.");
401 return;
402 }
403
404 int32_t width = 0;
405 int32_t height = 0;
406 format.GetIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_WIDTH, width);
407 format.GetIntValue(OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_HEIGHT, height);
408
409 cb_->OnStreamChanged(width, height, 0);
410 }
411
OnInputBufferAvailable(uint32_t index,std::shared_ptr<Media::AVSharedMemory> buffer)412 void DecoderCallbackImpl::OnInputBufferAvailable(uint32_t index, std::shared_ptr<Media::AVSharedMemory> buffer)
413 {
414 if (!cb_) {
415 WVLOG_E("callback is NULL.");
416 return;
417 }
418
419 if (buffer == nullptr || buffer->GetBase() == nullptr) {
420 return;
421 }
422
423 std::shared_ptr<OhosBufferAdapterImpl> ohosBuffer = std::make_shared<OhosBufferAdapterImpl>();
424 if (ohosBuffer == nullptr) {
425 WVLOG_E("new OhosBufferAdapterImpl failed");
426 return;
427 }
428
429 ohosBuffer->SetAddr(buffer->GetBase());
430 ohosBuffer->SetBufferSize(buffer->GetSize());
431 cb_->OnNeedInputData(index, ohosBuffer);
432 }
433
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<Media::AVSharedMemory> buffer)434 void DecoderCallbackImpl::OnOutputBufferAvailable(
435 uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag, std::shared_ptr<Media::AVSharedMemory> buffer)
436 {
437 if (!cb_) {
438 WVLOG_E("callback is NULL.");
439 return;
440 }
441
442 std::shared_ptr<BufferInfoAdapterImpl> info_ = std::make_shared<BufferInfoAdapterImpl>();
443 if (!info_) {
444 WVLOG_E("new BufferInfoAdapterImpl failed");
445 return;
446 }
447
448 info_->SetPresentationTimeUs(info.presentationTimeUs);
449 info_->SetSize(info.size);
450 info_->SetOffset(info.offset);
451
452 BufferFlag flag_;
453
454 flag_ = MediaCodecDecoderAdapterImpl::GetBufferFlag(flag);
455 cb_->OnNeedOutputData(index, info_, flag_);
456 }
457