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 return VEFError::ERR_OOM;
198 }
199 VEFError error = videoDecoder_->Init(videoFormat);
200 if (error != VEFError::ERR_OK) {
201 MEDIA_LOGE("[%{public}s] init decoder failed with error: %{public}d.", logTag_.c_str(), error);
202 videoDecoder_ = nullptr;
203 return error;
204 }
205 return InitAudioDecoder();
206 }
207
InitAudioDecoder()208 VEFError VideoDecoderEngineImpl::InitAudioDecoder()
209 {
210 auto audioFormat = deMuxer_->GetAudioFormat();
211 if (audioFormat == nullptr) {
212 OnAudioDecodeResult(CodecResult::SUCCESS);
213 return VEFError::ERR_OK;
214 }
215
216 std::function packetReader = [&](OH_AVCodec*, OH_AVMemory* data, OH_AVCodecBufferAttr* attr) -> VEFError {
217 return ReadAudioPacket(data, attr);
218 };
219
220 std::function onDecodeFrame = [&](uint64_t pts) -> void {
221 OnAudioDecodeFrame(pts);
222 };
223
224 std::function onDecodeResult = [&](CodecResult result) -> void {
225 OnAudioDecodeResult(result);
226 };
227
228 audioDecoder_ = std::make_shared<AudioDecoder>(id_, packetReader, onDecodeFrame, onDecodeResult);
229 if (audioDecoder_ == nullptr) {
230 MEDIA_LOGE("[%{public}s] create audio decoder object failed.", logTag_.c_str());
231 return VEFError::ERR_OOM;
232 }
233
234 OH_AVFormat* format = OH_AVFormat_Create();
235 if (!format) {
236 MEDIA_LOGE("[%{public}s] OH_AVFormat_Create failed.", logTag_.c_str());
237 return VEFError::ERR_OOM;
238 }
239
240 OH_AVFormat_Copy(format, audioFormat);
241
242 // 由于OHNative支持的采样格式有限,优先采样SAMPLE_S16LE,不同采样格式内部会实现转换
243 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
244
245 VEFError error = audioDecoder_->Init(format);
246 if (error != VEFError::ERR_OK) {
247 MEDIA_LOGE("[%{public}s] init audio decoder failed with error: %{public}d.", logTag_.c_str(), error);
248 audioDecoder_ = nullptr;
249 OH_AVFormat_Destroy(format);
250 return error;
251 }
252 OH_AVFormat_Destroy(format);
253 return VEFError::ERR_OK;
254 }
255
ReadVideoPacket(OH_AVMemory * packet,OH_AVCodecBufferAttr * attr)256 VEFError VideoDecoderEngineImpl::ReadVideoPacket(OH_AVMemory* packet, OH_AVCodecBufferAttr* attr)
257 {
258 auto ret = deMuxer_->ReadVideoData(packet, attr);
259 if (ret != VEFError::ERR_OK) {
260 MEDIA_LOGE("[%{public}s] video packets read failed, ret=%{public}d, flags=%{public}d.", logTag_.c_str(), ret,
261 attr->flags);
262 return ret;
263 }
264 if ((attr->flags & AVCODEC_BUFFER_FLAGS_EOS) == AVCODEC_BUFFER_FLAGS_EOS) {
265 MEDIA_LOGI("[%{public}s] decode video input eof, flags=%{public}d", logTag_.c_str(), attr->flags);
266 }
267 MEDIA_LOGD("[%{public}s] video packets read pts %{public}" PRIu64, logTag_.c_str(), attr->pts);
268 return VEFError::ERR_OK;
269 }
270
ReadAudioPacket(OH_AVMemory * packet,OH_AVCodecBufferAttr * attr)271 VEFError VideoDecoderEngineImpl::ReadAudioPacket(OH_AVMemory* packet, OH_AVCodecBufferAttr* attr)
272 {
273 auto ret = deMuxer_->ReadAudioData(packet, attr);
274 if (ret != VEFError::ERR_OK) {
275 MEDIA_LOGE("[%{public}s] audio packets read failed, ret=%{public}d, flags=%{public}d.", logTag_.c_str(), ret,
276 attr->flags);
277 return ret;
278 }
279 if ((attr->flags & AVCODEC_BUFFER_FLAGS_EOS) == AVCODEC_BUFFER_FLAGS_EOS) {
280 MEDIA_LOGI("[%{public}s] decode audio input eof, flags=%{public}d", logTag_.c_str(), attr->flags);
281 }
282 MEDIA_LOGD("[%{public}s] audio packets read pts %{public}" PRIu64, logTag_.c_str(), attr->pts);
283 return VEFError::ERR_OK;
284 }
285
OnAudioDecodeFrame(uint64_t)286 void VideoDecoderEngineImpl::OnAudioDecodeFrame(uint64_t)
287 {
288 }
289
OnAudioDecodeResult(CodecResult result)290 void VideoDecoderEngineImpl::OnAudioDecodeResult(CodecResult result)
291 {
292 MEDIA_LOGD("[%{public}s] audio trunk decode result %{public}d.", logTag_.c_str(), result);
293 if (result == CodecResult::SUCCESS) {
294 audioDecoderState_ = CodecState::FINISH_SUCCESS;
295 } else if (result == CodecResult::FAILED) {
296 audioDecoderState_ = CodecState::FINISH_FAILED;
297 } else {
298 audioDecoderState_ = CodecState::CANCEL;
299 }
300 NotifyDecodeResult();
301 }
302
OnVideoDecoderFrame(uint64_t pts)303 void VideoDecoderEngineImpl::OnVideoDecoderFrame(uint64_t pts)
304 {
305 if (cb_ == nullptr) {
306 MEDIA_LOGE("[%{public}s] OnDecodeFrame[pts= %{public}" PRIu64 "], but callback is expired.",
307 logTag_.c_str(), pts);
308 return;
309 }
310 cb_->OnDecodeFrame(pts);
311 }
312
OnVideoDecodeResult(CodecResult result)313 void VideoDecoderEngineImpl::OnVideoDecodeResult(CodecResult result)
314 {
315 MEDIA_LOGD("[%{public}s] video trunk decode result %{public}d.", logTag_.c_str(), result);
316 if (result == CodecResult::SUCCESS) {
317 videoDecoderState_ = CodecState::FINISH_SUCCESS;
318 } else if (result == CodecResult::FAILED) {
319 videoDecoderState_ = CodecState::FINISH_FAILED;
320 } else {
321 videoDecoderState_ = CodecState::CANCEL;
322 }
323 NotifyDecodeResult();
324 }
325
NotifyDecodeResult()326 void VideoDecoderEngineImpl::NotifyDecodeResult()
327 {
328 if (audioDecoderState_ == CodecState::FINISH_SUCCESS && videoDecoderState_ == CodecState::FINISH_SUCCESS) {
329 cb_->OnDecodeResult(CodecResult::SUCCESS);
330 } else if (audioDecoderState_ == CodecState::FINISH_FAILED || videoDecoderState_ == CodecState::FINISH_FAILED) {
331 cb_->OnDecodeResult(CodecResult::FAILED);
332 } else if (audioDecoderState_ == CodecState::CANCEL || videoDecoderState_ == CodecState::CANCEL) {
333 cb_->OnDecodeResult(CodecResult::CANCELED);
334 } else {
335 MEDIA_LOGD("[%{public}s] codec result id not finish, v= %{public}d, a= %{public}d.",
336 logTag_.c_str(), videoDecoderState_, audioDecoderState_);
337 }
338 }
339
340 } // namespace Media
341 } // namespace OHOS
342