[FFmpeg-cvslog] Merge commit '98c97994c5b90bdae02accb155eeceeb5224b8ef'
Clément Bœsch
git at videolan.org
Sun Jun 19 12:22:24 CEST 2016
ffmpeg | branch: master | Clément Bœsch <u at pkh.me> | Sun Jun 19 12:17:41 2016 +0200| [0bf5fd2e19b081ce17e523944c2735586b008159] | committer: Clément Bœsch
Merge commit '98c97994c5b90bdae02accb155eeceeb5224b8ef'
* commit '98c97994c5b90bdae02accb155eeceeb5224b8ef':
h264: decouple extradata parsing from the decoder
Main changes:
- move get_avc_nalsize() inside h264_parser.c and make it use
H264ParseContext instead of H264Context. This helps fixing
fate-flv-demux.
- Also use is_avc/nal_length_size from the H264ParseContext in various
places instead of the H264Context one as that's the fields now filled
by ff_h264_decode_extradata()
- h264_parse: dont fail decode_extradata_ps() due to nal split failure.
Change by Michael to fix decoding of h264/ref_10.avi.
Merged-by: Clément Bœsch <u at pkh.me>
Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=0bf5fd2e19b081ce17e523944c2735586b008159
---
libavcodec/h264.c | 153 ++++------------------------------------------
libavcodec/h264.h | 21 -------
libavcodec/h264_parse.c | 149 ++++++++++++++++++++++++++++++++++++++++++++
libavcodec/h264_parse.h | 5 ++
libavcodec/h264_parser.c | 61 +++++++++---------
5 files changed, 198 insertions(+), 191 deletions(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 831d918..b218350 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -300,120 +300,6 @@ fail:
return AVERROR(ENOMEM); // ff_h264_free_tables will clean up for us
}
-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, const uint8_t *buf, int size)
-{
- AVCodecContext *avctx = h->avctx;
- int ret;
-
- if (!buf || size <= 0)
- return -1;
-
- if (buf[0] == 1) {
- int i, cnt, nalsize;
- const unsigned char *p = buf;
-
- h->is_avc = 1;
-
- if (size < 7) {
- av_log(avctx, AV_LOG_ERROR,
- "avcC %d too short\n", size);
- return AVERROR_INVALIDDATA;
- }
- /* sps and pps in the avcC always have length coded with 2 bytes,
- * so put a fake nal_length_size = 2 while parsing them */
- h->nal_length_size = 2;
- // Decode sps from avcC
- cnt = *(p + 5) & 0x1f; // Number of sps
- p += 6;
- for (i = 0; i < cnt; i++) {
- nalsize = AV_RB16(p) + 2;
- if(nalsize > size - (p-buf))
- return AVERROR_INVALIDDATA;
- 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);
- return ret;
- }
- p += nalsize;
- }
- // Decode pps from avcC
- cnt = *(p++); // Number of pps
- for (i = 0; i < cnt; i++) {
- nalsize = AV_RB16(p) + 2;
- if(nalsize > size - (p-buf))
- return AVERROR_INVALIDDATA;
- 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);
- return ret;
- }
- p += nalsize;
- }
- // Store right nal length size that will be used to parse all other nals
- h->nal_length_size = (buf[4] & 0x03) + 1;
- } else {
- h->is_avc = 0;
- ret = decode_nal_units(h, buf, size, 1);
- if (ret < 0)
- return ret;
- }
- return size;
-}
-
static int h264_init_context(AVCodecContext *avctx, H264Context *h)
{
int i;
@@ -503,7 +389,9 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
}
if (avctx->extradata_size > 0 && avctx->extradata) {
- ret = ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size);
+ ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
+ &h->ps, &h->is_avc, &h->nal_length_size,
+ avctx->err_recognition, avctx);
if (ret < 0) {
h264_decode_end(avctx);
return ret;
@@ -992,8 +880,7 @@ static void debug_green_metadata(const H264SEIGreenMetaData *gm, void *logctx)
}
}
-static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
- int parse_extradata)
+static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
{
AVCodecContext *const avctx = h->avctx;
unsigned context_count = 0;
@@ -1025,8 +912,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR,
"Error splitting the input into NAL units.\n");
- /* don't consider NAL parsing failure a fatal error when parsing extradata, as the stream may work without it */
- return parse_extradata ? buf_size : ret;
+ return ret;
}
if (avctx->active_thread_type & FF_THREAD_FRAME)
@@ -1044,25 +930,6 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
continue;
again:
- /* Ignore per frame NAL unit type during extradata
- * parsing. Decoding slices is not possible in codec init
- * with frame-mt */
- if (parse_extradata) {
- switch (nal->type) {
- case NAL_IDR_SLICE:
- case NAL_SLICE:
- case NAL_DPA:
- case NAL_DPB:
- case NAL_DPC:
- av_log(h->avctx, AV_LOG_WARNING,
- "Ignoring NAL %d in global header/extradata\n",
- nal->type);
- // fall through to next case
- case NAL_AUXILIARY_SLICE:
- nal->type = NAL_FF_IGNORE;
- }
- }
-
// FIXME these should stop being context-global variables
h->nal_ref_idc = nal->ref_idc;
h->nal_unit_type = nal->type;
@@ -1440,14 +1307,18 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data,
int side_size;
uint8_t *side = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
if (is_extra(side, side_size))
- ff_h264_decode_extradata(h, side, side_size);
+ ff_h264_decode_extradata(side, side_size,
+ &h->ps, &h->is_avc, &h->nal_length_size,
+ avctx->err_recognition, avctx);
}
if(h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 && (buf[4]&0xFC)==0xFC && (buf[5]&0x1F) && buf[8]==0x67){
if (is_extra(buf, buf_size))
- return ff_h264_decode_extradata(h, buf, buf_size);
+ return ff_h264_decode_extradata(buf, buf_size,
+ &h->ps, &h->is_avc, &h->nal_length_size,
+ avctx->err_recognition, avctx);
}
- buf_index = decode_nal_units(h, buf, buf_size, 0);
+ buf_index = decode_nal_units(h, buf, buf_size);
if (buf_index < 0)
return AVERROR_INVALIDDATA;
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index ba6f43c..1dd4bc1 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -754,7 +754,6 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb,
int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice);
void ff_h264_hl_decode_mb(const H264Context *h, H264SliceContext *sl);
-int ff_h264_decode_extradata(H264Context *h, const uint8_t *buf, int size);
int ff_h264_decode_init(AVCodecContext *avctx);
void ff_h264_decode_init_vlc(void);
@@ -1000,26 +999,6 @@ static inline int find_start_code(const uint8_t *buf, int buf_size,
return FFMIN(buf_index, buf_size);
}
-static inline int get_avc_nalsize(H264Context *h, const uint8_t *buf,
- int buf_size, int *buf_index)
-{
- int i, nalsize = 0;
-
- if (*buf_index >= buf_size - h->nal_length_size) {
- // the end of the buffer is reached, refill it.
- return AVERROR(EAGAIN);
- }
-
- for (i = 0; i < h->nal_length_size; i++)
- nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];
- if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
- av_log(h->avctx, AV_LOG_ERROR,
- "AVC: nal size %d\n", nalsize);
- return AVERROR_INVALIDDATA;
- }
- return nalsize;
-}
-
int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup);
int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src);
diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
index 09a9fbe..4d2cacb 100644
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@ -16,6 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "bytestream.h"
#include "get_bits.h"
#include "golomb.h"
#include "h264.h"
@@ -319,3 +320,151 @@ int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc,
return 0;
}
+
+static int decode_extradata_ps(const uint8_t *data, int size, H264ParamSets *ps,
+ int is_avc, void *logctx)
+{
+ H2645Packet pkt = { 0 };
+ int i, ret = 0;
+
+ ret = ff_h2645_packet_split(&pkt, data, size, logctx, is_avc, 2, AV_CODEC_ID_H264);
+ if (ret < 0) {
+ ret = 0;
+ goto fail;
+ }
+
+ for (i = 0; i < pkt.nb_nals; i++) {
+ H2645NAL *nal = &pkt.nals[i];
+ switch (nal->type) {
+ case NAL_SPS:
+ ret = ff_h264_decode_seq_parameter_set(&nal->gb, logctx, ps, 0);
+ if (ret < 0)
+ goto fail;
+ break;
+ case NAL_PPS:
+ ret = ff_h264_decode_picture_parameter_set(&nal->gb, logctx, ps,
+ nal->size_bits);
+ if (ret < 0)
+ goto fail;
+ break;
+ default:
+ av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in extradata\n",
+ nal->type);
+ break;
+ }
+ }
+
+fail:
+ ff_h2645_packet_uninit(&pkt);
+ return ret;
+}
+
+/* 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(const uint8_t *buf, int buf_size, H264ParamSets *ps,
+ int err_recognition, void *logctx)
+{
+ int ret;
+
+ ret = decode_extradata_ps(buf, buf_size, ps, 1, logctx);
+ if (ret < 0 && !(err_recognition & AV_EF_EXPLODE)) {
+ GetByteContext gbc;
+ PutByteContext pbc;
+ uint8_t *escaped_buf;
+ int escaped_buf_size;
+
+ av_log(logctx, 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_extradata_ps(escaped_buf, escaped_buf_size, ps, 1, logctx);
+ av_freep(&escaped_buf);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+int ff_h264_decode_extradata(const uint8_t *data, int size, H264ParamSets *ps,
+ int *is_avc, int *nal_length_size,
+ int err_recognition, void *logctx)
+{
+ int ret;
+
+ if (!data || size <= 0)
+ return -1;
+
+ if (data[0] == 1) {
+ int i, cnt, nalsize;
+ const uint8_t *p = data;
+
+ *is_avc = 1;
+
+ if (size < 7) {
+ av_log(logctx, AV_LOG_ERROR, "avcC %d too short\n", size);
+ return AVERROR_INVALIDDATA;
+ }
+
+ // Decode sps from avcC
+ cnt = *(p + 5) & 0x1f; // Number of sps
+ p += 6;
+ for (i = 0; i < cnt; i++) {
+ nalsize = AV_RB16(p) + 2;
+ if (nalsize > size - (p - data))
+ return AVERROR_INVALIDDATA;
+ ret = decode_extradata_ps_mp4(p, nalsize, ps, err_recognition, logctx);
+ if (ret < 0) {
+ av_log(logctx, AV_LOG_ERROR,
+ "Decoding sps %d from avcC failed\n", i);
+ return ret;
+ }
+ p += nalsize;
+ }
+ // Decode pps from avcC
+ cnt = *(p++); // Number of pps
+ for (i = 0; i < cnt; i++) {
+ nalsize = AV_RB16(p) + 2;
+ if (nalsize > size - (p - data))
+ return AVERROR_INVALIDDATA;
+ ret = decode_extradata_ps_mp4(p, nalsize, ps, err_recognition, logctx);
+ if (ret < 0) {
+ av_log(logctx, AV_LOG_ERROR,
+ "Decoding pps %d from avcC failed\n", i);
+ return ret;
+ }
+ p += nalsize;
+ }
+ // Store right nal length size that will be used to parse all other nals
+ *nal_length_size = (data[4] & 0x03) + 1;
+ } else {
+ *is_avc = 0;
+ ret = decode_extradata_ps(data, size, ps, 0, logctx);
+ if (ret < 0)
+ return ret;
+ }
+ return size;
+}
diff --git a/libavcodec/h264_parse.h b/libavcodec/h264_parse.h
index 413f04d..5ff3dc3 100644
--- a/libavcodec/h264_parse.h
+++ b/libavcodec/h264_parse.h
@@ -54,6 +54,7 @@ typedef struct H264POCContext {
struct SPS;
struct PPS;
+struct H264ParamSets;
int ff_h264_pred_weight_table(GetBitContext *gb, const struct SPS *sps,
const int *ref_count, int slice_type_nos,
@@ -82,4 +83,8 @@ int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc,
const struct SPS *sps, H264POCContext *poc,
int picture_structure, int nal_ref_idc);
+int ff_h264_decode_extradata(const uint8_t *data, int size, struct H264ParamSets *ps,
+ int *is_avc, int *nal_length_size,
+ int err_recognition, void *logctx);
+
#endif /* AVCODEC_H264_PARSE_H */
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 9fccdc9..bb167b7 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -52,6 +52,8 @@ typedef struct H264ParseContext {
H264DSPContext h264dsp;
H264POCContext poc;
H264SEIContext sei;
+ int is_avc;
+ int nal_length_size;
int got_first;
} H264ParseContext;
@@ -64,20 +66,20 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
uint32_t state;
ParseContext *pc = &p->pc;
- int next_avc= h->is_avc ? 0 : buf_size;
+ int next_avc = p->is_avc ? 0 : buf_size;
// mb_addr= pc->mb_addr - 1;
state = pc->state;
if (state > 13)
state = 7;
- if (h->is_avc && !h->nal_length_size)
+ if (p->is_avc && !p->nal_length_size)
av_log(h->avctx, AV_LOG_ERROR, "AVC-parser: nal length size invalid\n");
for (i = 0; i < buf_size; i++) {
if (i >= next_avc) {
int nalsize = 0;
i = next_avc;
- for (j = 0; j < h->nal_length_size; j++)
+ for (j = 0; j < p->nal_length_size; j++)
nalsize = (nalsize << 8) | buf[i++];
if (nalsize <= 0 || nalsize > buf_size - i) {
av_log(h->avctx, AV_LOG_ERROR, "AVC-parser: nal size %d remaining %d\n", nalsize, buf_size - i);
@@ -132,14 +134,14 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
}
}
pc->state = state;
- if (h->is_avc)
+ if (p->is_avc)
return next_avc;
return END_NOT_FOUND;
found:
pc->state = 7;
pc->frame_start_found = 0;
- if (h->is_avc)
+ if (p->is_avc)
return next_avc;
return i - (state & 5) - 5 * (state > 7);
}
@@ -222,6 +224,26 @@ static int scan_mmco_reset(AVCodecParserContext *s, GetBitContext *gb)
return 0;
}
+static inline int get_avc_nalsize(H264ParseContext *p, const uint8_t *buf,
+ int buf_size, int *buf_index, void *logctx)
+{
+ int i, nalsize = 0;
+
+ if (*buf_index >= buf_size - p->nal_length_size) {
+ // the end of the buffer is reached, refill it
+ return AVERROR(EAGAIN);
+ }
+
+ for (i = 0; i < p->nal_length_size; i++)
+ nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];
+ if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
+ av_log(logctx, AV_LOG_ERROR,
+ "AVC: nal size %d\n", nalsize);
+ return AVERROR_INVALIDDATA;
+ }
+ return nalsize;
+}
+
/**
* Parse NAL units of found picture and decode some basic information.
*
@@ -258,13 +280,13 @@ static inline int parse_nal_units(AVCodecParserContext *s,
return 0;
buf_index = 0;
- next_avc = h->is_avc ? 0 : buf_size;
+ next_avc = p->is_avc ? 0 : buf_size;
for (;;) {
const SPS *sps;
int src_length, consumed, nalsize = 0;
if (buf_index >= next_avc) {
- nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
+ nalsize = get_avc_nalsize(p, buf, buf_size, &buf_index, avctx);
if (nalsize < 0)
break;
next_avc = buf_index + nalsize;
@@ -547,8 +569,6 @@ static int h264_parse(AVCodecParserContext *s,
if (!p->got_first) {
p->got_first = 1;
if (avctx->extradata_size) {
- int i;
-
h->avctx = avctx;
// must be done like in decoder, otherwise opening the parser,
// letting it create extradata and then closing and opening again
@@ -556,26 +576,9 @@ static int h264_parse(AVCodecParserContext *s,
// Note that estimate_timings_from_pts does exactly this.
if (!avctx->has_b_frames)
h->low_delay = 1;
- ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size);
-
- for (i = 0; i < FF_ARRAY_ELEMS(p->ps.sps_list); i++) {
- av_buffer_unref(&p->ps.sps_list[i]);
- if (h->ps.sps_list[i]) {
- p->ps.sps_list[i] = av_buffer_ref(h->ps.sps_list[i]);
- if (!p->ps.sps_list[i])
- return AVERROR(ENOMEM);
- }
- }
- for (i = 0; i < FF_ARRAY_ELEMS(p->ps.pps_list); i++) {
- av_buffer_unref(&p->ps.pps_list[i]);
- if (h->ps.pps_list[i]) {
- p->ps.pps_list[i] = av_buffer_ref(h->ps.pps_list[i]);
- if (!p->ps.pps_list[i])
- return AVERROR(ENOMEM);
- }
- }
-
- p->ps.sps = h->ps.sps;
+ ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
+ &p->ps, &p->is_avc, &p->nal_length_size,
+ avctx->err_recognition, avctx);
}
}
======================================================================
diff --cc libavcodec/h264.c
index 831d918,7db97ef..b218350
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@@ -503,11 -351,13 +389,13 @@@ av_cold int ff_h264_decode_init(AVCodec
}
if (avctx->extradata_size > 0 && avctx->extradata) {
- ret = ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size);
- ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
- &h->ps, &h->is_avc, &h->nal_length_size,
- avctx->err_recognition, avctx);
- if (ret < 0) {
- ff_h264_free_context(h);
- return ret;
- }
++ ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
++ &h->ps, &h->is_avc, &h->nal_length_size,
++ avctx->err_recognition, avctx);
+ if (ret < 0) {
+ h264_decode_end(avctx);
+ return ret;
+ }
}
if (h->ps.sps && h->ps.sps->bitstream_restriction_flag &&
@@@ -964,36 -810,7 +852,35 @@@ static int get_last_needed_nal(H264Cont
return nals_needed;
}
+static void debug_green_metadata(const H264SEIGreenMetaData *gm, void *logctx)
+{
+ av_log(logctx, AV_LOG_DEBUG, "Green Metadata Info SEI message\n");
+ av_log(logctx, AV_LOG_DEBUG, " green_metadata_type: %d\n", gm->green_metadata_type);
+
+ if (gm->green_metadata_type == 0) {
+ av_log(logctx, AV_LOG_DEBUG, " green_metadata_period_type: %d\n", gm->period_type);
+
+ if (gm->period_type == 2)
+ av_log(logctx, AV_LOG_DEBUG, " green_metadata_num_seconds: %d\n", gm->num_seconds);
+ else if (gm->period_type == 3)
+ av_log(logctx, AV_LOG_DEBUG, " green_metadata_num_pictures: %d\n", gm->num_pictures);
+
+ av_log(logctx, AV_LOG_DEBUG, " SEI GREEN Complexity Metrics: %f %f %f %f\n",
+ (float)gm->percent_non_zero_macroblocks/255,
+ (float)gm->percent_intra_coded_macroblocks/255,
+ (float)gm->percent_six_tap_filtering/255,
+ (float)gm->percent_alpha_point_deblocking_instance/255);
+
+ } else if (gm->green_metadata_type == 1) {
+ av_log(logctx, AV_LOG_DEBUG, " xsd_metric_type: %d\n", gm->xsd_metric_type);
+
+ if (gm->xsd_metric_type == 0)
+ av_log(logctx, AV_LOG_DEBUG, " xsd_metric_value: %f\n",
+ (float)gm->xsd_metric_value/100);
+ }
+}
+
- static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
- int parse_extradata)
+ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
{
AVCodecContext *const avctx = h->avctx;
unsigned context_count = 0;
@@@ -1436,18 -1059,8 +1303,22 @@@ static int h264_decode_frame(AVCodecCon
return buf_index;
}
+ if (h->is_avc && av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, NULL)) {
+ int side_size;
+ uint8_t *side = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
+ if (is_extra(side, side_size))
- ff_h264_decode_extradata(h, side, side_size);
++ ff_h264_decode_extradata(side, side_size,
++ &h->ps, &h->is_avc, &h->nal_length_size,
++ avctx->err_recognition, avctx);
+ }
+ if(h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 && (buf[4]&0xFC)==0xFC && (buf[5]&0x1F) && buf[8]==0x67){
+ if (is_extra(buf, buf_size))
- return ff_h264_decode_extradata(h, buf, buf_size);
++ return ff_h264_decode_extradata(buf, buf_size,
++ &h->ps, &h->is_avc, &h->nal_length_size,
++ avctx->err_recognition, avctx);
+ }
- buf_index = decode_nal_units(h, buf, buf_size, 0);
+ buf_index = decode_nal_units(h, buf, buf_size);
if (buf_index < 0)
return AVERROR_INVALIDDATA;
diff --cc libavcodec/h264.h
index ba6f43c,4590bdb..1dd4bc1
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@@ -990,36 -943,6 +989,16 @@@ static av_always_inline int get_dct8x8_
0x0001000100010001ULL));
}
+static inline int find_start_code(const uint8_t *buf, int buf_size,
+ int buf_index, int next_avc)
+{
+ uint32_t state = -1;
+
+ buf_index = avpriv_find_start_code(buf + buf_index, buf + next_avc + 1, &state) - buf - 1;
+
+ return FFMIN(buf_index, buf_size);
+}
+
- static inline int get_avc_nalsize(H264Context *h, const uint8_t *buf,
- int buf_size, int *buf_index)
- {
- int i, nalsize = 0;
-
- if (*buf_index >= buf_size - h->nal_length_size) {
- // the end of the buffer is reached, refill it.
- return AVERROR(EAGAIN);
- }
-
- for (i = 0; i < h->nal_length_size; i++)
- nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];
- if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
- av_log(h->avctx, AV_LOG_ERROR,
- "AVC: nal size %d\n", nalsize);
- return AVERROR_INVALIDDATA;
- }
- return nalsize;
- }
-
int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup);
int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src);
diff --cc libavcodec/h264_parse.c
index 09a9fbe,1fc8f41..4d2cacb
--- a/libavcodec/h264_parse.c
+++ b/libavcodec/h264_parse.c
@@@ -319,3 -306,146 +320,151 @@@ int ff_h264_init_poc(int pic_field_poc[
return 0;
}
+
+ static int decode_extradata_ps(const uint8_t *data, int size, H264ParamSets *ps,
+ int is_avc, void *logctx)
+ {
+ H2645Packet pkt = { 0 };
+ int i, ret = 0;
+
+ ret = ff_h2645_packet_split(&pkt, data, size, logctx, is_avc, 2, AV_CODEC_ID_H264);
- if (ret < 0)
++ if (ret < 0) {
++ ret = 0;
+ goto fail;
++ }
+
+ for (i = 0; i < pkt.nb_nals; i++) {
+ H2645NAL *nal = &pkt.nals[i];
+ switch (nal->type) {
+ case NAL_SPS:
- ret = ff_h264_decode_seq_parameter_set(&nal->gb, logctx, ps);
++ ret = ff_h264_decode_seq_parameter_set(&nal->gb, logctx, ps, 0);
+ if (ret < 0)
+ goto fail;
+ break;
+ case NAL_PPS:
+ ret = ff_h264_decode_picture_parameter_set(&nal->gb, logctx, ps,
+ nal->size_bits);
+ if (ret < 0)
+ goto fail;
+ break;
+ default:
+ av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in extradata\n",
+ nal->type);
+ break;
+ }
+ }
+
+ fail:
+ ff_h2645_packet_uninit(&pkt);
+ return ret;
+ }
+
+ /* 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(const uint8_t *buf, int buf_size, H264ParamSets *ps,
+ int err_recognition, void *logctx)
+ {
+ int ret;
+
+ ret = decode_extradata_ps(buf, buf_size, ps, 1, logctx);
+ if (ret < 0 && !(err_recognition & AV_EF_EXPLODE)) {
+ GetByteContext gbc;
+ PutByteContext pbc;
+ uint8_t *escaped_buf;
+ int escaped_buf_size;
+
+ av_log(logctx, 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_extradata_ps(escaped_buf, escaped_buf_size, ps, 1, logctx);
+ av_freep(&escaped_buf);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+ }
+
+ int ff_h264_decode_extradata(const uint8_t *data, int size, H264ParamSets *ps,
+ int *is_avc, int *nal_length_size,
+ int err_recognition, void *logctx)
+ {
+ int ret;
+
++ if (!data || size <= 0)
++ return -1;
++
+ if (data[0] == 1) {
+ int i, cnt, nalsize;
+ const uint8_t *p = data;
+
+ *is_avc = 1;
+
+ if (size < 7) {
+ av_log(logctx, AV_LOG_ERROR, "avcC %d too short\n", size);
+ return AVERROR_INVALIDDATA;
+ }
+
+ // Decode sps from avcC
+ cnt = *(p + 5) & 0x1f; // Number of sps
+ p += 6;
+ for (i = 0; i < cnt; i++) {
+ nalsize = AV_RB16(p) + 2;
- if (p - data + nalsize > size)
++ if (nalsize > size - (p - data))
+ return AVERROR_INVALIDDATA;
+ ret = decode_extradata_ps_mp4(p, nalsize, ps, err_recognition, logctx);
+ if (ret < 0) {
+ av_log(logctx, AV_LOG_ERROR,
+ "Decoding sps %d from avcC failed\n", i);
+ return ret;
+ }
+ p += nalsize;
+ }
+ // Decode pps from avcC
+ cnt = *(p++); // Number of pps
+ for (i = 0; i < cnt; i++) {
+ nalsize = AV_RB16(p) + 2;
- if (p - data + nalsize > size)
++ if (nalsize > size - (p - data))
+ return AVERROR_INVALIDDATA;
+ ret = decode_extradata_ps_mp4(p, nalsize, ps, err_recognition, logctx);
+ if (ret < 0) {
+ av_log(logctx, AV_LOG_ERROR,
+ "Decoding pps %d from avcC failed\n", i);
+ return ret;
+ }
+ p += nalsize;
+ }
+ // Store right nal length size that will be used to parse all other nals
+ *nal_length_size = (data[4] & 0x03) + 1;
+ } else {
+ *is_avc = 0;
+ ret = decode_extradata_ps(data, size, ps, 0, logctx);
+ if (ret < 0)
+ return ret;
+ }
- return 0;
++ return size;
+ }
diff --cc libavcodec/h264_parser.c
index 9fccdc9,9a6464c..bb167b7
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@@ -59,37 -59,18 +61,37 @@@ typedef struct H264ParseContext
static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
int buf_size)
{
- int i;
+ H264Context *h = &p->h;
+ int i, j;
uint32_t state;
ParseContext *pc = &p->pc;
+
- int next_avc= h->is_avc ? 0 : buf_size;
++ int next_avc = p->is_avc ? 0 : buf_size;
// mb_addr= pc->mb_addr - 1;
state = pc->state;
if (state > 13)
state = 7;
- if (h->is_avc && !h->nal_length_size)
++ if (p->is_avc && !p->nal_length_size)
+ av_log(h->avctx, AV_LOG_ERROR, "AVC-parser: nal length size invalid\n");
+
for (i = 0; i < buf_size; i++) {
+ if (i >= next_avc) {
+ int nalsize = 0;
+ i = next_avc;
- for (j = 0; j < h->nal_length_size; j++)
++ for (j = 0; j < p->nal_length_size; j++)
+ nalsize = (nalsize << 8) | buf[i++];
+ if (nalsize <= 0 || nalsize > buf_size - i) {
+ av_log(h->avctx, AV_LOG_ERROR, "AVC-parser: nal size %d remaining %d\n", nalsize, buf_size - i);
+ return buf_size;
+ }
+ next_avc = i + nalsize;
+ state = 5;
+ }
+
if (state == 7) {
- i += p->h264dsp.startcode_find_candidate(buf + i, buf_size - i);
- if (i < buf_size)
+ i += p->h264dsp.startcode_find_candidate(buf + i, next_avc - i);
+ if (i < next_avc)
state = 2;
} else if (state <= 2) {
if (buf[i] == 1)
@@@ -132,16 -98,18 +134,16 @@@
}
}
pc->state = state;
- if (h->is_avc)
++ if (p->is_avc)
+ return next_avc;
return END_NOT_FOUND;
found:
pc->state = 7;
pc->frame_start_found = 0;
- if (h->is_avc)
- return i - (state & 5);
++ if (p->is_avc)
+ return next_avc;
+ return i - (state & 5) - 5 * (state > 7);
}
static int scan_mmco_reset(AVCodecParserContext *s, GetBitContext *gb)
@@@ -222,6 -190,6 +224,26 @@@
return 0;
}
++static inline int get_avc_nalsize(H264ParseContext *p, const uint8_t *buf,
++ int buf_size, int *buf_index, void *logctx)
++{
++ int i, nalsize = 0;
++
++ if (*buf_index >= buf_size - p->nal_length_size) {
++ // the end of the buffer is reached, refill it
++ return AVERROR(EAGAIN);
++ }
++
++ for (i = 0; i < p->nal_length_size; i++)
++ nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];
++ if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
++ av_log(logctx, AV_LOG_ERROR,
++ "AVC: nal size %d\n", nalsize);
++ return AVERROR_INVALIDDATA;
++ }
++ return nalsize;
++}
++
/**
* Parse NAL units of found picture and decode some basic information.
*
@@@ -257,27 -225,14 +279,27 @@@ static inline int parse_nal_units(AVCod
if (!buf_size)
return 0;
+ buf_index = 0;
- next_avc = h->is_avc ? 0 : buf_size;
++ next_avc = p->is_avc ? 0 : buf_size;
for (;;) {
const SPS *sps;
- int src_length, consumed;
- buf = avpriv_find_start_code(buf, buf_end, &state);
- if (buf >= buf_end)
- break;
- --buf;
- src_length = buf_end - buf;
+ int src_length, consumed, nalsize = 0;
+
+ if (buf_index >= next_avc) {
- nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
++ nalsize = get_avc_nalsize(p, buf, buf_size, &buf_index, avctx);
+ if (nalsize < 0)
+ break;
+ next_avc = buf_index + nalsize;
+ } else {
+ buf_index = find_start_code(buf, buf_size, buf_index, next_avc);
+ if (buf_index >= buf_size)
+ break;
+ if (buf_index >= next_avc)
+ continue;
+ }
+ src_length = next_avc - buf_index;
+
+ state = buf[buf_index];
switch (state & 0x1f) {
case NAL_SLICE:
case NAL_IDR_SLICE:
@@@ -547,35 -494,17 +569,16 @@@ static int h264_parse(AVCodecParserCont
if (!p->got_first) {
p->got_first = 1;
if (avctx->extradata_size) {
- int i;
-
h->avctx = avctx;
- // must be done like in the decoder.
- // otherwise opening the parser, creating extradata,
- // and then closing and opening again
+ // must be done like in decoder, otherwise opening the parser,
+ // letting it create extradata and then closing and opening again
// will cause has_b_frames to be always set.
- // NB: estimate_timings_from_pts behaves exactly like this.
+ // Note that estimate_timings_from_pts does exactly this.
if (!avctx->has_b_frames)
h->low_delay = 1;
- ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size);
-
- for (i = 0; i < FF_ARRAY_ELEMS(p->ps.sps_list); i++) {
- av_buffer_unref(&p->ps.sps_list[i]);
- if (h->ps.sps_list[i]) {
- p->ps.sps_list[i] = av_buffer_ref(h->ps.sps_list[i]);
- if (!p->ps.sps_list[i])
- return AVERROR(ENOMEM);
- }
- }
- for (i = 0; i < FF_ARRAY_ELEMS(p->ps.pps_list); i++) {
- av_buffer_unref(&p->ps.pps_list[i]);
- if (h->ps.pps_list[i]) {
- p->ps.pps_list[i] = av_buffer_ref(h->ps.pps_list[i]);
- if (!p->ps.pps_list[i])
- return AVERROR(ENOMEM);
- }
- }
-
- p->ps.sps = h->ps.sps;
+ ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
+ &p->ps, &p->is_avc, &p->nal_length_size,
+ avctx->err_recognition, avctx);
}
}
More information about the ffmpeg-cvslog
mailing list