diff options
author | jmarshallnz <jcmarsha@gmail.com> | 2014-03-10 15:09:43 +1300 |
---|---|---|
committer | jmarshallnz <jcmarsha@gmail.com> | 2014-03-10 15:09:43 +1300 |
commit | 84c762e241ed3135412fc73f2eef33e502cc0fda (patch) | |
tree | 60e5554cb1c6536887f23f752471c19cf17f408e /lib/ffmpeg | |
parent | 59e9f7f11fb0fc3fccebf7ed19dddb17c6d7f342 (diff) | |
parent | 297d0522cf23b7558baeb45b3e4d0fabcadd6ff5 (diff) |
Merge pull request #4228 from afedchin/dxva_h264_intel
[DXVA] Fix h264 deconding with refs > 11 on recent Intel GPUs (SNB/IVB)
Diffstat (limited to 'lib/ffmpeg')
4 files changed, 147 insertions, 4 deletions
diff --git a/lib/ffmpeg/libavcodec/dxva2.h b/lib/ffmpeg/libavcodec/dxva2.h index ac39e06917..2639d89d90 100644 --- a/lib/ffmpeg/libavcodec/dxva2.h +++ b/lib/ffmpeg/libavcodec/dxva2.h @@ -49,6 +49,7 @@ */ #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards +#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface /** * This structure is used to provides the necessary configurations and data diff --git a/lib/ffmpeg/libavcodec/dxva2_h264.c b/lib/ffmpeg/libavcodec/dxva2_h264.c index 6ae5cd919f..cbb05e2dd0 100644 --- a/lib/ffmpeg/libavcodec/dxva2_h264.c +++ b/lib/ffmpeg/libavcodec/dxva2_h264.c @@ -115,6 +115,8 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) pp->Reserved16Bits = 0; + else if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) + pp->Reserved16Bits = 0x34c; else pp->Reserved16Bits = 3; /* FIXME is there a way to detect the right mode ? */ pp->StatusReportFeedbackNumber = 1 + ctx->report_id++; @@ -194,8 +196,18 @@ static void fill_slice_short(DXVA_Slice_H264_Short *slice, slice->wBadSliceChopping = 0; } +static int get_refpic_index(const DXVA_PicParams_H264 *pp, int surface_index) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) { + if ((pp->RefFrameList[i].bPicEntry & 0x7f) == surface_index) + return i; + } + return 0x7f; +} + static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, - unsigned position, unsigned size) + const DXVA_PicParams_H264 *pp, unsigned position, unsigned size) { const H264Context *h = avctx->priv_data; struct dxva_context *ctx = avctx->hwaccel_context; @@ -228,8 +240,12 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, if (list < h->list_count && i < h->ref_count[list]) { const Picture *r = &h->ref_list[list][i]; unsigned plane; - fill_picture_entry(&slice->RefPicList[list][i], - ff_dxva2_get_surface_index(ctx, r), + unsigned index; + if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) + index = ff_dxva2_get_surface_index(ctx, r); + else + index = get_refpic_index(pp, ff_dxva2_get_surface_index(ctx, r)); + fill_picture_entry(&slice->RefPicList[list][i], index, r->f.reference == PICT_BOTTOM_FIELD); for (plane = 0; plane < 3; plane++) { int w, o; @@ -414,7 +430,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx, position, size); else fill_slice_long(avctx, &ctx_pic->slice_long[ctx_pic->slice_count], - position, size); + &ctx_pic->pp, position, size); ctx_pic->slice_count++; if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI) diff --git a/lib/ffmpeg/patches/0069-dxva2_h264-set-the-correct-ref-frame-index-in-the-long-slice-struct.patch b/lib/ffmpeg/patches/0069-dxva2_h264-set-the-correct-ref-frame-index-in-the-long-slice-struct.patch new file mode 100644 index 0000000000..94f12d881e --- /dev/null +++ b/lib/ffmpeg/patches/0069-dxva2_h264-set-the-correct-ref-frame-index-in-the-long-slice-struct.patch @@ -0,0 +1,66 @@ +From patchwork Sat Mar 2 11:15:29 2013 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [1/2] dxva2_h264: set the correct ref frame index in the long slice + struct +Date: Sat, 02 Mar 2013 10:15:29 -0000 +From: Hendrik Leppkes <h.leppkes@gmail.com> +X-Patchwork-Id: 35320 +Message-Id: <1362222930-4764-2-git-send-email-h.leppkes@gmail.com> +To: libav-devel@libav.org + +The latest H.264 DXVA specification states that the index in this +structure should refer to a valid entry in the RefFrameList of the picture +parameter structure, and not to the actual surface index. + +Fixes H.264 DXVA2 decoding on recent Intel GPUs (tested on Sandy and Ivy) + +--- +libavcodec/dxva2_h264.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c +index 7009d6c..9dcb005 100644 +--- a/libavcodec/dxva2_h264.c ++++ b/libavcodec/dxva2_h264.c +@@ -194,8 +194,18 @@ static void fill_slice_short(DXVA_Slice_H264_Short *slice, + slice->wBadSliceChopping = 0; + } + ++static int get_refpic_index(const DXVA_PicParams_H264 *pp, int surface_index) ++{ ++ int i; ++ for (i = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) { ++ if ((pp->RefFrameList[i].bPicEntry & 0x7f) == surface_index) ++ return i; ++ } ++ return 0x7f; ++} ++ + static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, +- unsigned position, unsigned size) ++ const DXVA_PicParams_H264 *pp, unsigned position, unsigned size) + { + const H264Context *h = avctx->priv_data; + struct dxva_context *ctx = avctx->hwaccel_context; +@@ -228,8 +238,8 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, + if (list < h->list_count && i < h->ref_count[list]) { + const Picture *r = &h->ref_list[list][i]; + unsigned plane; +- fill_picture_entry(&slice->RefPicList[list][i], +- ff_dxva2_get_surface_index(ctx, r), ++ unsigned index = get_refpic_index(pp, ff_dxva2_get_surface_index(ctx, r)); ++ fill_picture_entry(&slice->RefPicList[list][i], index, + r->f.reference == PICT_BOTTOM_FIELD); + for (plane = 0; plane < 3; plane++) { + int w, o; +@@ -413,7 +423,7 @@ static int decode_slice(AVCodecContext *avctx, + position, size); + else + fill_slice_long(avctx, &ctx_pic->slice_long[ctx_pic->slice_count], +- position, size); ++ &ctx_pic->pp, position, size); + ctx_pic->slice_count++; + + if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI) diff --git a/lib/ffmpeg/patches/0070-dxva2_h264-add-a-workaround-for-old-intel-GPUs.patch b/lib/ffmpeg/patches/0070-dxva2_h264-add-a-workaround-for-old-intel-GPUs.patch new file mode 100644 index 0000000000..d87b19f433 --- /dev/null +++ b/lib/ffmpeg/patches/0070-dxva2_h264-add-a-workaround-for-old-intel-GPUs.patch @@ -0,0 +1,60 @@ +From patchwork Sat Mar 2 11:15:30 2013 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [2/2] dxva2_h264: add a workaround for old intel GPUs +Date: Sat, 02 Mar 2013 10:15:30 -0000 +From: Hendrik Leppkes <h.leppkes@gmail.com> +X-Patchwork-Id: 35321 +Message-Id: <1362222930-4764-3-git-send-email-h.leppkes@gmail.com> +To: libav-devel@libav.org + +Old Intel GPUs expect the reference frame index to the actual surface, +instead of the index into RefFrameList as specified by the spec. + +This workaround should be set when using one of the "ClearVideo" decoder +devices. + +--- +libavcodec/dxva2.h | 1 + + libavcodec/dxva2_h264.c | 8 +++++++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/dxva2.h b/libavcodec/dxva2.h +index d161eb9..78939be 100644 +--- a/libavcodec/dxva2.h ++++ b/libavcodec/dxva2.h +@@ -42,6 +42,7 @@ + */ + + #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards ++#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface + + /** + * This structure is used to provides the necessary configurations and data +diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c +index 9dcb005..4b3f83c 100644 +--- a/libavcodec/dxva2_h264.c ++++ b/libavcodec/dxva2_h264.c +@@ -115,6 +115,8 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context + pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; + if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) + pp->Reserved16Bits = 0; ++ else if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) ++ pp->Reserved16Bits = 0x34c; + else + pp->Reserved16Bits = 3; /* FIXME is there a way to detect the right mode ? */ + pp->StatusReportFeedbackNumber = 1 + ctx->report_id++; +@@ -238,7 +240,11 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, + if (list < h->list_count && i < h->ref_count[list]) { + const Picture *r = &h->ref_list[list][i]; + unsigned plane; +- unsigned index = get_refpic_index(pp, ff_dxva2_get_surface_index(ctx, r)); ++ unsigned index; ++ if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO) ++ index = ff_dxva2_get_surface_index(ctx, r); ++ else ++ index = get_refpic_index(pp, ff_dxva2_get_surface_index(ctx, r)); + fill_picture_entry(&slice->RefPicList[list][i], index, + r->f.reference == PICT_BOTTOM_FIELD); + for (plane = 0; plane < 3; plane++) { |