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