1 /*
2 * Copyright (c) 2021-2021 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 #define HST_LOG_TAG "FfmpegUtils"
17
18 #include <algorithm>
19 #include <functional>
20 #include <unordered_map>
21 #include "common/log.h"
22 #include "meta/mime_type.h"
23 #include "meta/audio_types.h"
24 #include "ffmpeg_utils.h"
25
26 #define AV_CODEC_TIME_BASE (static_cast<int64_t>(1))
27 #define AV_CODEC_NSECOND AV_CODEC_TIME_BASE
28 #define AV_CODEC_USECOND (static_cast<int64_t>(1000) * AV_CODEC_NSECOND)
29 #define AV_CODEC_MSECOND (static_cast<int64_t>(1000) * AV_CODEC_USECOND)
30 #define AV_CODEC_SECOND (static_cast<int64_t>(1000) * AV_CODEC_MSECOND)
31
32 namespace OHOS {
33 namespace Media {
34 namespace Plugins {
35 namespace Ffmpeg {
Mime2CodecId(const std::string & mime,AVCodecID & codecId)36 bool Mime2CodecId(const std::string &mime, AVCodecID &codecId)
37 {
38 /* MIME to AVCodecID */
39 static const std::unordered_map<std::string, AVCodecID> table = {
40 {MimeType::AUDIO_MPEG, AV_CODEC_ID_MP3},
41 {MimeType::AUDIO_AAC, AV_CODEC_ID_AAC},
42 {MimeType::VIDEO_MPEG4, AV_CODEC_ID_MPEG4},
43 {MimeType::VIDEO_AVC, AV_CODEC_ID_H264},
44 {MimeType::VIDEO_HEVC, AV_CODEC_ID_HEVC},
45 {MimeType::IMAGE_JPG, AV_CODEC_ID_MJPEG},
46 {MimeType::IMAGE_PNG, AV_CODEC_ID_PNG},
47 {MimeType::IMAGE_BMP, AV_CODEC_ID_BMP},
48 };
49 auto it = table.find(mime);
50 if (it != table.end()) {
51 codecId = it->second;
52 return true;
53 }
54 return false;
55 }
56
AVStrError(int errnum)57 std::string AVStrError(int errnum)
58 {
59 char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0};
60 av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
61 return std::string(errbuf);
62 }
63
ConvertTimeFromFFmpeg(int64_t pts,AVRational base)64 int64_t ConvertTimeFromFFmpeg(int64_t pts, AVRational base)
65 {
66 int64_t out;
67 if (pts == AV_NOPTS_VALUE) {
68 out = -1;
69 } else {
70 AVRational bq = {1, AV_CODEC_SECOND};
71 out = av_rescale_q(pts, base, bq);
72 }
73 MEDIA_LOG_D("Base: [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "], time convert ["
74 PUBLIC_LOG_D64 "]->[" PUBLIC_LOG_D64 "].", base.num, base.den, pts, out);
75 return out;
76 }
77
ConvertPts(int64_t pts,int64_t startTime)78 int64_t ConvertPts(int64_t pts, int64_t startTime)
79 {
80 int64_t inputPts;
81 if (startTime >= 0 && (pts < INT64_MIN + startTime)) {
82 inputPts = AV_NOPTS_VALUE;
83 MEDIA_LOG_D("pts is anomalous, pts: " PUBLIC_LOG_D64, pts);
84 return inputPts;
85 } else if (startTime < 0 && (pts > INT64_MAX + startTime)) {
86 inputPts = AV_NOPTS_VALUE;
87 MEDIA_LOG_D("pts is anomalous, pts: " PUBLIC_LOG_D64, pts);
88 return inputPts;
89 }
90 inputPts = pts - startTime;
91
92 return inputPts;
93 }
94
ConvertTimeToFFmpeg(int64_t timestampUs,AVRational base)95 int64_t ConvertTimeToFFmpeg(int64_t timestampUs, AVRational base)
96 {
97 int64_t result;
98 if (base.num == 0) {
99 result = AV_NOPTS_VALUE;
100 } else {
101 AVRational bq = {1, AV_CODEC_SECOND};
102 result = av_rescale_q(timestampUs, bq, base);
103 }
104 MEDIA_LOG_D("Base: [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "], time convert ["
105 PUBLIC_LOG_D64 "]->[" PUBLIC_LOG_D64 "].", base.num, base.den, timestampUs, result);
106 return result;
107 }
108
ConvertFFmpegMediaTypeToString(AVMediaType mediaType)109 std::string_view ConvertFFmpegMediaTypeToString(AVMediaType mediaType)
110 {
111 static const std::unordered_map<AVMediaType, std::string_view> table = {
112 {AVMediaType::AVMEDIA_TYPE_VIDEO, "video"},
113 {AVMediaType::AVMEDIA_TYPE_AUDIO, "audio"},
114 {AVMediaType::AVMEDIA_TYPE_DATA, "data"},
115 {AVMediaType::AVMEDIA_TYPE_SUBTITLE, "subtitle"},
116 {AVMediaType::AVMEDIA_TYPE_ATTACHMENT, "attachment"},
117 };
118 auto it = table.find(mediaType);
119 if (it == table.end()) {
120 return "unknow";
121 }
122 return it->second;
123 }
124
StartWith(const char * name,const char * chars)125 bool StartWith(const char* name, const char* chars)
126 {
127 MEDIA_LOG_D("[" PUBLIC_LOG_S "] start with [" PUBLIC_LOG_S "].", name, chars);
128 return !strncmp(name, chars, strlen(chars));
129 }
130
ConvertFlagsFromFFmpeg(const AVPacket & pkt,bool memoryNotEnough)131 uint32_t ConvertFlagsFromFFmpeg(const AVPacket& pkt, bool memoryNotEnough)
132 {
133 uint32_t flags = (uint32_t)(AVBufferFlag::NONE);
134 if (static_cast<uint32_t>(pkt.flags) & static_cast<uint32_t>(AV_PKT_FLAG_KEY)) {
135 flags |= (uint32_t)(AVBufferFlag::SYNC_FRAME);
136 flags |= (uint32_t)(AVBufferFlag::CODEC_DATA);
137 }
138 if (memoryNotEnough) {
139 flags |= (uint32_t)(AVBufferFlag::PARTIAL_FRAME);
140 }
141 return flags;
142 }
143
CalculateTimeByFrameIndex(AVStream * avStream,int keyFrameIdx)144 int64_t CalculateTimeByFrameIndex(AVStream* avStream, int keyFrameIdx)
145 {
146 FALSE_RETURN_V_MSG_E(avStream != nullptr, 0, "Track is nullptr.");
147 #if defined(LIBAVFORMAT_VERSION_INT) && defined(AV_VERSION_INT)
148 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 78, 0) // 58 and 78 are avformat version range
149 return avformat_index_get_entry(avStream, keyFrameIdx)->timestamp;
150 #elif LIBAVFORMAT_VERSION_INT == AV_VERSION_INT(58, 76, 100) // 58, 76 and 100 are avformat version range
151 return avStream->index_entries[keyFrameIdx].timestamp;
152 #elif LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(58, 64, 100) // 58, 64 and 100 are avformat version range
153 return avStream->internal->index_entries[keyFrameIdx].timestamp;
154 #else
155 return avStream->index_entries[keyFrameIdx].timestamp;
156 #endif
157 #else
158 return avStream->index_entries[keyFrameIdx].timestamp;
159 #endif
160 }
161
ReplaceDelimiter(const std::string & delimiters,char newDelimiter,std::string & str)162 void ReplaceDelimiter(const std::string &delimiters, char newDelimiter, std::string &str)
163 {
164 for (char &it : str) {
165 if (delimiters.find(newDelimiter) != std::string::npos) {
166 it = newDelimiter;
167 }
168 }
169 }
170
SplitString(const char * str,char delimiter)171 std::vector<std::string> SplitString(const char* str, char delimiter)
172 {
173 std::vector<std::string> rtv;
174 if (str) {
175 SplitString(std::string(str), delimiter).swap(rtv);
176 }
177 return rtv;
178 }
179
SplitString(const std::string & str,char delimiter)180 std::vector<std::string> SplitString(const std::string& str, char delimiter)
181 {
182 if (str.empty()) {
183 return {};
184 }
185 std::vector<std::string> rtv;
186 std::string::size_type startPos = 0;
187 std::string::size_type endPos = str.find_first_of(delimiter, startPos);
188 while (startPos != endPos) {
189 rtv.emplace_back(str.substr(startPos, endPos - startPos));
190 if (endPos == std::string::npos) {
191 break;
192 }
193 startPos = endPos + 1;
194 endPos = str.find_first_of(delimiter, startPos);
195 }
196 return rtv;
197 }
198
ColorPrimary2AVColorPrimaries(ColorPrimary primary)199 std::pair<bool, AVColorPrimaries> ColorPrimary2AVColorPrimaries(ColorPrimary primary)
200 {
201 static const std::unordered_map<ColorPrimary, AVColorPrimaries> table = {
202 {ColorPrimary::BT709, AVCOL_PRI_BT709},
203 {ColorPrimary::UNSPECIFIED, AVCOL_PRI_UNSPECIFIED},
204 {ColorPrimary::BT470_M, AVCOL_PRI_BT470M},
205 {ColorPrimary::BT601_625, AVCOL_PRI_BT470BG},
206 {ColorPrimary::BT601_525, AVCOL_PRI_SMPTE170M},
207 {ColorPrimary::SMPTE_ST240, AVCOL_PRI_SMPTE240M},
208 {ColorPrimary::GENERIC_FILM, AVCOL_PRI_FILM},
209 {ColorPrimary::BT2020, AVCOL_PRI_BT2020},
210 {ColorPrimary::SMPTE_ST428, AVCOL_PRI_SMPTE428},
211 {ColorPrimary::P3DCI, AVCOL_PRI_SMPTE431},
212 {ColorPrimary::P3D65, AVCOL_PRI_SMPTE432},
213 };
214 auto it = table.find(primary);
215 if (it != table.end()) {
216 return { true, it->second };
217 }
218 return { false, AVCOL_PRI_UNSPECIFIED };
219 }
220
ColorTransfer2AVColorTransfer(TransferCharacteristic transfer)221 std::pair<bool, AVColorTransferCharacteristic> ColorTransfer2AVColorTransfer(TransferCharacteristic transfer)
222 {
223 static const std::unordered_map<TransferCharacteristic, AVColorTransferCharacteristic> table = {
224 {TransferCharacteristic::BT709, AVCOL_TRC_BT709},
225 {TransferCharacteristic::UNSPECIFIED, AVCOL_TRC_UNSPECIFIED},
226 {TransferCharacteristic::GAMMA_2_2, AVCOL_TRC_GAMMA22},
227 {TransferCharacteristic::GAMMA_2_8, AVCOL_TRC_GAMMA28},
228 {TransferCharacteristic::BT601, AVCOL_TRC_SMPTE170M},
229 {TransferCharacteristic::SMPTE_ST240, AVCOL_TRC_SMPTE240M},
230 {TransferCharacteristic::LINEAR, AVCOL_TRC_LINEAR},
231 {TransferCharacteristic::LOG, AVCOL_TRC_LOG},
232 {TransferCharacteristic::LOG_SQRT, AVCOL_TRC_LOG_SQRT},
233 {TransferCharacteristic::IEC_61966_2_4, AVCOL_TRC_IEC61966_2_4},
234 {TransferCharacteristic::BT1361, AVCOL_TRC_BT1361_ECG},
235 {TransferCharacteristic::IEC_61966_2_1, AVCOL_TRC_IEC61966_2_1},
236 {TransferCharacteristic::BT2020_10BIT, AVCOL_TRC_BT2020_10},
237 {TransferCharacteristic::BT2020_12BIT, AVCOL_TRC_BT2020_12},
238 {TransferCharacteristic::PQ, AVCOL_TRC_SMPTE2084},
239 {TransferCharacteristic::SMPTE_ST428, AVCOL_TRC_SMPTE428},
240 {TransferCharacteristic::HLG, AVCOL_TRC_ARIB_STD_B67},
241 };
242 auto it = table.find(transfer);
243 if (it != table.end()) {
244 return { true, it->second };
245 }
246 return { false, AVCOL_TRC_UNSPECIFIED };
247 }
248
ColorMatrix2AVColorSpace(MatrixCoefficient matrix)249 std::pair<bool, AVColorSpace> ColorMatrix2AVColorSpace(MatrixCoefficient matrix)
250 {
251 static const std::unordered_map<MatrixCoefficient, AVColorSpace> table = {
252 {MatrixCoefficient::IDENTITY, AVCOL_SPC_RGB},
253 {MatrixCoefficient::BT709, AVCOL_SPC_BT709},
254 {MatrixCoefficient::UNSPECIFIED, AVCOL_SPC_UNSPECIFIED},
255 {MatrixCoefficient::FCC, AVCOL_SPC_FCC},
256 {MatrixCoefficient::BT601_625, AVCOL_SPC_BT470BG},
257 {MatrixCoefficient::BT601_525, AVCOL_SPC_SMPTE170M},
258 {MatrixCoefficient::SMPTE_ST240, AVCOL_SPC_SMPTE240M},
259 {MatrixCoefficient::YCGCO, AVCOL_SPC_YCGCO},
260 {MatrixCoefficient::BT2020_NCL, AVCOL_SPC_BT2020_NCL},
261 {MatrixCoefficient::BT2020_CL, AVCOL_SPC_BT2020_CL},
262 {MatrixCoefficient::SMPTE_ST2085, AVCOL_SPC_SMPTE2085},
263 {MatrixCoefficient::CHROMATICITY_NCL, AVCOL_SPC_CHROMA_DERIVED_NCL},
264 {MatrixCoefficient::CHROMATICITY_CL, AVCOL_SPC_CHROMA_DERIVED_CL},
265 {MatrixCoefficient::ICTCP, AVCOL_SPC_ICTCP},
266 };
267 auto it = table.find(matrix);
268 if (it != table.end()) {
269 return { true, it->second };
270 }
271 return { false, AVCOL_SPC_UNSPECIFIED };
272 }
273
GenerateAACCodecConfig(int32_t profile,int32_t sampleRate,int32_t channels)274 std::vector<uint8_t> GenerateAACCodecConfig(int32_t profile, int32_t sampleRate, int32_t channels)
275 {
276 const std::unordered_map<AACProfile, int32_t> profiles = {
277 {AAC_PROFILE_LC, 1},
278 {AAC_PROFILE_ELD, 38},
279 {AAC_PROFILE_ERLC, 1},
280 {AAC_PROFILE_HE, 4},
281 {AAC_PROFILE_HE_V2, 28},
282 {AAC_PROFILE_LD, 22},
283 {AAC_PROFILE_MAIN, 0},
284 };
285 const std::unordered_map<int32_t, int32_t> sampleRates = {
286 {96000, 0}, {88200, 1}, {64000, 2}, {48000, 3},
287 {44100, 4}, {32000, 5}, {24000, 6}, {22050, 7},
288 {16000, 8}, {12000, 9}, {11025, 10}, {8000, 11},
289 {7350, 12},
290 };
291 int32_t profileVal = FF_PROFILE_AAC_LOW;
292 auto it1 = profiles.find(static_cast<AACProfile>(profile));
293 if (it1 != profiles.end()) {
294 profileVal = it1->second;
295 }
296 int32_t sampleRateIndex = 0x10;
297 auto it2 = sampleRates.find(sampleRate);
298 if (it2 != sampleRates.end()) {
299 sampleRateIndex = it2->second;
300 }
301 std::vector<uint8_t> codecConfig = {0, 0, 0x56, 0xE5, 0};
302 codecConfig[0] = ((profileVal + 1) << 0x03) | ((sampleRateIndex & 0x0F) >> 0x01);
303 codecConfig[1] = ((sampleRateIndex & 0x01) << 0x07) | ((channels & 0x0F) << 0x03);
304 return codecConfig;
305 }
306 } // namespace Ffmpeg
307 } // namespace Plugins
308 } // namespace Media
309 } // namespace OHOS
310