From 90ed6c5cf7f236bc9efb47c97b40358c666d1386 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 21 Mar 2016 12:42:12 +0100 Subject: [PATCH] h2645_parse: compute the actual data length, without trailing paddding This is required by h264. --- libavcodec/h2645_parse.c | 39 ++++++++++++++++++++++++++++++++++++--- libavcodec/h2645_parse.h | 6 ++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 310b0093ca..defe001de7 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -22,13 +22,12 @@ #include "config.h" +#include "libavutil/intmath.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" #include "h2645_parse.h" -/* FIXME: This is adapted from ff_h264_decode_nal, avoiding duplication - * between these functions would be nice. */ int ff_h2645_extract_rbsp(const uint8_t *src, int length, H2645NAL *nal) { @@ -128,6 +127,31 @@ nsc: return si; } +static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros) +{ + int size = nal->size; + int v; + + while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0) + size--; + + if (!size) + return 0; + + v = nal->data[size - 1]; + + if (size > INT_MAX / 8) + return AVERROR(ERANGE); + size *= 8; + + /* remove the stop bit and following trailing zeros, + * or nothing for damaged bitstreams */ + if (v) + size -= av_ctz(v) + 1; + + return size; +} + /** * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit, * 0 if the unit should be skipped, 1 otherwise @@ -181,6 +205,7 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, while (length >= 4) { H2645NAL *nal; int extract_length = 0; + int skip_trailing_zeros = 1; if (is_nalff) { int i; @@ -224,7 +249,15 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, if (consumed < 0) return consumed; - ret = init_get_bits8(&nal->gb, nal->data, nal->size); + /* see commit 3566042a0 */ + if (consumed < length - 3 && + buf[consumed] == 0x00 && buf[consumed + 1] == 0x00 && + buf[consumed + 2] == 0x01 && buf[consumed + 3] == 0xE0) + skip_trailing_zeros = 0; + + nal->size_bits = get_bit_length(nal, skip_trailing_zeros); + + ret = init_get_bits(&nal->gb, nal->data, nal->size_bits); if (ret < 0) return ret; diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h index 148ccf30ac..651cf26795 100644 --- a/libavcodec/h2645_parse.h +++ b/libavcodec/h2645_parse.h @@ -33,6 +33,12 @@ typedef struct H2645NAL { int size; const uint8_t *data; + /** + * Size, in bits, of just the data, excluding the stop bit and any trailing + * padding. I.e. what HEVC calls SODB. + */ + int size_bits; + int raw_size; const uint8_t *raw_data;