FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/codecstring.c
Date: 2026-01-03 02:55:35
Exec Total Coverage
Lines: 77 114 67.5%
Functions: 2 3 66.7%
Branches: 49 90 54.4%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2014 Martin Storsjo
3 * Copyright (c) 2018 Akamai Technologies, Inc.
4 *
5 * This file is part of FFmpeg.
6 *
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.
11 *
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.
16 *
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
20 */
21
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"
27
28 #include "av1.h"
29 #include "avc.h"
30 #include "avformat.h"
31 #include "internal.h"
32 #include "nal.h"
33 #include "vpcc.h"
34
35 static const struct codec_string {
36 enum AVCodecID id;
37 char str[8];
38 } codecs[] = {
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" },
44 { AV_CODEC_ID_NONE }
45 };
46
47 static void set_vp9_codec_str(void *logctx, const AVCodecParameters *par,
48 const AVRational *frame_rate, AVBPrint *out)
49 {
50 VPCC vpcc;
51 int ret = ff_isom_get_vpcc_features(logctx, par, NULL, 0, frame_rate, &vpcc);
52 if (ret == 0) {
53 av_bprintf(out, "vp09.%02d.%02d.%02d",
54 vpcc.profile, vpcc.level, vpcc.bitdepth);
55 } else {
56 // Default to just vp9 in case of error while finding out profile or level
57 if (logctx)
58 av_log(logctx, AV_LOG_WARNING, "Could not find VP9 profile and/or level\n");
59 av_bprintf(out, "vp9");
60 }
61 }
62
63 363 int ff_make_codec_str(void *logctx, const AVCodecParameters *par,
64 const AVRational *frame_rate, struct AVBPrint *out)
65 {
66 int i;
67
68 // common Webm codecs are not part of RFC 6381
69
2/2
✓ Branch 0 taken 1773 times.
✓ Branch 1 taken 196 times.
1969 for (i = 0; codecs[i].id != AV_CODEC_ID_NONE; i++)
70
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 1606 times.
1773 if (codecs[i].id == par->codec_id) {
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 if (codecs[i].id == AV_CODEC_ID_VP9) {
72 set_vp9_codec_str(logctx, par, frame_rate, out);
73 } else {
74 167 av_bprintf(out, "%s", codecs[i].str);
75 }
76 167 return 0;
77 }
78
79
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 177 times.
196 if (par->codec_id == AV_CODEC_ID_H264) {
80 // RFC 6381
81 19 uint8_t *data = par->extradata;
82
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (data) {
83 const uint8_t *p;
84
85
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
19 if (AV_RB32(data) == 0x01 && (data[4] & 0x1F) == 7)
86 p = &data[5];
87
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
19 else if (AV_RB24(data) == 0x01 && (data[3] & 0x1F) == 7)
88 2 p = &data[4];
89
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 else if (data[0] == 0x01) /* avcC */
90 17 p = &data[1];
91 else
92 return AVERROR(EINVAL);
93 19 av_bprintf(out, "avc1.%02x%02x%02x", p[0], p[1], p[2]);
94 } else {
95 return AVERROR(EINVAL);
96 }
97
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 155 times.
177 } else if (par->codec_id == AV_CODEC_ID_HEVC) {
98 // 3GPP TS 26.244
99 22 uint8_t *data = par->extradata;
100 22 int profile = AV_PROFILE_UNKNOWN;
101 22 uint32_t profile_compatibility = AV_PROFILE_UNKNOWN;
102 22 char tier = 0;
103 22 int level = AV_LEVEL_UNKNOWN;
104 22 char constraints[8] = "";
105
106
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (par->profile != AV_PROFILE_UNKNOWN)
107 22 profile = par->profile;
108
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (par->level != AV_LEVEL_UNKNOWN)
109 22 level = par->level;
110
111 /* check the boundary of data which from current position is small than extradata_size */
112
3/4
✓ Branch 0 taken 2218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2201 times.
✓ Branch 3 taken 17 times.
2218 while (data && (data - par->extradata + 19) < par->extradata_size) {
113 /* get HEVC SPS NAL and seek to profile_tier_level */
114
5/6
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 2096 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 100 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
2201 if (!(data[0] | data[1] | data[2]) && data[3] == 1 && ((data[4] & 0x7E) == 0x42)) {
115 uint8_t *rbsp_buf;
116 5 int remain_size = 0;
117 5 int rbsp_size = 0;
118 5 uint32_t profile_compatibility_flags = 0;
119 5 uint8_t high_nibble = 0;
120 /* skip start code + nalu header */
121 5 data += 6;
122 /* process by reference General NAL unit syntax */
123 5 remain_size = par->extradata_size - (data - par->extradata);
124 5 rbsp_buf = ff_nal_unit_extract_rbsp(data, remain_size, &rbsp_size, 0);
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!rbsp_buf)
126 return AVERROR(EINVAL);
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (rbsp_size < 13) {
128 av_freep(&rbsp_buf);
129 5 break;
130 }
131 /* skip sps_video_parameter_set_id u(4),
132 * sps_max_sub_layers_minus1 u(3),
133 * and sps_temporal_id_nesting_flag u(1)
134 *
135 * TIER represents the general_tier_flag, with 'L' indicating the flag is 0,
136 * and 'H' indicating the flag is 1
137 */
138
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 tier = (rbsp_buf[1] & 0x20) == 0 ? 'L' : 'H';
139 5 profile = rbsp_buf[1] & 0x1f;
140 /* PROFILE_COMPATIBILITY is general_profile_compatibility_flags, but in reverse bit order,
141 * in a hexadecimal representation (leading zeroes may be omitted).
142 */
143 5 profile_compatibility_flags = AV_RB32(rbsp_buf + 2);
144 /* revise these bits to get the profile compatibility value */
145 5 profile_compatibility_flags = ((profile_compatibility_flags & 0x55555555U) << 1) | ((profile_compatibility_flags >> 1) & 0x55555555U);
146 5 profile_compatibility_flags = ((profile_compatibility_flags & 0x33333333U) << 2) | ((profile_compatibility_flags >> 2) & 0x33333333U);
147 5 profile_compatibility_flags = ((profile_compatibility_flags & 0x0F0F0F0FU) << 4) | ((profile_compatibility_flags >> 4) & 0x0F0F0F0FU);
148 5 profile_compatibility_flags = ((profile_compatibility_flags & 0x00FF00FFU) << 8) | ((profile_compatibility_flags >> 8) & 0x00FF00FFU);
149 5 profile_compatibility = (profile_compatibility_flags << 16) | (profile_compatibility_flags >> 16);
150 /* skip 8 + 8 + 32
151 * CONSTRAINTS is a hexadecimal representation of the general_constraint_indicator_flags.
152 * each byte is separated by a '.', and trailing zero bytes may be omitted.
153 * drop the trailing zero bytes refer to ISO/IEC14496-15.
154 */
155 5 high_nibble = rbsp_buf[7] >> 4;
156 5 snprintf(constraints, sizeof(constraints),
157 high_nibble ? "%02x.%x" : "%02x",
158
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 rbsp_buf[6], high_nibble);
159 /* skip 8 + 8 + 32 + 4 + 43 + 1 bit */
160 5 level = rbsp_buf[12];
161 5 av_freep(&rbsp_buf);
162 5 break;
163 }
164 2196 data++;
165 }
166
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
22 if (par->codec_tag == MKTAG('h','v','c','1') &&
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 profile != AV_PROFILE_UNKNOWN &&
168 profile_compatibility != AV_PROFILE_UNKNOWN &&
169 tier != 0 &&
170 level != AV_LEVEL_UNKNOWN &&
171 constraints[0] != '\0') {
172 av_bprintf(out, "%s.%d.%x.%c%d.%s",
173 av_fourcc2str(par->codec_tag), profile,
174 profile_compatibility, tier, level, constraints);
175 } else
176 22 return AVERROR(EINVAL);
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 155 times.
155 } else if (par->codec_id == AV_CODEC_ID_AV1) {
178 // https://aomediacodec.github.io/av1-isobmff/#codecsparam
179 AV1SequenceParameters seq;
180 int err;
181 if (!par->extradata_size)
182 return AVERROR(EINVAL);
183 if ((err = ff_av1_parse_seq_header(&seq, par->extradata, par->extradata_size)) < 0)
184 return err;
185
186 av_bprintf(out, "av01.%01u.%02u%s.%02u",
187 seq.profile, seq.level, seq.tier ? "H" : "M", seq.bitdepth);
188 if (seq.color_description_present_flag)
189 av_bprintf(out, ".%01u.%01u%01u%01u.%02u.%02u.%02u.%01u",
190 seq.monochrome,
191 seq.chroma_subsampling_x, seq.chroma_subsampling_y, seq.chroma_sample_position,
192 seq.color_primaries, seq.transfer_characteristics, seq.matrix_coefficients,
193 seq.color_range);
194
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 153 times.
155 } else if (par->codec_id == AV_CODEC_ID_MPEG4) {
195 // RFC 6381
196 2 av_bprintf(out, "mp4v.20");
197 // Unimplemented, should output ProfileLevelIndication as a decimal number
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (logctx)
199 av_log(logctx, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n");
200
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 142 times.
153 } else if (par->codec_id == AV_CODEC_ID_MP2) {
201 11 av_bprintf(out, "mp4a.40.33");
202
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 140 times.
142 } else if (par->codec_id == AV_CODEC_ID_MP3) {
203 2 av_bprintf(out, "mp4a.40.34");
204
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 122 times.
140 } else if (par->codec_id == AV_CODEC_ID_AAC) {
205 // RFC 6381
206 18 int aot = 2;
207
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (par->extradata_size >= 2) {
208 18 aot = par->extradata[0] >> 3;
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (aot == 31)
210 aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32;
211 } else if (par->profile != AV_PROFILE_UNKNOWN)
212 aot = par->profile + 1;
213 18 av_bprintf(out, "mp4a.40.%d", aot);
214
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 107 times.
122 } else if (par->codec_id == AV_CODEC_ID_AC3) {
215 15 av_bprintf(out, "ac-3");
216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 } else if (par->codec_id == AV_CODEC_ID_EAC3) {
217 av_bprintf(out, "ec-3");
218 } else {
219 107 return AVERROR(EINVAL);
220 }
221 67 return 0;
222 }
223
224 352 int av_mime_codec_str(const AVCodecParameters *par,
225 AVRational frame_rate, struct AVBPrint *out)
226 {
227 352 return ff_make_codec_str(NULL, par, &frame_rate, out);
228 }
229