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

Reply via email to