aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Borsboom <jerome.borsboom@carpalis.nl>2018-05-09 07:50:28 +0200
committerMark Thompson <sw@jkqxz.net>2018-06-17 16:35:36 +0100
commit89651c82b86e43021b0ebcde129fd98a2b922fa2 (patch)
tree3c19b43f71b06f9d33062481b4648dc8115d0517
parent3d028b7b72a071df7ec2b5a2ccdbf767eec60505 (diff)
downloadffmpeg-89651c82b86e43021b0ebcde129fd98a2b922fa2.tar.gz
avcodec/vc1: support multi-slice field interlaced pictures with hwaccel
When using hardware accelerated decoding for multi-slice field interlaced pictures, only the first slice was decoded. This patch adds the neccesary looping over the remaining slices that may exist in field interlaced pictures. Additionally, we align the calculation of mby_start for the second field with the method given in VC-1 spec. Signed-off-by: Jerome Borsboom <jerome.borsboom@carpalis.nl>
-rw-r--r--libavcodec/vc1dec.c67
1 files changed, 60 insertions, 7 deletions
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 4f7b20a4a4..fdbc852ec2 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -698,9 +698,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
slices[n_slices].buf);
init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
buf_size3 << 3);
- /* assuming that the field marker is at the exact middle,
- hope it's correct */
- slices[n_slices].mby_start = s->mb_height + 1 >> 1;
+ slices[n_slices].mby_start = avctx->coded_height + 31 >> 5;
slices[n_slices].rawbuf = start;
slices[n_slices].raw_size = size + 4;
n_slices1 = n_slices - 1; // index of the last slice of the first field
@@ -903,13 +901,41 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
s->picture_structure = PICT_BOTTOM_FIELD - v->tff;
if ((ret = avctx->hwaccel->start_frame(avctx, buf_start, buf_start_second_field - buf_start)) < 0)
goto err;
- if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start)) < 0)
- goto err;
+
+ if (n_slices1 == -1) {
+ // no slices, decode the field as-is
+ if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start)) < 0)
+ goto err;
+ } else {
+ if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start, slices[0].rawbuf - buf_start)) < 0)
+ goto err;
+
+ for (i = 0 ; i < n_slices1 + 1; i++) {
+ s->gb = slices[i].gb;
+ s->mb_y = slices[i].mby_start;
+
+ v->pic_header_flag = get_bits1(&s->gb);
+ if (v->pic_header_flag) {
+ if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
+ av_log(v->s.avctx, AV_LOG_ERROR, "Slice header damaged\n");
+ ret = AVERROR_INVALIDDATA;
+ if (avctx->err_recognition & AV_EF_EXPLODE)
+ goto err;
+ continue;
+ }
+ }
+
+ if ((ret = avctx->hwaccel->decode_slice(avctx, slices[i].rawbuf, slices[i].raw_size)) < 0)
+ goto err;
+ }
+ }
+
if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
goto err;
// decode second field
s->gb = slices[n_slices1 + 1].gb;
+ s->mb_y = slices[n_slices1 + 1].mby_start;
s->picture_structure = PICT_TOP_FIELD + v->tff;
v->second_field = 1;
v->pic_header_flag = 0;
@@ -922,8 +948,35 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
if ((ret = avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field)) < 0)
goto err;
- if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field)) < 0)
- goto err;
+
+ if (n_slices - n_slices1 == 2) {
+ // no slices, decode the field as-is
+ if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field)) < 0)
+ goto err;
+ } else {
+ if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start_second_field, slices[n_slices1 + 2].rawbuf - buf_start_second_field)) < 0)
+ goto err;
+
+ for (i = n_slices1 + 2; i < n_slices; i++) {
+ s->gb = slices[i].gb;
+ s->mb_y = slices[i].mby_start;
+
+ v->pic_header_flag = get_bits1(&s->gb);
+ if (v->pic_header_flag) {
+ if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
+ av_log(v->s.avctx, AV_LOG_ERROR, "Slice header damaged\n");
+ ret = AVERROR_INVALIDDATA;
+ if (avctx->err_recognition & AV_EF_EXPLODE)
+ goto err;
+ continue;
+ }
+ }
+
+ if ((ret = avctx->hwaccel->decode_slice(avctx, slices[i].rawbuf, slices[i].raw_size)) < 0)
+ goto err;
+ }
+ }
+
if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
goto err;
} else {