| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * H.264 MP4 to Annex B byte stream format filter | ||
| 3 | * Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> | ||
| 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/intreadwrite.h" | ||
| 26 | #include "libavutil/mem.h" | ||
| 27 | |||
| 28 | #include "bsf.h" | ||
| 29 | #include "bsf_internal.h" | ||
| 30 | #include "bytestream.h" | ||
| 31 | #include "defs.h" | ||
| 32 | #include "h264.h" | ||
| 33 | #include "sei.h" | ||
| 34 | |||
| 35 | typedef struct H264BSFContext { | ||
| 36 | uint8_t *sps; | ||
| 37 | uint8_t *pps; | ||
| 38 | int sps_size; | ||
| 39 | int pps_size; | ||
| 40 | unsigned sps_buf_size; | ||
| 41 | unsigned pps_buf_size; | ||
| 42 | uint8_t length_size; | ||
| 43 | uint8_t new_idr; | ||
| 44 | uint8_t idr_sps_seen; | ||
| 45 | uint8_t idr_pps_seen; | ||
| 46 | int extradata_parsed; | ||
| 47 | } H264BSFContext; | ||
| 48 | |||
| 49 | enum PsSource { | ||
| 50 | PS_OUT_OF_BAND = -1, | ||
| 51 | PS_NONE = 0, | ||
| 52 | PS_IN_BAND = 1, | ||
| 53 | }; | ||
| 54 | |||
| 55 | 3618 | static void count_or_copy(uint8_t **out, uint64_t *out_size, | |
| 56 | const uint8_t *in, int in_size, enum PsSource ps, int copy) | ||
| 57 | { | ||
| 58 | uint8_t start_code_size; | ||
| 59 | |||
| 60 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 3510 times.
|
3618 | if (ps == PS_OUT_OF_BAND) |
| 61 | /* start code already present in out-of-band ps data, so don't need to | ||
| 62 | * add it manually again | ||
| 63 | */ | ||
| 64 | 108 | start_code_size = 0; | |
| 65 |
4/4✓ Branch 0 taken 3506 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 820 times.
✓ Branch 3 taken 2686 times.
|
3510 | else if (ps == PS_IN_BAND || *out_size == 0) |
| 66 | 824 | start_code_size = 4; | |
| 67 | else | ||
| 68 | 2686 | start_code_size = 3; | |
| 69 | |||
| 70 |
2/2✓ Branch 0 taken 1809 times.
✓ Branch 1 taken 1809 times.
|
3618 | if (copy) { |
| 71 | 1809 | memcpy(*out + start_code_size, in, in_size); | |
| 72 |
2/2✓ Branch 0 taken 412 times.
✓ Branch 1 taken 1397 times.
|
1809 | if (start_code_size == 4) { |
| 73 | 412 | AV_WB32(*out, 1); | |
| 74 |
2/2✓ Branch 0 taken 1343 times.
✓ Branch 1 taken 54 times.
|
1397 | } else if (start_code_size) { |
| 75 | 1343 | (*out)[0] = | |
| 76 | 1343 | (*out)[1] = 0; | |
| 77 | 1343 | (*out)[2] = 1; | |
| 78 | } | ||
| 79 | 1809 | *out += start_code_size + in_size; | |
| 80 | } | ||
| 81 | 3618 | *out_size += start_code_size + in_size; | |
| 82 | 3618 | } | |
| 83 | |||
| 84 | 8 | static int h264_extradata_to_annexb(AVBSFContext *ctx, | |
| 85 | uint8_t *extradata, int extradata_size) | ||
| 86 | { | ||
| 87 | 8 | H264BSFContext *s = ctx->priv_data; | |
| 88 | 8 | GetByteContext ogb, *gb = &ogb; | |
| 89 | uint16_t unit_size; | ||
| 90 | 8 | uint32_t total_size = 0; | |
| 91 | 8 | uint8_t *out = NULL, unit_nb, sps_done = 0; | |
| 92 | static const uint8_t nalu_header[4] = { 0, 0, 0, 1 }; | ||
| 93 | 8 | const int padding = AV_INPUT_BUFFER_PADDING_SIZE; | |
| 94 | 8 | int length_size, pps_offset = 0; | |
| 95 | |||
| 96 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (extradata_size < 7) { |
| 97 | ✗ | av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extradata_size); | |
| 98 | ✗ | return AVERROR_INVALIDDATA; | |
| 99 | } | ||
| 100 | |||
| 101 | 8 | bytestream2_init(gb, extradata, extradata_size); | |
| 102 | |||
| 103 | 8 | bytestream2_skipu(gb, 4); | |
| 104 | |||
| 105 | /* retrieve length coded size */ | ||
| 106 | 8 | length_size = (bytestream2_get_byteu(gb) & 0x3) + 1; | |
| 107 | |||
| 108 | /* retrieve sps and pps unit(s) */ | ||
| 109 | 8 | unit_nb = bytestream2_get_byteu(gb) & 0x1f; /* number of sps unit(s) */ | |
| 110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!unit_nb) { |
| 111 | ✗ | goto pps; | |
| 112 | } | ||
| 113 | |||
| 114 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
|
24 | while (unit_nb--) { |
| 115 | int err; | ||
| 116 | |||
| 117 | /* possible overread ok due to padding */ | ||
| 118 | 16 | unit_size = bytestream2_get_be16u(gb); | |
| 119 | 16 | total_size += unit_size + 4; | |
| 120 | av_assert1(total_size <= INT_MAX - padding); | ||
| 121 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | if (bytestream2_get_bytes_left(gb) < unit_size + !sps_done) { |
| 122 | ✗ | av_log(ctx, AV_LOG_ERROR, "Global extradata truncated, " | |
| 123 | "corrupted stream or invalid MP4/AVCC bitstream\n"); | ||
| 124 | ✗ | av_free(out); | |
| 125 | ✗ | return AVERROR_INVALIDDATA; | |
| 126 | } | ||
| 127 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | if ((err = av_reallocp(&out, total_size + padding)) < 0) |
| 128 | ✗ | return err; | |
| 129 | 16 | memcpy(out + total_size - unit_size - 4, nalu_header, 4); | |
| 130 | 16 | bytestream2_get_bufferu(gb, out + total_size - unit_size, unit_size); | |
| 131 | 16 | pps: | |
| 132 |
3/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
|
16 | if (!unit_nb && !sps_done++) { |
| 133 | 8 | unit_nb = bytestream2_get_byteu(gb); /* number of pps unit(s) */ | |
| 134 | 8 | pps_offset = total_size; | |
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (out) |
| 139 | 8 | memset(out + total_size, 0, padding); | |
| 140 | |||
| 141 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (pps_offset) { |
| 142 | uint8_t *sps; | ||
| 143 | |||
| 144 | 8 | s->sps_size = pps_offset; | |
| 145 | 8 | sps = av_fast_realloc(s->sps, &s->sps_buf_size, s->sps_size); | |
| 146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!sps) { |
| 147 | ✗ | av_free(out); | |
| 148 | ✗ | return AVERROR(ENOMEM); | |
| 149 | } | ||
| 150 | 8 | s->sps = sps; | |
| 151 | 8 | memcpy(s->sps, out, s->sps_size); | |
| 152 | } else { | ||
| 153 | ✗ | av_log(ctx, AV_LOG_WARNING, | |
| 154 | "Warning: SPS NALU missing or invalid. " | ||
| 155 | "The resulting stream may not play.\n"); | ||
| 156 | } | ||
| 157 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (pps_offset < total_size) { |
| 158 | uint8_t *pps; | ||
| 159 | |||
| 160 | 8 | s->pps_size = total_size - pps_offset; | |
| 161 | 8 | pps = av_fast_realloc(s->pps, &s->pps_buf_size, s->pps_size); | |
| 162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!pps) { |
| 163 | ✗ | av_freep(&s->sps); | |
| 164 | ✗ | av_free(out); | |
| 165 | ✗ | return AVERROR(ENOMEM); | |
| 166 | } | ||
| 167 | 8 | s->pps = pps; | |
| 168 | 8 | memcpy(s->pps, out + pps_offset, s->pps_size); | |
| 169 | } else { | ||
| 170 | ✗ | av_log(ctx, AV_LOG_WARNING, | |
| 171 | "Warning: PPS NALU missing or invalid. " | ||
| 172 | "The resulting stream may not play.\n"); | ||
| 173 | } | ||
| 174 | |||
| 175 | 8 | av_freep(&ctx->par_out->extradata); | |
| 176 | 8 | ctx->par_out->extradata = out; | |
| 177 | 8 | ctx->par_out->extradata_size = total_size; | |
| 178 | |||
| 179 | 8 | s->length_size = length_size; | |
| 180 | 8 | s->new_idr = 1; | |
| 181 | 8 | s->idr_sps_seen = 0; | |
| 182 | 8 | s->idr_pps_seen = 0; | |
| 183 | 8 | s->extradata_parsed = 1; | |
| 184 | |||
| 185 | 8 | return 0; | |
| 186 | } | ||
| 187 | |||
| 188 | 2 | static int h264_mp4toannexb_save_ps(uint8_t **dst, int *dst_size, | |
| 189 | unsigned *dst_buf_size, | ||
| 190 | const uint8_t *nal, uint32_t nal_size, | ||
| 191 | int first) | ||
| 192 | { | ||
| 193 | static const uint8_t nalu_header[4] = { 0, 0, 0, 1 }; | ||
| 194 | 2 | const int start_code_size = sizeof(nalu_header); | |
| 195 | uint8_t *ptr; | ||
| 196 | uint32_t size; | ||
| 197 | |||
| 198 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (first) |
| 199 | 2 | size = 0; | |
| 200 | else | ||
| 201 | ✗ | size = *dst_size; | |
| 202 | |||
| 203 | 2 | ptr = av_fast_realloc(*dst, dst_buf_size, size + nal_size + start_code_size); | |
| 204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!ptr) |
| 205 | ✗ | return AVERROR(ENOMEM); | |
| 206 | |||
| 207 | 2 | memcpy(ptr + size, nalu_header, start_code_size); | |
| 208 | 2 | size += start_code_size; | |
| 209 | 2 | memcpy(ptr + size, nal, nal_size); | |
| 210 | 2 | size += nal_size; | |
| 211 | |||
| 212 | 2 | *dst = ptr; | |
| 213 | 2 | *dst_size = size; | |
| 214 | 2 | return 0; | |
| 215 | } | ||
| 216 | |||
| 217 | 412 | static int h264_mp4toannexb_filter_ps(H264BSFContext *s, | |
| 218 | const uint8_t *buf, | ||
| 219 | const uint8_t *buf_end) | ||
| 220 | { | ||
| 221 | 412 | int sps_count = 0; | |
| 222 | 412 | int pps_count = 0; | |
| 223 | uint8_t unit_type; | ||
| 224 | |||
| 225 | do { | ||
| 226 | 1760 | uint32_t nal_size = 0; | |
| 227 | |||
| 228 | /* possible overread ok due to padding */ | ||
| 229 |
2/2✓ Branch 0 taken 7040 times.
✓ Branch 1 taken 1760 times.
|
8800 | for (int i = 0; i < s->length_size; i++) |
| 230 | 7040 | nal_size = (nal_size << 8) | buf[i]; | |
| 231 | |||
| 232 | 1760 | buf += s->length_size; | |
| 233 | |||
| 234 | /* This check requires the cast as the right side might | ||
| 235 | * otherwise be promoted to an unsigned value. */ | ||
| 236 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1759 times.
|
1760 | if ((int64_t)nal_size > buf_end - buf) |
| 237 | 1 | return AVERROR_INVALIDDATA; | |
| 238 | |||
| 239 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1759 times.
|
1759 | if (!nal_size) |
| 240 | ✗ | continue; | |
| 241 | |||
| 242 | 1759 | unit_type = *buf & 0x1f; | |
| 243 | |||
| 244 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1758 times.
|
1759 | if (unit_type == H264_NAL_SPS) { |
| 245 | 1 | h264_mp4toannexb_save_ps(&s->sps, &s->sps_size, &s->sps_buf_size, buf, | |
| 246 | nal_size, !sps_count); | ||
| 247 | 1 | sps_count++; | |
| 248 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1757 times.
|
1758 | } else if (unit_type == H264_NAL_PPS) { |
| 249 | 1 | h264_mp4toannexb_save_ps(&s->pps, &s->pps_size, &s->pps_buf_size, buf, | |
| 250 | nal_size, !pps_count); | ||
| 251 | 1 | pps_count++; | |
| 252 | } | ||
| 253 | |||
| 254 | 1759 | buf += nal_size; | |
| 255 |
2/2✓ Branch 0 taken 1348 times.
✓ Branch 1 taken 411 times.
|
1759 | } while (buf < buf_end); |
| 256 | |||
| 257 | 411 | return 0; | |
| 258 | } | ||
| 259 | |||
| 260 | 7 | static int h264_mp4toannexb_init(AVBSFContext *ctx) | |
| 261 | { | ||
| 262 | 7 | int extra_size = ctx->par_in->extradata_size; | |
| 263 | |||
| 264 | /* retrieve sps and pps NAL units from extradata */ | ||
| 265 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | if (!extra_size || |
| 266 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | (extra_size >= 3 && AV_RB24(ctx->par_in->extradata) == 1) || |
| 267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | (extra_size >= 4 && AV_RB32(ctx->par_in->extradata) == 1)) { |
| 268 | ✗ | av_log(ctx, AV_LOG_VERBOSE, | |
| 269 | "The input looks like it is Annex B already\n"); | ||
| 270 | ✗ | return 0; | |
| 271 | } | ||
| 272 | 7 | return h264_extradata_to_annexb(ctx, | |
| 273 | 7 | ctx->par_in->extradata, | |
| 274 | 7 | ctx->par_in->extradata_size); | |
| 275 | } | ||
| 276 | |||
| 277 | 831 | static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt) | |
| 278 | { | ||
| 279 | 831 | H264BSFContext *s = ctx->priv_data; | |
| 280 | AVPacket *in; | ||
| 281 | uint8_t unit_type, new_idr, sps_seen, pps_seen; | ||
| 282 | const uint8_t *buf; | ||
| 283 | const uint8_t *buf_end; | ||
| 284 | uint8_t *out; | ||
| 285 | uint64_t out_size; | ||
| 286 | int ret; | ||
| 287 | size_t extradata_size; | ||
| 288 | uint8_t *extradata; | ||
| 289 | |||
| 290 | 831 | ret = ff_bsf_get_packet(ctx, &in); | |
| 291 |
2/2✓ Branch 0 taken 419 times.
✓ Branch 1 taken 412 times.
|
831 | if (ret < 0) |
| 292 | 419 | return ret; | |
| 293 | |||
| 294 | 412 | extradata = av_packet_get_side_data(in, AV_PKT_DATA_NEW_EXTRADATA, | |
| 295 | &extradata_size); | ||
| 296 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 411 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
412 | if (extradata && extradata[0] == 1) { |
| 297 | 1 | ret = h264_extradata_to_annexb(ctx, extradata, extradata_size); | |
| 298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
| 299 | ✗ | goto fail; | |
| 300 | 1 | av_packet_side_data_remove(in->side_data, &in->side_data_elems, | |
| 301 | AV_PKT_DATA_NEW_EXTRADATA); | ||
| 302 | } | ||
| 303 | |||
| 304 | /* nothing to filter */ | ||
| 305 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 412 times.
|
412 | if (!s->extradata_parsed) { |
| 306 | ✗ | av_packet_move_ref(opkt, in); | |
| 307 | ✗ | av_packet_free(&in); | |
| 308 | ✗ | return 0; | |
| 309 | } | ||
| 310 | |||
| 311 | 412 | buf_end = in->data + in->size; | |
| 312 | 412 | ret = h264_mp4toannexb_filter_ps(s, in->data, buf_end); | |
| 313 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 411 times.
|
412 | if (ret < 0) |
| 314 | 1 | goto fail; | |
| 315 | |||
| 316 | #define LOG_ONCE(...) \ | ||
| 317 | if (j) \ | ||
| 318 | av_log(__VA_ARGS__) | ||
| 319 |
2/2✓ Branch 0 taken 822 times.
✓ Branch 1 taken 411 times.
|
1233 | for (int j = 0; j < 2; j++) { |
| 320 | 822 | buf = in->data; | |
| 321 | 822 | new_idr = s->new_idr; | |
| 322 | 822 | sps_seen = s->idr_sps_seen; | |
| 323 | 822 | pps_seen = s->idr_pps_seen; | |
| 324 | 822 | out_size = 0; | |
| 325 | |||
| 326 | do { | ||
| 327 | 3510 | uint32_t nal_size = 0; | |
| 328 | enum PsSource ps; | ||
| 329 | |||
| 330 | /* possible overread ok due to padding */ | ||
| 331 |
2/2✓ Branch 0 taken 14040 times.
✓ Branch 1 taken 3510 times.
|
17550 | for (int i = 0; i < s->length_size; i++) |
| 332 | 14040 | nal_size = (nal_size << 8) | buf[i]; | |
| 333 | |||
| 334 | 3510 | buf += s->length_size; | |
| 335 | |||
| 336 | /* This check requires the cast as the right side might | ||
| 337 | * otherwise be promoted to an unsigned value. */ | ||
| 338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3510 times.
|
3510 | if ((int64_t)nal_size > buf_end - buf) { |
| 339 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 340 | ✗ | goto fail; | |
| 341 | } | ||
| 342 | |||
| 343 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3510 times.
|
3510 | if (!nal_size) |
| 344 | ✗ | continue; | |
| 345 | |||
| 346 | 3510 | unit_type = *buf & 0x1f; | |
| 347 | |||
| 348 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3508 times.
|
3510 | if (unit_type == H264_NAL_SPS) { |
| 349 | 2 | sps_seen = new_idr = 1; | |
| 350 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3506 times.
|
3508 | } else if (unit_type == H264_NAL_PPS) { |
| 351 | 2 | pps_seen = new_idr = 1; | |
| 352 | /* if SPS has not been seen yet, prepend the AVCC one to PPS */ | ||
| 353 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!sps_seen) { |
| 354 | ✗ | if (!s->sps_size) { | |
| 355 | ✗ | LOG_ONCE(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n"); | |
| 356 | } else { | ||
| 357 | ✗ | count_or_copy(&out, &out_size, s->sps, s->sps_size, PS_OUT_OF_BAND, j); | |
| 358 | ✗ | sps_seen = 1; | |
| 359 | } | ||
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | /* If this is a new IDR picture following an IDR picture, reset the idr flag. | ||
| 364 | * Just check first_mb_in_slice to be 0 as this is the simplest solution. | ||
| 365 | * This could be checking idr_pic_id instead, but would complexify the parsing. */ | ||
| 366 |
5/6✓ Branch 0 taken 70 times.
✓ Branch 1 taken 3440 times.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 56 times.
|
3510 | if (!new_idr && unit_type == H264_NAL_IDR_SLICE && (buf[1] & 0x80)) |
| 367 | ✗ | new_idr = 1; | |
| 368 | |||
| 369 | /* If this is a buffering period SEI without a corresponding sps/pps | ||
| 370 | * then prepend any existing sps/pps before the SEI */ | ||
| 371 |
5/6✓ Branch 0 taken 864 times.
✓ Branch 1 taken 2646 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 824 times.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
|
3510 | if (unit_type == H264_NAL_SEI && buf[1] == SEI_TYPE_BUFFERING_PERIOD && |
| 372 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | !sps_seen && !pps_seen) { |
| 373 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | if (s->sps_size) { |
| 374 | 40 | count_or_copy(&out, &out_size, s->sps, s->sps_size, PS_OUT_OF_BAND, j); | |
| 375 | 40 | sps_seen = 1; | |
| 376 | } | ||
| 377 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | if (s->pps_size) { |
| 378 | 40 | count_or_copy(&out, &out_size, s->pps, s->pps_size, PS_OUT_OF_BAND, j); | |
| 379 | 40 | pps_seen = 1; | |
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */ | ||
| 384 |
7/8✓ Branch 0 taken 3440 times.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 3356 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 70 times.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
|
3510 | if (new_idr && unit_type == H264_NAL_IDR_SLICE && !sps_seen && !pps_seen) { |
| 385 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | if (s->sps_size) |
| 386 | 14 | count_or_copy(&out, &out_size, s->sps, s->sps_size, PS_OUT_OF_BAND, j); | |
| 387 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | if (s->pps_size) |
| 388 | 14 | count_or_copy(&out, &out_size, s->pps, s->pps_size, PS_OUT_OF_BAND, j); | |
| 389 | 14 | new_idr = 0; | |
| 390 | /* if only SPS has been seen, also insert PPS */ | ||
| 391 |
6/8✓ Branch 0 taken 3426 times.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 3356 times.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 70 times.
|
3496 | } else if (new_idr && unit_type == H264_NAL_IDR_SLICE && sps_seen && !pps_seen) { |
| 392 | ✗ | if (!s->pps_size) { | |
| 393 | ✗ | LOG_ONCE(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n"); | |
| 394 | } else { | ||
| 395 | ✗ | count_or_copy(&out, &out_size, s->pps, s->pps_size, PS_OUT_OF_BAND, j); | |
| 396 | } | ||
| 397 | } | ||
| 398 | |||
| 399 |
4/4✓ Branch 0 taken 3508 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3506 times.
|
3510 | if (unit_type == H264_NAL_SPS || unit_type == H264_NAL_PPS) |
| 400 | 4 | ps = PS_IN_BAND; | |
| 401 | else | ||
| 402 | 3506 | ps = PS_NONE; | |
| 403 | 3510 | count_or_copy(&out, &out_size, buf, nal_size, ps, j); | |
| 404 |
2/2✓ Branch 0 taken 1760 times.
✓ Branch 1 taken 1750 times.
|
3510 | if (unit_type == H264_NAL_SLICE) { |
| 405 | 1760 | new_idr = 1; | |
| 406 | 1760 | sps_seen = 0; | |
| 407 | 1760 | pps_seen = 0; | |
| 408 | } | ||
| 409 | |||
| 410 | 3510 | buf += nal_size; | |
| 411 |
2/2✓ Branch 0 taken 2688 times.
✓ Branch 1 taken 822 times.
|
3510 | } while (buf < buf_end); |
| 412 | |||
| 413 |
2/2✓ Branch 0 taken 411 times.
✓ Branch 1 taken 411 times.
|
822 | if (!j) { |
| 414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 411 times.
|
411 | if (out_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { |
| 415 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 416 | ✗ | goto fail; | |
| 417 | } | ||
| 418 | 411 | ret = av_new_packet(opkt, out_size); | |
| 419 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 411 times.
|
411 | if (ret < 0) |
| 420 | ✗ | goto fail; | |
| 421 | 411 | out = opkt->data; | |
| 422 | } | ||
| 423 | } | ||
| 424 | #undef LOG_ONCE | ||
| 425 | |||
| 426 | av_assert1(out_size == opkt->size); | ||
| 427 | |||
| 428 | 411 | s->new_idr = new_idr; | |
| 429 | 411 | s->idr_sps_seen = sps_seen; | |
| 430 | 411 | s->idr_pps_seen = pps_seen; | |
| 431 | |||
| 432 | 411 | ret = av_packet_copy_props(opkt, in); | |
| 433 |
1/2✓ Branch 0 taken 411 times.
✗ Branch 1 not taken.
|
411 | if (ret < 0) |
| 434 | ✗ | goto fail; | |
| 435 | |||
| 436 | 411 | fail: | |
| 437 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 411 times.
|
412 | if (ret < 0) |
| 438 | 1 | av_packet_unref(opkt); | |
| 439 | 412 | av_packet_free(&in); | |
| 440 | |||
| 441 | 412 | return ret; | |
| 442 | } | ||
| 443 | |||
| 444 | 7 | static void h264_mp4toannexb_close(AVBSFContext *ctx) | |
| 445 | { | ||
| 446 | 7 | H264BSFContext *s = ctx->priv_data; | |
| 447 | |||
| 448 | 7 | av_freep(&s->sps); | |
| 449 | 7 | av_freep(&s->pps); | |
| 450 | 7 | } | |
| 451 | |||
| 452 | ✗ | static void h264_mp4toannexb_flush(AVBSFContext *ctx) | |
| 453 | { | ||
| 454 | ✗ | H264BSFContext *s = ctx->priv_data; | |
| 455 | |||
| 456 | ✗ | s->idr_sps_seen = 0; | |
| 457 | ✗ | s->idr_pps_seen = 0; | |
| 458 | ✗ | s->new_idr = s->extradata_parsed; | |
| 459 | ✗ | } | |
| 460 | |||
| 461 | static const enum AVCodecID codec_ids[] = { | ||
| 462 | AV_CODEC_ID_H264, AV_CODEC_ID_NONE, | ||
| 463 | }; | ||
| 464 | |||
| 465 | const FFBitStreamFilter ff_h264_mp4toannexb_bsf = { | ||
| 466 | .p.name = "h264_mp4toannexb", | ||
| 467 | .p.codec_ids = codec_ids, | ||
| 468 | .priv_data_size = sizeof(H264BSFContext), | ||
| 469 | .init = h264_mp4toannexb_init, | ||
| 470 | .filter = h264_mp4toannexb_filter, | ||
| 471 | .close = h264_mp4toannexb_close, | ||
| 472 | .flush = h264_mp4toannexb_flush, | ||
| 473 | }; | ||
| 474 |