On 2016-03-23 14:44:59 +0100, Anton Khirnov wrote:
> Instead of handling the problem inside NAL decoding code, add a higher
> level wrapper function. This should be more robust against future
> changes (and easier to read).
> ---
> libavcodec/h264.c | 61
> ++++++++++++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 51 insertions(+), 10 deletions(-)
>
> diff --git a/libavcodec/h264.c b/libavcodec/h264.c
> index 0b5b6c2..67b90c5 100644
> --- a/libavcodec/h264.c
> +++ b/libavcodec/h264.c
> @@ -32,6 +32,7 @@
> #include "libavutil/stereo3d.h"
> #include "libavutil/timer.h"
> #include "internal.h"
> +#include "bytestream.h"
> #include "cabac.h"
> #include "cabac_functions.h"
> #include "error_resilience.h"
> @@ -501,6 +502,52 @@ fail:
> static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
> int parse_extradata);
>
> +/* There are (invalid) samples in the wild with mp4-style extradata, where
> the
> + * parameter sets are stored unescaped (i.e. as RBSP).
> + * This function catches the parameter set decoding failure and tries again
> + * after escaping it */
> +static int decode_extradata_ps_mp4(H264Context *h, const uint8_t *buf, int
> buf_size)
> +{
> + int ret;
> +
> + ret = decode_nal_units(h, buf, buf_size, 1);
> + if (ret < 0 && !(h->avctx->err_recognition & AV_EF_EXPLODE)) {
> + GetByteContext gbc;
> + PutByteContext pbc;
> + uint8_t *escaped_buf;
> + int escaped_buf_size;
> +
> + av_log(h->avctx, AV_LOG_WARNING,
> + "SPS decoding failure, trying again after escaping the
> NAL\n");
> +
> + if (buf_size / 3 >= (INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) / 4)
> + return AVERROR(ERANGE);
> + escaped_buf_size = buf_size * 4 / 3 + AV_INPUT_BUFFER_PADDING_SIZE;
shouldn't that be buf_size * 3 / 2 when you consider a all zero byte
sequence?
> + escaped_buf = av_mallocz(escaped_buf_size);
> + if (!escaped_buf)
> + return AVERROR(ENOMEM);
> +
> + bytestream2_init(&gbc, buf, buf_size);
> + bytestream2_init_writer(&pbc, escaped_buf, escaped_buf_size);
> +
> + while (bytestream2_get_bytes_left(&gbc)) {
> + uint32_t b = bytestream2_peek_be24(&gbc);
> + if (b <= 3) {
> + bytestream2_put_be24(&pbc, 3);
> + bytestream2_skip(&gbc, 2);
> + } else
> + bytestream2_put_byte(&pbc, bytestream2_get_byte(&gbc));
or you could remove the else since it's always valid to write the
escaped byte.
Janne
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel