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