On 2016-03-21 15:00:23 +0100, Anton Khirnov wrote:
> ---
> libavcodec/Makefile | 3 +-
> libavcodec/h264.c | 443
> ++++++++++++++++++----------------------------------
> libavcodec/h264.h | 3 +
> 3 files changed, 154 insertions(+), 295 deletions(-)
>
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 9892f85..8592410 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -251,7 +251,8 @@ OBJS-$(CONFIG_H263_ENCODER) += mpeg4videoenc.o
> mpeg4video.o \
> OBJS-$(CONFIG_H264_DECODER) += h264.o h264_cabac.o h264_cavlc.o \
> h264_direct.o h264_loopfilter.o \
> h264_mb.o h264_picture.o h264_ps.o
> \
> - h264_refs.o h264_sei.o h264_slice.o
> + h264_refs.o h264_sei.o
> h264_slice.o \
> + h2645_parse.o
> OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o
> OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o
> OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o
> diff --git a/libavcodec/h264.c b/libavcodec/h264.c
> index 613c633..241258f 100644
> --- a/libavcodec/h264.c
> +++ b/libavcodec/h264.c
> @@ -38,6 +38,7 @@
> #include "error_resilience.h"
> #include "avcodec.h"
> #include "h264.h"
> +#include "h2645_parse.h"
> #include "h264data.h"
> #include "h264chroma.h"
> #include "h264_mvpred.h"
> @@ -315,25 +316,6 @@ nsc:
> return dst;
> }
>
> -/**
> - * Identify the exact end of the bitstream
> - * @return the length of the trailing, or 0 if damaged
> - */
> -static int decode_rbsp_trailing(H264Context *h, const uint8_t *src)
> -{
> - int v = *src;
> - int r;
> -
> - ff_tlog(h->avctx, "rbsp trailing %X\n", v);
> -
> - for (r = 1; r < 9; r++) {
> - if (v & 1)
> - return r;
> - v >>= 1;
> - }
> - return 0;
> -}
> -
> void ff_h264_free_tables(H264Context *h)
> {
> int i;
> @@ -1284,113 +1266,30 @@ int ff_set_ref_count(H264Context *h,
> H264SliceContext *sl)
> return 0;
> }
>
> -static int find_start_code(const uint8_t *buf, int buf_size,
> - int buf_index, int next_avc)
> -{
> - // start code prefix search
> - for (; buf_index + 3 < next_avc; buf_index++)
> - // This should always succeed in the first iteration.
> - if (buf[buf_index] == 0 &&
> - buf[buf_index + 1] == 0 &&
> - buf[buf_index + 2] == 1)
> - break;
> -
> - if (buf_index + 3 >= buf_size)
> - return buf_size;
> -
> - return buf_index + 3;
> -}
> -
> -static int get_avc_nalsize(H264Context *h, const uint8_t *buf,
> - int buf_size, int *buf_index)
> +static int get_last_needed_nal(H264Context *h)
> {
> - 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 = (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;
> -}
> -
> -static int get_bit_length(H264Context *h, const uint8_t *buf,
> - const uint8_t *ptr, int dst_length,
> - int i, int next_avc)
> -{
> - if ((h->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc &&
> - buf[i] == 0x00 && buf[i + 1] == 0x00 &&
> - buf[i + 2] == 0x01 && buf[i + 3] == 0xE0)
> - h->workaround_bugs |= FF_BUG_TRUNCATED;
> -
> - if (!(h->workaround_bugs & FF_BUG_TRUNCATED))
> - while (dst_length > 0 && ptr[dst_length - 1] == 0)
> - dst_length--;
> -
> - if (!dst_length)
> - return 0;
> -
> - return 8 * dst_length - decode_rbsp_trailing(h, ptr + dst_length - 1);
> -}
> -
> -static int get_last_needed_nal(H264Context *h, const uint8_t *buf, int
> buf_size)
> -{
> - int next_avc = h->is_avc ? 0 : buf_size;
> - int nal_index = 0;
> - int buf_index = 0;
> int nals_needed = 0;
> + int i;
>
> - while(1) {
> + for (i = 0; i < h->pkt.nb_nals; i++) {
> + H2645NAL *nal = &h->pkt.nals[i];
> GetBitContext gb;
> - int nalsize = 0;
> - int dst_length, bit_length, consumed;
> - const uint8_t *ptr;
> -
> - if (buf_index >= next_avc) {
> - nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
> - 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;
> - }
> -
> - ptr = ff_h264_decode_nal(h, &h->slice_ctx[0], buf + buf_index,
> &dst_length, &consumed,
> - next_avc - buf_index);
> -
> - if (!ptr || dst_length < 0)
> - return AVERROR_INVALIDDATA;
> -
> - buf_index += consumed;
> -
> - bit_length = get_bit_length(h, buf, ptr, dst_length,
> - buf_index, next_avc);
> - nal_index++;
>
> /* packets can sometimes contain multiple PPS/SPS,
> * e.g. two PAFF field pictures in one packet, or a demuxer
> * which splits NALs strangely if so, when frame threading we
> * can't start the next thread until we've read all of them */
> - switch (h->nal_unit_type) {
> + switch (nal->type) {
> case NAL_SPS:
> case NAL_PPS:
> - nals_needed = nal_index;
> + nals_needed = i;
> break;
> case NAL_DPA:
> case NAL_IDR_SLICE:
> case NAL_SLICE:
> - init_get_bits(&gb, ptr, bit_length);
> + init_get_bits(&gb, nal->data + 1, (nal->size - 1) * 8);
> if (!get_ue_golomb(&gb))
> - nals_needed = nal_index;
> + nals_needed = i;
> }
> }
>
> @@ -1401,13 +1300,9 @@ static int decode_nal_units(H264Context *h, const
> uint8_t *buf, int buf_size,
> int parse_extradata)
> {
> AVCodecContext *const avctx = h->avctx;
> - H264SliceContext *sl;
> - int buf_index;
> - unsigned context_count;
> - int next_avc;
> + unsigned context_count = 0;
> int nals_needed = 0; ///< number of NALs that need decoding before the
> next frame thread starts
> - int nal_index;
> - int ret = 0;
> + int i, ret = 0;
>
> h->max_contexts = h->slice_context_count;
> if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
> @@ -1417,199 +1312,157 @@ static int decode_nal_units(H264Context *h, const
> uint8_t *buf, int buf_size,
> ff_h264_reset_sei(h);
> }
>
> - if (avctx->active_thread_type & FF_THREAD_FRAME)
> - nals_needed = get_last_needed_nal(h, buf, buf_size);
> -
> - {
> - buf_index = 0;
> - context_count = 0;
> - next_avc = h->is_avc ? 0 : buf_size;
> - nal_index = 0;
> - for (;;) {
> - int consumed;
> - int dst_length;
> - int bit_length;
> - const uint8_t *ptr;
> - int nalsize = 0;
> - int err;
> -
> - if (buf_index >= next_avc) {
> - nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
> - 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;
> - }
> + ret = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, h->is_avc,
> + h->nal_length_size, avctx->codec_id);
> + if (ret < 0) {
> + av_log(avctx, AV_LOG_ERROR,
> + "Error splitting the input into NAL units.\n");
> + return ret;
> + }
>
> - sl = &h->slice_ctx[context_count];
> + if (avctx->active_thread_type & FF_THREAD_FRAME)
> + nals_needed = get_last_needed_nal(h);
>
> - ptr = ff_h264_decode_nal(h, sl, buf + buf_index, &dst_length,
> - &consumed, next_avc - buf_index);
> - if (!ptr || dst_length < 0) {
> - ret = -1;
> - goto end;
> - }
> + for (i = 0; i < h->pkt.nb_nals; i++) {
> + H2645NAL *nal = &h->pkt.nals[i];
> + H264SliceContext *sl = &h->slice_ctx[context_count];
> + int err;
>
> - bit_length = get_bit_length(h, buf, ptr, dst_length,
> - buf_index + consumed, next_avc);
> + if (avctx->skip_frame >= AVDISCARD_NONREF &&
> + nal->ref_idc == 0 && nal->type != NAL_SEI)
> + continue;
>
> - if (h->avctx->debug & FF_DEBUG_STARTCODE)
> - av_log(h->avctx, AV_LOG_DEBUG,
> - "NAL %d at %d/%d length %d\n",
> - h->nal_unit_type, buf_index, buf_size, dst_length);
> + // FIXME these should stop being context-global variables
> + h->nal_ref_idc = nal->ref_idc;
> + h->nal_unit_type = nal->type;
>
> - if (h->is_avc && (nalsize != consumed) && nalsize)
> - av_log(h->avctx, AV_LOG_DEBUG,
> - "AVC: Consumed only %d bytes instead of %d\n",
> - consumed, nalsize);
> +again:
> + /* Ignore every NAL unit type except PPS and SPS during extradata
> + * parsing. Decoding slices is not possible in codec init
> + * with frame-mt */
> + if (parse_extradata && HAVE_THREADS &&
> + (h->avctx->active_thread_type & FF_THREAD_FRAME) &&
> + (nal->type != NAL_PPS && nal->type != NAL_SPS)) {
> + if (nal->type < NAL_AUD || nal->type > NAL_AUXILIARY_SLICE)
> + av_log(avctx, AV_LOG_INFO,
> + "Ignoring NAL unit %d during extradata parsing\n",
> + h->nal_unit_type);
using nal->type as argument in the av_log would be better
> + nal->type = NAL_FF_IGNORE;
I don't think it is used anywhere but to keep the old behaviour you
should set h->nal_unit_type NAL_FF_IGNORE too. I would just move the
setting of h->nal_ref_idc and h->nal_unit_type below this block.
> + }
>
> - buf_index += consumed;
> - nal_index++;
> + err = 0;
> + switch (nal->type) {
> + case NAL_IDR_SLICE:
> + if (nal->type != NAL_IDR_SLICE) {
this looks like it will be always false, not changed by this commit but
in 51d8725a6e4c7f989d6f0f38b59cb54a2d72846c
looks fine otherwise
Janne
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel