|
|
@@ -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" |
|
|
@@ -407,6 +408,55 @@ 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 / 2 >= (INT16_MAX - AV_INPUT_BUFFER_PADDING_SIZE) / 3) |
|
|
|
return AVERROR(ERANGE); |
|
|
|
escaped_buf_size = buf_size * 3 / 2 + AV_INPUT_BUFFER_PADDING_SIZE; |
|
|
|
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)) { |
|
|
|
if (bytestream2_get_bytes_left(&gbc) >= 3 && |
|
|
|
bytestream2_peek_be24(&gbc) <= 3) { |
|
|
|
bytestream2_put_be24(&pbc, 3); |
|
|
|
bytestream2_skip(&gbc, 2); |
|
|
|
} else |
|
|
|
bytestream2_put_byte(&pbc, bytestream2_get_byte(&gbc)); |
|
|
|
} |
|
|
|
|
|
|
|
escaped_buf_size = bytestream2_tell_p(&pbc); |
|
|
|
AV_WB16(escaped_buf, escaped_buf_size - 2); |
|
|
|
|
|
|
|
ret = decode_nal_units(h, escaped_buf, escaped_buf_size, 1); |
|
|
|
av_freep(&escaped_buf); |
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int ff_h264_decode_extradata(H264Context *h) |
|
|
|
{ |
|
|
|
AVCodecContext *avctx = h->avctx; |
|
|
@@ -433,7 +483,7 @@ int ff_h264_decode_extradata(H264Context *h) |
|
|
|
nalsize = AV_RB16(p) + 2; |
|
|
|
if (p - avctx->extradata + nalsize > avctx->extradata_size) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
ret = decode_nal_units(h, p, nalsize, 1); |
|
|
|
ret = decode_extradata_ps_mp4(h, p, nalsize); |
|
|
|
if (ret < 0) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, |
|
|
|
"Decoding sps %d from avcC failed\n", i); |
|
|
@@ -447,7 +497,7 @@ int ff_h264_decode_extradata(H264Context *h) |
|
|
|
nalsize = AV_RB16(p) + 2; |
|
|
|
if (p - avctx->extradata + nalsize > avctx->extradata_size) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
ret = decode_nal_units(h, p, nalsize, 1); |
|
|
|
ret = decode_extradata_ps_mp4(h, p, nalsize); |
|
|
|
if (ret < 0) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, |
|
|
|
"Decoding pps %d from avcC failed\n", i); |
|
|
@@ -1379,14 +1429,8 @@ again: |
|
|
|
case NAL_SPS: |
|
|
|
init_get_bits(&h->gb, ptr, bit_length); |
|
|
|
ret = ff_h264_decode_seq_parameter_set(h); |
|
|
|
if (ret < 0 && h->is_avc && (nalsize != consumed) && nalsize) { |
|
|
|
av_log(h->avctx, AV_LOG_DEBUG, |
|
|
|
"SPS decoding failure, trying again with the complete NAL\n"); |
|
|
|
init_get_bits(&h->gb, buf + buf_index + 1 - consumed, |
|
|
|
8 * (nalsize - 1)); |
|
|
|
ff_h264_decode_seq_parameter_set(h); |
|
|
|
} |
|
|
|
|
|
|
|
if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) |
|
|
|
goto end; |
|
|
|
break; |
|
|
|
case NAL_PPS: |
|
|
|
init_get_bits(&h->gb, ptr, bit_length); |
|
|
|