| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * HEVC MP4 to Annex B byte stream format filter | ||
| 3 | * copyright (c) 2015 Anton Khirnov | ||
| 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 <string.h> | ||
| 23 | |||
| 24 | #include "libavutil/avassert.h" | ||
| 25 | #include "libavutil/common.h" | ||
| 26 | #include "libavutil/intreadwrite.h" | ||
| 27 | #include "libavutil/mem.h" | ||
| 28 | |||
| 29 | #include "libavcodec/bsf.h" | ||
| 30 | #include "libavcodec/bsf_internal.h" | ||
| 31 | #include "libavcodec/bytestream.h" | ||
| 32 | #include "libavcodec/defs.h" | ||
| 33 | |||
| 34 | #include "libavcodec/hevc/hevc.h" | ||
| 35 | |||
| 36 | #define MIN_HEVCC_LENGTH 23 | ||
| 37 | #define MAX_EXTRADATA_NALS 2048 | ||
| 38 | #define MAX_PS_CHAIN_DEPTH 16 | ||
| 39 | #define MAX_PS_CHECKS_PER_PACKET 128 | ||
| 40 | |||
| 41 | /* 32-bit FNV-1a hash algorithm constants */ | ||
| 42 | #define FNV1A_32_OFFSET_BASIS 2166136261u | ||
| 43 | #define FNV1A_32_PRIME 16777619u | ||
| 44 | |||
| 45 | 93 | static inline uint32_t hash_ps(const uint8_t *data, size_t size) | |
| 46 | { | ||
| 47 | 93 | uint32_t h = FNV1A_32_OFFSET_BASIS; | |
| 48 |
2/2✓ Branch 0 taken 1660 times.
✓ Branch 1 taken 93 times.
|
1753 | for (size_t i = 0; i < size; i++) { |
| 49 | 1660 | h ^= data[i]; | |
| 50 | 1660 | h *= FNV1A_32_PRIME; | |
| 51 | } | ||
| 52 | 93 | return h; | |
| 53 | } | ||
| 54 | |||
| 55 | typedef struct HEVCNALUnit { | ||
| 56 | size_t offset; | ||
| 57 | size_t size; | ||
| 58 | int type; | ||
| 59 | uint32_t hash; | ||
| 60 | int matched; | ||
| 61 | int emit; | ||
| 62 | int next; | ||
| 63 | } HEVCNALUnit; | ||
| 64 | |||
| 65 | typedef struct HEVCBSFContext { | ||
| 66 | uint8_t *extradata; | ||
| 67 | size_t extradata_size; | ||
| 68 | HEVCNALUnit *nals; | ||
| 69 | int nb_nals; | ||
| 70 | int nb_ps; | ||
| 71 | int *ps_buckets; | ||
| 72 | int ps_table_size; | ||
| 73 | uint8_t length_size; | ||
| 74 | int extradata_parsed; | ||
| 75 | int dup_ps_logged; | ||
| 76 | unsigned emitted_types; | ||
| 77 | int sps_seen; | ||
| 78 | } HEVCBSFContext; | ||
| 79 | |||
| 80 | 14 | static int hevc_extradata_to_annexb(AVBSFContext *ctx, | |
| 81 | const uint8_t *extradata, size_t extradata_size, | ||
| 82 | uint8_t **out_extradata, int *out_extradata_size) | ||
| 83 | { | ||
| 84 | 14 | HEVCBSFContext *s = ctx->priv_data; | |
| 85 | GetByteContext gb, gb_scan; | ||
| 86 | int length_size, num_arrays, i, j; | ||
| 87 | 14 | int total_nals = 0; | |
| 88 | 14 | size_t total_size = 0; | |
| 89 | 14 | int ret = 0; | |
| 90 | |||
| 91 | 14 | uint8_t *new_extradata = NULL; | |
| 92 | 14 | size_t new_extradata_size = 0; | |
| 93 | 14 | HEVCNALUnit *new_nals = NULL; | |
| 94 | 14 | int nb_nals = 0; | |
| 95 | 14 | int *ps_buckets = NULL; | |
| 96 | 14 | int ps_table_size = 0; | |
| 97 | 14 | int nb_ps = 0; | |
| 98 | |||
| 99 | /* bytestream2 and AVCodecParameters.extradata_size are both int. */ | ||
| 100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (extradata_size > INT_MAX) { |
| 101 | ✗ | av_log(ctx, AV_LOG_ERROR, "Extradata size exceeds INT_MAX\n"); | |
| 102 | ✗ | return AVERROR_INVALIDDATA; | |
| 103 | } | ||
| 104 | |||
| 105 | 14 | bytestream2_init(&gb, extradata, (int)extradata_size); | |
| 106 | |||
| 107 | 14 | bytestream2_skip(&gb, 21); | |
| 108 | 14 | length_size = (bytestream2_get_byte(&gb) & 3) + 1; | |
| 109 | 14 | num_arrays = bytestream2_get_byte(&gb); | |
| 110 | |||
| 111 | /* First pass: validate hvcC arrays and compute exact size and NAL count upfront */ | ||
| 112 | 14 | gb_scan = gb; | |
| 113 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 13 times.
|
54 | for (i = 0; i < num_arrays; i++) { |
| 114 | int type, cnt; | ||
| 115 | |||
| 116 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
|
41 | if (bytestream2_get_bytes_left(&gb_scan) < 3) { |
| 117 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 118 | ✗ | goto fail; | |
| 119 | } | ||
| 120 | 41 | type = bytestream2_get_byte(&gb_scan) & 0x3f; | |
| 121 | 41 | cnt = bytestream2_get_be16(&gb_scan); | |
| 122 | |||
| 123 |
7/10✓ Branch 0 taken 28 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
41 | if (!(type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS || |
| 124 | type == HEVC_NAL_SEI_PREFIX || type == HEVC_NAL_SEI_SUFFIX)) { | ||
| 125 | ✗ | av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n", | |
| 126 | type); | ||
| 127 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 128 | ✗ | goto fail; | |
| 129 | } | ||
| 130 | |||
| 131 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 40 times.
|
41 | if (cnt > MAX_EXTRADATA_NALS - total_nals) { |
| 132 | 1 | av_log(ctx, AV_LOG_ERROR, "Too many NAL units in extradata: exceeds %d\n", | |
| 133 | MAX_EXTRADATA_NALS); | ||
| 134 | 1 | ret = AVERROR_INVALIDDATA; | |
| 135 | 1 | goto fail; | |
| 136 | } | ||
| 137 | |||
| 138 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 40 times.
|
81 | for (j = 0; j < cnt; j++) { |
| 139 | int nalu_len; | ||
| 140 | |||
| 141 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
|
41 | if (bytestream2_get_bytes_left(&gb_scan) < 2) { |
| 142 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 143 | ✗ | goto fail; | |
| 144 | } | ||
| 145 | 41 | nalu_len = bytestream2_get_be16(&gb_scan); | |
| 146 | |||
| 147 |
2/4✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
|
82 | if (nalu_len < 2 || |
| 148 | 41 | nalu_len > bytestream2_get_bytes_left(&gb_scan) || | |
| 149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | 4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - total_size) { |
| 150 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 151 | ✗ | goto fail; | |
| 152 | } | ||
| 153 | /* Each hvcC length prefix grows into a 4-byte start code. */ | ||
| 154 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (total_size > (size_t)INT_MAX - 4 - (size_t)nalu_len) { |
| 155 | ✗ | av_log(ctx, AV_LOG_ERROR, "Annex B extradata size exceeds INT_MAX\n"); | |
| 156 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 157 | ✗ | goto fail; | |
| 158 | } | ||
| 159 | 41 | total_size += 4 + nalu_len; | |
| 160 | 41 | total_nals++; | |
| 161 | 41 | bytestream2_skip(&gb_scan, nalu_len); | |
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | /* Single allocation for exact extradata buffer and NAL descriptor array */ | ||
| 166 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (total_nals > 0) { |
| 167 | 13 | new_extradata = av_malloc(total_size + AV_INPUT_BUFFER_PADDING_SIZE); | |
| 168 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!new_extradata) { |
| 169 | ✗ | ret = AVERROR(ENOMEM); | |
| 170 | ✗ | goto fail; | |
| 171 | } | ||
| 172 | 13 | new_nals = av_malloc_array(total_nals, sizeof(*new_nals)); | |
| 173 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!new_nals) { |
| 174 | ✗ | ret = AVERROR(ENOMEM); | |
| 175 | ✗ | goto fail; | |
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | /* Second pass: copy NAL units and fill descriptor array without reallocations */ | ||
| 180 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 13 times.
|
53 | for (i = 0; i < num_arrays; i++) { |
| 181 | 40 | int type = bytestream2_get_byte(&gb) & 0x3f; | |
| 182 | 40 | int cnt = bytestream2_get_be16(&gb); | |
| 183 | |||
| 184 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 40 times.
|
81 | for (j = 0; j < cnt; j++) { |
| 185 | 41 | const int nalu_len = bytestream2_get_be16(&gb); | |
| 186 | |||
| 187 | 41 | new_nals[nb_nals].offset = new_extradata_size; | |
| 188 | 41 | new_nals[nb_nals].size = 4 + nalu_len; | |
| 189 | 41 | new_nals[nb_nals].type = type; | |
| 190 | 41 | new_nals[nb_nals].matched = 0; | |
| 191 | 41 | new_nals[nb_nals].emit = 1; | |
| 192 | 41 | new_nals[nb_nals].hash = 0; | |
| 193 | 41 | new_nals[nb_nals].next = -1; | |
| 194 | 41 | nb_nals++; | |
| 195 | |||
| 196 | 41 | AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode | |
| 197 | 41 | bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, nalu_len); | |
| 198 | 41 | new_extradata_size += 4 + nalu_len; | |
| 199 | } | ||
| 200 | } | ||
| 201 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (new_extradata) |
| 202 | 13 | memset(new_extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
| 203 | |||
| 204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!new_extradata_size) |
| 205 | ✗ | av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n"); | |
| 206 | |||
| 207 |
3/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
13 | if (out_extradata && out_extradata_size) { |
| 208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (new_extradata_size > INT_MAX) { |
| 209 | ✗ | av_log(ctx, AV_LOG_ERROR, "Annex B extradata size exceeds INT_MAX\n"); | |
| 210 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 211 | ✗ | goto fail; | |
| 212 | } | ||
| 213 | 12 | av_freep(out_extradata); | |
| 214 | 12 | *out_extradata = | |
| 215 | 12 | av_malloc(new_extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); | |
| 216 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!(*out_extradata)) { |
| 217 | ✗ | ret = AVERROR(ENOMEM); | |
| 218 | ✗ | goto fail; | |
| 219 | } | ||
| 220 | 12 | *out_extradata_size = (int)new_extradata_size; | |
| 221 | 12 | memcpy(*out_extradata, new_extradata, new_extradata_size); | |
| 222 | 12 | memset(*out_extradata + new_extradata_size, 0, | |
| 223 | AV_INPUT_BUFFER_PADDING_SIZE); | ||
| 224 | } | ||
| 225 | |||
| 226 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 13 times.
|
54 | for (i = 0; i < nb_nals; i++) { |
| 227 |
3/4✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 1 times.
|
41 | if (new_nals[i].type >= HEVC_NAL_VPS && new_nals[i].type <= HEVC_NAL_PPS) |
| 228 | 40 | nb_ps++; | |
| 229 | } | ||
| 230 | |||
| 231 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (nb_ps > 0) { |
| 232 | 13 | ps_table_size = 1 << av_ceil_log2(FFMAX(32, nb_ps * 2)); | |
| 233 | 13 | ps_buckets = av_malloc_array(ps_table_size, sizeof(*ps_buckets)); | |
| 234 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!ps_buckets) { |
| 235 | ✗ | ret = AVERROR(ENOMEM); | |
| 236 | ✗ | goto fail; | |
| 237 | } | ||
| 238 |
2/2✓ Branch 0 taken 416 times.
✓ Branch 1 taken 13 times.
|
429 | for (i = 0; i < ps_table_size; i++) |
| 239 | 416 | ps_buckets[i] = -1; | |
| 240 | |||
| 241 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 13 times.
|
54 | for (i = 0; i < nb_nals; i++) { |
| 242 | 41 | HEVCNALUnit *nal = &new_nals[i]; | |
| 243 |
3/4✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 1 times.
|
41 | if (nal->type >= HEVC_NAL_VPS && nal->type <= HEVC_NAL_PPS) { |
| 244 | 40 | nal->hash = hash_ps(new_extradata + nal->offset + 4, nal->size - 4); | |
| 245 | 40 | int bucket = nal->hash & (ps_table_size - 1); | |
| 246 | 40 | nal->next = ps_buckets[bucket]; | |
| 247 | 40 | ps_buckets[bucket] = i; | |
| 248 | } | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | 13 | av_freep(&s->nals); | |
| 253 | 13 | av_freep(&s->extradata); | |
| 254 | 13 | av_freep(&s->ps_buckets); | |
| 255 | 13 | s->extradata = new_extradata; | |
| 256 | 13 | s->extradata_size = new_extradata_size; | |
| 257 | 13 | s->nals = new_nals; | |
| 258 | 13 | s->nb_nals = nb_nals; | |
| 259 | 13 | s->nb_ps = nb_ps; | |
| 260 | 13 | s->ps_buckets = ps_buckets; | |
| 261 | 13 | s->ps_table_size = ps_table_size; | |
| 262 | 13 | s->length_size = length_size; | |
| 263 | 13 | s->extradata_parsed = 1; | |
| 264 | 13 | s->dup_ps_logged = 0; | |
| 265 | 13 | return 0; | |
| 266 | 1 | fail: | |
| 267 | 1 | av_freep(&new_extradata); | |
| 268 | 1 | av_freep(&new_nals); | |
| 269 | 1 | av_freep(&ps_buckets); | |
| 270 | 1 | return ret; | |
| 271 | } | ||
| 272 | |||
| 273 | 13 | static int hevc_mp4toannexb_init(AVBSFContext *ctx) | |
| 274 | { | ||
| 275 | int ret; | ||
| 276 | |||
| 277 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH || |
| 278 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | AV_RB24(ctx->par_in->extradata) == 1 || |
| 279 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | AV_RB32(ctx->par_in->extradata) == 1) { |
| 280 | ✗ | av_log(ctx, AV_LOG_VERBOSE, | |
| 281 | "The input looks like it is Annex B already\n"); | ||
| 282 | } else { | ||
| 283 | 13 | ret = hevc_extradata_to_annexb(ctx, | |
| 284 | 13 | ctx->par_in->extradata, | |
| 285 | 13 | ctx->par_in->extradata_size, | |
| 286 | 13 | &ctx->par_out->extradata, | |
| 287 | 13 | &ctx->par_out->extradata_size); | |
| 288 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
|
13 | if (ret < 0) |
| 289 | 1 | return ret; | |
| 290 | } | ||
| 291 | |||
| 292 | 12 | return 0; | |
| 293 | } | ||
| 294 | |||
| 295 | 231 | static void emit_extradata_type(HEVCBSFContext *s, uint8_t *dst, size_t *out_offset, int type) | |
| 296 | { | ||
| 297 | 231 | unsigned bit = 1U << (type - HEVC_NAL_VPS); | |
| 298 |
2/2✓ Branch 0 taken 166 times.
✓ Branch 1 taken 65 times.
|
231 | if (s->emitted_types & bit) |
| 299 | 166 | return; | |
| 300 | 65 | s->emitted_types |= bit; | |
| 301 | |||
| 302 |
2/2✓ Branch 0 taken 205 times.
✓ Branch 1 taken 65 times.
|
270 | for (int i = 0; i < s->nb_nals; i++) { |
| 303 | 205 | HEVCNALUnit *nal = &s->nals[i]; | |
| 304 |
4/4✓ Branch 0 taken 45 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 24 times.
|
205 | if (nal->emit && nal->type == type) { |
| 305 | 21 | memcpy(dst + *out_offset, s->extradata + nal->offset, nal->size); | |
| 306 | 21 | *out_offset += nal->size; | |
| 307 | 21 | nal->emit = 0; | |
| 308 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 14 times.
|
21 | if (type == HEVC_NAL_SPS) |
| 309 | 7 | s->sps_seen = 1; | |
| 310 | } | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | 456 | static void flush_extradata_before(HEVCBSFContext *s, uint8_t *dst, size_t *out_offset, | |
| 315 | int nalu_type, int has_irap) | ||
| 316 | { | ||
| 317 |
2/2✓ Branch 0 taken 379 times.
✓ Branch 1 taken 77 times.
|
456 | if (!has_irap) |
| 318 | 379 | return; | |
| 319 | |||
| 320 |
6/7✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 39 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 13 times.
|
77 | switch (nalu_type) { |
| 321 | ✗ | case HEVC_NAL_AUD: | |
| 322 | ✗ | break; | |
| 323 | 9 | case HEVC_NAL_VPS: | |
| 324 | 9 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_VPS); | |
| 325 | 9 | break; | |
| 326 | 10 | case HEVC_NAL_SPS: | |
| 327 | 10 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_VPS); | |
| 328 | 10 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_SPS); | |
| 329 | 10 | break; | |
| 330 | 39 | case HEVC_NAL_PPS: | |
| 331 | 39 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_VPS); | |
| 332 | 39 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_SPS); | |
| 333 | 39 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_PPS); | |
| 334 | 39 | break; | |
| 335 | 5 | case HEVC_NAL_SEI_PREFIX: | |
| 336 | 5 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_VPS); | |
| 337 | 5 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_SPS); | |
| 338 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (s->sps_seen) |
| 339 | 5 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_PPS); | |
| 340 | 5 | break; | |
| 341 | 1 | case HEVC_NAL_SEI_SUFFIX: | |
| 342 | 1 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_VPS); | |
| 343 | 1 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_SPS); | |
| 344 | 1 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_PPS); | |
| 345 | 1 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_SEI_PREFIX); | |
| 346 | 1 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_SEI_SUFFIX); | |
| 347 | 1 | break; | |
| 348 | 13 | default: | |
| 349 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (nalu_type <= HEVC_NAL_RSV_VCL31) { |
| 350 | 13 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_VPS); | |
| 351 | 13 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_SPS); | |
| 352 | 13 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_PPS); | |
| 353 | 13 | emit_extradata_type(s, dst, out_offset, HEVC_NAL_SEI_PREFIX); | |
| 354 | } | ||
| 355 | 13 | break; | |
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | 116 | static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) | |
| 360 | { | ||
| 361 | 116 | HEVCBSFContext *s = ctx->priv_data; | |
| 362 | AVPacket *in; | ||
| 363 | GetByteContext gb; | ||
| 364 | |||
| 365 | 116 | int got_irap = 0, got_ps = 0, seen_irap_ps = 0; | |
| 366 | 116 | int i, ret = 0; | |
| 367 | 116 | size_t extradata_size = 0; | |
| 368 | 116 | size_t in_annexb_size = 0; | |
| 369 | 116 | size_t extra_insert_size = 0; | |
| 370 | 116 | size_t total_out_size = 0; | |
| 371 | 116 | size_t out_offset = 0; | |
| 372 | 116 | uint8_t *extradata = NULL; | |
| 373 | |||
| 374 | 116 | ret = ff_bsf_get_packet(ctx, &in); | |
| 375 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 62 times.
|
116 | if (ret < 0) |
| 376 | 54 | return ret; | |
| 377 | |||
| 378 | extradata = | ||
| 379 | 62 | av_packet_get_side_data(in, AV_PKT_DATA_NEW_EXTRADATA, &extradata_size); | |
| 380 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
62 | if (extradata && extradata_size >= MIN_HEVCC_LENGTH && |
| 381 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | ((extradata[0] == 1) || |
| 382 | ✗ | (extradata[0] == 0 && (extradata[1] || extradata[2] > 1)))) { | |
| 383 | 1 | ret = hevc_extradata_to_annexb(ctx, extradata, extradata_size, | |
| 384 | NULL, NULL); | ||
| 385 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
| 386 | ✗ | goto fail; | |
| 387 | 1 | av_packet_side_data_remove(in->side_data, &in->side_data_elems, | |
| 388 | AV_PKT_DATA_NEW_EXTRADATA); | ||
| 389 | } | ||
| 390 | |||
| 391 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | if (!s->extradata_parsed) { |
| 392 | ✗ | av_packet_move_ref(out, in); | |
| 393 | ✗ | av_packet_free(&in); | |
| 394 | ✗ | return 0; | |
| 395 | } | ||
| 396 | |||
| 397 | 62 | bytestream2_init(&gb, in->data, in->size); | |
| 398 | |||
| 399 |
2/2✓ Branch 0 taken 188 times.
✓ Branch 1 taken 62 times.
|
250 | for (i = 0; i < s->nb_nals; i++) |
| 400 | 188 | s->nals[i].matched = 0; | |
| 401 | |||
| 402 | { | ||
| 403 | 62 | int unmatched_ps = s->nb_ps; | |
| 404 | 62 | int ps_checks = 0; | |
| 405 | 62 | int max_inband_ps_level = 0; | |
| 406 | |||
| 407 |
2/2✓ Branch 1 taken 456 times.
✓ Branch 2 taken 62 times.
|
518 | while (bytestream2_get_bytes_left(&gb)) { |
| 408 | 456 | uint32_t nalu_size = 0; | |
| 409 | int nalu_type; | ||
| 410 | |||
| 411 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 456 times.
|
456 | if (bytestream2_get_bytes_left(&gb) < s->length_size) { |
| 412 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 413 | ✗ | goto fail; | |
| 414 | } | ||
| 415 |
2/2✓ Branch 0 taken 1824 times.
✓ Branch 1 taken 456 times.
|
2280 | for (i = 0; i < s->length_size; i++) |
| 416 | 1824 | nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); | |
| 417 | |||
| 418 |
2/4✓ Branch 0 taken 456 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 456 times.
|
456 | if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) { |
| 419 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 420 | ✗ | goto fail; | |
| 421 | } | ||
| 422 | |||
| 423 | 456 | nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f; | |
| 424 | /* Prefix SEI can flush dependent extradata before later VPS/SPS. */ | ||
| 425 |
4/4✓ Branch 0 taken 455 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 450 times.
|
456 | if (!got_irap && nalu_type == HEVC_NAL_SEI_PREFIX) |
| 426 | 5 | max_inband_ps_level = HEVC_NAL_PPS - HEVC_NAL_VPS; | |
| 427 |
6/6✓ Branch 0 taken 455 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 345 times.
✓ Branch 4 taken 58 times.
✓ Branch 5 taken 52 times.
|
456 | if (!got_irap && nalu_type >= HEVC_NAL_VPS && nalu_type <= HEVC_NAL_PPS) { |
| 428 | 58 | int inband_level = nalu_type - HEVC_NAL_VPS; | |
| 429 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 5 times.
|
58 | if (inband_level < max_inband_ps_level) { |
| 430 | /* Inverted topological order (e.g. PPS before SPS). | ||
| 431 | * Earlier dependencies cannot be suppressed by this out-of-order PS. */ | ||
| 432 | } else { | ||
| 433 | 53 | max_inband_ps_level = inband_level; | |
| 434 |
3/6✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53 times.
✗ Branch 5 not taken.
|
53 | if (unmatched_ps > 0 && s->ps_buckets && |
| 435 | ps_checks < MAX_PS_CHECKS_PER_PACKET) { | ||
| 436 | uint32_t hash; | ||
| 437 | 53 | int idx, depth = 0; | |
| 438 | |||
| 439 | 53 | ps_checks++; | |
| 440 | 53 | hash = hash_ps(gb.buffer, nalu_size); | |
| 441 | 53 | idx = s->ps_buckets[hash & (s->ps_table_size - 1)]; | |
| 442 | |||
| 443 |
3/4✓ Branch 0 taken 22 times.
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
75 | while (idx >= 0 && depth++ < MAX_PS_CHAIN_DEPTH) { |
| 444 | 22 | HEVCNALUnit *nal = &s->nals[idx]; | |
| 445 |
3/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
22 | if (nal->type == nalu_type && (nal->size - 4) == nalu_size && |
| 446 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | nal->hash == hash && |
| 447 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | !memcmp(s->extradata + nal->offset + 4, gb.buffer, nalu_size)) { |
| 448 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | if (!nal->matched) { |
| 449 | 20 | nal->matched = 1; | |
| 450 | 20 | unmatched_ps--; | |
| 451 | } | ||
| 452 | } | ||
| 453 | 22 | idx = nal->next; | |
| 454 | } | ||
| 455 | } | ||
| 456 | } | ||
| 457 | } | ||
| 458 |
1/2✓ Branch 0 taken 456 times.
✗ Branch 1 not taken.
|
456 | if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size || |
| 459 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
|
456 | in_annexb_size > INT_MAX - 4 - nalu_size) { |
| 460 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 461 | ✗ | goto fail; | |
| 462 | } | ||
| 463 | 456 | in_annexb_size += 4 + nalu_size; | |
| 464 | |||
| 465 | 456 | bytestream2_skip(&gb, nalu_size); | |
| 466 |
6/6✓ Branch 0 taken 455 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 345 times.
✓ Branch 4 taken 58 times.
✓ Branch 5 taken 52 times.
|
456 | got_ps |= !got_irap && (nalu_type >= HEVC_NAL_VPS && nalu_type <= HEVC_NAL_PPS); |
| 467 |
4/4✓ Branch 0 taken 124 times.
✓ Branch 1 taken 332 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 111 times.
|
456 | got_irap |= nalu_type >= HEVC_NAL_BLA_W_LP && |
| 468 | nalu_type <= HEVC_NAL_RSV_IRAP_VCL23; | ||
| 469 | } | ||
| 470 | } | ||
| 471 |
4/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 3 times.
|
62 | seen_irap_ps = got_irap && got_ps; |
| 472 | |||
| 473 | 62 | s->emitted_types = 0; | |
| 474 | 62 | s->sps_seen = 0; | |
| 475 | |||
| 476 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 49 times.
|
62 | if (got_irap) { |
| 477 | 13 | int omitted = 0; | |
| 478 | |||
| 479 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 13 times.
|
54 | for (i = 0; i < s->nb_nals; i++) { |
| 480 | 41 | HEVCNALUnit *nal = &s->nals[i]; | |
| 481 | |||
| 482 | 41 | nal->emit = 1; | |
| 483 |
4/4✓ Branch 0 taken 32 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 12 times.
|
41 | if (seen_irap_ps && nal->matched && |
| 484 |
2/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
20 | nal->type >= HEVC_NAL_VPS && nal->type <= HEVC_NAL_PPS) { |
| 485 | 20 | nal->emit = 0; | |
| 486 | 20 | omitted++; | |
| 487 | } | ||
| 488 | |||
| 489 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 20 times.
|
41 | if (nal->emit) |
| 490 | 21 | extra_insert_size += nal->size; | |
| 491 | } | ||
| 492 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
13 | if (omitted && !s->dup_ps_logged) { |
| 493 | 8 | av_log(ctx, AV_LOG_VERBOSE, | |
| 494 | "Omitting %d extradata parameter sets already present in-band\n", | ||
| 495 | omitted); | ||
| 496 | 8 | s->dup_ps_logged = 1; | |
| 497 | } | ||
| 498 | } else { | ||
| 499 |
2/2✓ Branch 0 taken 147 times.
✓ Branch 1 taken 49 times.
|
196 | for (i = 0; i < s->nb_nals; i++) |
| 500 | 147 | s->nals[i].emit = 0; | |
| 501 | } | ||
| 502 | |||
| 503 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | if (extra_insert_size > INT_MAX - in_annexb_size) { |
| 504 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 505 | ✗ | goto fail; | |
| 506 | } | ||
| 507 | 62 | total_out_size = in_annexb_size + extra_insert_size; | |
| 508 | |||
| 509 | 62 | ret = av_new_packet(out, total_out_size); | |
| 510 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | if (ret < 0) |
| 511 | ✗ | goto fail; | |
| 512 | |||
| 513 | 62 | bytestream2_init(&gb, in->data, in->size); | |
| 514 | |||
| 515 |
2/2✓ Branch 1 taken 456 times.
✓ Branch 2 taken 62 times.
|
518 | while (bytestream2_get_bytes_left(&gb)) { |
| 516 | 456 | uint32_t nalu_size = 0; | |
| 517 | int nalu_type; | ||
| 518 | |||
| 519 |
2/2✓ Branch 0 taken 1824 times.
✓ Branch 1 taken 456 times.
|
2280 | for (i = 0; i < s->length_size; i++) |
| 520 | 1824 | nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); | |
| 521 | |||
| 522 | 456 | nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f; | |
| 523 | |||
| 524 | 456 | flush_extradata_before(s, out->data, &out_offset, nalu_type, got_irap); | |
| 525 | |||
| 526 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 446 times.
|
456 | if (nalu_type == HEVC_NAL_SPS) |
| 527 | 10 | s->sps_seen = 1; | |
| 528 | |||
| 529 | 456 | AV_WB32(out->data + out_offset, 1); | |
| 530 | 456 | out_offset += 4; | |
| 531 | 456 | bytestream2_get_buffer(&gb, out->data + out_offset, nalu_size); | |
| 532 | 456 | out_offset += nalu_size; | |
| 533 | } | ||
| 534 | |||
| 535 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 49 times.
|
62 | if (got_irap) |
| 536 | 13 | emit_extradata_type(s, out->data, &out_offset, HEVC_NAL_SEI_SUFFIX); | |
| 537 | |||
| 538 | av_assert1(out_offset == out->size); | ||
| 539 | |||
| 540 | 62 | ret = av_packet_copy_props(out, in); | |
| 541 |
1/2✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
|
62 | if (ret < 0) |
| 542 | ✗ | goto fail; | |
| 543 | |||
| 544 | 62 | fail: | |
| 545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | if (ret < 0) |
| 546 | ✗ | av_packet_unref(out); | |
| 547 | 62 | av_packet_free(&in); | |
| 548 | |||
| 549 | 62 | return ret; | |
| 550 | } | ||
| 551 | |||
| 552 | 13 | static void hevc_mp4toannexb_close(AVBSFContext *ctx) | |
| 553 | { | ||
| 554 | 13 | HEVCBSFContext *s = ctx->priv_data; | |
| 555 | 13 | av_freep(&s->nals); | |
| 556 | 13 | av_freep(&s->extradata); | |
| 557 | 13 | av_freep(&s->ps_buckets); | |
| 558 | 13 | } | |
| 559 | |||
| 560 | static const enum AVCodecID codec_ids[] = { | ||
| 561 | AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE, | ||
| 562 | }; | ||
| 563 | |||
| 564 | const FFBitStreamFilter ff_hevc_mp4toannexb_bsf = { | ||
| 565 | .p.name = "hevc_mp4toannexb", | ||
| 566 | .p.codec_ids = codec_ids, | ||
| 567 | .priv_data_size = sizeof(HEVCBSFContext), | ||
| 568 | .init = hevc_mp4toannexb_init, | ||
| 569 | .filter = hevc_mp4toannexb_filter, | ||
| 570 | .close = hevc_mp4toannexb_close, | ||
| 571 | }; | ||
| 572 |