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 #include <cstdint>
16 #include <native_avcodec_audiodecoder.h>
17 #include "media_log.h"
18 #include "video_decoder_engine_impl.h"
19
20 namespace OHOS {
21 namespace Media {
22
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_VIDEOEDITOR, "VideoEditorDecode"};
25 }
26
VideoDecoderEngineImpl(uint64_t id,int fd,VideoDecodeCallback * cb)27 VideoDecoderEngineImpl::VideoDecoderEngineImpl(uint64_t id, int fd, VideoDecodeCallback* cb)
28 : id_(id), fd_(fd), cb_(cb)
29 {
30 logTag_ = "video-decoder-engine-" + std::to_string(id);
31 }
32
~VideoDecoderEngineImpl()33 VideoDecoderEngineImpl::~VideoDecoderEngineImpl()
34 {
35 MEDIA_LOGD("[%{public}s] destruct, file fd: %{public}d.", logTag_.c_str(), fd_);
36 }
37
GetId() const38 uint64_t VideoDecoderEngineImpl::GetId() const
39 {
40 return id_;
41 }
42
Init()43 VEFError VideoDecoderEngineImpl::Init()
44 {
45 MEDIA_LOGI("[%{public}s] init.", logTag_.c_str());
46 VEFError error = InitDeMuxer();
47 if (error != VEFError::ERR_OK) {
48 MEDIA_LOGE("[%{public}s] init demuxer failed with error: %{public}d.", logTag_.c_str(), error);
49 return error;
50 }
51 error = InitDecoder();
52 if (error != VEFError::ERR_OK) {
53 MEDIA_LOGE("[%{public}s] init decoder failed with error: %{public}d.", logTag_.c_str(), error);
54 return error;
55 }
56 MEDIA_LOGI("[%{public}s] init success.", logTag_.c_str());
57 return VEFError::ERR_OK;
58 }
59
SetVideoOutputWindow(OHNativeWindow * surfaceWindow)60 VEFError VideoDecoderEngineImpl::SetVideoOutputWindow(OHNativeWindow* surfaceWindow)
61 {
62 return videoDecoder_->SetNativeWindow(surfaceWindow);
63 }
64
SetAudioOutputBufferQueue(std::shared_ptr<PcmBufferQueue> & queue)65 void VideoDecoderEngineImpl::SetAudioOutputBufferQueue(std::shared_ptr<PcmBufferQueue>& queue)
66 {
67 if (audioDecoder_ != nullptr) {
68 audioDecoder_->SetPcmOutputBufferQueue(queue);
69 }
70 }
71
GetVideoFormat()72 OH_AVFormat* VideoDecoderEngineImpl::GetVideoFormat()
73 {
74 return deMuxer_->GetVideoFormat();
75 }
76
GetAudioFormat()77 OH_AVFormat* VideoDecoderEngineImpl::GetAudioFormat()
78 {
79 return deMuxer_->GetAudioFormat();
80 }
81
GetRotation() const82 int32_t VideoDecoderEngineImpl::GetRotation() const
83 {
84 int32_t rotation = 0;
85 auto videoFormat = deMuxer_->GetVideoFormat();
86 if (videoFormat == nullptr) {
87 MEDIA_LOGE("[%{public}s] get video format failed.", logTag_.c_str());
88 return rotation;
89 }
90 if (OH_AVFormat_GetIntValue(videoFormat, OH_MD_KEY_ROTATION, &rotation)) {
91 MEDIA_LOGD("[%{public}s] get rotation [%{public}d].", logTag_.c_str(), rotation);
92 } else {
93 MEDIA_LOGD("[%{public}s] not find rotation.", logTag_.c_str());
94 }
95 return rotation;
96 }
97
GetVideoDuration() const98 int64_t VideoDecoderEngineImpl::GetVideoDuration() const
99 {
100 int64_t duration = -1;
101 auto sourceFormat = deMuxer_->GetSourceFormat();
102 if (sourceFormat == nullptr) {
103 MEDIA_LOGE("[%{public}s] get source format failed.", logTag_.c_str());
104 return duration;
105 }
106 if (!OH_AVFormat_GetLongValue(sourceFormat, OH_MD_KEY_DURATION, &duration)) {
107 MEDIA_LOGE("[%{public}s] get duration failed.", logTag_.c_str());
108 }
109 return duration;
110 }
111
StartDecode()112 VEFError VideoDecoderEngineImpl::StartDecode()
113 {
114 if (audioDecoder_ == nullptr) {
115 MEDIA_LOGI("[%{public}s] StartDecode audioDecoder_ is null.", logTag_.c_str());
116 } else {
117 audioDecoderState_ = CodecState::RUNNING;
118 VEFError error = audioDecoder_->Start();
119 if (error != VEFError::ERR_OK) {
120 MEDIA_LOGE("[%{public}s] audio decoder start failed, err: %{public}d.", logTag_.c_str(), error);
121 audioDecoderState_ = CodecState::FINISH_FAILED;
122 return error;
123 }
124 }
125 if (videoDecoder_ == nullptr) {
126 MEDIA_LOGE("[%{public}s] StartDecode video decoder is nullptr.", logTag_.c_str());
127 return VEFError::ERR_INTERNAL_ERROR;
128 }
129 videoDecoderState_ = CodecState::RUNNING;
130 VEFError error = videoDecoder_->Start();
131 if (error != VEFError::ERR_OK) {
132 MEDIA_LOGE("[%{public}s] video decoder start failed, err: %{public}d.", logTag_.c_str(), error);
133 videoDecoderState_ = CodecState::FINISH_FAILED;
134 return error;
135 }
136 return VEFError::ERR_OK;
137 }
138
StopDecode()139 VEFError VideoDecoderEngineImpl::StopDecode()
140 {
141 if (audioDecoder_ == nullptr) {
142 MEDIA_LOGE("[%{public}s] StopDecode audio Decoder_ is null.", logTag_.c_str());
143 } else {
144 VEFError error = audioDecoder_->Stop();
145 if (error != VEFError::ERR_OK) {
146 MEDIA_LOGE("[%{public}s] audio decoder stop failed, err: %{public}d.", logTag_.c_str(), error);
147 return error;
148 }
149 }
150 if (videoDecoder_ == nullptr) {
151 MEDIA_LOGD("[%{public}s] StopDecode video decoder is nullptr.", logTag_.c_str());
152 return VEFError::ERR_INTERNAL_ERROR;
153 }
154 return videoDecoder_->Stop();
155 }
156
InitDeMuxer()157 VEFError VideoDecoderEngineImpl::InitDeMuxer()
158 {
159 MEDIA_LOGI("[%{public}s] init deMuxer.", logTag_.c_str());
160 deMuxer_ = std::make_shared<VideoDeMuxer>(id_, fd_);
161
162 VEFError error = deMuxer_->Init();
163 if (error != VEFError::ERR_OK) {
164 MEDIA_LOGE("[%{public}s] init video deMuxer object failed with error: %{public}d.", logTag_.c_str(), error);
165 return error;
166 }
167
168 auto videoFormat = deMuxer_->GetVideoFormat();
169
170 MEDIA_LOGI("[%{public}s] init deMuxer success.", logTag_.c_str());
171 return VEFError::ERR_OK;
172 }
173
InitDecoder()174 VEFError VideoDecoderEngineImpl::InitDecoder()
175 {
176 std::function packetReader = [&](OH_AVCodec*, OH_AVMemory* data, OH_AVCodecBufferAttr* attr) -> VEFError {
177 return ReadVideoPacket(data, attr);
178 };
179
180 std::function onDecodeFrame = [&](uint64_t pts) -> void {
181 OnVideoDecoderFrame(pts);
182 };
183
184 std::function onDecodeResult = [&](CodecResult result) -> void {
185 OnVideoDecodeResult(result);
186 };
187
188 videoDecoder_ = std::make_shared<VideoDecoder>(id_, packetReader, onDecodeFrame, onDecodeResult);
189 if (videoDecoder_ == nullptr) {
190 MEDIA_LOGE("[%{public}s] create decoder object failed.", logTag_.c_str());
191 return VEFError::ERR_OOM;
192 }
193 auto videoFormat = deMuxer_->GetVideoFormat();
194 if (videoFormat == nullptr) {
195 MEDIA_LOGE("[%{public}s] init decoder failed, get video format from deMuxer failed.", logTag_.c_str());
196 videoDecoder_ = nullptr;
197 }
198 VEFError error = videoDecoder_->Init(videoFormat);
199 if (error != VEFError::ERR_OK) {
200 MEDIA_LOGE("[%{public}s] init decoder failed with error: %{public}d.", logTag_.c_str(), error);
201 videoDecoder_ = nullptr;
202 return error;
203 }
204 return InitAudioDecoder();
205 }
206
InitAudioDecoder()207 VEFError VideoDecoderEngineImpl::InitAudioDecoder()
208 {
209 auto audioFormat = deMuxer_->GetAudioFormat();
210 if (audioFormat == nullptr) {
211 OnAudioDecodeResult(CodecResult::SUCCESS);
212 return VEFError::ERR_OK;
213 }
214
215 std::function packetReader = [&](OH_AVCodec*, OH_AVMemory* data, OH_AVCodecBufferAttr* attr) -> VEFError {
216 return ReadAudioPacket(data, attr);
217 };
218
219 std::function onDecodeFrame = [&](uint64_t pts) -> void {
220 OnAudioDecodeFrame(pts);
221 };
222
223 std::function onDecodeResult = [&](CodecResult result) -> void {
224 OnAudioDecodeResult(result);
225 };
226
227 audioDecoder_ = std::make_shared<AudioDecoder>(id_, packetReader, onDecodeFrame, onDecodeResult);
228 if (audioDecoder_ == nullptr) {
229 MEDIA_LOGE("[%{public}s] create audio decoder object failed.", logTag_.c_str());
230 return VEFError::ERR_OOM;
231 }
232
233 OH_AVFormat* format = OH_AVFormat_Create();
234 if (!format) {
235 MEDIA_LOGE("[%{public}s] OH_AVFormat_Create failed.", logTag_.c_str());
236 return VEFError::ERR_OOM;
237 }
238
239 OH_AVFormat_Copy(format, audioFormat);
240
241 // 由于OHNative支持的采样格式有限,优先采样SAMPLE_S16LE,不同采样格式内部会实现转换
242 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
243
244 VEFError error = audioDecoder_->Init(format);
245 if (error != VEFError::ERR_OK) {
246 MEDIA_LOGE("[%{public}s] init audio decoder failed with error: %{public}d.", logTag_.c_str(), error);
247 audioDecoder_ = nullptr;
248 OH_AVFormat_Destroy(format);
249 return error;
250 }
251
252 return VEFError::ERR_OK;
253 }
254
ReadVideoPacket(OH_AVMemory * packet,OH_AVCodecBufferAttr * attr)255 VEFError VideoDecoderEngineImpl::ReadVideoPacket(OH_AVMemory* packet, OH_AVCodecBufferAttr* attr)
256 {
257 auto ret = deMuxer_->ReadVideoData(packet, attr);
258 if (ret != VEFError::ERR_OK) {
259 MEDIA_LOGE("[%{public}s] video packets read failed, ret=%{public}d, flags=%{public}d.", logTag_.c_str(), ret,
260 attr->flags);
261 return ret;
262 }
263 if ((attr->flags & AVCODEC_BUFFER_FLAGS_EOS) == AVCODEC_BUFFER_FLAGS_EOS) {
264 MEDIA_LOGI("[%{public}s] decode video input eof, flags=%{public}d", logTag_.c_str(), attr->flags);
265 }
266 MEDIA_LOGD("[%{public}s] video packets read pts %{public}" PRIu64, logTag_.c_str(), attr->pts);
267 return VEFError::ERR_OK;
268 }
269
ReadAudioPacket(OH_AVMemory * packet,OH_AVCodecBufferAttr * attr)270 VEFError VideoDecoderEngineImpl::ReadAudioPacket(OH_AVMemory* packet, OH_AVCodecBufferAttr* attr)
271 {
272 auto ret = deMuxer_->ReadAudioData(packet, attr);
273 if (ret != VEFError::ERR_OK) {
274 MEDIA_LOGE("[%{public}s] audio packets read failed, ret=%{public}d, flags=%{public}d.", logTag_.c_str(), ret,
275 attr->flags);
276 return ret;
277 }
278 if ((attr->flags & AVCODEC_BUFFER_FLAGS_EOS) == AVCODEC_BUFFER_FLAGS_EOS) {
279 MEDIA_LOGI("[%{public}s] decode audio input eof, flags=%{public}d", logTag_.c_str(), attr->flags);
280 }
281 MEDIA_LOGD("[%{public}s] audio packets read pts %{public}" PRIu64, logTag_.c_str(), attr->pts);
282 return VEFError::ERR_OK;
283 }
284
OnAudioDecodeFrame(uint64_t)285 void VideoDecoderEngineImpl::OnAudioDecodeFrame(uint64_t)
286 {
287 }
288
OnAudioDecodeResult(CodecResult result)289 void VideoDecoderEngineImpl::OnAudioDecodeResult(CodecResult result)
290 {
291 MEDIA_LOGD("[%{public}s] audio trunk decode result %{public}d.", logTag_.c_str(), result);
292 if (result == CodecResult::SUCCESS) {
293 audioDecoderState_ = CodecState::FINISH_SUCCESS;
294 } else if (result == CodecResult::FAILED) {
295 audioDecoderState_ = CodecState::FINISH_FAILED;
296 } else {
297 audioDecoderState_ = CodecState::CANCEL;
298 }
299 NotifyDecodeResult();
300 }
301
OnVideoDecoderFrame(uint64_t pts)302 void VideoDecoderEngineImpl::OnVideoDecoderFrame(uint64_t pts)
303 {
304 if (cb_ == nullptr) {
305 MEDIA_LOGE("[%{public}s] OnDecodeFrame[pts= %{public}" PRIu64 "], but callback is expired.",
306 logTag_.c_str(), pts);
307 return;
308 }
309 cb_->OnDecodeFrame(pts);
310 }
311
OnVideoDecodeResult(CodecResult result)312 void VideoDecoderEngineImpl::OnVideoDecodeResult(CodecResult result)
313 {
314 MEDIA_LOGD("[%{public}s] video trunk decode result %{public}d.", logTag_.c_str(), result);
315 if (result == CodecResult::SUCCESS) {
316 videoDecoderState_ = CodecState::FINISH_SUCCESS;
317 } else if (result == CodecResult::FAILED) {
318 videoDecoderState_ = CodecState::FINISH_FAILED;
319 } else {
320 videoDecoderState_ = CodecState::CANCEL;
321 }
322 NotifyDecodeResult();
323 }
324
NotifyDecodeResult()325 void VideoDecoderEngineImpl::NotifyDecodeResult()
326 {
327 if (audioDecoderState_ == CodecState::FINISH_SUCCESS && videoDecoderState_ == CodecState::FINISH_SUCCESS) {
328 cb_->OnDecodeResult(CodecResult::SUCCESS);
329 } else if (audioDecoderState_ == CodecState::FINISH_FAILED || videoDecoderState_ == CodecState::FINISH_FAILED) {
330 cb_->OnDecodeResult(CodecResult::FAILED);
331 } else if (audioDecoderState_ == CodecState::CANCEL || videoDecoderState_ == CodecState::CANCEL) {
332 cb_->OnDecodeResult(CodecResult::CANCELED);
333 } else {
334 MEDIA_LOGD("[%{public}s] codec result id not finish, v= %{public}d, a= %{public}d.",
335 logTag_.c_str(), videoDecoderState_, audioDecoderState_);
336 }
337 }
338
339 } // namespace Media
340 } // namespace OHOS
341