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