| 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 |