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