summaryrefslogtreecommitdiffstats
path: root/libavcodec/vc1dec.c
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2012-01-13 22:13:51 +0100
committerMichael Niedermayer <michaelni@gmx.at>2012-10-20 00:07:14 +0200
commitb87ff3449662e4f6b8415471dd4b7c76f06fbcda (patch)
tree285b2d3f8ed445b744707138acdc51d04f00ae59 /libavcodec/vc1dec.c
parent8fb8d539a4c594a58df226bc1bd7a4d149f39424 (diff)
downloadffmpeg-streaming-b87ff3449662e4f6b8415471dd4b7c76f06fbcda.zip
ffmpeg-streaming-b87ff3449662e4f6b8415471dd4b7c76f06fbcda.tar.gz
vc1: implement vc1 field interlaced dxva2 decoding
Tested-by: Gwenole Beauchesne <gb.devel@gmail.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/vc1dec.c')
-rw-r--r--libavcodec/vc1dec.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 7aae8cc..3832b2a 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -5318,7 +5318,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
MpegEncContext *s = &v->s;
AVFrame *pict = data;
uint8_t *buf2 = NULL;
- const uint8_t *buf_start = buf;
+ const uint8_t *buf_start = buf, *buf_start_second_field = NULL;
int mb_height, n_slices1=-1;
struct {
uint8_t *buf;
@@ -5326,6 +5326,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
int mby_start;
} *slices = NULL, *tmp;
+ v->second_field = 0;
+
if(s->flags & CODEC_FLAG_LOW_DELAY)
s->low_delay = 1;
@@ -5372,6 +5374,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
break;
case VC1_CODE_FIELD: {
int buf_size3;
+ if (avctx->hwaccel ||
+ s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+ buf_start_second_field = start;
tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
if (!tmp)
goto err;
@@ -5423,6 +5428,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
av_log(avctx, AV_LOG_ERROR, "Error in WVC1 interlaced frame\n");
goto err;
} else { // found field marker, unescape second field
+ if (avctx->hwaccel ||
+ s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+ buf_start_second_field = divider;
tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
if (!tmp)
goto err;
@@ -5558,12 +5566,42 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
&&s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
ff_vdpau_vc1_decode_picture(s, buf_start, (buf + buf_size) - buf_start);
else if (avctx->hwaccel) {
- if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0)
- goto err;
- if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
- goto err;
- if (avctx->hwaccel->end_frame(avctx) < 0)
- goto err;
+ if (v->field_mode && buf_start_second_field) {
+ // decode first field
+ s->picture_structure = PICT_BOTTOM_FIELD - v->tff;
+ if (avctx->hwaccel->start_frame(avctx, buf_start, buf_start_second_field - buf_start) < 0)
+ goto err;
+ if (avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start) < 0)
+ goto err;
+ if (avctx->hwaccel->end_frame(avctx) < 0)
+ goto err;
+
+ // decode second field
+ s->gb = slices[n_slices1 + 1].gb;
+ s->picture_structure = PICT_TOP_FIELD + v->tff;
+ v->second_field = 1;
+ v->pic_header_flag = 0;
+ if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "parsing header for second field failed");
+ goto err;
+ }
+ v->s.current_picture_ptr->f.pict_type = v->s.pict_type;
+
+ if (avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0)
+ goto err;
+ if (avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0)
+ goto err;
+ if (avctx->hwaccel->end_frame(avctx) < 0)
+ goto err;
+ } else {
+ s->picture_structure = PICT_FRAME;
+ if (avctx->hwaccel->start_frame(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
+ goto err;
+ if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
+ goto err;
+ if (avctx->hwaccel->end_frame(avctx) < 0)
+ goto err;
+ }
} else {
ff_er_frame_start(s);
OpenPOWER on IntegriCloud