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)
|