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