summaryrefslogtreecommitdiff
path: root/libavcodec/h264dec.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2016-06-12 14:22:50 +0200
committerAnton Khirnov <anton@khirnov.net>2016-07-15 15:33:54 +0200
commit4a9bab3db0d9ec449ebc8b5e823374d1d1df7761 (patch)
tree496394aa8226d1b340b40104f34ff8bb57f1d715 /libavcodec/h264dec.c
parentf450cc7bc595155bacdb9f5d2414a076ccf81b4a (diff)
h264: fix decoding multiple fields per packet with slice threads
Since we only know whether a NAL unit corresponds to a new field after parsing the slice header, this requires reorganizing the calls to slice parsing, per-slice/field/frame init and actual decoding. In the previous code, the function for slice header decoding also immediately started a new field/frame as necessary, so any slices already queued for decoding would no longer be decodable. After this patch, we first parse the slice header, and if we determine that a new field needs to be started we decode all the queued slices.
Diffstat (limited to 'libavcodec/h264dec.c')
-rw-r--r--libavcodec/h264dec.c47
1 files changed, 14 insertions, 33 deletions
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 3ce76eae64..1086eab8d3 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -508,7 +508,6 @@ static int get_last_needed_nal(H264Context *h)
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
{
AVCodecContext *const avctx = h->avctx;
- unsigned context_count = 0;
int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts
int i, ret = 0;
@@ -532,8 +531,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
for (i = 0; i < h->pkt.nb_nals; i++) {
H2645NAL *nal = &h->pkt.nals[i];
- H264SliceContext *sl = &h->slice_ctx[context_count];
- int err;
+ int max_slice_ctx, err;
if (avctx->skip_frame >= AVDISCARD_NONREF &&
nal->ref_idc == 0 && nal->type != H264_NAL_SEI)
@@ -548,12 +546,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
case H264_NAL_IDR_SLICE:
idr(h); // FIXME ensure we don't lose some frames if there is reordering
case H264_NAL_SLICE:
- sl->gb = nal->gb;
-
- if ((err = ff_h264_decode_slice_header(h, sl, nal)))
- break;
-
- if (sl->redundant_pic_count > 0)
+ if ((err = ff_h264_queue_decode_slice(h, nal)))
break;
if (avctx->active_thread_type & FF_THREAD_FRAME && !h->avctx->hwaccel &&
@@ -562,18 +555,14 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
h->setup_finished = 1;
}
- if ((avctx->skip_frame < AVDISCARD_NONREF || nal->ref_idc) &&
- (avctx->skip_frame < AVDISCARD_BIDIR ||
- sl->slice_type_nos != AV_PICTURE_TYPE_B) &&
- (avctx->skip_frame < AVDISCARD_NONKEY ||
- h->cur_pic_ptr->f->key_frame) &&
- avctx->skip_frame < AVDISCARD_ALL) {
- if (avctx->hwaccel) {
+ max_slice_ctx = avctx->hwaccel ? 1 : h->nb_slice_ctx;
+ if (h->nb_slice_ctx_queued == max_slice_ctx) {
+ if (avctx->hwaccel)
ret = avctx->hwaccel->decode_slice(avctx, nal->raw_data, nal->raw_size);
- if (ret < 0)
- return ret;
- } else
- context_count++;
+ else
+ ret = ff_h264_execute_decode_slices(h);
+ if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+ goto end;
}
break;
case H264_NAL_DPA:
@@ -611,23 +600,14 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
nal->type, nal->size_bits);
}
- if (context_count == h->nb_slice_ctx) {
- ret = ff_h264_execute_decode_slices(h, context_count);
- if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
- goto end;
- context_count = 0;
- }
-
if (err < 0) {
av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n");
- sl->ref_count[0] = sl->ref_count[1] = sl->list_count = 0;
}
}
- if (context_count) {
- ret = ff_h264_execute_decode_slices(h, context_count);
- if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
- goto end;
- }
+
+ ret = ff_h264_execute_decode_slices(h);
+ if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+ goto end;
ret = 0;
end:
@@ -687,6 +667,7 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data,
h->flags = avctx->flags;
h->setup_finished = 0;
+ h->nb_slice_ctx_queued = 0;
/* end of stream, output what is still in the buffers */
out: