• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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