• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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_log.h"
17 #include "codec/util/codec_util.h"
18 #include "codec/video/decoder/video_decoder.h"
19 #include <native_avcodec_videodecoder.h>
20 #include "codec/video/decoder/video_demuxer.h"
21 
22 namespace OHOS {
23 namespace Media {
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_VIDEOEDITOR, "VideoEditorDecode"};
26 }
27 
VideoDecoder(uint64_t id,const CodecOnInData & cb,const CodecOnDecodeFrame & onDecodeFrameCallback,const CodecOnDecodeResult & onDecodeResultCallback)28 VideoDecoder::VideoDecoder(uint64_t id, const CodecOnInData& cb,
29     const CodecOnDecodeFrame& onDecodeFrameCallback, const CodecOnDecodeResult& onDecodeResultCallback)
30     : packetReadFunc_(cb), onDecodeFrameCallback_(onDecodeFrameCallback),
31     onDecodeResultCallback_(onDecodeResultCallback)
32 {
33     logTag_ = "video-decoder-" + std::to_string(id);
34 }
35 
~VideoDecoder()36 VideoDecoder::~VideoDecoder()
37 {
38     MEDIA_LOGD("[%{public}s] destruct.", logTag_.c_str());
39     if (decoder_ != nullptr) {
40         OH_VideoDecoder_Destroy(decoder_);
41         decoder_ = nullptr;
42     }
43 }
44 
Init(OH_AVFormat * videoFormat)45 VEFError VideoDecoder::Init(OH_AVFormat* videoFormat)
46 {
47     MEDIA_LOGI("[%{public}s] init.", logTag_.c_str());
48     if (videoFormat == nullptr) {
49         MEDIA_LOGE("[%{public}s] init failed, parameter videoFormat is nullptr.", logTag_.c_str());
50         return VEFError::ERR_INTERNAL_ERROR;
51     }
52     std::string dumpInfo = OH_AVFormat_DumpInfo(videoFormat);
53     MEDIA_LOGI("[%{public}s] initializing decoder, format: %{public}s.", logTag_.c_str(), dumpInfo.c_str());
54     const char* mime = nullptr;
55     if (!OH_AVFormat_GetStringValue(videoFormat, OH_MD_KEY_CODEC_MIME, &mime)) {
56         MEDIA_LOGE("[%{public}s] get [%{public}s] from video format failed.", logTag_.c_str(), OH_MD_KEY_CODEC_MIME);
57         return VEFError::ERR_INTERNAL_ERROR;
58     }
59 
60     codecMime_ = mime;
61     MEDIA_LOGI("[%{public}s] initializing decoder, video mime = %{public}s.", logTag_.c_str(), mime);
62     VEFError err = CreateDecoder();
63     if (err != VEFError::ERR_OK) {
64         MEDIA_LOGE("[%{public}s] init failed, create decoder failed with error: %{public}d.", logTag_.c_str(), err);
65         return err;
66     }
67 
68     err = ConfigureDecoder(videoFormat);
69     if (err != VEFError::ERR_OK) {
70         MEDIA_LOGE("[%{public}s] init failed, configure decoder failed with error: %{public}d.", logTag_.c_str(), err);
71         return err;
72     }
73     MEDIA_LOGI("[%{public}s] init success.", logTag_.c_str());
74     return VEFError::ERR_OK;
75 }
76 
SetNativeWindow(OHNativeWindow * surfaceWindow)77 VEFError VideoDecoder::SetNativeWindow(OHNativeWindow* surfaceWindow)
78 {
79     if (surfaceWindow == nullptr) {
80         MEDIA_LOGE("[%{public}s] set native window failed, window is nullptr.", logTag_.c_str());
81         return VEFError::ERR_INTERNAL_ERROR;
82     }
83     OH_AVErrCode err = OH_VideoDecoder_SetSurface(decoder_, surfaceWindow);
84     if (err != AV_ERR_OK) {
85         MEDIA_LOGE("[%{public}s] set decoder surface failed with error, ret %{public}d %{public}s.", logTag_.c_str(),
86             err, CodecUtil::GetCodecErrorStr(err));
87         return VEFError::ERR_INTERNAL_ERROR;
88     }
89     return VEFError::ERR_OK;
90 }
91 
Start()92 VEFError VideoDecoder::Start()
93 {
94     MEDIA_LOGI("[%{public}s] start.", logTag_.c_str());
95     auto ret = OH_VideoDecoder_Prepare(decoder_);
96     if (ret != AV_ERR_OK) {
97         MEDIA_LOGE("[%{public}s] start failed, OH_VideoDecoder_Prepare return %{public}d(%{public}s).", logTag_.c_str(),
98             ret, CodecUtil::GetCodecErrorStr(ret));
99         return VEFError::ERR_INTERNAL_ERROR;
100     }
101     ret = OH_VideoDecoder_Start(decoder_);
102     if (ret != AV_ERR_OK) {
103         MEDIA_LOGE("[%{public}s] start failed, OH_VideoDecoder_Start return %{public}d(%{public}s).", logTag_.c_str(),
104             ret, CodecUtil::GetCodecErrorStr(ret));
105         return VEFError::ERR_INTERNAL_ERROR;
106     }
107     state_ = CodecState::RUNNING;
108     MEDIA_LOGI("[%{public}s] start success.", logTag_.c_str());
109     return VEFError::ERR_OK;
110 }
111 
Stop()112 VEFError VideoDecoder::Stop()
113 {
114     MEDIA_LOGI("[%{public}s] stop.", logTag_.c_str());
115     auto ret = OH_VideoDecoder_Stop(decoder_);
116     if (ret != AV_ERR_OK) {
117         MEDIA_LOGE("[%{public}s] stop failed, OH_VideoDecoder_Stop return %{public}d(%{public}s).", logTag_.c_str(),
118             ret, CodecUtil::GetCodecErrorStr(ret));
119         return VEFError::ERR_INTERNAL_ERROR;
120     }
121     state_ = CodecState::CANCEL;
122     MEDIA_LOGI("[%{public}s] stop success.", logTag_.c_str());
123     return VEFError::ERR_OK;
124 }
125 
CreateDecoder()126 VEFError VideoDecoder::CreateDecoder()
127 {
128     decoder_ = OH_VideoDecoder_CreateByMime(codecMime_.c_str());
129     if (decoder_ == nullptr) {
130         MEDIA_LOGE("[%{public}s] create decoder failed, OH_VideoDecoder_CreateByMime failed, mime = %{public}s!",
131             logTag_.c_str(), codecMime_.c_str());
132         return VEFError::ERR_INTERNAL_ERROR;
133     }
134     auto CodecOnError = [](OH_AVCodec*, int32_t errorCode, void* context) {
135         auto error = static_cast<OH_AVErrCode>(errorCode);
136         VideoDecoder* decoder = static_cast<VideoDecoder*>(context);
137         if (decoder == nullptr) {
138             std::string subTag = "video-decoder";
139             MEDIA_LOGE("[%{public}s] CodecOnError, context is nullptr, error: %{public}d(%{public}s)", subTag.c_str(),
140                 error, CodecUtil::GetCodecErrorStr(error));
141         } else {
142             MEDIA_LOGI("[%{public}s] CodecOnError %{public}d(%{public}s)", decoder->logTag_.c_str(), error,
143                 CodecUtil::GetCodecErrorStr(error));
144         }
145     };
146     auto CodecOnStreamChanged = [](OH_AVCodec*, OH_AVFormat* format, void* context) {
147         VideoDecoder* decoder = static_cast<VideoDecoder*>(context);
148         if (decoder) {
149             decoder->CodecOnStreamChangedInner(format);
150         }
151     };
152     auto CodecOnNeedInputData = [](OH_AVCodec* codec, uint32_t index, OH_AVMemory* data, void* context) {
153         VideoDecoder* decoder = static_cast<VideoDecoder*>(context);
154         if (decoder) {
155             decoder->CodecOnNeedInputDataInner(codec, index, data);
156         }
157     };
158     auto CodecOnNewOutputData = [](OH_AVCodec* codec, uint32_t index, OH_AVMemory* data, OH_AVCodecBufferAttr* attr,
159         void* context) {
160         VideoDecoder* decoder = static_cast<VideoDecoder*>(context);
161         if (decoder) {
162             decoder->CodecOnNewOutputData(codec, index, data, attr);
163         }
164     };
165     // 设置回调
166     OH_AVCodecAsyncCallback callback = { CodecOnError, CodecOnStreamChanged, CodecOnNeedInputData,
167         CodecOnNewOutputData };
168     auto ret = OH_VideoDecoder_SetCallback(decoder_, callback, this);
169     if (ret != AV_ERR_OK) {
170         MEDIA_LOGE("[%{public}s] set callback for decoder error, OH_VideoDecoder_SetCallback return"
171             " %{public}d(%{public}s)", logTag_.c_str(), ret, CodecUtil::GetCodecErrorStr(ret));
172         return VEFError::ERR_INTERNAL_ERROR;
173     }
174     return VEFError::ERR_OK;
175 }
176 
CodecOnStreamChangedInner(OH_AVFormat * format)177 void VideoDecoder::CodecOnStreamChangedInner(OH_AVFormat* format)
178 {
179     MEDIA_LOGI("[%{public}s] OnStreamChanged %{public}s", logTag_.c_str(), OH_AVFormat_DumpInfo(format));
180 }
181 
CodecOnNeedInputDataInner(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data)182 void VideoDecoder::CodecOnNeedInputDataInner(OH_AVCodec* codec, uint32_t index, OH_AVMemory* data)
183 {
184     MEDIA_LOGD("[%{public}s] CodecOnNeedInputDataInner index %{public}u", logTag_.c_str(), index);
185 
186     OH_AVCodecBufferAttr attr;
187     VEFError error = packetReadFunc_(codec, data, &attr);
188     if (error != VEFError::ERR_OK) {
189         MEDIA_LOGE("[%{public}s] read packet failed with error: %{public}d.", logTag_.c_str(), error);
190         return;
191     }
192     auto errCode = OH_VideoDecoder_PushInputData(decoder_, index, attr);
193     if (errCode != AV_ERR_OK) {
194         MEDIA_LOGE("[%{public}s] push inputData index %{public}u pts %{public}" PRIu64 " size %{public}d "
195             "flags %{public}u ret %{public}s", logTag_.c_str(), index, attr.pts, attr.size, attr.flags,
196             CodecUtil::GetCodecErrorStr(errCode));
197         return;
198     }
199 }
200 
CodecOnNewOutputData(OH_AVCodec * codec,uint32_t index,OH_AVMemory *,OH_AVCodecBufferAttr * attr)201 void VideoDecoder::CodecOnNewOutputData(OH_AVCodec* codec, uint32_t index, OH_AVMemory*,
202     OH_AVCodecBufferAttr* attr)
203 {
204     bool eosFlag = (attr->flags & AVCODEC_BUFFER_FLAGS_EOS) == AVCODEC_BUFFER_FLAGS_EOS;
205     if (eosFlag) {
206         onDecodeResultCallback_(CodecResult::SUCCESS);
207         return;
208     }
209     auto ret = OH_VideoDecoder_RenderOutputData(codec, index);
210     if (ret != AV_ERR_OK) {
211         MEDIA_LOGW("[%{public}s] RenderToSurface failed, index %{public}u pts=%{public}" PRIu64 " ret: "
212             "%{public}d %{public}s!", logTag_.c_str(), index, attr->pts, ret,
213             CodecUtil::GetCodecErrorStr(ret));
214         return;
215     }
216     onDecodeFrameCallback_(attr->pts);
217     MEDIA_LOGD("[%{public}s] OnNewOutputData index %{public}u, pts %{public}" PRIu64 ", flags %{public}u",
218         logTag_.c_str(), index, attr->pts, attr->flags);
219 }
220 
ConfigureDecoder(OH_AVFormat * videoFormat)221 VEFError VideoDecoder::ConfigureDecoder(OH_AVFormat* videoFormat)
222 {
223     OH_AVFormat* format = OH_AVFormat_Create();
224     if (format == nullptr) {
225         MEDIA_LOGE("[%{public}s] configure decoder, OH_AVFormat_Create failed.", logTag_.c_str());
226         return VEFError::ERR_INTERNAL_ERROR;
227     }
228     if (!OH_AVFormat_Copy(format, videoFormat)) {
229         MEDIA_LOGE("[%{public}s] configure decoder failed, OH_AVFormat_Copy failed.", logTag_.c_str());
230         OH_AVFormat_Destroy(format);
231         return VEFError::ERR_INTERNAL_ERROR;
232     }
233     // 必选参数:像素格式
234     if (!OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_SURFACE_FORMAT)) {
235         MEDIA_LOGE("[%{public}s] configure decoder failed, OH_AVFormat_Set [%{public}s] to [%{public}d] failed.",
236             logTag_.c_str(), OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_SURFACE_FORMAT);
237         OH_AVFormat_Destroy(format);
238         return VEFError::ERR_INTERNAL_ERROR;
239     }
240     OH_AVErrCode err = OH_VideoDecoder_Configure(decoder_, format);
241     if (err != AV_ERR_OK) {
242         MEDIA_LOGE("[%{public}s] configure decoder failed, OH_VideoDecoder_Configure return: %{public}d(%{public}s).",
243             logTag_.c_str(), err, CodecUtil::GetCodecErrorStr(err));
244         OH_AVFormat_Destroy(format);
245         return VEFError::ERR_INTERNAL_ERROR;
246     }
247     OH_AVFormat_Destroy(format);
248     return VEFError::ERR_OK;
249 }
250 } // namespace Media
251 } // namespace OHOS
252