aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2013-03-02 10:15:29 +0000
committerAnton Fedchin <afedchin@ruswizards.com>2014-03-07 21:18:19 +0400
commit478ba25be5680cc4d78a4d4181295839aad6db4a (patch)
treeb7faf8c4b829bc195a22346e1d632ebd54b3895e /lib
parent28f60eda8a95d559048e1bcc280a42d92f4bf6db (diff)
ffmpeg: dxva2_h264: set the correct ref frame index in the long slice struct
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)
Diffstat (limited to 'lib')
-rw-r--r--lib/ffmpeg/libavcodec/dxva2_h264.c18
-rw-r--r--lib/ffmpeg/patches/0069-dxva2_h264-set-the-correct-ref-frame-index-in-the-long-slice-struct.patch66
2 files changed, 80 insertions, 4 deletions
diff --git a/lib/ffmpeg/libavcodec/dxva2_h264.c b/lib/ffmpeg/libavcodec/dxva2_h264.c
index 6ae5cd919f..cc6d8307bc 100644
--- a/lib/ffmpeg/libavcodec/dxva2_h264.c
+++ b/lib/ffmpeg/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;
@@ -414,7 +424,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)