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