• 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 "ffmpeg_utils.h"
24 
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "HiStreamer" };
27 constexpr uint32_t FLAC_CODEC_CONFIG_SIZE = 34;
28 }
29 
30 #define AV_CODEC_TIME_BASE (static_cast<int64_t>(1))
31 #define AV_CODEC_NSECOND AV_CODEC_TIME_BASE
32 #define AV_CODEC_USECOND (static_cast<int64_t>(1000) * AV_CODEC_NSECOND)
33 #define AV_CODEC_MSECOND (static_cast<int64_t>(1000) * AV_CODEC_USECOND)
34 #define AV_CODEC_SECOND (static_cast<int64_t>(1000) * AV_CODEC_MSECOND)
35 
36 namespace OHOS {
37 namespace Media {
38 namespace Plugins {
39 namespace Ffmpeg {
Mime2CodecId(const std::string & mime,AVCodecID & codecId)40 bool Mime2CodecId(const std::string &mime, AVCodecID &codecId)
41 {
42     /* MIME to AVCodecID */
43     static const std::unordered_map<std::string, AVCodecID> table = {
44         {MimeType::AUDIO_MPEG, AV_CODEC_ID_MP3},
45         {MimeType::AUDIO_AAC, AV_CODEC_ID_AAC},
46         {MimeType::AUDIO_AMR_NB, AV_CODEC_ID_AMR_NB},
47         {MimeType::AUDIO_AMR_WB, AV_CODEC_ID_AMR_WB},
48         {MimeType::AUDIO_RAW, AV_CODEC_ID_PCM_U8},
49         {MimeType::AUDIO_G711MU, AV_CODEC_ID_PCM_MULAW},
50         {MimeType::AUDIO_FLAC, AV_CODEC_ID_FLAC},
51         {MimeType::VIDEO_MPEG4, AV_CODEC_ID_MPEG4},
52         {MimeType::VIDEO_AVC, AV_CODEC_ID_H264},
53         {MimeType::VIDEO_HEVC, AV_CODEC_ID_HEVC},
54         {MimeType::IMAGE_JPG, AV_CODEC_ID_MJPEG},
55         {MimeType::IMAGE_PNG, AV_CODEC_ID_PNG},
56         {MimeType::IMAGE_BMP, AV_CODEC_ID_BMP},
57         {MimeType::TIMED_METADATA, AV_CODEC_ID_FFMETADATA},
58     };
59     auto it = table.find(mime);
60     if (it != table.end()) {
61         codecId = it->second;
62         return true;
63     }
64     return false;
65 }
66 
Raw2CodecId(AudioSampleFormat sampleFormat,AVCodecID & codecId)67 bool Raw2CodecId(AudioSampleFormat sampleFormat, AVCodecID &codecId)
68 {
69     static const std::unordered_map<AudioSampleFormat, AVCodecID> table = {
70         {AudioSampleFormat::SAMPLE_U8, AV_CODEC_ID_PCM_U8},
71         {AudioSampleFormat::SAMPLE_S16LE, AV_CODEC_ID_PCM_S16LE},
72         {AudioSampleFormat::SAMPLE_S24LE, AV_CODEC_ID_PCM_S24LE},
73         {AudioSampleFormat::SAMPLE_S32LE, AV_CODEC_ID_PCM_S32LE},
74         {AudioSampleFormat::SAMPLE_F32LE, AV_CODEC_ID_PCM_F32LE},
75     };
76     auto it = table.find(sampleFormat);
77     if (it != table.end()) {
78         codecId = it->second;
79         return true;
80     }
81     return false;
82 }
83 
Raw2BitPerSample(AudioSampleFormat sampleFormat,uint8_t & bitPerSample)84 bool Raw2BitPerSample(AudioSampleFormat sampleFormat, uint8_t &bitPerSample)
85 {
86     static const std::unordered_map<AudioSampleFormat, uint8_t> table = {
87         {AudioSampleFormat::SAMPLE_U8, 8},
88         {AudioSampleFormat::SAMPLE_S16LE, 16},
89         {AudioSampleFormat::SAMPLE_S24LE, 24},
90         {AudioSampleFormat::SAMPLE_S32LE, 32},
91         {AudioSampleFormat::SAMPLE_F32LE, 32},
92         {AudioSampleFormat::SAMPLE_U8P, 8},
93         {AudioSampleFormat::SAMPLE_S16P, 16},
94         {AudioSampleFormat::SAMPLE_S24P, 24},
95         {AudioSampleFormat::SAMPLE_S32P, 32},
96         {AudioSampleFormat::SAMPLE_F32P, 32},
97     };
98     auto it = table.find(sampleFormat);
99     if (it != table.end()) {
100         bitPerSample = it->second;
101         return true;
102     }
103     return false;
104 }
105 
AVStrError(int errnum)106 std::string AVStrError(int errnum)
107 {
108     char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0};
109     av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
110     return std::string(errbuf);
111 }
112 
ConvertTimeFromFFmpeg(int64_t pts,AVRational base)113 int64_t ConvertTimeFromFFmpeg(int64_t pts, AVRational base)
114 {
115     int64_t out;
116     if (pts == AV_NOPTS_VALUE) {
117         out = -1;
118     } else {
119         AVRational bq = {1, AV_CODEC_SECOND};
120         out = av_rescale_q(pts, base, bq);
121     }
122     MEDIA_LOG_D("Base: [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "], time convert ["
123         PUBLIC_LOG_D64 "]->[" PUBLIC_LOG_D64 "].", base.num, base.den, pts, out);
124     return out;
125 }
126 
ConvertTimeToFFmpeg(int64_t timestampNs,AVRational base)127 int64_t ConvertTimeToFFmpeg(int64_t timestampNs, AVRational base)
128 {
129     int64_t result;
130     if (base.num == 0) {
131         result = AV_NOPTS_VALUE;
132     } else {
133         AVRational bq = {1, AV_CODEC_SECOND};
134         result = av_rescale_q(timestampNs, bq, base);
135     }
136     MEDIA_LOG_D("Base: [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "], time convert ["
137         PUBLIC_LOG_D64 "]->[" PUBLIC_LOG_D64 "].", base.num, base.den, timestampNs, result);
138     return result;
139 }
140 
ConvertTimeToFFmpegByUs(int64_t timestampUs,AVRational base)141 int64_t ConvertTimeToFFmpegByUs(int64_t timestampUs, AVRational base)
142 {
143     int64_t result;
144     if (base.num == 0) {
145         result = AV_NOPTS_VALUE;
146     } else {
147         AVRational bq = {1, AV_CODEC_MSECOND};
148         result = av_rescale_q(timestampUs, bq, base);
149     }
150     MEDIA_LOG_D("Base: [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "], time convert ["
151         PUBLIC_LOG_D64 "]->[" PUBLIC_LOG_D64 "].", base.num, base.den, timestampUs, result);
152     return result;
153 }
154 
StartWith(const char * name,const char * chars)155 bool StartWith(const char* name, const char* chars)
156 {
157     if (name == nullptr || chars == nullptr) {
158         return false;
159     }
160     return !strncmp(name, chars, strlen(chars));
161 }
162 
ConvertFlagsFromFFmpeg(const AVPacket & pkt,bool memoryNotEnough)163 uint32_t ConvertFlagsFromFFmpeg(const AVPacket& pkt, bool memoryNotEnough)
164 {
165     uint32_t flags = (uint32_t)(AVBufferFlag::NONE);
166     if (static_cast<uint32_t>(pkt.flags) & static_cast<uint32_t>(AV_PKT_FLAG_KEY)) {
167         flags |= (uint32_t)(AVBufferFlag::SYNC_FRAME);
168         flags |= (uint32_t)(AVBufferFlag::CODEC_DATA);
169     }
170     if (static_cast<uint32_t>(pkt.flags) & static_cast<uint32_t>(AV_PKT_FLAG_DISCARD)) {
171         flags |= (uint32_t)(AVBufferFlag::DISCARD);
172     }
173     if (memoryNotEnough) {
174         flags |= (uint32_t)(AVBufferFlag::PARTIAL_FRAME);
175     }
176     return flags;
177 }
178 
CalculateTimeByFrameIndex(AVStream * avStream,int keyFrameIdx)179 int64_t CalculateTimeByFrameIndex(AVStream* avStream, int keyFrameIdx)
180 {
181     FALSE_RETURN_V_MSG_E(avStream != nullptr, 0, "Track is nullptr.");
182 #if defined(LIBAVFORMAT_VERSION_INT) && defined(AV_VERSION_INT)
183 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 78, 0) // 58 and 78 are avformat version range
184     FALSE_RETURN_V_MSG_E(avformat_index_get_entry(avStream, keyFrameIdx) != nullptr, 0, "Track is nullptr.");
185     return avformat_index_get_entry(avStream, keyFrameIdx)->timestamp;
186 #elif LIBAVFORMAT_VERSION_INT == AV_VERSION_INT(58, 76, 100) // 58, 76 and 100 are avformat version range
187     return avStream->index_entries[keyFrameIdx].timestamp;
188 #elif LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(58, 64, 100) // 58, 64 and 100 are avformat version range
189     FALSE_RETURN_V_MSG_E(avStream->internal != nullptr, 0, "Track is nullptr.");
190     return avStream->internal->index_entries[keyFrameIdx].timestamp;
191 #else
192     return avStream->index_entries[keyFrameIdx].timestamp;
193 #endif
194 #else
195     return avStream->index_entries[keyFrameIdx].timestamp;
196 #endif
197 }
198 
ReplaceDelimiter(const std::string & delimiters,char newDelimiter,std::string & str)199 void ReplaceDelimiter(const std::string &delimiters, char newDelimiter, std::string &str)
200 {
201     for (char &it : str) {
202         if (delimiters.find(newDelimiter) != std::string::npos) {
203             it = newDelimiter;
204         }
205     }
206 }
207 
SplitString(const char * str,char delimiter)208 std::vector<std::string> SplitString(const char* str, char delimiter)
209 {
210     std::vector<std::string> rtv;
211     if (str) {
212         SplitString(std::string(str), delimiter).swap(rtv);
213     }
214     return rtv;
215 }
216 
SplitString(const std::string & str,char delimiter)217 std::vector<std::string> SplitString(const std::string& str, char delimiter)
218 {
219     if (str.empty()) {
220         return {};
221     }
222     std::vector<std::string> rtv;
223     std::string::size_type startPos = 0;
224     std::string::size_type endPos = str.find_first_of(delimiter, startPos);
225     while (startPos != endPos) {
226         rtv.emplace_back(str.substr(startPos, endPos - startPos));
227         if (endPos == std::string::npos) {
228             break;
229         }
230         startPos = endPos + 1;
231         endPos = str.find_first_of(delimiter, startPos);
232     }
233     return rtv;
234 }
235 
ColorPrimary2AVColorPrimaries(ColorPrimary primary)236 std::pair<bool, AVColorPrimaries> ColorPrimary2AVColorPrimaries(ColorPrimary primary)
237 {
238     static const std::unordered_map<ColorPrimary, AVColorPrimaries> table = {
239         {ColorPrimary::BT709, AVCOL_PRI_BT709},
240         {ColorPrimary::UNSPECIFIED, AVCOL_PRI_UNSPECIFIED},
241         {ColorPrimary::BT470_M, AVCOL_PRI_BT470M},
242         {ColorPrimary::BT601_625, AVCOL_PRI_BT470BG},
243         {ColorPrimary::BT601_525, AVCOL_PRI_SMPTE170M},
244         {ColorPrimary::SMPTE_ST240, AVCOL_PRI_SMPTE240M},
245         {ColorPrimary::GENERIC_FILM, AVCOL_PRI_FILM},
246         {ColorPrimary::BT2020, AVCOL_PRI_BT2020},
247         {ColorPrimary::SMPTE_ST428, AVCOL_PRI_SMPTE428},
248         {ColorPrimary::P3DCI, AVCOL_PRI_SMPTE431},
249         {ColorPrimary::P3D65, AVCOL_PRI_SMPTE432},
250     };
251     auto it = table.find(primary);
252     if (it != table.end()) {
253         return { true, it->second };
254     }
255     return { false, AVCOL_PRI_UNSPECIFIED };
256 }
257 
ColorTransfer2AVColorTransfer(TransferCharacteristic transfer)258 std::pair<bool, AVColorTransferCharacteristic> ColorTransfer2AVColorTransfer(TransferCharacteristic transfer)
259 {
260     static const std::unordered_map<TransferCharacteristic, AVColorTransferCharacteristic> table = {
261         {TransferCharacteristic::BT709, AVCOL_TRC_BT709},
262         {TransferCharacteristic::UNSPECIFIED, AVCOL_TRC_UNSPECIFIED},
263         {TransferCharacteristic::GAMMA_2_2, AVCOL_TRC_GAMMA22},
264         {TransferCharacteristic::GAMMA_2_8, AVCOL_TRC_GAMMA28},
265         {TransferCharacteristic::BT601, AVCOL_TRC_SMPTE170M},
266         {TransferCharacteristic::SMPTE_ST240, AVCOL_TRC_SMPTE240M},
267         {TransferCharacteristic::LINEAR, AVCOL_TRC_LINEAR},
268         {TransferCharacteristic::LOG, AVCOL_TRC_LOG},
269         {TransferCharacteristic::LOG_SQRT, AVCOL_TRC_LOG_SQRT},
270         {TransferCharacteristic::IEC_61966_2_4, AVCOL_TRC_IEC61966_2_4},
271         {TransferCharacteristic::BT1361, AVCOL_TRC_BT1361_ECG},
272         {TransferCharacteristic::IEC_61966_2_1, AVCOL_TRC_IEC61966_2_1},
273         {TransferCharacteristic::BT2020_10BIT, AVCOL_TRC_BT2020_10},
274         {TransferCharacteristic::BT2020_12BIT, AVCOL_TRC_BT2020_12},
275         {TransferCharacteristic::PQ, AVCOL_TRC_SMPTE2084},
276         {TransferCharacteristic::SMPTE_ST428, AVCOL_TRC_SMPTE428},
277         {TransferCharacteristic::HLG, AVCOL_TRC_ARIB_STD_B67},
278     };
279     auto it = table.find(transfer);
280     if (it != table.end()) {
281         return { true, it->second };
282     }
283     return { false, AVCOL_TRC_UNSPECIFIED };
284 }
285 
ColorMatrix2AVColorSpace(MatrixCoefficient matrix)286 std::pair<bool, AVColorSpace> ColorMatrix2AVColorSpace(MatrixCoefficient matrix)
287 {
288     static const std::unordered_map<MatrixCoefficient, AVColorSpace> table = {
289         {MatrixCoefficient::IDENTITY, AVCOL_SPC_RGB},
290         {MatrixCoefficient::BT709, AVCOL_SPC_BT709},
291         {MatrixCoefficient::UNSPECIFIED, AVCOL_SPC_UNSPECIFIED},
292         {MatrixCoefficient::FCC, AVCOL_SPC_FCC},
293         {MatrixCoefficient::BT601_625, AVCOL_SPC_BT470BG},
294         {MatrixCoefficient::BT601_525, AVCOL_SPC_SMPTE170M},
295         {MatrixCoefficient::SMPTE_ST240, AVCOL_SPC_SMPTE240M},
296         {MatrixCoefficient::YCGCO, AVCOL_SPC_YCGCO},
297         {MatrixCoefficient::BT2020_NCL, AVCOL_SPC_BT2020_NCL},
298         {MatrixCoefficient::BT2020_CL, AVCOL_SPC_BT2020_CL},
299         {MatrixCoefficient::SMPTE_ST2085, AVCOL_SPC_SMPTE2085},
300         {MatrixCoefficient::CHROMATICITY_NCL, AVCOL_SPC_CHROMA_DERIVED_NCL},
301         {MatrixCoefficient::CHROMATICITY_CL, AVCOL_SPC_CHROMA_DERIVED_CL},
302         {MatrixCoefficient::ICTCP, AVCOL_SPC_ICTCP},
303     };
304     auto it = table.find(matrix);
305     if (it != table.end()) {
306         return { true, it->second };
307     }
308     return { false, AVCOL_SPC_UNSPECIFIED };
309 }
310 
GenerateAACCodecConfig(int32_t profile,int32_t sampleRate,int32_t channels)311 std::vector<uint8_t> GenerateAACCodecConfig(int32_t profile, int32_t sampleRate, int32_t channels)
312 {
313     const std::unordered_map<AACProfile, int32_t> profiles = {
314         {AAC_PROFILE_LC, 1},
315         {AAC_PROFILE_ELD, 38},
316         {AAC_PROFILE_ERLC, 1},
317         {AAC_PROFILE_HE, 4},
318         {AAC_PROFILE_HE_V2, 28},
319         {AAC_PROFILE_LD, 22},
320         {AAC_PROFILE_MAIN, 0},
321     };
322     const std::unordered_map<uint32_t, uint32_t> sampleRates = {
323         {96000, 0}, {88200, 1}, {64000, 2}, {48000, 3},
324         {44100, 4}, {32000, 5}, {24000, 6}, {22050, 7},
325         {16000, 8}, {12000, 9}, {11025, 10}, {8000,  11},
326         {7350,  12},
327     };
328     uint32_t profileVal = FF_PROFILE_AAC_LOW;
329     auto it1 = profiles.find(static_cast<AACProfile>(profile));
330     if (it1 != profiles.end()) {
331         profileVal = it1->second;
332     }
333     uint32_t sampleRateIndex = 0x10;
334     uint32_t baseIndex = 0xF;
335     auto it2 = sampleRates.find(sampleRate);
336     if (it2 != sampleRates.end()) {
337         sampleRateIndex = it2->second;
338     }
339     it2 = sampleRates.find(sampleRate / 2); // 2: HE-AAC require divide base sample rate
340     if (it2 != sampleRates.end()) {
341         baseIndex = it2->second;
342     }
343     std::vector<uint8_t> codecConfig;
344     if (profile == AAC_PROFILE_HE || profile == AAC_PROFILE_HE_V2) {
345         // HE-AAC v2 only support stereo and only one channel exist
346         uint32_t realCh = (profile == AAC_PROFILE_HE_V2) ? 1 : static_cast<uint32_t>(channels);
347         codecConfig = {0, 0, 0, 0, 0};
348         // 5 bit AOT(0x03:left 3 bits for sample rate) + 4 bit sample rate idx(0x01: 4 - 0x03)
349         codecConfig[0] = ((profileVal + 1) << 0x03) | ((baseIndex & 0x0F) >> 0x01);
350         // 0x07: left 7bits for other, 4 bit channel cfg,0x03:left for other
351         codecConfig[1] = ((baseIndex & 0x01) << 0x07) | ((realCh & 0x0F) << 0x03) | ((sampleRateIndex & 0x0F) >> 1) ;
352         // 4 bit ext sample rate idx(0x07: left 7 bits for other) + 4 bit aot(2: LC-AAC, 0x02: left for other)
353         codecConfig[2] = ((sampleRateIndex & 0x01) << 0x07) | (2 << 0x02);
354     } else {
355         codecConfig = {0, 0, 0x56, 0xE5, 0};
356         codecConfig[0] = ((profileVal + 1) << 0x03) | ((sampleRateIndex & 0x0F) >> 0x01);
357         codecConfig[1] = ((sampleRateIndex & 0x01) << 0x07) | ((channels & 0x0F) << 0x03);
358     }
359 
360     return codecConfig;
361 }
362 
FindNaluSpliter(int size,const uint8_t * data)363 int FindNaluSpliter(int size, const uint8_t* data)
364 {
365     int naluPos = -1;
366     if (size >= 4 && data[0] == 0x00 && data[1] == 0x00) { // 4: least size
367         if (data[2] == 0x01) { // 2: next index
368             naluPos = 3; // 3: the actual start pos of nal unit
369         } else if (size >= 5 && data[2] == 0x00 && data[3] == 0x01) { // 5: least size, 2, 3: next indecies
370             naluPos = 4; // 4: the actual start pos of nal unit
371         }
372     }
373     return naluPos;
374 }
375 
CanDropAvcPkt(const AVPacket & pkt)376 bool CanDropAvcPkt(const AVPacket& pkt)
377 {
378     const uint8_t *data = pkt.data;
379     int size = pkt.size;
380     int naluPos = FindNaluSpliter(size, data);
381     if (naluPos < 0) {
382         MEDIA_LOG_D("pkt->data starts with error start code!");
383         return false;
384     }
385     int nalRefIdc = (data[naluPos] >> 5) & 0x03; // 5: get H.264 nal_ref_idc
386     int nalUnitType = data[naluPos] & 0x1f; // get H.264 nal_unit_type
387     bool isCodedSliceData = nalUnitType == 1 || nalUnitType == 2 || // 1: non-IDR, 2: partiton A
388         nalUnitType == 3 || nalUnitType == 4 || nalUnitType == 5; // 3: partiton B, 4: partiton C, 5: IDR
389     return nalRefIdc == 0 && isCodedSliceData;
390 }
391 
CanDropHevcPkt(const AVPacket & pkt)392 bool CanDropHevcPkt(const AVPacket& pkt)
393 {
394     const uint8_t *data = pkt.data;
395     int size = pkt.size;
396     int naluPos = FindNaluSpliter(size, data);
397     if (naluPos < 0) {
398         MEDIA_LOG_D("pkt->data starts with error start code!");
399         return false;
400     }
401     int nalUnitType = (data[naluPos] >> 1) & 0x3f; // get H.265 nal_unit_type
402     return nalUnitType == 0 || nalUnitType == 2 || nalUnitType == 4 || // 0: TRAIL_N, 2: TSA_N, 4: STSA_N
403         nalUnitType == 6 || nalUnitType == 8; // 6: RADL_N, 8: RASL_N
404 }
405 
SetDropTag(const AVPacket & pkt,std::shared_ptr<AVBuffer> sample,AVCodecID codecId)406 void SetDropTag(const AVPacket& pkt, std::shared_ptr<AVBuffer> sample, AVCodecID codecId)
407 {
408     sample->meta_->Remove(Media::Tag::VIDEO_BUFFER_CAN_DROP);
409     bool canDrop = false;
410     if (codecId == AV_CODEC_ID_HEVC) {
411         canDrop = CanDropHevcPkt(pkt);
412     } else if (codecId == AV_CODEC_ID_H264) {
413         canDrop = CanDropAvcPkt(pkt);
414     }
415     if (canDrop) {
416         sample->meta_->SetData(Media::Tag::VIDEO_BUFFER_CAN_DROP, true);
417     }
418 }
419 
AvTime2Us(int64_t hTime)420 int64_t AvTime2Us(int64_t hTime)
421 {
422     return hTime / AV_CODEC_USECOND;
423 }
424 
GenerateCodecConfig(const std::shared_ptr<Meta> & trackDesc)425 bool FlacCodecConfig::GenerateCodecConfig(const std::shared_ptr<Meta> &trackDesc)
426 {
427     constexpr uint32_t index10 = 10;
428     constexpr uint32_t offset4 = 4;
429     constexpr uint32_t offset12 = 12;
430     constexpr int32_t maxChannel = 8;
431     mCodecConfig.resize(FLAC_CODEC_CONFIG_SIZE, 0);
432     AudioSampleFormat sampleFormat = INVALID_WIDTH;
433     mSampleRate = 0;
434     mChannels = 0;
435     bool ret = trackDesc->Get<Tag::AUDIO_SAMPLE_FORMAT>(sampleFormat);
436     trackDesc->Get<Tag::AUDIO_SAMPLE_RATE>(mSampleRate);
437     trackDesc->Get<Tag::AUDIO_CHANNEL_COUNT>(mChannels);
438     if (!ret || !Raw2BitPerSample(sampleFormat, mBitPerSample)) {
439         MEDIA_LOG_E("not support codec_id: " PUBLIC_LOG_D32 ", ret: " PUBLIC_LOG_D32,
440             static_cast<int32_t>(sampleFormat), static_cast<int32_t>(ret));
441         return false;
442     }
443     if (mChannels < 1 || mChannels > maxChannel) {
444         MEDIA_LOG_E("not support mChannels:" PUBLIC_LOG_D32, mChannels);
445         return false;
446     }
447     uint32_t i = index10;
448     // 10 - 12
449     mCodecConfig.data()[i++] = static_cast<uint8_t>((static_cast<uint32_t>(mSampleRate) >> offset12) & 0XFF);
450     mCodecConfig.data()[i++] = static_cast<uint8_t>((static_cast<uint32_t>(mSampleRate) >> offset4) & 0XFF);
451     mCodecConfig.data()[i] = static_cast<uint8_t>((static_cast<uint32_t>(mSampleRate) << offset4) & 0XF0);
452     mCodecConfig.data()[i] |= static_cast<uint8_t>((static_cast<uint32_t>(mChannels - 1) << 1) & 0x0E);
453     mIsFirstDataFrame = true;
454     return true;
455 }
456 
Update()457 bool FlacCodecConfig::Update()
458 {
459     if (mIsUpdateExtraData) {
460         return true;
461     }
462     constexpr uint32_t index12 = 12;
463     constexpr uint32_t offset4 = 4;
464     constexpr uint32_t offset8 = 8;
465     constexpr uint32_t offset16 = 16;
466     constexpr uint32_t offset24 = 24;
467     constexpr uint32_t offset32 = 32;
468     FALSE_RETURN_V_MSG_E(mCodecConfig.size() >= FLAC_CODEC_CONFIG_SIZE, false,
469         "FlacCodecConfig::Update failed! mCodecConfig size not enough!");
470     uint32_t i = 0;
471     // block size
472     mCodecConfig.data()[i++] = static_cast<uint8_t>((mBlockSize >> offset8) & 0xff);
473     mCodecConfig.data()[i++] = static_cast<uint8_t>(mBlockSize & 0xff) ;
474     mCodecConfig.data()[i++] = mCodecConfig.data()[0];
475     mCodecConfig.data()[i++] = mCodecConfig.data()[1];
476     // min max auido frame size
477     mCodecConfig.data()[i++] |= static_cast<uint8_t>((mMinFrameSize >> offset16) & 0xff);  // 4
478     mCodecConfig.data()[i++] |= static_cast<uint8_t>((mMinFrameSize >> offset8) & 0xff);  // 5
479     mCodecConfig.data()[i++] |= static_cast<uint8_t>(mMinFrameSize & 0xff);  // 6
480     mCodecConfig.data()[i++] |= static_cast<uint8_t>((mMaxFrameSize >> offset16) & 0xff);  // 7
481     mCodecConfig.data()[i++] |= static_cast<uint8_t>((mMaxFrameSize >> offset8) & 0xff);  // 8
482     mCodecConfig.data()[i++] |= static_cast<uint8_t>(mMaxFrameSize & 0xff);  // 9
483 
484     // total sample num
485     i = index12;
486     // 12
487     mCodecConfig.data()[i++] |= static_cast<uint8_t>((static_cast<uint32_t>(mBitPerSample - 1) >> offset4) & 0x01);
488     // 13
489     mCodecConfig.data()[i] |= static_cast<uint8_t>((static_cast<uint32_t>(mBitPerSample - 1) << offset4) & 0xf0);
490     mCodecConfig.data()[i++] |= static_cast<uint8_t>((mTotalSample >> offset32) & 0x0f);  // 13
491     mCodecConfig.data()[i++] |= static_cast<uint8_t>((mTotalSample >> offset24) & 0xff);  // 14
492     mCodecConfig.data()[i++] |= static_cast<uint8_t>((mTotalSample >> offset16) & 0xff);  // 15
493     mCodecConfig.data()[i++] |= static_cast<uint8_t>((mTotalSample >> offset8) & 0xff);  // 16
494     mCodecConfig.data()[i++] |= static_cast<uint8_t>(mTotalSample & 0xff);  // 17
495     return true;
496 }
497 
UpdateNewConfig(uint8_t * data,size_t size)498 void FlacCodecConfig::UpdateNewConfig(uint8_t *data, size_t size)
499 {
500     if (size != mCodecConfig.size() || size < FLAC_CODEC_CONFIG_SIZE || data == nullptr) {
501         MEDIA_LOG_E("UpdateNewConfig failed! curSize:%{public}zu, size:%{public}zu", mCodecConfig.size(), size);
502         return;
503     }
504     constexpr uint32_t startIndex = 10;
505     constexpr uint32_t offset4 = 4;
506     constexpr uint32_t offset12 = 12;
507     int32_t tmpSampleRate = 0;
508     int32_t tmpChannels = 0;
509     uint8_t tmpBitPerSample = 0;
510     uint32_t i = startIndex;
511     // 10 - 13
512     tmpSampleRate = static_cast<int32_t>((static_cast<uint32_t>(data[i++]) << offset12));
513     tmpSampleRate += static_cast<int32_t>(static_cast<uint32_t>(data[i++]) << offset4);
514     tmpSampleRate += static_cast<int32_t>(static_cast<uint32_t>(data[i] & 0xf0) >> offset4);
515     tmpChannels = static_cast<int32_t>((static_cast<uint32_t>(data[i]) & 0x0e) >> 1);
516     tmpChannels += 1;
517     tmpBitPerSample = static_cast<uint8_t>(((static_cast<uint32_t>(data[i++]) & 0x01) << offset4));
518     tmpBitPerSample |= static_cast<uint8_t>(static_cast<uint32_t>(data[i++] & 0xf0) >> offset4);
519     tmpBitPerSample += 1;
520     if (tmpSampleRate != mSampleRate || tmpChannels != mChannels || tmpBitPerSample != mBitPerSample) {
521         MEDIA_LOG_E("flac muxer params change! SampleRate:" PUBLIC_LOG_D32 " to " PUBLIC_LOG_D32
522             " mChannels:" PUBLIC_LOG_D32 " to " PUBLIC_LOG_D32 " mBitPerSample:" PUBLIC_LOG_U8 " to " PUBLIC_LOG_U8,
523             mSampleRate, tmpSampleRate, mChannels, tmpChannels, mBitPerSample, tmpBitPerSample);
524         mSampleRate = tmpSampleRate;
525         mChannels = tmpChannels;
526         mBitPerSample = tmpBitPerSample;
527     }
528     if (memcpy_s(mCodecConfig.data(), mCodecConfig.size(), data, size) != EOK) {
529         MEDIA_LOG_E("flac UpdateNewConfig memcpy_s failed!");
530         return;
531     }
532     mIsUpdateExtraData = true;
533 }
534 
GetUtf8Bytes(uint8_t data)535 static uint32_t GetUtf8Bytes(uint8_t data)
536 {
537     constexpr uint32_t num2 = 2;
538     constexpr int32_t maxBit = 7;
539     uint32_t bytes = 0;
540     for (int32_t i = maxBit; i > 0; i--) {  // 7 - 1, 7bits
541         if ((data & static_cast<uint8_t>(1 << i)) == 0) {
542             break;
543         }
544         bytes++;
545     }
546     return bytes < num2 ? (bytes + 1) : bytes;
547 }
548 
UpdateBitPerSample(uint8_t byte)549 void FlacCodecConfig::UpdateBitPerSample(uint8_t byte)
550 {
551     static const uint8_t flacBitDepthTable[8] = {0, 8, 12, 0, 16, 20, 24, 32};
552     uint8_t index = static_cast<uint8_t>((byte >> 1) & 0x07);
553     uint8_t bitPerSample = flacBitDepthTable[index];
554     if (bitPerSample == 0 || bitPerSample == mBitPerSample || mCodecConfig.size() < FLAC_CODEC_CONFIG_SIZE) {
555         return;
556     }
557     MEDIA_LOG_I("update bit per sample from " PUBLIC_LOG_U8 " to " PUBLIC_LOG_U8, mBitPerSample, bitPerSample);
558     mBitPerSample = bitPerSample;
559 }
560 
UpdatePerFrame(uint8_t * data,size_t size)561 void FlacCodecConfig::UpdatePerFrame(uint8_t* data, size_t size)
562 {
563     constexpr size_t minSize = 16;
564     constexpr uint32_t offset4 = 4;
565     constexpr uint32_t offset8 = 8;
566     constexpr uint32_t index2 = 2;
567     constexpr uint32_t index3 = 3;
568     constexpr uint32_t index6 = 6;
569     constexpr uint32_t index7 = 7;
570     if (size < minSize || data == nullptr) {
571         return;
572     }
573     if (data[0] != 0xff || (data[1] & 0xf8) != 0xf8) {  // flac frame head
574         return;
575     }
576     uint32_t tempBlockSize = 0;
577     static const uint16_t flacBlockList[minSize] = {
578         0, 192, 576, 1152, 2304, 4608, 0, 0, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
579     };
580     uint32_t index = static_cast<uint8_t>((data[index2] >> offset4) & 0x0f);
581     if (index == index6) {
582         uint32_t offset = offset4 + GetUtf8Bytes(data[offset4]);
583         tempBlockSize = static_cast<uint32_t>(data[offset]) + 1;
584     } else if (index == index7) {
585         uint32_t offset = offset4 + GetUtf8Bytes(data[offset4]);
586         tempBlockSize = static_cast<uint32_t>(data[offset] << offset8) +
587             static_cast<uint32_t>(data[offset + 1]) + 1;
588     } else {
589         tempBlockSize = flacBlockList[index];
590     }
591     mTotalSample += tempBlockSize;
592     if (tempBlockSize > mBlockSize) {
593         mBlockSize = tempBlockSize;
594     }
595     if (mIsFirstDataFrame) {
596         mMinFrameSize = size;
597         mMaxFrameSize = size;
598         mIsFirstDataFrame = false;
599         UpdateBitPerSample(data[index3]);
600     }
601     if (size > mMaxFrameSize) {
602         mMaxFrameSize = size;
603     }
604     if (size < mMinFrameSize) {
605         mMinFrameSize = size;
606     }
607     mIsUpdateExtraData = false;
608 }
609 
hexEncode(const std::vector<uint8_t> & data)610 std::string hexEncode(const std::vector<uint8_t>& data)
611 {
612     static const char hexDigits[] = "0123456789ABCDEF";
613     std::string result;
614     result.reserve(data.size() * 2); // extend data size 2
615     for (unsigned char c : data) {
616         result.push_back(hexDigits[(c >> 4) & 0xF]); // shift right by 4
617         result.push_back(hexDigits[c & 0xF]);
618     }
619     return result;
620 }
621 } // namespace Ffmpeg
622 } // namespace Plugins
623 } // namespace Media
624 } // namespace OHOS
625