• 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 #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