diff options
author | Hendrik Leppkes <h.leppkes@gmail.com> | 2012-01-13 22:13:51 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-10-20 00:07:14 +0200 |
commit | b87ff3449662e4f6b8415471dd4b7c76f06fbcda (patch) | |
tree | 285b2d3f8ed445b744707138acdc51d04f00ae59 | |
parent | 8fb8d539a4c594a58df226bc1bd7a4d149f39424 (diff) | |
download | ffmpeg-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>
-rw-r--r-- | libavcodec/dxva2_vc1.c | 7 | ||||
-rw-r--r-- | libavcodec/vc1dec.c | 52 |
2 files changed, 50 insertions, 9 deletions
diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index e47db4d9c1..ed4836dc8b 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -68,7 +68,7 @@ static void fill_picture_parameters(AVCodecContext *avctx, pp->bPicStructure |= 0x01; if (s->picture_structure & PICT_BOTTOM_FIELD) pp->bPicStructure |= 0x02; - pp->bSecondField = v->interlace && v->fcm != ILACE_FIELD && !s->first_field; + pp->bSecondField = v->interlace && v->fcm == ILACE_FIELD && v->second_field; pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type; pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type; pp->bBidirectionalAveragingMode = (1 << 7) | @@ -183,8 +183,11 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, result = data_size <= dxva_size ? 0 : -1; if (!result) { - if (start_code_size > 0) + if (start_code_size > 0) { memcpy(dxva_data, start_code, start_code_size); + if (v->second_field) + dxva_data[3] = 0x0c; + } memcpy(dxva_data + start_code_size, ctx_pic->bitstream + slice->dwSliceDataLocation, slice_size); if (padding > 0) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 7aae8cc926..3832b2afba 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); |