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 <sys/stat.h>
17 #include "media_log.h"
18 #include <native_avcapability.h>
19 #include <native_avcodec_videoencoder.h>
20 #include <native_averrors.h>
21 #include <native_avformat.h>
22 #include "codec/video/decoder/video_demuxer.h"
23
24 namespace OHOS {
25 namespace Media {
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_VIDEOEDITOR, "VideoEditorDemuxer"};
28 }
29
VideoDeMuxer(uint64_t id,int fd)30 VideoDeMuxer::VideoDeMuxer(uint64_t id, int fd) : fd_(fd)
31 {
32 logTag_ = "video-demuxer-" + std::to_string(id);
33 }
34
~VideoDeMuxer()35 VideoDeMuxer::~VideoDeMuxer()
36 {
37 MEDIA_LOGI("[%{public}s] video deMuxer destruct begin.", logTag_.c_str());
38 if (sourceFormat_) {
39 OH_AVFormat_Destroy(sourceFormat_);
40 sourceFormat_ = nullptr;
41 }
42 if (videoFormat_) {
43 OH_AVFormat_Destroy(videoFormat_);
44 videoFormat_ = nullptr;
45 }
46 if (audioFormat_) {
47 OH_AVFormat_Destroy(audioFormat_);
48 audioFormat_ = nullptr;
49 }
50 if (deMuxer_) {
51 OH_AVDemuxer_Destroy(deMuxer_);
52 deMuxer_ = nullptr;
53 }
54 if (source_) {
55 OH_AVSource_Destroy(source_);
56 source_ = nullptr;
57 }
58 MEDIA_LOGI("[%{public}s] video deMuxer destruct finish.", logTag_.c_str());
59 }
60
Init()61 VEFError VideoDeMuxer::Init()
62 {
63 MEDIA_LOGI("[%{public}s] init, source file fd: %{public}d.", logTag_.c_str(), fd_);
64 struct stat st;
65 if (fstat(fd_, &st) != 0) {
66 MEDIA_LOGE("[%{public}s] init failed, fstat file failed with error: %{public}d.", logTag_.c_str(), errno);
67 return VEFError::ERR_INTERNAL_ERROR;
68 }
69 MEDIA_LOGI("[%{public}s] init, source file size: %{public}" PRIu64 ".", logTag_.c_str(), st.st_size);
70 source_ = OH_AVSource_CreateWithFD(fd_, 0, st.st_size);
71 if (source_ == nullptr) {
72 MEDIA_LOGE("[%{public}s] init failed, OH_AVSource_CreateWithFD failed.", logTag_.c_str());
73 return VEFError::ERR_INTERNAL_ERROR;
74 }
75 deMuxer_ = OH_AVDemuxer_CreateWithSource(source_);
76 if (deMuxer_ == nullptr) {
77 MEDIA_LOGE("[%{public}s] init failed, OH_AVDemuxer_CreateWithSource failed.", logTag_.c_str());
78 return VEFError::ERR_INTERNAL_ERROR;
79 }
80 sourceFormat_ = OH_AVSource_GetSourceFormat(source_);
81 if (sourceFormat_ == nullptr) {
82 MEDIA_LOGE("[%{public}s] init failed, OH_AVSource_GetSourceFormat failed.", logTag_.c_str());
83 return VEFError::ERR_INTERNAL_ERROR;
84 }
85
86 VEFError error = ParseTrackInfo();
87 if (error != VEFError::ERR_OK) {
88 MEDIA_LOGE("[%{public}s] init failed, parse track info with error: %{public}d.", logTag_.c_str(), error);
89 return VEFError::ERR_INTERNAL_ERROR;
90 }
91
92 MEDIA_LOGI("[%{public}s] init success.", logTag_.c_str());
93 return VEFError::ERR_OK;
94 }
95
ParseTrackInfo()96 VEFError VideoDeMuxer::ParseTrackInfo()
97 {
98 int32_t trackCount = 0;
99 if (!OH_AVFormat_GetIntValue(sourceFormat_, OH_MD_KEY_TRACK_COUNT, &trackCount)) {
100 MEDIA_LOGE("[%{public}s] get [%{public}s] from source format failed.", logTag_.c_str(), OH_MD_KEY_TRACK_COUNT);
101 return VEFError::ERR_INTERNAL_ERROR;
102 }
103 MEDIA_LOGI("[%{public}s] get track count = %{public}d.", logTag_.c_str(), trackCount);
104
105 for (int32_t trackIndex = 0; trackIndex < trackCount; trackIndex++) {
106 OH_AVFormat* trackFormat = OH_AVSource_GetTrackFormat(source_, trackIndex);
107 if (trackFormat == nullptr) {
108 MEDIA_LOGE("[%{public}s] get track format of track[%{public}d] failed.", logTag_.c_str(), trackIndex);
109 continue;
110 }
111 int32_t trackType;
112 if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType)) {
113 MEDIA_LOGE("[%{public}s] get track type of track[%{public}d] failed.", logTag_.c_str(), trackIndex);
114 continue;
115 }
116 if (trackType == OH_MediaType::MEDIA_TYPE_VID) {
117 videoFormat_ = trackFormat;
118 videoTrackId_ = trackIndex;
119 MEDIA_LOGI("[%{public}s] get video track success, track id = %{public}d.", logTag_.c_str(), trackIndex);
120 } else if (trackType == OH_MediaType::MEDIA_TYPE_AUD) {
121 audioFormat_ = trackFormat;
122 audioTrackId_ = trackIndex;
123 MEDIA_LOGI("[%{public}s] get audio track success, track id = %{public}d.", logTag_.c_str(), trackIndex);
124 }
125 }
126
127 if (videoTrackId_ == -1 || videoFormat_ == nullptr) {
128 MEDIA_LOGE("[%{public}s] get video track failed.", logTag_.c_str());
129 return VEFError::ERR_INTERNAL_ERROR;
130 }
131
132 if (audioTrackId_ == -1 || audioFormat_ == nullptr) {
133 audioTrackId_ = -1;
134 audioFormat_ = nullptr;
135 MEDIA_LOGW("[%{public}s] no invalid audio track.", logTag_.c_str());
136 } else {
137 auto ret = OH_AVDemuxer_SelectTrackByID(deMuxer_, audioTrackId_);
138 if (ret != AV_ERR_OK) {
139 MEDIA_LOGE("[%{public}s] select audio track failed with error: %{public}d.", logTag_.c_str(), ret);
140 return VEFError::ERR_INTERNAL_ERROR;
141 }
142 }
143
144 auto ret = OH_AVDemuxer_SelectTrackByID(deMuxer_, videoTrackId_);
145 if (ret != AV_ERR_OK) {
146 MEDIA_LOGE("[%{public}s] select video track failed with error: %{public}d.", logTag_.c_str(), ret);
147 return VEFError::ERR_INTERNAL_ERROR;
148 }
149 return VEFError::ERR_OK;
150 }
151
GetVideoFormat() const152 OH_AVFormat* VideoDeMuxer::GetVideoFormat() const
153 {
154 return videoFormat_;
155 }
156
GetAudioFormat() const157 OH_AVFormat* VideoDeMuxer::GetAudioFormat() const
158 {
159 return audioFormat_;
160 }
161
GetSourceFormat() const162 OH_AVFormat* VideoDeMuxer::GetSourceFormat() const
163 {
164 return sourceFormat_;
165 }
166
ReadVideoData(OH_AVMemory * data,OH_AVCodecBufferAttr * attr)167 VEFError VideoDeMuxer::ReadVideoData(OH_AVMemory* data, OH_AVCodecBufferAttr* attr)
168 {
169 auto ret = OH_AVDemuxer_ReadSample(deMuxer_, videoTrackId_, data, attr);
170 if (ret != AV_ERR_OK) {
171 MEDIA_LOGE("[%{public}s] read video packet failed, OH_AVDemuxer_ReadSample return: %{public}d.",
172 logTag_.c_str(), ret);
173 return VEFError::ERR_INTERNAL_ERROR;
174 }
175 return VEFError::ERR_OK;
176 }
177
ReadAudioData(OH_AVMemory * data,OH_AVCodecBufferAttr * attr)178 VEFError VideoDeMuxer::ReadAudioData(OH_AVMemory* data, OH_AVCodecBufferAttr* attr)
179 {
180 auto ret = OH_AVDemuxer_ReadSample(deMuxer_, audioTrackId_, data, attr);
181 if (ret != AV_ERR_OK) {
182 MEDIA_LOGE("[%{public}s] read audio packet failed, OH_AVDemuxer_ReadSample return: %{public}d.",
183 logTag_.c_str(), ret);
184 return VEFError::ERR_INTERNAL_ERROR;
185 }
186 return VEFError::ERR_OK;
187 }
188 } // namespace Media
189 } // namespace OHOS
190