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 }
28
29 #define AV_CODEC_TIME_BASE (static_cast<int64_t>(1))
30 #define AV_CODEC_NSECOND AV_CODEC_TIME_BASE
31 #define AV_CODEC_USECOND (static_cast<int64_t>(1000) * AV_CODEC_NSECOND)
32 #define AV_CODEC_MSECOND (static_cast<int64_t>(1000) * AV_CODEC_USECOND)
33 #define AV_CODEC_SECOND (static_cast<int64_t>(1000) * AV_CODEC_MSECOND)
34
35 namespace OHOS {
36 namespace Media {
37 namespace Plugins {
38 namespace Ffmpeg {
Mime2CodecId(const std::string & mime,AVCodecID & codecId)39 bool Mime2CodecId(const std::string &mime, AVCodecID &codecId)
40 {
41 /* MIME to AVCodecID */
42 static const std::unordered_map<std::string, AVCodecID> table = {
43 {MimeType::AUDIO_MPEG, AV_CODEC_ID_MP3},
44 {MimeType::AUDIO_AAC, AV_CODEC_ID_AAC},
45 {MimeType::AUDIO_AMR_NB, AV_CODEC_ID_AMR_NB},
46 {MimeType::AUDIO_AMR_WB, AV_CODEC_ID_AMR_WB},
47 {MimeType::AUDIO_RAW, AV_CODEC_ID_PCM_U8},
48 {MimeType::AUDIO_G711MU, AV_CODEC_ID_PCM_MULAW},
49 {MimeType::VIDEO_MPEG4, AV_CODEC_ID_MPEG4},
50 {MimeType::VIDEO_AVC, AV_CODEC_ID_H264},
51 {MimeType::VIDEO_HEVC, AV_CODEC_ID_HEVC},
52 {MimeType::IMAGE_JPG, AV_CODEC_ID_MJPEG},
53 {MimeType::IMAGE_PNG, AV_CODEC_ID_PNG},
54 {MimeType::IMAGE_BMP, AV_CODEC_ID_BMP},
55 {MimeType::TIMED_METADATA, AV_CODEC_ID_FFMETADATA},
56 };
57 auto it = table.find(mime);
58 if (it != table.end()) {
59 codecId = it->second;
60 return true;
61 }
62 return false;
63 }
64
Raw2CodecId(AudioSampleFormat sampleFormat,AVCodecID & codecId)65 bool Raw2CodecId(AudioSampleFormat sampleFormat, AVCodecID &codecId)
66 {
67 static const std::unordered_map<AudioSampleFormat, AVCodecID> table = {
68 {AudioSampleFormat::SAMPLE_U8, AV_CODEC_ID_PCM_U8},
69 {AudioSampleFormat::SAMPLE_S16LE, AV_CODEC_ID_PCM_S16LE},
70 {AudioSampleFormat::SAMPLE_S24LE, AV_CODEC_ID_PCM_S24LE},
71 {AudioSampleFormat::SAMPLE_S32LE, AV_CODEC_ID_PCM_S32LE},
72 {AudioSampleFormat::SAMPLE_F32LE, AV_CODEC_ID_PCM_F32LE},
73 };
74 auto it = table.find(sampleFormat);
75 if (it != table.end()) {
76 codecId = it->second;
77 return true;
78 }
79 return false;
80 }
81
AVStrError(int errnum)82 std::string AVStrError(int errnum)
83 {
84 char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0};
85 av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
86 return std::string(errbuf);
87 }
88
ConvertTimeFromFFmpeg(int64_t pts,AVRational base)89 int64_t ConvertTimeFromFFmpeg(int64_t pts, AVRational base)
90 {
91 int64_t out;
92 if (pts == AV_NOPTS_VALUE) {
93 out = -1;
94 } else {
95 AVRational bq = {1, AV_CODEC_SECOND};
96 out = av_rescale_q(pts, base, bq);
97 }
98 MEDIA_LOG_D("Base: [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "], time convert ["
99 PUBLIC_LOG_D64 "]->[" PUBLIC_LOG_D64 "].", base.num, base.den, pts, out);
100 return out;
101 }
102
ConvertPts(int64_t pts,int64_t startTime)103 int64_t ConvertPts(int64_t pts, int64_t startTime)
104 {
105 int64_t inputPts;
106 if (startTime >= 0 && (pts < INT64_MIN + startTime)) {
107 inputPts = AV_NOPTS_VALUE;
108 MEDIA_LOG_D("pts is anomalous, pts: " PUBLIC_LOG_D64, pts);
109 return inputPts;
110 } else if (startTime < 0 && (pts > INT64_MAX + startTime)) {
111 inputPts = AV_NOPTS_VALUE;
112 MEDIA_LOG_D("pts is anomalous, pts: " PUBLIC_LOG_D64, pts);
113 return inputPts;
114 }
115 inputPts = pts - startTime;
116
117 return inputPts;
118 }
119
ConvertTimeToFFmpeg(int64_t timestampNs,AVRational base)120 int64_t ConvertTimeToFFmpeg(int64_t timestampNs, AVRational base)
121 {
122 int64_t result;
123 if (base.num == 0) {
124 result = AV_NOPTS_VALUE;
125 } else {
126 AVRational bq = {1, AV_CODEC_SECOND};
127 result = av_rescale_q(timestampNs, bq, base);
128 }
129 MEDIA_LOG_D("Base: [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "], time convert ["
130 PUBLIC_LOG_D64 "]->[" PUBLIC_LOG_D64 "].", base.num, base.den, timestampNs, result);
131 return result;
132 }
133
ConvertTimeToFFmpegByUs(int64_t timestampUs,AVRational base)134 int64_t ConvertTimeToFFmpegByUs(int64_t timestampUs, AVRational base)
135 {
136 int64_t result;
137 if (base.num == 0) {
138 result = AV_NOPTS_VALUE;
139 } else {
140 AVRational bq = {1, AV_CODEC_MSECOND};
141 result = av_rescale_q(timestampUs, bq, base);
142 }
143 MEDIA_LOG_D("Base: [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "], time convert ["
144 PUBLIC_LOG_D64 "]->[" PUBLIC_LOG_D64 "].", base.num, base.den, timestampUs, result);
145 return result;
146 }
147
ConvertFFmpegMediaTypeToString(AVMediaType mediaType)148 std::string_view ConvertFFmpegMediaTypeToString(AVMediaType mediaType)
149 {
150 static const std::unordered_map<AVMediaType, std::string_view> table = {
151 {AVMediaType::AVMEDIA_TYPE_VIDEO, "video"},
152 {AVMediaType::AVMEDIA_TYPE_AUDIO, "audio"},
153 {AVMediaType::AVMEDIA_TYPE_DATA, "data"},
154 {AVMediaType::AVMEDIA_TYPE_SUBTITLE, "subtitle"},
155 {AVMediaType::AVMEDIA_TYPE_ATTACHMENT, "attachment"},
156 {AVMediaType::AVMEDIA_TYPE_TIMEDMETA, "timedmetadata"}
157 };
158 auto it = table.find(mediaType);
159 if (it == table.end()) {
160 return "unknow";
161 }
162 return it->second;
163 }
164
StartWith(const char * name,const char * chars)165 bool StartWith(const char* name, const char* chars)
166 {
167 MEDIA_LOG_D("[" PUBLIC_LOG_S "] start with [" PUBLIC_LOG_S "].", name, chars);
168 return !strncmp(name, chars, strlen(chars));
169 }
170
ConvertFlagsFromFFmpeg(const AVPacket & pkt,bool memoryNotEnough)171 uint32_t ConvertFlagsFromFFmpeg(const AVPacket& pkt, bool memoryNotEnough)
172 {
173 uint32_t flags = (uint32_t)(AVBufferFlag::NONE);
174 if (static_cast<uint32_t>(pkt.flags) & static_cast<uint32_t>(AV_PKT_FLAG_KEY)) {
175 flags |= (uint32_t)(AVBufferFlag::SYNC_FRAME);
176 flags |= (uint32_t)(AVBufferFlag::CODEC_DATA);
177 }
178 if (static_cast<uint32_t>(pkt.flags) & static_cast<uint32_t>(AV_PKT_FLAG_DISCARD)) {
179 flags |= (uint32_t)(AVBufferFlag::DISCARD);
180 }
181 if (memoryNotEnough) {
182 flags |= (uint32_t)(AVBufferFlag::PARTIAL_FRAME);
183 }
184 return flags;
185 }
186
CalculateTimeByFrameIndex(AVStream * avStream,int keyFrameIdx)187 int64_t CalculateTimeByFrameIndex(AVStream* avStream, int keyFrameIdx)
188 {
189 FALSE_RETURN_V_MSG_E(avStream != nullptr, 0, "Track is nullptr.");
190 #if defined(LIBAVFORMAT_VERSION_INT) && defined(AV_VERSION_INT)
191 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 78, 0) // 58 and 78 are avformat version range
192 FALSE_RETURN_V_MSG_E(avformat_index_get_entry(avStream, keyFrameIdx) != nullptr, 0, "Track is nullptr.");
193 return avformat_index_get_entry(avStream, keyFrameIdx)->timestamp;
194 #elif LIBAVFORMAT_VERSION_INT == AV_VERSION_INT(58, 76, 100) // 58, 76 and 100 are avformat version range
195 return avStream->index_entries[keyFrameIdx].timestamp;
196 #elif LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(58, 64, 100) // 58, 64 and 100 are avformat version range
197 FALSE_RETURN_V_MSG_E(avStream->internal != nullptr, 0, "Track is nullptr.");
198 return avStream->internal->index_entries[keyFrameIdx].timestamp;
199 #else
200 return avStream->index_entries[keyFrameIdx].timestamp;
201 #endif
202 #else
203 return avStream->index_entries[keyFrameIdx].timestamp;
204 #endif
205 }
206
ReplaceDelimiter(const std::string & delimiters,char newDelimiter,std::string & str)207 void ReplaceDelimiter(const std::string &delimiters, char newDelimiter, std::string &str)
208 {
209 for (char &it : str) {
210 if (delimiters.find(newDelimiter) != std::string::npos) {
211 it = newDelimiter;
212 }
213 }
214 }
215
SplitString(const char * str,char delimiter)216 std::vector<std::string> SplitString(const char* str, char delimiter)
217 {
218 std::vector<std::string> rtv;
219 if (str) {
220 SplitString(std::string(str), delimiter).swap(rtv);
221 }
222 return rtv;
223 }
224
SplitString(const std::string & str,char delimiter)225 std::vector<std::string> SplitString(const std::string& str, char delimiter)
226 {
227 if (str.empty()) {
228 return {};
229 }
230 std::vector<std::string> rtv;
231 std::string::size_type startPos = 0;
232 std::string::size_type endPos = str.find_first_of(delimiter, startPos);
233 while (startPos != endPos) {
234 rtv.emplace_back(str.substr(startPos, endPos - startPos));
235 if (endPos == std::string::npos) {
236 break;
237 }
238 startPos = endPos + 1;
239 endPos = str.find_first_of(delimiter, startPos);
240 }
241 return rtv;
242 }
243
ColorPrimary2AVColorPrimaries(ColorPrimary primary)244 std::pair<bool, AVColorPrimaries> ColorPrimary2AVColorPrimaries(ColorPrimary primary)
245 {
246 static const std::unordered_map<ColorPrimary, AVColorPrimaries> table = {
247 {ColorPrimary::BT709, AVCOL_PRI_BT709},
248 {ColorPrimary::UNSPECIFIED, AVCOL_PRI_UNSPECIFIED},
249 {ColorPrimary::BT470_M, AVCOL_PRI_BT470M},
250 {ColorPrimary::BT601_625, AVCOL_PRI_BT470BG},
251 {ColorPrimary::BT601_525, AVCOL_PRI_SMPTE170M},
252 {ColorPrimary::SMPTE_ST240, AVCOL_PRI_SMPTE240M},
253 {ColorPrimary::GENERIC_FILM, AVCOL_PRI_FILM},
254 {ColorPrimary::BT2020, AVCOL_PRI_BT2020},
255 {ColorPrimary::SMPTE_ST428, AVCOL_PRI_SMPTE428},
256 {ColorPrimary::P3DCI, AVCOL_PRI_SMPTE431},
257 {ColorPrimary::P3D65, AVCOL_PRI_SMPTE432},
258 };
259 auto it = table.find(primary);
260 if (it != table.end()) {
261 return { true, it->second };
262 }
263 return { false, AVCOL_PRI_UNSPECIFIED };
264 }
265
ColorTransfer2AVColorTransfer(TransferCharacteristic transfer)266 std::pair<bool, AVColorTransferCharacteristic> ColorTransfer2AVColorTransfer(TransferCharacteristic transfer)
267 {
268 static const std::unordered_map<TransferCharacteristic, AVColorTransferCharacteristic> table = {
269 {TransferCharacteristic::BT709, AVCOL_TRC_BT709},
270 {TransferCharacteristic::UNSPECIFIED, AVCOL_TRC_UNSPECIFIED},
271 {TransferCharacteristic::GAMMA_2_2, AVCOL_TRC_GAMMA22},
272 {TransferCharacteristic::GAMMA_2_8, AVCOL_TRC_GAMMA28},
273 {TransferCharacteristic::BT601, AVCOL_TRC_SMPTE170M},
274 {TransferCharacteristic::SMPTE_ST240, AVCOL_TRC_SMPTE240M},
275 {TransferCharacteristic::LINEAR, AVCOL_TRC_LINEAR},
276 {TransferCharacteristic::LOG, AVCOL_TRC_LOG},
277 {TransferCharacteristic::LOG_SQRT, AVCOL_TRC_LOG_SQRT},
278 {TransferCharacteristic::IEC_61966_2_4, AVCOL_TRC_IEC61966_2_4},
279 {TransferCharacteristic::BT1361, AVCOL_TRC_BT1361_ECG},
280 {TransferCharacteristic::IEC_61966_2_1, AVCOL_TRC_IEC61966_2_1},
281 {TransferCharacteristic::BT2020_10BIT, AVCOL_TRC_BT2020_10},
282 {TransferCharacteristic::BT2020_12BIT, AVCOL_TRC_BT2020_12},
283 {TransferCharacteristic::PQ, AVCOL_TRC_SMPTE2084},
284 {TransferCharacteristic::SMPTE_ST428, AVCOL_TRC_SMPTE428},
285 {TransferCharacteristic::HLG, AVCOL_TRC_ARIB_STD_B67},
286 };
287 auto it = table.find(transfer);
288 if (it != table.end()) {
289 return { true, it->second };
290 }
291 return { false, AVCOL_TRC_UNSPECIFIED };
292 }
293
ColorMatrix2AVColorSpace(MatrixCoefficient matrix)294 std::pair<bool, AVColorSpace> ColorMatrix2AVColorSpace(MatrixCoefficient matrix)
295 {
296 static const std::unordered_map<MatrixCoefficient, AVColorSpace> table = {
297 {MatrixCoefficient::IDENTITY, AVCOL_SPC_RGB},
298 {MatrixCoefficient::BT709, AVCOL_SPC_BT709},
299 {MatrixCoefficient::UNSPECIFIED, AVCOL_SPC_UNSPECIFIED},
300 {MatrixCoefficient::FCC, AVCOL_SPC_FCC},
301 {MatrixCoefficient::BT601_625, AVCOL_SPC_BT470BG},
302 {MatrixCoefficient::BT601_525, AVCOL_SPC_SMPTE170M},
303 {MatrixCoefficient::SMPTE_ST240, AVCOL_SPC_SMPTE240M},
304 {MatrixCoefficient::YCGCO, AVCOL_SPC_YCGCO},
305 {MatrixCoefficient::BT2020_NCL, AVCOL_SPC_BT2020_NCL},
306 {MatrixCoefficient::BT2020_CL, AVCOL_SPC_BT2020_CL},
307 {MatrixCoefficient::SMPTE_ST2085, AVCOL_SPC_SMPTE2085},
308 {MatrixCoefficient::CHROMATICITY_NCL, AVCOL_SPC_CHROMA_DERIVED_NCL},
309 {MatrixCoefficient::CHROMATICITY_CL, AVCOL_SPC_CHROMA_DERIVED_CL},
310 {MatrixCoefficient::ICTCP, AVCOL_SPC_ICTCP},
311 };
312 auto it = table.find(matrix);
313 if (it != table.end()) {
314 return { true, it->second };
315 }
316 return { false, AVCOL_SPC_UNSPECIFIED };
317 }
318
GenerateAACCodecConfig(int32_t profile,int32_t sampleRate,int32_t channels)319 std::vector<uint8_t> GenerateAACCodecConfig(int32_t profile, int32_t sampleRate, int32_t channels)
320 {
321 const std::unordered_map<AACProfile, int32_t> profiles = {
322 {AAC_PROFILE_LC, 1},
323 {AAC_PROFILE_ELD, 38},
324 {AAC_PROFILE_ERLC, 1},
325 {AAC_PROFILE_HE, 4},
326 {AAC_PROFILE_HE_V2, 28},
327 {AAC_PROFILE_LD, 22},
328 {AAC_PROFILE_MAIN, 0},
329 };
330 const std::unordered_map<int32_t, int32_t> sampleRates = {
331 {96000, 0}, {88200, 1}, {64000, 2}, {48000, 3},
332 {44100, 4}, {32000, 5}, {24000, 6}, {22050, 7},
333 {16000, 8}, {12000, 9}, {11025, 10}, {8000, 11},
334 {7350, 12},
335 };
336 int32_t profileVal = FF_PROFILE_AAC_LOW;
337 auto it1 = profiles.find(static_cast<AACProfile>(profile));
338 if (it1 != profiles.end()) {
339 profileVal = it1->second;
340 }
341 int32_t sampleRateIndex = 0x10;
342 auto it2 = sampleRates.find(sampleRate);
343 if (it2 != sampleRates.end()) {
344 sampleRateIndex = it2->second;
345 }
346 std::vector<uint8_t> codecConfig = {0, 0, 0x56, 0xE5, 0};
347 codecConfig[0] = ((profileVal + 1) << 0x03) | ((sampleRateIndex & 0x0F) >> 0x01);
348 codecConfig[1] = ((sampleRateIndex & 0x01) << 0x07) | ((channels & 0x0F) << 0x03);
349 return codecConfig;
350 }
351
FfmpegLogPrint(void * avcl,int level,const char * fmt,va_list vl)352 void FfmpegLogPrint(void* avcl, int level, const char* fmt, va_list vl)
353 {
354 (void)avcl;
355 char buf[500] = {0}; // 500
356 int ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf), fmt, vl);
357 if (ret < 0) {
358 return;
359 }
360 switch (level) {
361 case AV_LOG_WARNING:
362 MEDIA_LOG_D("[FFmpeg Log " PUBLIC_LOG_D32 " WARN] " PUBLIC_LOG_S, level, buf);
363 break;
364 case AV_LOG_ERROR:
365 MEDIA_LOG_D("[FFmpeg Log " PUBLIC_LOG_D32 " ERROR] " PUBLIC_LOG_S, level, buf);
366 break;
367 case AV_LOG_FATAL:
368 MEDIA_LOG_D("[FFmpeg Log " PUBLIC_LOG_D32 " FATAL] " PUBLIC_LOG_S, level, buf);
369 break;
370 case AV_LOG_INFO:
371 MEDIA_LOG_D("[FFmpeg Log " PUBLIC_LOG_D32 " INFO] " PUBLIC_LOG_S, level, buf);
372 break;
373 case AV_LOG_DEBUG:
374 MEDIA_LOG_D("[FFmpeg Log " PUBLIC_LOG_D32 " DEBUG] " PUBLIC_LOG_S, level, buf);
375 break;
376 default:
377 break;
378 }
379 }
380
FindNaluSpliter(int size,const uint8_t * data)381 int FindNaluSpliter(int size, const uint8_t* data)
382 {
383 int naluPos = -1;
384 if (size >= 4 && data[0] == 0x00 && data[1] == 0x00) { // 4: least size
385 if (data[2] == 0x01) { // 2: next index
386 naluPos = 3; // 3: the actual start pos of nal unit
387 } else if (size >= 5 && data[2] == 0x00 && data[3] == 0x01) { // 5: least size, 2, 3: next indecies
388 naluPos = 4; // 4: the actual start pos of nal unit
389 }
390 }
391 return naluPos;
392 }
393
CanDropAvcPkt(const AVPacket & pkt)394 bool CanDropAvcPkt(const AVPacket& pkt)
395 {
396 const uint8_t *data = pkt.data;
397 int size = pkt.size;
398 int naluPos = FindNaluSpliter(size, data);
399 if (naluPos < 0) {
400 MEDIA_LOG_D("pkt->data starts with error start code!");
401 return false;
402 }
403 int nalRefIdc = (data[naluPos] >> 5) & 0x03; // 5: get H.264 nal_ref_idc
404 int nalUnitType = data[naluPos] & 0x1f; // get H.264 nal_unit_type
405 bool isCodedSliceData = nalUnitType == 1 || nalUnitType == 2 || // 1: non-IDR, 2: partiton A
406 nalUnitType == 3 || nalUnitType == 4 || nalUnitType == 5; // 3: partiton B, 4: partiton C, 5: IDR
407 return nalRefIdc == 0 && isCodedSliceData;
408 }
409
CanDropHevcPkt(const AVPacket & pkt)410 bool CanDropHevcPkt(const AVPacket& pkt)
411 {
412 const uint8_t *data = pkt.data;
413 int size = pkt.size;
414 int naluPos = FindNaluSpliter(size, data);
415 if (naluPos < 0) {
416 MEDIA_LOG_D("pkt->data starts with error start code!");
417 return false;
418 }
419 int nalUnitType = (data[naluPos] >> 1) & 0x3f; // get H.265 nal_unit_type
420 return nalUnitType == 0 || nalUnitType == 2 || nalUnitType == 4 || // 0: TRAIL_N, 2: TSA_N, 4: STSA_N
421 nalUnitType == 6 || nalUnitType == 8; // 6: RADL_N, 8: RASL_N
422 }
423
SetDropTag(const AVPacket & pkt,std::shared_ptr<AVBuffer> sample,AVCodecID codecId)424 void SetDropTag(const AVPacket& pkt, std::shared_ptr<AVBuffer> sample, AVCodecID codecId)
425 {
426 sample->meta_->Remove(Media::Tag::VIDEO_BUFFER_CAN_DROP);
427 bool canDrop = false;
428 if (codecId == AV_CODEC_ID_HEVC) {
429 canDrop = CanDropHevcPkt(pkt);
430 } else if (codecId == AV_CODEC_ID_H264) {
431 canDrop = CanDropAvcPkt(pkt);
432 }
433 if (canDrop) {
434 sample->meta_->SetData(Media::Tag::VIDEO_BUFFER_CAN_DROP, true);
435 }
436 }
437
IsInputFormatSupported(const char * name)438 bool IsInputFormatSupported(const char* name)
439 {
440 MEDIA_LOG_D("Check support " PUBLIC_LOG_S " or not.", name);
441 if (!strcmp(name, "audio_device") || StartWith(name, "image") ||
442 !strcmp(name, "mjpeg") || !strcmp(name, "redir") || StartWith(name, "u8") ||
443 StartWith(name, "u16") || StartWith(name, "u24") ||
444 StartWith(name, "u32") ||
445 StartWith(name, "s8") || StartWith(name, "s16") ||
446 StartWith(name, "s24") ||
447 StartWith(name, "s32") || StartWith(name, "f32") ||
448 StartWith(name, "f64") ||
449 !strcmp(name, "mulaw") || !strcmp(name, "alaw")) {
450 return false;
451 }
452 if (!strcmp(name, "sdp") || !strcmp(name, "rtsp") || !strcmp(name, "applehttp")) {
453 return false;
454 }
455 return true;
456 }
457
AvTime2Us(int64_t hTime)458 int64_t AvTime2Us(int64_t hTime)
459 {
460 return hTime / AV_CODEC_USECOND;
461 }
462 } // namespace Ffmpeg
463 } // namespace Plugins
464 } // namespace Media
465 } // namespace OHOS
466