2 * Copyright (c) 2014 Martin Storsjo
3 * Copyright (c) 2018 Akamai Technologies, Inc.
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/avstring.h"
23 #include "libavutil/bprint.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/rational.h"
35 static const struct codec_string
{
39 { AV_CODEC_ID_VP8
, "vp8" },
40 { AV_CODEC_ID_VP9
, "vp9" },
41 { AV_CODEC_ID_VORBIS
, "vorbis" },
42 { AV_CODEC_ID_OPUS
, "opus" },
43 { AV_CODEC_ID_FLAC
, "flac" },
47 static void set_vp9_codec_str(void *logctx
, const AVCodecParameters
*par
,
48 const AVRational
*frame_rate
, AVBPrint
*out
)
51 int ret
= ff_isom_get_vpcc_features(logctx
, par
, NULL
, 0, frame_rate
, &vpcc
);
53 av_bprintf(out
, "vp09.%02d.%02d.%02d",
54 vpcc
.profile
, vpcc
.level
, vpcc
.bitdepth
);
56 // Default to just vp9 in case of error while finding out profile or level
57 av_log(logctx
, AV_LOG_WARNING
, "Could not find VP9 profile and/or level\n");
58 av_bprintf(out
, "vp9");
62 int ff_make_codec_str(void *logctx
, const AVCodecParameters
*par
,
63 const AVRational
*frame_rate
, struct AVBPrint
*out
)
67 // common Webm codecs are not part of RFC 6381
68 for (i
= 0; codecs
[i
].id
!= AV_CODEC_ID_NONE
; i
++)
69 if (codecs
[i
].id
== par
->codec_id
) {
70 if (codecs
[i
].id
== AV_CODEC_ID_VP9
) {
71 set_vp9_codec_str(logctx
, par
, frame_rate
, out
);
73 av_bprintf(out
, "%s", codecs
[i
].str
);
78 if (par
->codec_id
== AV_CODEC_ID_H264
) {
80 uint8_t *data
= par
->extradata
;
84 if (AV_RB32(data
) == 0x01 && (data
[4] & 0x1F) == 7)
86 else if (AV_RB24(data
) == 0x01 && (data
[3] & 0x1F) == 7)
88 else if (data
[0] == 0x01) /* avcC */
91 return AVERROR(EINVAL
);
92 av_bprintf(out
, "avc1.%02x%02x%02x", p
[0], p
[1], p
[2]);
94 return AVERROR(EINVAL
);
96 } else if (par
->codec_id
== AV_CODEC_ID_HEVC
) {
98 uint8_t *data
= par
->extradata
;
99 int profile
= AV_PROFILE_UNKNOWN
;
100 uint32_t profile_compatibility
= AV_PROFILE_UNKNOWN
;
102 int level
= AV_LEVEL_UNKNOWN
;
103 char constraints
[8] = "";
105 if (par
->profile
!= AV_PROFILE_UNKNOWN
)
106 profile
= par
->profile
;
107 if (par
->level
!= AV_LEVEL_UNKNOWN
)
110 /* check the boundary of data which from current position is small than extradata_size */
111 while (data
&& (data
- par
->extradata
+ 19) < par
->extradata_size
) {
112 /* get HEVC SPS NAL and seek to profile_tier_level */
113 if (!(data
[0] | data
[1] | data
[2]) && data
[3] == 1 && ((data
[4] & 0x7E) == 0x42)) {
117 uint32_t profile_compatibility_flags
= 0;
118 uint8_t high_nibble
= 0;
119 /* skip start code + nalu header */
121 /* process by reference General NAL unit syntax */
122 remain_size
= par
->extradata_size
- (data
- par
->extradata
);
123 rbsp_buf
= ff_nal_unit_extract_rbsp(data
, remain_size
, &rbsp_size
, 0);
125 return AVERROR(EINVAL
);
126 if (rbsp_size
< 13) {
130 /* skip sps_video_parameter_set_id u(4),
131 * sps_max_sub_layers_minus1 u(3),
132 * and sps_temporal_id_nesting_flag u(1)
134 * TIER represents the general_tier_flag, with 'L' indicating the flag is 0,
135 * and 'H' indicating the flag is 1
137 tier
= (rbsp_buf
[1] & 0x20) == 0 ? 'L' : 'H';
138 profile
= rbsp_buf
[1] & 0x1f;
139 /* PROFILE_COMPATIBILITY is general_profile_compatibility_flags, but in reverse bit order,
140 * in a hexadecimal representation (leading zeroes may be omitted).
142 profile_compatibility_flags
= AV_RB32(rbsp_buf
+ 2);
143 /* revise these bits to get the profile compatibility value */
144 profile_compatibility_flags
= ((profile_compatibility_flags
& 0x55555555U
) << 1) | ((profile_compatibility_flags
>> 1) & 0x55555555U
);
145 profile_compatibility_flags
= ((profile_compatibility_flags
& 0x33333333U
) << 2) | ((profile_compatibility_flags
>> 2) & 0x33333333U
);
146 profile_compatibility_flags
= ((profile_compatibility_flags
& 0x0F0F0F0FU
) << 4) | ((profile_compatibility_flags
>> 4) & 0x0F0F0F0FU
);
147 profile_compatibility_flags
= ((profile_compatibility_flags
& 0x00FF00FFU
) << 8) | ((profile_compatibility_flags
>> 8) & 0x00FF00FFU
);
148 profile_compatibility
= (profile_compatibility_flags
<< 16) | (profile_compatibility_flags
>> 16);
150 * CONSTRAINTS is a hexadecimal representation of the general_constraint_indicator_flags.
151 * each byte is separated by a '.', and trailing zero bytes may be omitted.
152 * drop the trailing zero bytes refer to ISO/IEC14496-15.
154 high_nibble
= rbsp_buf
[7] >> 4;
155 snprintf(constraints
, sizeof(constraints
),
156 high_nibble
? "%02x.%x" : "%02x",
157 rbsp_buf
[6], high_nibble
);
158 /* skip 8 + 8 + 32 + 4 + 43 + 1 bit */
159 level
= rbsp_buf
[12];
165 if (par
->codec_tag
== MKTAG('h','v','c','1') &&
166 profile
!= AV_PROFILE_UNKNOWN
&&
167 profile_compatibility
!= AV_PROFILE_UNKNOWN
&&
169 level
!= AV_LEVEL_UNKNOWN
&&
170 constraints
[0] != '\0') {
171 av_bprintf(out
, "%s.%d.%x.%c%d.%s",
172 av_fourcc2str(par
->codec_tag
), profile
,
173 profile_compatibility
, tier
, level
, constraints
);
175 return AVERROR(EINVAL
);
176 } else if (par
->codec_id
== AV_CODEC_ID_AV1
) {
177 // https://aomediacodec.github.io/av1-isobmff/#codecsparam
178 AV1SequenceParameters seq
;
180 if (!par
->extradata_size
)
181 return AVERROR(EINVAL
);
182 if ((err
= ff_av1_parse_seq_header(&seq
, par
->extradata
, par
->extradata_size
)) < 0)
185 av_bprintf(out
, "av01.%01u.%02u%s.%02u",
186 seq
.profile
, seq
.level
, seq
.tier
? "H" : "M", seq
.bitdepth
);
187 if (seq
.color_description_present_flag
)
188 av_bprintf(out
, ".%01u.%01u%01u%01u.%02u.%02u.%02u.%01u",
190 seq
.chroma_subsampling_x
, seq
.chroma_subsampling_y
, seq
.chroma_sample_position
,
191 seq
.color_primaries
, seq
.transfer_characteristics
, seq
.matrix_coefficients
,
193 } else if (par
->codec_id
== AV_CODEC_ID_MPEG4
) {
195 av_bprintf(out
, "mp4v.20");
196 // Unimplemented, should output ProfileLevelIndication as a decimal number
197 av_log(logctx
, AV_LOG_WARNING
, "Incomplete RFC 6381 codec string for mp4v\n");
198 } else if (par
->codec_id
== AV_CODEC_ID_MP2
) {
199 av_bprintf(out
, "mp4a.40.33");
200 } else if (par
->codec_id
== AV_CODEC_ID_MP3
) {
201 av_bprintf(out
, "mp4a.40.34");
202 } else if (par
->codec_id
== AV_CODEC_ID_AAC
) {
205 if (par
->extradata_size
>= 2) {
206 aot
= par
->extradata
[0] >> 3;
208 aot
= ((AV_RB16(par
->extradata
) >> 5) & 0x3f) + 32;
209 } else if (par
->profile
!= AV_PROFILE_UNKNOWN
)
210 aot
= par
->profile
+ 1;
211 av_bprintf(out
, "mp4a.40.%d", aot
);
212 } else if (par
->codec_id
== AV_CODEC_ID_AC3
) {
213 av_bprintf(out
, "ac-3");
214 } else if (par
->codec_id
== AV_CODEC_ID_EAC3
) {
215 av_bprintf(out
, "ec-3");
217 return AVERROR(EINVAL
);