aboutsummaryrefslogtreecommitdiff
path: root/lib/ffmpeg/patches/0069-dxva2_h264-set-the-correct-ref-frame-index-in-the-long-slice-struct.patch
blob: 94f12d881e8b644e234fedceaea94682ab541ed1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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)