• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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