Merge lp:~3v1n0/ubuntu/trusty/vdpau-video/fix-buffers into lp:ubuntu/trusty/vdpau-video

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merge reported by: Martin Pitt
Merged at revision: not available
Proposed branch: lp:~3v1n0/ubuntu/trusty/vdpau-video/fix-buffers
Merge into: lp:ubuntu/trusty/vdpau-video
Diff against target: 4699 lines (+4523/-11)
17 files modified
.pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.c (+257/-0)
.pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.h (+115/-0)
.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.c (+259/-0)
.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.h (+116/-0)
.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_decode.c (+1271/-0)
.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_video.c (+995/-0)
.pc/03_mark_destroyed_buffers_as_deleted.patch/src/vdpau_decode.c (+1264/-0)
.pc/applied-patches (+3/-0)
debian/changelog (+7/-0)
debian/patches/01_dont_clear_va_buffer_too_early.patch (+56/-0)
debian/patches/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch (+111/-0)
debian/patches/03_mark_destroyed_buffers_as_deleted.patch (+28/-0)
debian/patches/series (+3/-0)
src/vdpau_buffer.c (+24/-1)
src/vdpau_buffer.h (+8/-0)
src/vdpau_decode.c (+4/-10)
src/vdpau_video.c (+2/-0)
To merge this branch: bzr merge lp:~3v1n0/ubuntu/trusty/vdpau-video/fix-buffers
Reviewer Review Type Date Requested Status
Martin Pitt Approve
Review via email: mp+218516@code.launchpad.net

Commit message

Added patch-set from upstream to fix crash when using gstreamer-vaapi

To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote :

Uploaded as

vdpau-video (0.7.3-2ubuntu1.1) trusty-proposed; urgency=medium

Thanks!

review: Approve
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Thank you!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory '.pc/01_dont_clear_va_buffer_too_early.patch'
=== added directory '.pc/01_dont_clear_va_buffer_too_early.patch/src'
=== added file '.pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.c'
--- .pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.c 1970-01-01 00:00:00 +0000
+++ .pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.c 2014-05-06 21:31:51 +0000
@@ -0,0 +1,257 @@
1/*
2 * vdpau_buffer.c - VDPAU backend for VA-API (VA buffers)
3 *
4 * vdpau-video (C) 2009-2011 Splitted-Desktop Systems
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "sysdeps.h"
22#include "vdpau_buffer.h"
23#include "vdpau_driver.h"
24#include "vdpau_video.h"
25#include "vdpau_dump.h"
26#include "utils.h"
27
28#define DEBUG 1
29#include "debug.h"
30
31
32// Create VA buffer object
33object_buffer_p
34create_va_buffer(
35 vdpau_driver_data_t *driver_data,
36 VAContextID context,
37 VABufferType buffer_type,
38 unsigned int num_elements,
39 unsigned int size
40)
41{
42 VABufferID buffer_id;
43 object_buffer_p obj_buffer;
44
45 buffer_id = object_heap_allocate(&driver_data->buffer_heap);
46 if (buffer_id == VA_INVALID_BUFFER)
47 return NULL;
48
49 obj_buffer = VDPAU_BUFFER(buffer_id);
50 if (!obj_buffer)
51 return NULL;
52
53 obj_buffer->va_context = context;
54 obj_buffer->type = buffer_type;
55 obj_buffer->max_num_elements = num_elements;
56 obj_buffer->num_elements = num_elements;
57 obj_buffer->buffer_size = size * num_elements;
58 obj_buffer->buffer_data = malloc(obj_buffer->buffer_size);
59 obj_buffer->mtime = 0;
60
61 if (!obj_buffer->buffer_data) {
62 destroy_va_buffer(driver_data, obj_buffer);
63 return NULL;
64 }
65 return obj_buffer;
66}
67
68// Destroy VA buffer object
69void
70destroy_va_buffer(
71 vdpau_driver_data_t *driver_data,
72 object_buffer_p obj_buffer
73)
74{
75 if (!obj_buffer)
76 return;
77
78 if (obj_buffer->buffer_data) {
79 free(obj_buffer->buffer_data);
80 obj_buffer->buffer_data = NULL;
81 }
82 object_heap_free(&driver_data->buffer_heap, (object_base_p)obj_buffer);
83}
84
85// Schedule VA buffer object for destruction
86void
87schedule_destroy_va_buffer(
88 vdpau_driver_data_p driver_data,
89 object_buffer_p obj_buffer
90)
91{
92 object_context_p obj_context = VDPAU_CONTEXT(obj_buffer->va_context);
93 if (!obj_context)
94 return;
95
96 realloc_buffer(
97 &obj_context->dead_buffers,
98 &obj_context->dead_buffers_count_max,
99 16 + obj_context->dead_buffers_count,
100 sizeof(*obj_context->dead_buffers)
101 );
102
103 ASSERT(obj_context->dead_buffers);
104 obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id;
105 obj_context->dead_buffers_count++;
106}
107
108// vaCreateBuffer
109VAStatus
110vdpau_CreateBuffer(
111 VADriverContextP ctx,
112 VAContextID context,
113 VABufferType type,
114 unsigned int size,
115 unsigned int num_elements,
116 void *data,
117 VABufferID *buf_id
118)
119{
120 VDPAU_DRIVER_DATA_INIT;
121
122 if (buf_id)
123 *buf_id = VA_INVALID_BUFFER;
124
125 /* Validate type */
126 switch (type) {
127 case VAPictureParameterBufferType:
128 case VAIQMatrixBufferType:
129 case VASliceParameterBufferType:
130 case VASliceDataBufferType:
131 case VABitPlaneBufferType:
132 case VAImageBufferType:
133 /* Ok */
134 break;
135 default:
136 D(bug("ERROR: unsupported buffer type %d\n", type));
137 return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
138 }
139
140 object_buffer_p obj_buffer;
141 obj_buffer = create_va_buffer(driver_data, context, type, num_elements, size);
142 if (!obj_buffer)
143 return VA_STATUS_ERROR_ALLOCATION_FAILED;
144
145 if (data)
146 memcpy(obj_buffer->buffer_data, data, obj_buffer->buffer_size);
147
148 if (buf_id)
149 *buf_id = obj_buffer->base.id;
150
151 return VA_STATUS_SUCCESS;
152}
153
154// vaDestroyBuffer
155VAStatus
156vdpau_DestroyBuffer(
157 VADriverContextP ctx,
158 VABufferID buffer_id
159)
160{
161 VDPAU_DRIVER_DATA_INIT;
162
163 object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id);
164
165 if (obj_buffer)
166 destroy_va_buffer(driver_data, obj_buffer);
167
168 return VA_STATUS_SUCCESS;
169}
170
171// vaBufferSetNumElements
172VAStatus
173vdpau_BufferSetNumElements(
174 VADriverContextP ctx,
175 VABufferID buf_id,
176 unsigned int num_elements
177)
178{
179 VDPAU_DRIVER_DATA_INIT;
180
181 object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id);
182 if (!obj_buffer)
183 return VA_STATUS_ERROR_INVALID_BUFFER;
184
185 if (num_elements < 0 || num_elements > obj_buffer->max_num_elements)
186 return VA_STATUS_ERROR_UNKNOWN;
187
188 obj_buffer->num_elements = num_elements;
189 return VA_STATUS_SUCCESS;
190}
191
192// vaMapBuffer
193VAStatus
194vdpau_MapBuffer(
195 VADriverContextP ctx,
196 VABufferID buf_id,
197 void **pbuf
198)
199{
200 VDPAU_DRIVER_DATA_INIT;
201
202 object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id);
203 if (!obj_buffer)
204 return VA_STATUS_ERROR_INVALID_BUFFER;
205
206 if (pbuf)
207 *pbuf = obj_buffer->buffer_data;
208
209 if (obj_buffer->buffer_data == NULL)
210 return VA_STATUS_ERROR_UNKNOWN;
211
212 ++obj_buffer->mtime;
213 return VA_STATUS_SUCCESS;
214}
215
216// vaUnmapBuffer
217VAStatus
218vdpau_UnmapBuffer(
219 VADriverContextP ctx,
220 VABufferID buf_id
221)
222{
223 VDPAU_DRIVER_DATA_INIT;
224
225 object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id);
226 if (!obj_buffer)
227 return VA_STATUS_ERROR_INVALID_BUFFER;
228
229 ++obj_buffer->mtime;
230 return VA_STATUS_SUCCESS;
231}
232
233// vaBufferInfo
234VAStatus
235vdpau_BufferInfo(
236 VADriverContextP ctx,
237 VAContextID context,
238 VABufferID buf_id,
239 VABufferType *type,
240 unsigned int *size,
241 unsigned int *num_elements
242)
243{
244 VDPAU_DRIVER_DATA_INIT;
245
246 object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id);
247 if (!obj_buffer)
248 return VA_STATUS_ERROR_INVALID_BUFFER;
249
250 if (type)
251 *type = obj_buffer->type;
252 if (size)
253 *size = obj_buffer->buffer_size / obj_buffer->num_elements;
254 if (num_elements)
255 *num_elements = obj_buffer->num_elements;
256 return VA_STATUS_SUCCESS;
257}
0258
=== added file '.pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.h'
--- .pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.h 1970-01-01 00:00:00 +0000
+++ .pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.h 2014-05-06 21:31:51 +0000
@@ -0,0 +1,115 @@
1/*
2 * vdpau_buffer.h - VDPAU backend for VA-API (VA buffers)
3 *
4 * vdpau-video (C) 2009-2011 Splitted-Desktop Systems
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#ifndef VDPAU_BUFFER_H
22#define VDPAU_BUFFER_H
23
24#include "vdpau_driver.h"
25
26typedef struct object_buffer object_buffer_t;
27struct object_buffer {
28 struct object_base base;
29 VAContextID va_context;
30 VABufferType type;
31 void *buffer_data;
32 unsigned int buffer_size;
33 unsigned int max_num_elements;
34 unsigned int num_elements;
35 uint64_t mtime;
36};
37
38// Create VA buffer object
39object_buffer_p
40create_va_buffer(
41 vdpau_driver_data_p driver_data,
42 VAContextID context,
43 VABufferType buffer_type,
44 unsigned int num_elements,
45 unsigned int size
46) attribute_hidden;
47
48// Destroy VA buffer object
49void
50destroy_va_buffer(
51 vdpau_driver_data_p driver_data,
52 object_buffer_p obj_buffer
53) attribute_hidden;
54
55// Schedule VA buffer object for destruction
56void
57schedule_destroy_va_buffer(
58 vdpau_driver_data_p driver_data,
59 object_buffer_p obj_buffer
60) attribute_hidden;
61
62// vaCreateBuffer
63VAStatus
64vdpau_CreateBuffer(
65 VADriverContextP ctx,
66 VAContextID context,
67 VABufferType type,
68 unsigned int size,
69 unsigned int num_elements,
70 void *data,
71 VABufferID *buf_id
72) attribute_hidden;
73
74// vaDestroyBuffer
75VAStatus
76vdpau_DestroyBuffer(
77 VADriverContextP ctx,
78 VABufferID buffer_id
79) attribute_hidden;
80
81// vaBufferSetNumElements
82VAStatus
83vdpau_BufferSetNumElements(
84 VADriverContextP ctx,
85 VABufferID buf_id,
86 unsigned int num_elements
87) attribute_hidden;
88
89// vaMapBuffer
90VAStatus
91vdpau_MapBuffer(
92 VADriverContextP ctx,
93 VABufferID buf_id,
94 void **pbuf
95) attribute_hidden;
96
97// vaUnmapBuffer
98VAStatus
99vdpau_UnmapBuffer(
100 VADriverContextP ctx,
101 VABufferID buf_id
102) attribute_hidden;
103
104// vaBufferInfo
105VAStatus
106vdpau_BufferInfo(
107 VADriverContextP ctx,
108 VAContextID context,
109 VABufferID buf_id,
110 VABufferType *type,
111 unsigned int *size,
112 unsigned int *num_elements
113) attribute_hidden;
114
115#endif /* VDPAU_BUFFER_H */
0116
=== added directory '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch'
=== added directory '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src'
=== added file '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.c'
--- .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.c 1970-01-01 00:00:00 +0000
+++ .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.c 2014-05-06 21:31:51 +0000
@@ -0,0 +1,259 @@
1/*
2 * vdpau_buffer.c - VDPAU backend for VA-API (VA buffers)
3 *
4 * vdpau-video (C) 2009-2011 Splitted-Desktop Systems
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "sysdeps.h"
22#include "vdpau_buffer.h"
23#include "vdpau_driver.h"
24#include "vdpau_video.h"
25#include "vdpau_dump.h"
26#include "utils.h"
27
28#define DEBUG 1
29#include "debug.h"
30
31
32// Create VA buffer object
33object_buffer_p
34create_va_buffer(
35 vdpau_driver_data_t *driver_data,
36 VAContextID context,
37 VABufferType buffer_type,
38 unsigned int num_elements,
39 unsigned int size
40)
41{
42 VABufferID buffer_id;
43 object_buffer_p obj_buffer;
44
45 buffer_id = object_heap_allocate(&driver_data->buffer_heap);
46 if (buffer_id == VA_INVALID_BUFFER)
47 return NULL;
48
49 obj_buffer = VDPAU_BUFFER(buffer_id);
50 if (!obj_buffer)
51 return NULL;
52
53 obj_buffer->va_context = context;
54 obj_buffer->type = buffer_type;
55 obj_buffer->max_num_elements = num_elements;
56 obj_buffer->num_elements = num_elements;
57 obj_buffer->buffer_size = size * num_elements;
58 obj_buffer->buffer_data = malloc(obj_buffer->buffer_size);
59 obj_buffer->mtime = 0;
60 obj_buffer->delayed_destroy = 0;
61
62 if (!obj_buffer->buffer_data) {
63 destroy_va_buffer(driver_data, obj_buffer);
64 return NULL;
65 }
66 return obj_buffer;
67}
68
69// Destroy VA buffer object
70void
71destroy_va_buffer(
72 vdpau_driver_data_t *driver_data,
73 object_buffer_p obj_buffer
74)
75{
76 if (!obj_buffer)
77 return;
78
79 if (obj_buffer->buffer_data) {
80 free(obj_buffer->buffer_data);
81 obj_buffer->buffer_data = NULL;
82 }
83 object_heap_free(&driver_data->buffer_heap, (object_base_p)obj_buffer);
84}
85
86// Schedule VA buffer object for destruction
87void
88schedule_destroy_va_buffer(
89 vdpau_driver_data_p driver_data,
90 object_buffer_p obj_buffer
91)
92{
93 object_context_p obj_context = VDPAU_CONTEXT(obj_buffer->va_context);
94 if (!obj_context)
95 return;
96
97 realloc_buffer(
98 &obj_context->dead_buffers,
99 &obj_context->dead_buffers_count_max,
100 16 + obj_context->dead_buffers_count,
101 sizeof(*obj_context->dead_buffers)
102 );
103
104 ASSERT(obj_context->dead_buffers);
105 obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id;
106 obj_context->dead_buffers_count++;
107 obj_buffer->delayed_destroy = 1;
108}
109
110// vaCreateBuffer
111VAStatus
112vdpau_CreateBuffer(
113 VADriverContextP ctx,
114 VAContextID context,
115 VABufferType type,
116 unsigned int size,
117 unsigned int num_elements,
118 void *data,
119 VABufferID *buf_id
120)
121{
122 VDPAU_DRIVER_DATA_INIT;
123
124 if (buf_id)
125 *buf_id = VA_INVALID_BUFFER;
126
127 /* Validate type */
128 switch (type) {
129 case VAPictureParameterBufferType:
130 case VAIQMatrixBufferType:
131 case VASliceParameterBufferType:
132 case VASliceDataBufferType:
133 case VABitPlaneBufferType:
134 case VAImageBufferType:
135 /* Ok */
136 break;
137 default:
138 D(bug("ERROR: unsupported buffer type %d\n", type));
139 return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
140 }
141
142 object_buffer_p obj_buffer;
143 obj_buffer = create_va_buffer(driver_data, context, type, num_elements, size);
144 if (!obj_buffer)
145 return VA_STATUS_ERROR_ALLOCATION_FAILED;
146
147 if (data)
148 memcpy(obj_buffer->buffer_data, data, obj_buffer->buffer_size);
149
150 if (buf_id)
151 *buf_id = obj_buffer->base.id;
152
153 return VA_STATUS_SUCCESS;
154}
155
156// vaDestroyBuffer
157VAStatus
158vdpau_DestroyBuffer(
159 VADriverContextP ctx,
160 VABufferID buffer_id
161)
162{
163 VDPAU_DRIVER_DATA_INIT;
164
165 object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id);
166
167 if (obj_buffer && !obj_buffer->delayed_destroy)
168 destroy_va_buffer(driver_data, obj_buffer);
169
170 return VA_STATUS_SUCCESS;
171}
172
173// vaBufferSetNumElements
174VAStatus
175vdpau_BufferSetNumElements(
176 VADriverContextP ctx,
177 VABufferID buf_id,
178 unsigned int num_elements
179)
180{
181 VDPAU_DRIVER_DATA_INIT;
182
183 object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id);
184 if (!obj_buffer)
185 return VA_STATUS_ERROR_INVALID_BUFFER;
186
187 if (num_elements < 0 || num_elements > obj_buffer->max_num_elements)
188 return VA_STATUS_ERROR_UNKNOWN;
189
190 obj_buffer->num_elements = num_elements;
191 return VA_STATUS_SUCCESS;
192}
193
194// vaMapBuffer
195VAStatus
196vdpau_MapBuffer(
197 VADriverContextP ctx,
198 VABufferID buf_id,
199 void **pbuf
200)
201{
202 VDPAU_DRIVER_DATA_INIT;
203
204 object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id);
205 if (!obj_buffer)
206 return VA_STATUS_ERROR_INVALID_BUFFER;
207
208 if (pbuf)
209 *pbuf = obj_buffer->buffer_data;
210
211 if (obj_buffer->buffer_data == NULL)
212 return VA_STATUS_ERROR_UNKNOWN;
213
214 ++obj_buffer->mtime;
215 return VA_STATUS_SUCCESS;
216}
217
218// vaUnmapBuffer
219VAStatus
220vdpau_UnmapBuffer(
221 VADriverContextP ctx,
222 VABufferID buf_id
223)
224{
225 VDPAU_DRIVER_DATA_INIT;
226
227 object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id);
228 if (!obj_buffer)
229 return VA_STATUS_ERROR_INVALID_BUFFER;
230
231 ++obj_buffer->mtime;
232 return VA_STATUS_SUCCESS;
233}
234
235// vaBufferInfo
236VAStatus
237vdpau_BufferInfo(
238 VADriverContextP ctx,
239 VAContextID context,
240 VABufferID buf_id,
241 VABufferType *type,
242 unsigned int *size,
243 unsigned int *num_elements
244)
245{
246 VDPAU_DRIVER_DATA_INIT;
247
248 object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id);
249 if (!obj_buffer)
250 return VA_STATUS_ERROR_INVALID_BUFFER;
251
252 if (type)
253 *type = obj_buffer->type;
254 if (size)
255 *size = obj_buffer->buffer_size / obj_buffer->num_elements;
256 if (num_elements)
257 *num_elements = obj_buffer->num_elements;
258 return VA_STATUS_SUCCESS;
259}
0260
=== added file '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.h'
--- .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.h 1970-01-01 00:00:00 +0000
+++ .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.h 2014-05-06 21:31:51 +0000
@@ -0,0 +1,116 @@
1/*
2 * vdpau_buffer.h - VDPAU backend for VA-API (VA buffers)
3 *
4 * vdpau-video (C) 2009-2011 Splitted-Desktop Systems
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#ifndef VDPAU_BUFFER_H
22#define VDPAU_BUFFER_H
23
24#include "vdpau_driver.h"
25
26typedef struct object_buffer object_buffer_t;
27struct object_buffer {
28 struct object_base base;
29 VAContextID va_context;
30 VABufferType type;
31 void *buffer_data;
32 unsigned int buffer_size;
33 unsigned int max_num_elements;
34 unsigned int num_elements;
35 uint64_t mtime;
36 unsigned int delayed_destroy : 1;
37};
38
39// Create VA buffer object
40object_buffer_p
41create_va_buffer(
42 vdpau_driver_data_p driver_data,
43 VAContextID context,
44 VABufferType buffer_type,
45 unsigned int num_elements,
46 unsigned int size
47) attribute_hidden;
48
49// Destroy VA buffer object
50void
51destroy_va_buffer(
52 vdpau_driver_data_p driver_data,
53 object_buffer_p obj_buffer
54) attribute_hidden;
55
56// Schedule VA buffer object for destruction
57void
58schedule_destroy_va_buffer(
59 vdpau_driver_data_p driver_data,
60 object_buffer_p obj_buffer
61) attribute_hidden;
62
63// vaCreateBuffer
64VAStatus
65vdpau_CreateBuffer(
66 VADriverContextP ctx,
67 VAContextID context,
68 VABufferType type,
69 unsigned int size,
70 unsigned int num_elements,
71 void *data,
72 VABufferID *buf_id
73) attribute_hidden;
74
75// vaDestroyBuffer
76VAStatus
77vdpau_DestroyBuffer(
78 VADriverContextP ctx,
79 VABufferID buffer_id
80) attribute_hidden;
81
82// vaBufferSetNumElements
83VAStatus
84vdpau_BufferSetNumElements(
85 VADriverContextP ctx,
86 VABufferID buf_id,
87 unsigned int num_elements
88) attribute_hidden;
89
90// vaMapBuffer
91VAStatus
92vdpau_MapBuffer(
93 VADriverContextP ctx,
94 VABufferID buf_id,
95 void **pbuf
96) attribute_hidden;
97
98// vaUnmapBuffer
99VAStatus
100vdpau_UnmapBuffer(
101 VADriverContextP ctx,
102 VABufferID buf_id
103) attribute_hidden;
104
105// vaBufferInfo
106VAStatus
107vdpau_BufferInfo(
108 VADriverContextP ctx,
109 VAContextID context,
110 VABufferID buf_id,
111 VABufferType *type,
112 unsigned int *size,
113 unsigned int *num_elements
114) attribute_hidden;
115
116#endif /* VDPAU_BUFFER_H */
0117
=== added file '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_decode.c'
--- .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_decode.c 1970-01-01 00:00:00 +0000
+++ .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_decode.c 2014-05-06 21:31:51 +0000
@@ -0,0 +1,1271 @@
1/*
2 * vdpau_decode.c - VDPAU backend for VA-API (decoder)
3 *
4 * vdpau-video (C) 2009-2011 Splitted-Desktop Systems
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "sysdeps.h"
22#include "vdpau_decode.h"
23#include "vdpau_driver.h"
24#include "vdpau_buffer.h"
25#include "vdpau_video.h"
26#include "vdpau_dump.h"
27#include "utils.h"
28#include "put_bits.h"
29
30#define DEBUG 1
31#include "debug.h"
32
33
34// Translates VdpDecoderProfile to VdpCodec
35VdpCodec get_VdpCodec(VdpDecoderProfile profile)
36{
37 switch (profile) {
38 case VDP_DECODER_PROFILE_MPEG1:
39 return VDP_CODEC_MPEG1;
40 case VDP_DECODER_PROFILE_MPEG2_SIMPLE:
41 case VDP_DECODER_PROFILE_MPEG2_MAIN:
42 return VDP_CODEC_MPEG2;
43#if USE_VDPAU_MPEG4
44 case VDP_DECODER_PROFILE_MPEG4_PART2_SP:
45 case VDP_DECODER_PROFILE_MPEG4_PART2_ASP:
46 case VDP_DECODER_PROFILE_DIVX4_QMOBILE:
47 case VDP_DECODER_PROFILE_DIVX4_MOBILE:
48 case VDP_DECODER_PROFILE_DIVX4_HOME_THEATER:
49 case VDP_DECODER_PROFILE_DIVX4_HD_1080P:
50 case VDP_DECODER_PROFILE_DIVX5_QMOBILE:
51 case VDP_DECODER_PROFILE_DIVX5_MOBILE:
52 case VDP_DECODER_PROFILE_DIVX5_HOME_THEATER:
53 case VDP_DECODER_PROFILE_DIVX5_HD_1080P:
54 return VDP_CODEC_MPEG4;
55#endif
56 case VDP_DECODER_PROFILE_H264_BASELINE:
57 case VDP_DECODER_PROFILE_H264_MAIN:
58 case VDP_DECODER_PROFILE_H264_HIGH:
59 return VDP_CODEC_H264;
60 case VDP_DECODER_PROFILE_VC1_SIMPLE:
61 case VDP_DECODER_PROFILE_VC1_MAIN:
62 case VDP_DECODER_PROFILE_VC1_ADVANCED:
63 return VDP_CODEC_VC1;
64 }
65 return 0;
66}
67
68// Translates VAProfile to VdpDecoderProfile
69VdpDecoderProfile get_VdpDecoderProfile(VAProfile profile)
70{
71 switch (profile) {
72 case VAProfileMPEG2Simple: return VDP_DECODER_PROFILE_MPEG2_SIMPLE;
73 case VAProfileMPEG2Main: return VDP_DECODER_PROFILE_MPEG2_MAIN;
74#if USE_VDPAU_MPEG4
75 case VAProfileMPEG4Simple: return VDP_DECODER_PROFILE_MPEG4_PART2_SP;
76 case VAProfileMPEG4AdvancedSimple: return VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
77#endif
78 case VAProfileH264Baseline: return VDP_DECODER_PROFILE_H264_BASELINE;
79 case VAProfileH264Main: return VDP_DECODER_PROFILE_H264_MAIN;
80 case VAProfileH264High: return VDP_DECODER_PROFILE_H264_HIGH;
81 case VAProfileVC1Simple: return VDP_DECODER_PROFILE_VC1_SIMPLE;
82 case VAProfileVC1Main: return VDP_DECODER_PROFILE_VC1_MAIN;
83 case VAProfileVC1Advanced: return VDP_DECODER_PROFILE_VC1_ADVANCED;
84 default: break;
85 }
86 return (VdpDecoderProfile)-1;
87}
88
89// Checks whether the VDPAU implementation supports the specified profile
90static inline VdpBool
91is_supported_profile(
92 vdpau_driver_data_t *driver_data,
93 VdpDecoderProfile profile
94)
95{
96 VdpBool is_supported = VDP_FALSE;
97 VdpStatus vdp_status;
98 uint32_t max_level, max_references, max_width, max_height;
99
100 if (profile == (VdpDecoderProfile)-1)
101 return VDP_FALSE;
102
103 vdp_status = vdpau_decoder_query_capabilities(
104 driver_data,
105 driver_data->vdp_device,
106 profile,
107 &is_supported,
108 &max_level,
109 &max_references,
110 &max_width,
111 &max_height
112 );
113 return (VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderQueryCapabilities()") &&
114 is_supported);
115}
116
117// Checks decoder for profile/entrypoint is available
118VAStatus
119check_decoder(
120 vdpau_driver_data_t *driver_data,
121 VAProfile profile,
122 VAEntrypoint entrypoint
123)
124{
125 if (!is_supported_profile(driver_data, get_VdpDecoderProfile(profile)))
126 return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
127
128 /* VDPAU only supports VLD */
129 if (entrypoint != VAEntrypointVLD)
130 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
131
132 return VA_STATUS_SUCCESS;
133}
134
135// Computes value for VdpDecoderCreate()::max_references parameter
136static int
137get_max_ref_frames(
138 VdpDecoderProfile profile,
139 unsigned int width,
140 unsigned int height
141)
142{
143 int max_ref_frames = 2;
144
145 switch (profile) {
146 case VDP_DECODER_PROFILE_H264_MAIN:
147 case VDP_DECODER_PROFILE_H264_HIGH:
148 {
149 /* level 4.1 limits */
150 unsigned int aligned_width = (width + 15) & -16;
151 unsigned int aligned_height = (height + 15) & -16;
152 unsigned int surface_size = (aligned_width * aligned_height * 3) / 2;
153 if ((max_ref_frames = (12 * 1024 * 1024) / surface_size) > 16)
154 max_ref_frames = 16;
155 break;
156 }
157 }
158 return max_ref_frames;
159}
160
161// Returns the maximum number of reference frames of a decode session
162static inline int get_num_ref_frames(object_context_p obj_context)
163{
164 if (obj_context->vdp_codec == VDP_CODEC_H264)
165 return obj_context->vdp_picture_info.h264.num_ref_frames;
166 return 2;
167}
168
169// Ensure VDPAU decoder is created for the specified number of reference frames
170static VdpStatus
171ensure_decoder_with_max_refs(
172 vdpau_driver_data_t *driver_data,
173 object_context_p obj_context,
174 int max_ref_frames
175)
176{
177 VdpStatus vdp_status;
178
179 if (max_ref_frames < 0)
180 max_ref_frames =
181 get_max_ref_frames(obj_context->vdp_profile,
182 obj_context->picture_width,
183 obj_context->picture_height);
184
185 if (obj_context->vdp_decoder == VDP_INVALID_HANDLE ||
186 obj_context->max_ref_frames < max_ref_frames) {
187 obj_context->max_ref_frames = max_ref_frames;
188
189 if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) {
190 vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder);
191 obj_context->vdp_decoder = VDP_INVALID_HANDLE;
192 }
193
194 vdp_status = vdpau_decoder_create(
195 driver_data,
196 driver_data->vdp_device,
197 obj_context->vdp_profile,
198 obj_context->picture_width,
199 obj_context->picture_height,
200 max_ref_frames,
201 &obj_context->vdp_decoder
202 );
203 if (!VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderCreate()"))
204 return vdp_status;
205 }
206 return VDP_STATUS_OK;
207}
208
209// Lazy allocate (generated) slice data buffer. Buffer lives until vaDestroyContext()
210static uint8_t *
211alloc_gen_slice_data(object_context_p obj_context, unsigned int size)
212{
213 uint8_t *gen_slice_data = obj_context->gen_slice_data;
214
215 if (obj_context->gen_slice_data_size + size > obj_context->gen_slice_data_size_max) {
216 obj_context->gen_slice_data_size_max += size;
217 gen_slice_data = realloc(obj_context->gen_slice_data,
218 obj_context->gen_slice_data_size_max);
219 if (!gen_slice_data)
220 return NULL;
221 obj_context->gen_slice_data = gen_slice_data;
222 }
223 gen_slice_data += obj_context->gen_slice_data_size;
224 obj_context->gen_slice_data_size += size;
225 return gen_slice_data;
226}
227
228// Lazy allocate VdpBitstreamBuffer. Buffer lives until vaDestroyContext()
229static VdpBitstreamBuffer *
230alloc_VdpBitstreamBuffer(object_context_p obj_context)
231{
232 VdpBitstreamBuffer *vdp_bitstream_buffers;
233
234 vdp_bitstream_buffers = realloc_buffer(
235 &obj_context->vdp_bitstream_buffers,
236 &obj_context->vdp_bitstream_buffers_count_max,
237 1 + obj_context->vdp_bitstream_buffers_count,
238 sizeof(*obj_context->vdp_bitstream_buffers)
239 );
240 if (!vdp_bitstream_buffers)
241 return NULL;
242
243 return &vdp_bitstream_buffers[obj_context->vdp_bitstream_buffers_count++];
244}
245
246// Append VASliceDataBuffer hunk into VDPAU buffer
247static int
248append_VdpBitstreamBuffer(
249 object_context_p obj_context,
250 const uint8_t *buffer,
251 uint32_t buffer_size
252)
253{
254 VdpBitstreamBuffer *bitstream_buffer;
255
256 bitstream_buffer = alloc_VdpBitstreamBuffer(obj_context);
257 if (!bitstream_buffer)
258 return -1;
259
260 bitstream_buffer->struct_version = VDP_BITSTREAM_BUFFER_VERSION;
261 bitstream_buffer->bitstream = buffer;
262 bitstream_buffer->bitstream_bytes = buffer_size;
263 return 0;
264}
265
266// Initialize VdpReferenceFrameH264 to default values
267static void init_VdpReferenceFrameH264(VdpReferenceFrameH264 *rf)
268{
269 rf->surface = VDP_INVALID_HANDLE;
270 rf->is_long_term = VDP_FALSE;
271 rf->top_is_reference = VDP_FALSE;
272 rf->bottom_is_reference = VDP_FALSE;
273 rf->field_order_cnt[0] = 0;
274 rf->field_order_cnt[1] = 0;
275 rf->frame_idx = 0;
276}
277
278static const uint8_t ff_identity[64] = {
279 0, 1, 2, 3, 4, 5, 6, 7,
280 8, 9, 10, 11, 12, 13, 14, 15,
281 16, 17, 18, 19, 20, 21, 22, 23,
282 24, 25, 26, 27, 28, 29, 30, 31,
283 32, 33, 34, 35, 36, 37, 38, 39,
284 40, 41, 42, 43, 44, 45, 46, 47,
285 48, 49, 50, 51, 52, 53, 54, 55,
286 56, 57, 58, 59, 60, 61, 62, 63
287};
288
289static const uint8_t ff_zigzag_direct[64] = {
290 0, 1, 8, 16, 9, 2, 3, 10,
291 17, 24, 32, 25, 18, 11, 4, 5,
292 12, 19, 26, 33, 40, 48, 41, 34,
293 27, 20, 13, 6, 7, 14, 21, 28,
294 35, 42, 49, 56, 57, 50, 43, 36,
295 29, 22, 15, 23, 30, 37, 44, 51,
296 58, 59, 52, 45, 38, 31, 39, 46,
297 53, 60, 61, 54, 47, 55, 62, 63
298};
299
300static const uint8_t ff_mpeg1_default_intra_matrix[64] = {
301 8, 16, 19, 22, 26, 27, 29, 34,
302 16, 16, 22, 24, 27, 29, 34, 37,
303 19, 22, 26, 27, 29, 34, 34, 38,
304 22, 22, 26, 27, 29, 34, 37, 40,
305 22, 26, 27, 29, 32, 35, 40, 48,
306 26, 27, 29, 32, 35, 40, 48, 58,
307 26, 27, 29, 34, 38, 46, 56, 69,
308 27, 29, 35, 38, 46, 56, 69, 83
309};
310
311static const uint8_t ff_mpeg1_default_non_intra_matrix[64] = {
312 16, 16, 16, 16, 16, 16, 16, 16,
313 16, 16, 16, 16, 16, 16, 16, 16,
314 16, 16, 16, 16, 16, 16, 16, 16,
315 16, 16, 16, 16, 16, 16, 16, 16,
316 16, 16, 16, 16, 16, 16, 16, 16,
317 16, 16, 16, 16, 16, 16, 16, 16,
318 16, 16, 16, 16, 16, 16, 16, 16,
319 16, 16, 16, 16, 16, 16, 16, 16
320};
321
322static const uint8_t ff_mpeg4_default_intra_matrix[64] = {
323 8, 17, 18, 19, 21, 23, 25, 27,
324 17, 18, 19, 21, 23, 25, 27, 28,
325 20, 21, 22, 23, 24, 26, 28, 30,
326 21, 22, 23, 24, 26, 28, 30, 32,
327 22, 23, 24, 26, 28, 30, 32, 35,
328 23, 24, 26, 28, 30, 32, 35, 38,
329 25, 26, 28, 30, 32, 35, 38, 41,
330 27, 28, 30, 32, 35, 38, 41, 45,
331};
332
333static const uint8_t ff_mpeg4_default_non_intra_matrix[64] = {
334 16, 17, 18, 19, 20, 21, 22, 23,
335 17, 18, 19, 20, 21, 22, 23, 24,
336 18, 19, 20, 21, 22, 23, 24, 25,
337 19, 20, 21, 22, 23, 24, 26, 27,
338 20, 21, 22, 23, 25, 26, 27, 28,
339 21, 22, 23, 24, 26, 27, 28, 30,
340 22, 23, 24, 26, 27, 28, 30, 31,
341 23, 24, 25, 27, 28, 30, 31, 33,
342};
343
344// Compute integer log2
345static inline int ilog2(uint32_t v)
346{
347 /* From <http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog> */
348 uint32_t r, shift;
349 r = (v > 0xffff) << 4; v >>= r;
350 shift = (v > 0xff ) << 3; v >>= shift; r |= shift;
351 shift = (v > 0xf ) << 2; v >>= shift; r |= shift;
352 shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
353 return r | (v >> 1);
354}
355
356// Translate VASurfaceID
357static int
358translate_VASurfaceID(
359 vdpau_driver_data_t *driver_data,
360 VASurfaceID va_surface,
361 VdpVideoSurface *vdp_surface
362)
363{
364 object_surface_p obj_surface;
365
366 if (va_surface == VA_INVALID_SURFACE) {
367 *vdp_surface = VDP_INVALID_HANDLE;
368 return 1;
369 }
370
371 obj_surface = VDPAU_SURFACE(va_surface);
372 if (!obj_surface)
373 return 0;
374
375 *vdp_surface = obj_surface->vdp_surface;
376 return 1;
377}
378
379// Translate VAPictureH264
380static int
381translate_VAPictureH264(
382 vdpau_driver_data_t *driver_data,
383 const VAPictureH264 *va_pic,
384 VdpReferenceFrameH264 *rf
385)
386{
387 // Handle invalid surfaces specifically
388 if (va_pic->picture_id == VA_INVALID_SURFACE) {
389 init_VdpReferenceFrameH264(rf);
390 return 1;
391 }
392
393 if (!translate_VASurfaceID(driver_data, va_pic->picture_id, &rf->surface))
394 return 0;
395 rf->is_long_term = (va_pic->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE) != 0;
396 if ((va_pic->flags & (VA_PICTURE_H264_TOP_FIELD|VA_PICTURE_H264_BOTTOM_FIELD)) == 0) {
397 rf->top_is_reference = VDP_TRUE;
398 rf->bottom_is_reference = VDP_TRUE;
399 }
400 else {
401 rf->top_is_reference = (va_pic->flags & VA_PICTURE_H264_TOP_FIELD) != 0;
402 rf->bottom_is_reference = (va_pic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0;
403 }
404 rf->field_order_cnt[0] = va_pic->TopFieldOrderCnt;
405 rf->field_order_cnt[1] = va_pic->BottomFieldOrderCnt;
406 rf->frame_idx = va_pic->frame_idx;
407 return 1;
408}
409
410// Translate no buffer
411static int
412translate_nothing(
413 vdpau_driver_data_t *driver_data,
414 object_context_p obj_context,
415 object_buffer_p obj_buffer
416)
417{
418 return 1;
419}
420
421// Translate VASliceDataBuffer
422static int
423translate_VASliceDataBuffer(
424 vdpau_driver_data_t *driver_data,
425 object_context_p obj_context,
426 object_buffer_p obj_buffer
427)
428{
429 if (obj_context->vdp_codec == VDP_CODEC_H264) {
430 /* Check we have the start code */
431 /* XXX: check for other codecs too? */
432 /* XXX: this assumes we get SliceParams before SliceData */
433 static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 };
434 VASliceParameterBufferH264 * const slice_params = obj_context->last_slice_params;
435 unsigned int i;
436 for (i = 0; i < obj_context->last_slice_params_count; i++) {
437 VASliceParameterBufferH264 * const slice_param = &slice_params[i];
438 uint8_t *buf = (uint8_t *)obj_buffer->buffer_data + slice_param->slice_data_offset;
439 if (memcmp(buf, start_code_prefix, sizeof(start_code_prefix)) != 0) {
440 if (append_VdpBitstreamBuffer(obj_context,
441 start_code_prefix,
442 sizeof(start_code_prefix)) < 0)
443 return 0;
444 }
445 if (append_VdpBitstreamBuffer(obj_context,
446 buf,
447 slice_param->slice_data_size) < 0)
448 return 0;
449 }
450 return 1;
451 }
452
453#if USE_VDPAU_MPEG4
454 if (obj_context->vdp_codec == VDP_CODEC_MPEG4 &&
455 obj_context->vdp_bitstream_buffers_count == 0) {
456 PutBitContext pb;
457 uint8_t slice_header_buffer[32];
458 uint8_t *slice_header;
459 int slice_header_size;
460 const uint8_t *slice_data = obj_buffer->buffer_data;
461 uint32_t slice_data_size = obj_buffer->buffer_size;
462 VAPictureParameterBufferMPEG4 * const pic_param = obj_context->last_pic_param;
463 VASliceParameterBufferMPEG4 * const slice_param = obj_context->last_slice_params;
464
465 int time_incr = 1 + ilog2(pic_param->vop_time_increment_resolution - 1);
466 if (time_incr < 1)
467 time_incr = 1;
468
469 static const uint16_t VOP_STARTCODE = 0x01b6;
470 enum {
471 VOP_I_TYPE = 0,
472 VOP_P_TYPE,
473 VOP_B_TYPE,
474 VOP_S_TYPE
475 };
476
477 /* XXX: this is a hack to compute the length of
478 modulo_time_base "1" sequence. We probably should be
479 reconstructing through an extra VOP field in VA-API? */
480 int nbits = (32 + /* VOP start code */
481 2 + /* vop_coding_type */
482 1 + /* modulo_time_base "0" */
483 1 + /* marker_bit */
484 time_incr + /* vop_time_increment */
485 1 + /* marker_bit */
486 1 + /* vop_coded */
487 (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE ? 1 : 0) +
488 3 + /* intra_dc_vlc_thr */
489 (pic_param->vol_fields.bits.interlaced ? 2 : 0) +
490 5 + /* vop_quant */
491 (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE ? 3 : 0) +
492 (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE ? 3 : 0));
493 if ((nbits = slice_param->macroblock_offset - (nbits % 8)) < 0)
494 nbits += 8;
495
496 /* Reconstruct the VOP header */
497 init_put_bits(&pb, slice_header_buffer, sizeof(slice_header_buffer));
498 put_bits(&pb, 16, 0); /* vop header */
499 put_bits(&pb, 16, VOP_STARTCODE); /* vop header */
500 put_bits(&pb, 2, pic_param->vop_fields.bits.vop_coding_type);
501 while (nbits-- > 0)
502 put_bits(&pb, 1, 1); /* modulo_time_base "1" */
503 put_bits(&pb, 1, 0); /* modulo_time_base "0" */
504 put_bits(&pb, 1, 1); /* marker */
505 put_bits(&pb, time_incr, 0); /* time increment */
506 put_bits(&pb, 1, 1); /* marker */
507 put_bits(&pb, 1, 1); /* vop coded */
508 if (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE)
509 put_bits(&pb, 1, pic_param->vop_fields.bits.vop_rounding_type);
510 put_bits(&pb, 3, pic_param->vop_fields.bits.intra_dc_vlc_thr);
511 if (pic_param->vol_fields.bits.interlaced) {
512 put_bits(&pb, 1, pic_param->vop_fields.bits.top_field_first);
513 put_bits(&pb, 1, pic_param->vop_fields.bits.alternate_vertical_scan_flag);
514 }
515 put_bits(&pb, 5, slice_param->quant_scale);
516 if (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE)
517 put_bits(&pb, 3, pic_param->vop_fcode_forward);
518 if (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE)
519 put_bits(&pb, 3, pic_param->vop_fcode_backward);
520
521 /* Merge in bits from the first byte of the slice */
522 ASSERT((put_bits_count(&pb) % 8) == slice_param->macroblock_offset);
523 if ((put_bits_count(&pb) % 8) != slice_param->macroblock_offset)
524 return 0;
525 const int r = 8 - (put_bits_count(&pb) % 8);
526 if (r > 0)
527 put_bits(&pb, r, slice_data[0] & ((1U << r) - 1));
528 flush_put_bits(&pb);
529
530 ASSERT((put_bits_count(&pb) % 8) == 0);
531 slice_header_size = put_bits_count(&pb) / 8;
532 ASSERT(slice_header_size <= sizeof(slice_header_buffer));
533 slice_header = alloc_gen_slice_data(obj_context, slice_header_size);
534 if (!slice_header)
535 return 0;
536 memcpy(slice_header, slice_header_buffer, slice_header_size);
537 if (append_VdpBitstreamBuffer(obj_context, slice_header, slice_header_size) < 0)
538 return 0;
539 if (append_VdpBitstreamBuffer(obj_context, slice_data + 1, slice_data_size - 1) < 0)
540 return 0;
541 return 1;
542 }
543#endif
544
545 if (append_VdpBitstreamBuffer(obj_context,
546 obj_buffer->buffer_data,
547 obj_buffer->buffer_size) < 0)
548 return 0;
549 return 1;
550}
551
552// Translate VAPictureParameterBufferMPEG2
553static int
554translate_VAPictureParameterBufferMPEG2(
555 vdpau_driver_data_t *driver_data,
556 object_context_p obj_context,
557 object_buffer_p obj_buffer
558)
559{
560 VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2;
561 VAPictureParameterBufferMPEG2 * const pic_param = obj_buffer->buffer_data;
562
563 if (!translate_VASurfaceID(driver_data,
564 pic_param->forward_reference_picture,
565 &pic_info->forward_reference))
566 return 0;
567
568 if (!translate_VASurfaceID(driver_data,
569 pic_param->backward_reference_picture,
570 &pic_info->backward_reference))
571 return 0;
572
573 pic_info->picture_structure = pic_param->picture_coding_extension.bits.picture_structure;
574 pic_info->picture_coding_type = pic_param->picture_coding_type;
575 pic_info->intra_dc_precision = pic_param->picture_coding_extension.bits.intra_dc_precision;
576 pic_info->frame_pred_frame_dct = pic_param->picture_coding_extension.bits.frame_pred_frame_dct;
577 pic_info->concealment_motion_vectors = pic_param->picture_coding_extension.bits.concealment_motion_vectors;
578 pic_info->intra_vlc_format = pic_param->picture_coding_extension.bits.intra_vlc_format;
579 pic_info->alternate_scan = pic_param->picture_coding_extension.bits.alternate_scan;
580 pic_info->q_scale_type = pic_param->picture_coding_extension.bits.q_scale_type;
581 pic_info->top_field_first = pic_param->picture_coding_extension.bits.top_field_first;
582 pic_info->full_pel_forward_vector = 0;
583 pic_info->full_pel_backward_vector = 0;
584 pic_info->f_code[0][0] = (pic_param->f_code >> 12) & 0xf;
585 pic_info->f_code[0][1] = (pic_param->f_code >> 8) & 0xf;
586 pic_info->f_code[1][0] = (pic_param->f_code >> 4) & 0xf;
587 pic_info->f_code[1][1] = pic_param->f_code & 0xf;
588 return 1;
589}
590
591// Translate VAIQMatrixBufferMPEG2
592static int
593translate_VAIQMatrixBufferMPEG2(
594 vdpau_driver_data_t *driver_data,
595 object_context_p obj_context,
596 object_buffer_p obj_buffer
597)
598{
599 VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2;
600 VAIQMatrixBufferMPEG2 * const iq_matrix = obj_buffer->buffer_data;
601 const uint8_t *intra_matrix;
602 const uint8_t *intra_matrix_lookup;
603 const uint8_t *inter_matrix;
604 const uint8_t *inter_matrix_lookup;
605 int i;
606
607 if (iq_matrix->load_intra_quantiser_matrix) {
608 intra_matrix = iq_matrix->intra_quantiser_matrix;
609 intra_matrix_lookup = ff_zigzag_direct;
610 }
611 else {
612 intra_matrix = ff_mpeg1_default_intra_matrix;
613 intra_matrix_lookup = ff_identity;
614 }
615
616 if (iq_matrix->load_non_intra_quantiser_matrix) {
617 inter_matrix = iq_matrix->non_intra_quantiser_matrix;
618 inter_matrix_lookup = ff_zigzag_direct;
619 }
620 else {
621 inter_matrix = ff_mpeg1_default_non_intra_matrix;
622 inter_matrix_lookup = ff_identity;
623 }
624
625 for (i = 0; i < 64; i++) {
626 pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] =
627 intra_matrix[i];
628 pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] =
629 inter_matrix[i];
630 }
631 return 1;
632}
633
634// Translate VASliceParameterBufferMPEG2
635static int
636translate_VASliceParameterBufferMPEG2(
637 vdpau_driver_data_t *driver_data,
638 object_context_p obj_context,
639 object_buffer_p obj_buffer
640 )
641{
642 VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2;
643
644 pic_info->slice_count += obj_buffer->num_elements;
645 obj_context->last_slice_params = obj_buffer->buffer_data;
646 obj_context->last_slice_params_count = obj_buffer->num_elements;
647 return 1;
648}
649
650#if USE_VDPAU_MPEG4
651// Translate VAPictureParameterBufferMPEG4
652static int
653translate_VAPictureParameterBufferMPEG4(
654 vdpau_driver_data_p driver_data,
655 object_context_p obj_context,
656 object_buffer_p obj_buffer
657)
658{
659 VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4;
660 VAPictureParameterBufferMPEG4 * const pic_param = obj_buffer->buffer_data;
661
662 /* XXX: we don't support short-video-header formats */
663 if (pic_param->vol_fields.bits.short_video_header)
664 return 0;
665
666 if (!translate_VASurfaceID(driver_data,
667 pic_param->forward_reference_picture,
668 &pic_info->forward_reference))
669 return 0;
670
671 if (!translate_VASurfaceID(driver_data,
672 pic_param->backward_reference_picture,
673 &pic_info->backward_reference))
674 return 0;
675
676 if (pic_param->vol_fields.bits.interlaced) {
677 vdpau_information_message("unsupported MPEG-4 video with interlaced "
678 "content, please report this video\n");
679 pic_info->trd[0] = 2*pic_param->TRD; /* XXX: + d(0) */
680 pic_info->trb[0] = 2*pic_param->TRB; /* XXX: + d(0) */
681 pic_info->trd[1] = 2*pic_param->TRD; /* XXX: + d(1) */
682 pic_info->trb[1] = 2*pic_param->TRB; /* XXX: + d(1) */
683 }
684 else {
685 pic_info->trd[0] = pic_param->TRD;
686 pic_info->trb[0] = pic_param->TRB;
687 pic_info->trd[1] = 0;
688 pic_info->trb[1] = 0;
689 }
690
691 pic_info->vop_time_increment_resolution = pic_param->vop_time_increment_resolution;
692 pic_info->vop_coding_type = pic_param->vop_fields.bits.vop_coding_type;
693 pic_info->vop_fcode_forward = pic_param->vop_fcode_forward;
694 pic_info->vop_fcode_backward = pic_param->vop_fcode_backward;
695 pic_info->resync_marker_disable = pic_param->vol_fields.bits.resync_marker_disable;
696 pic_info->interlaced = pic_param->vol_fields.bits.interlaced;
697 pic_info->quant_type = pic_param->vol_fields.bits.quant_type;
698 pic_info->quarter_sample = pic_param->vol_fields.bits.quarter_sample;
699 pic_info->short_video_header = pic_param->vol_fields.bits.short_video_header;
700 pic_info->rounding_control = pic_param->vop_fields.bits.vop_rounding_type;
701 pic_info->alternate_vertical_scan_flag = pic_param->vop_fields.bits.alternate_vertical_scan_flag;
702 pic_info->top_field_first = pic_param->vop_fields.bits.top_field_first;
703
704 obj_context->last_pic_param = obj_buffer->buffer_data;
705 return 1;
706}
707
708// Translate VAIQMatrixBufferMPEG4
709static int
710translate_VAIQMatrixBufferMPEG4(
711 vdpau_driver_data_p driver_data,
712 object_context_p obj_context,
713 object_buffer_p obj_buffer
714)
715{
716 VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4;
717 VAIQMatrixBufferMPEG4 * const iq_matrix = obj_buffer->buffer_data;
718 const uint8_t *intra_matrix;
719 const uint8_t *intra_matrix_lookup;
720 const uint8_t *inter_matrix;
721 const uint8_t *inter_matrix_lookup;
722 int i;
723
724 if (iq_matrix->load_intra_quant_mat) {
725 intra_matrix = iq_matrix->intra_quant_mat;
726 intra_matrix_lookup = ff_zigzag_direct;
727 }
728 else {
729 intra_matrix = ff_mpeg4_default_intra_matrix;
730 intra_matrix_lookup = ff_identity;
731 }
732
733 if (iq_matrix->load_non_intra_quant_mat) {
734 inter_matrix = iq_matrix->non_intra_quant_mat;
735 inter_matrix_lookup = ff_zigzag_direct;
736 }
737 else {
738 inter_matrix = ff_mpeg4_default_non_intra_matrix;
739 inter_matrix_lookup = ff_identity;
740 }
741
742 for (i = 0; i < 64; i++) {
743 pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] =
744 intra_matrix[i];
745 pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] =
746 inter_matrix[i];
747 }
748 return 1;
749}
750
751// Translate VASliceParameterBufferMPEG4
752static int
753translate_VASliceParameterBufferMPEG4(
754 vdpau_driver_data_p driver_data,
755 object_context_p obj_context,
756 object_buffer_p obj_buffer
757 )
758{
759 obj_context->last_slice_params = obj_buffer->buffer_data;
760 obj_context->last_slice_params_count = obj_buffer->num_elements;
761 return 1;
762}
763#endif
764
765// Translate VAPictureParameterBufferH264
766static int
767translate_VAPictureParameterBufferH264(
768 vdpau_driver_data_t *driver_data,
769 object_context_p obj_context,
770 object_buffer_p obj_buffer
771)
772{
773 VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264;
774 VAPictureParameterBufferH264 * const pic_param = obj_buffer->buffer_data;
775 VAPictureH264 * const CurrPic = &pic_param->CurrPic;
776 unsigned int i;
777
778 pic_info->field_order_cnt[0] = CurrPic->TopFieldOrderCnt;
779 pic_info->field_order_cnt[1] = CurrPic->BottomFieldOrderCnt;
780 pic_info->is_reference = pic_param->pic_fields.bits.reference_pic_flag;
781
782 pic_info->frame_num = pic_param->frame_num;
783 pic_info->field_pic_flag = pic_param->pic_fields.bits.field_pic_flag;
784 pic_info->bottom_field_flag = pic_param->pic_fields.bits.field_pic_flag && (CurrPic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0;
785 pic_info->num_ref_frames = pic_param->num_ref_frames;
786 pic_info->mb_adaptive_frame_field_flag = pic_param->seq_fields.bits.mb_adaptive_frame_field_flag && !pic_info->field_pic_flag;
787 pic_info->constrained_intra_pred_flag = pic_param->pic_fields.bits.constrained_intra_pred_flag;
788 pic_info->weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag;
789 pic_info->weighted_bipred_idc = pic_param->pic_fields.bits.weighted_bipred_idc;
790 pic_info->frame_mbs_only_flag = pic_param->seq_fields.bits.frame_mbs_only_flag;
791 pic_info->transform_8x8_mode_flag = pic_param->pic_fields.bits.transform_8x8_mode_flag;
792 pic_info->chroma_qp_index_offset = pic_param->chroma_qp_index_offset;
793 pic_info->second_chroma_qp_index_offset = pic_param->second_chroma_qp_index_offset;
794 pic_info->pic_init_qp_minus26 = pic_param->pic_init_qp_minus26;
795 pic_info->log2_max_frame_num_minus4 = pic_param->seq_fields.bits.log2_max_frame_num_minus4;
796 pic_info->pic_order_cnt_type = pic_param->seq_fields.bits.pic_order_cnt_type;
797 pic_info->log2_max_pic_order_cnt_lsb_minus4 = pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4;
798 pic_info->delta_pic_order_always_zero_flag = pic_param->seq_fields.bits.delta_pic_order_always_zero_flag;
799 pic_info->direct_8x8_inference_flag = pic_param->seq_fields.bits.direct_8x8_inference_flag;
800 pic_info->entropy_coding_mode_flag = pic_param->pic_fields.bits.entropy_coding_mode_flag;
801 pic_info->pic_order_present_flag = pic_param->pic_fields.bits.pic_order_present_flag;
802 pic_info->deblocking_filter_control_present_flag = pic_param->pic_fields.bits.deblocking_filter_control_present_flag;
803 pic_info->redundant_pic_cnt_present_flag = pic_param->pic_fields.bits.redundant_pic_cnt_present_flag;
804
805 for (i = 0; i < 16; i++) {
806 if (!translate_VAPictureH264(driver_data,
807 &pic_param->ReferenceFrames[i],
808 &pic_info->referenceFrames[i]))
809 return 0;
810 }
811 return 1;
812}
813
814// Translate VAIQMatrixBufferH264
815static int
816translate_VAIQMatrixBufferH264(
817 vdpau_driver_data_t *driver_data,
818 object_context_p obj_context,
819 object_buffer_p obj_buffer
820)
821{
822 VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264;
823 VAIQMatrixBufferH264 * const iq_matrix = obj_buffer->buffer_data;
824 int i, j;
825
826 if (sizeof(pic_info->scaling_lists_4x4) == sizeof(iq_matrix->ScalingList4x4))
827 memcpy(pic_info->scaling_lists_4x4, iq_matrix->ScalingList4x4,
828 sizeof(pic_info->scaling_lists_4x4));
829 else {
830 for (j = 0; j < 6; j++) {
831 for (i = 0; i < 16; i++)
832 pic_info->scaling_lists_4x4[j][i] = iq_matrix->ScalingList4x4[j][i];
833 }
834 }
835
836 if (sizeof(pic_info->scaling_lists_8x8) == sizeof(iq_matrix->ScalingList8x8))
837 memcpy(pic_info->scaling_lists_8x8, iq_matrix->ScalingList8x8,
838 sizeof(pic_info->scaling_lists_8x8));
839 else {
840 for (j = 0; j < 2; j++) {
841 for (i = 0; i < 64; i++)
842 pic_info->scaling_lists_8x8[j][i] = iq_matrix->ScalingList8x8[j][i];
843 }
844 }
845 return 1;
846}
847
848// Translate VASliceParameterBufferH264
849static int
850translate_VASliceParameterBufferH264(
851 vdpau_driver_data_t *driver_data,
852 object_context_p obj_context,
853 object_buffer_p obj_buffer
854)
855{
856 VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264;
857 VASliceParameterBufferH264 * const slice_params = obj_buffer->buffer_data;
858 VASliceParameterBufferH264 * const slice_param = &slice_params[obj_buffer->num_elements - 1];
859
860 pic_info->slice_count += obj_buffer->num_elements;
861 pic_info->num_ref_idx_l0_active_minus1 = slice_param->num_ref_idx_l0_active_minus1;
862 pic_info->num_ref_idx_l1_active_minus1 = slice_param->num_ref_idx_l1_active_minus1;
863 obj_context->last_slice_params = obj_buffer->buffer_data;
864 obj_context->last_slice_params_count = obj_buffer->num_elements;
865 return 1;
866}
867
868// Translate VAPictureParameterBufferVC1
869static int
870translate_VAPictureParameterBufferVC1(
871 vdpau_driver_data_t *driver_data,
872 object_context_p obj_context,
873 object_buffer_p obj_buffer
874)
875{
876 VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1;
877 VAPictureParameterBufferVC1 * const pic_param = obj_buffer->buffer_data;
878 int picture_type, major_version, minor_version;
879
880 if (!translate_VASurfaceID(driver_data,
881 pic_param->forward_reference_picture,
882 &pic_info->forward_reference))
883 return 0;
884
885 if (!translate_VASurfaceID(driver_data,
886 pic_param->backward_reference_picture,
887 &pic_info->backward_reference))
888 return 0;
889
890 switch (pic_param->picture_fields.bits.picture_type) {
891 case 0: picture_type = 0; break; /* I */
892 case 1: picture_type = 1; break; /* P */
893 case 2: picture_type = 3; break; /* B */
894 case 3: picture_type = 4; break; /* BI */
895 case 4: picture_type = 1; break; /* P "skipped" */
896 default: return 0;
897 }
898
899 pic_info->picture_type = picture_type;
900 pic_info->frame_coding_mode = pic_param->picture_fields.bits.frame_coding_mode;
901 pic_info->postprocflag = pic_param->post_processing != 0;
902 pic_info->pulldown = pic_param->sequence_fields.bits.pulldown;
903 pic_info->interlace = pic_param->sequence_fields.bits.interlace;
904 pic_info->tfcntrflag = pic_param->sequence_fields.bits.tfcntrflag;
905 pic_info->finterpflag = pic_param->sequence_fields.bits.finterpflag;
906 pic_info->psf = pic_param->sequence_fields.bits.psf;
907 pic_info->dquant = pic_param->pic_quantizer_fields.bits.dquant;
908 pic_info->panscan_flag = pic_param->entrypoint_fields.bits.panscan_flag;
909 pic_info->refdist_flag = pic_param->reference_fields.bits.reference_distance_flag;
910 pic_info->quantizer = pic_param->pic_quantizer_fields.bits.quantizer;
911 pic_info->extended_mv = pic_param->mv_fields.bits.extended_mv_flag;
912 pic_info->extended_dmv = pic_param->mv_fields.bits.extended_dmv_flag;
913 pic_info->overlap = pic_param->sequence_fields.bits.overlap;
914 pic_info->vstransform = pic_param->transform_fields.bits.variable_sized_transform_flag;
915 pic_info->loopfilter = pic_param->entrypoint_fields.bits.loopfilter;
916 pic_info->fastuvmc = pic_param->fast_uvmc_flag;
917 pic_info->range_mapy_flag = pic_param->range_mapping_fields.bits.luma_flag;
918 pic_info->range_mapy = pic_param->range_mapping_fields.bits.luma;
919 pic_info->range_mapuv_flag = pic_param->range_mapping_fields.bits.chroma_flag;
920 pic_info->range_mapuv = pic_param->range_mapping_fields.bits.chroma;
921 pic_info->multires = pic_param->sequence_fields.bits.multires;
922 pic_info->syncmarker = pic_param->sequence_fields.bits.syncmarker;
923 pic_info->rangered = pic_param->sequence_fields.bits.rangered;
924 if (!vdpau_is_nvidia(driver_data, &major_version, &minor_version) ||
925 (major_version > 180 || minor_version >= 35))
926 pic_info->rangered |= pic_param->range_reduction_frame << 1;
927 pic_info->maxbframes = pic_param->sequence_fields.bits.max_b_frames;
928 pic_info->deblockEnable = pic_param->post_processing != 0; /* XXX: this is NVIDIA's vdpau.c semantics (postprocflag & 1) */
929 pic_info->pquant = pic_param->pic_quantizer_fields.bits.pic_quantizer_scale;
930 return 1;
931}
932
933// Translate VASliceParameterBufferVC1
934static int
935translate_VASliceParameterBufferVC1(
936 vdpau_driver_data_t *driver_data,
937 object_context_p obj_context,
938 object_buffer_p obj_buffer
939)
940{
941 VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1;
942
943 pic_info->slice_count += obj_buffer->num_elements;
944 obj_context->last_slice_params = obj_buffer->buffer_data;
945 obj_context->last_slice_params_count = obj_buffer->num_elements;
946 return 1;
947}
948
949// Translate VA buffer
950typedef int
951(*translate_buffer_func_t)(vdpau_driver_data_t *driver_data,
952 object_context_p obj_context,
953 object_buffer_p obj_buffer);
954
955typedef struct translate_buffer_info translate_buffer_info_t;
956struct translate_buffer_info {
957 VdpCodec codec;
958 VABufferType type;
959 translate_buffer_func_t func;
960};
961
962static int
963translate_buffer(
964 vdpau_driver_data_t *driver_data,
965 object_context_p obj_context,
966 object_buffer_p obj_buffer
967)
968{
969 static const translate_buffer_info_t translate_info[] = {
970#define _(CODEC, TYPE) \
971 { VDP_CODEC_##CODEC, VA##TYPE##BufferType, \
972 translate_VA##TYPE##Buffer##CODEC }
973 _(MPEG2, PictureParameter),
974 _(MPEG2, IQMatrix),
975 _(MPEG2, SliceParameter),
976#if USE_VDPAU_MPEG4
977 _(MPEG4, PictureParameter),
978 _(MPEG4, IQMatrix),
979 _(MPEG4, SliceParameter),
980#endif
981 _(H264, PictureParameter),
982 _(H264, IQMatrix),
983 _(H264, SliceParameter),
984 _(VC1, PictureParameter),
985 _(VC1, SliceParameter),
986#undef _
987 { VDP_CODEC_VC1, VABitPlaneBufferType, translate_nothing },
988 { 0, VASliceDataBufferType, translate_VASliceDataBuffer },
989 { 0, 0, NULL }
990 };
991 const translate_buffer_info_t *tbip;
992 for (tbip = translate_info; tbip->func != NULL; tbip++) {
993 if (tbip->codec && tbip->codec != obj_context->vdp_codec)
994 continue;
995 if (tbip->type != obj_buffer->type)
996 continue;
997 return tbip->func(driver_data, obj_context, obj_buffer);
998 }
999 D(bug("ERROR: no translate function found for %s%s\n",
1000 string_of_VABufferType(obj_buffer->type),
1001 obj_context->vdp_codec ? string_of_VdpCodec(obj_context->vdp_codec) : NULL));
1002 return 0;
1003}
1004
1005// vaQueryConfigProfiles
1006VAStatus
1007vdpau_QueryConfigProfiles(
1008 VADriverContextP ctx,
1009 VAProfile *profile_list,
1010 int *num_profiles
1011)
1012{
1013 VDPAU_DRIVER_DATA_INIT;
1014
1015 static const VAProfile va_profiles[] = {
1016 VAProfileMPEG2Simple,
1017 VAProfileMPEG2Main,
1018 VAProfileMPEG4Simple,
1019 VAProfileMPEG4AdvancedSimple,
1020 VAProfileMPEG4Main,
1021 VAProfileH264Baseline,
1022 VAProfileH264Main,
1023 VAProfileH264High,
1024 VAProfileVC1Simple,
1025 VAProfileVC1Main,
1026 VAProfileVC1Advanced
1027 };
1028
1029 int i, n = 0;
1030 for (i = 0; i < ARRAY_ELEMS(va_profiles); i++) {
1031 VAProfile profile = va_profiles[i];
1032 VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile);
1033 if (is_supported_profile(driver_data, vdp_profile))
1034 profile_list[n++] = profile;
1035 }
1036
1037 /* If the assert fails then VDPAU_MAX_PROFILES needs to be bigger */
1038 ASSERT(n <= VDPAU_MAX_PROFILES);
1039 if (num_profiles)
1040 *num_profiles = n;
1041
1042 return VA_STATUS_SUCCESS;
1043}
1044
1045// vaQueryConfigEntrypoints
1046VAStatus
1047vdpau_QueryConfigEntrypoints(
1048 VADriverContextP ctx,
1049 VAProfile profile,
1050 VAEntrypoint *entrypoint_list,
1051 int *num_entrypoints
1052)
1053{
1054 VDPAU_DRIVER_DATA_INIT;
1055
1056 VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile);
1057 if (!is_supported_profile(driver_data, vdp_profile))
1058 return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1059
1060 VAEntrypoint entrypoint;
1061 switch (profile) {
1062 case VAProfileMPEG2Simple:
1063 case VAProfileMPEG2Main:
1064 entrypoint = VAEntrypointVLD;
1065 break;
1066 case VAProfileMPEG4Simple:
1067 case VAProfileMPEG4AdvancedSimple:
1068 case VAProfileMPEG4Main:
1069 entrypoint = VAEntrypointVLD;
1070 break;
1071 case VAProfileH264Baseline:
1072 case VAProfileH264Main:
1073 case VAProfileH264High:
1074 entrypoint = VAEntrypointVLD;
1075 break;
1076 case VAProfileVC1Simple:
1077 case VAProfileVC1Main:
1078 case VAProfileVC1Advanced:
1079 entrypoint = VAEntrypointVLD;
1080 break;
1081 default:
1082 entrypoint = 0;
1083 break;
1084 }
1085
1086 if (entrypoint_list)
1087 *entrypoint_list = entrypoint;
1088
1089 if (num_entrypoints)
1090 *num_entrypoints = entrypoint != 0;
1091
1092 return VA_STATUS_SUCCESS;
1093}
1094
1095// vaBeginPicture
1096VAStatus
1097vdpau_BeginPicture(
1098 VADriverContextP ctx,
1099 VAContextID context,
1100 VASurfaceID render_target
1101)
1102{
1103 VDPAU_DRIVER_DATA_INIT;
1104
1105 object_context_p obj_context = VDPAU_CONTEXT(context);
1106 if (!obj_context)
1107 return VA_STATUS_ERROR_INVALID_CONTEXT;
1108
1109 object_surface_p obj_surface = VDPAU_SURFACE(render_target);
1110 if (!obj_surface)
1111 return VA_STATUS_ERROR_INVALID_SURFACE;
1112
1113 obj_surface->va_surface_status = VASurfaceRendering;
1114 obj_context->last_pic_param = NULL;
1115 obj_context->last_slice_params = NULL;
1116 obj_context->last_slice_params_count = 0;
1117 obj_context->current_render_target = obj_surface->base.id;
1118 obj_context->gen_slice_data_size = 0;
1119 obj_context->vdp_bitstream_buffers_count = 0;
1120
1121 switch (obj_context->vdp_codec) {
1122 case VDP_CODEC_MPEG1:
1123 case VDP_CODEC_MPEG2:
1124 obj_context->vdp_picture_info.mpeg2.slice_count = 0;
1125 break;
1126 case VDP_CODEC_MPEG4:
1127 break;
1128 case VDP_CODEC_H264:
1129 obj_context->vdp_picture_info.h264.slice_count = 0;
1130 break;
1131 case VDP_CODEC_VC1:
1132 obj_context->vdp_picture_info.vc1.slice_count = 0;
1133 break;
1134 default:
1135 return VA_STATUS_ERROR_UNKNOWN;
1136 }
1137 return VA_STATUS_SUCCESS;
1138}
1139
1140// vaRenderPicture
1141VAStatus
1142vdpau_RenderPicture(
1143 VADriverContextP ctx,
1144 VAContextID context,
1145 VABufferID *buffers,
1146 int num_buffers
1147)
1148{
1149 VDPAU_DRIVER_DATA_INIT;
1150 int i;
1151
1152 object_context_p obj_context = VDPAU_CONTEXT(context);
1153 if (!obj_context)
1154 return VA_STATUS_ERROR_INVALID_CONTEXT;
1155
1156 object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target);
1157 if (!obj_surface)
1158 return VA_STATUS_ERROR_INVALID_SURFACE;
1159
1160 /* Verify that we got valid buffer references */
1161 for (i = 0; i < num_buffers; i++) {
1162 object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]);
1163 if (!obj_buffer)
1164 return VA_STATUS_ERROR_INVALID_BUFFER;
1165 }
1166
1167 /* Translate buffers */
1168 for (i = 0; i < num_buffers; i++) {
1169 object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]);
1170 if (!translate_buffer(driver_data, obj_context, obj_buffer))
1171 return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1172 /* Release any buffer that is not VASliceDataBuffer */
1173 /* VASliceParameterBuffer is also needed to check for start_codes */
1174 switch (obj_buffer->type) {
1175 case VASliceParameterBufferType:
1176 case VASliceDataBufferType:
1177 schedule_destroy_va_buffer(driver_data, obj_buffer);
1178 break;
1179 case VAPictureParameterBufferType:
1180 /* Preserve VAPictureParameterBufferMPEG4 */
1181 if (obj_context->vdp_codec == VDP_CODEC_MPEG4) {
1182 schedule_destroy_va_buffer(driver_data, obj_buffer);
1183 break;
1184 }
1185 /* fall-through */
1186 default:
1187 destroy_va_buffer(driver_data, obj_buffer);
1188 break;
1189 }
1190 }
1191
1192 return VA_STATUS_SUCCESS;
1193}
1194
1195// vaEndPicture
1196VAStatus
1197vdpau_EndPicture(
1198 VADriverContextP ctx,
1199 VAContextID context
1200)
1201{
1202 VDPAU_DRIVER_DATA_INIT;
1203 unsigned int i;
1204
1205 object_context_p obj_context = VDPAU_CONTEXT(context);
1206 if (!obj_context)
1207 return VA_STATUS_ERROR_INVALID_CONTEXT;
1208
1209 object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target);
1210 if (!obj_surface)
1211 return VA_STATUS_ERROR_INVALID_SURFACE;
1212
1213 if (trace_enabled()) {
1214 switch (obj_context->vdp_codec) {
1215 case VDP_CODEC_MPEG1:
1216 case VDP_CODEC_MPEG2:
1217 dump_VdpPictureInfoMPEG1Or2(&obj_context->vdp_picture_info.mpeg2);
1218 break;
1219#if HAVE_VDPAU_MPEG4
1220 case VDP_CODEC_MPEG4:
1221 dump_VdpPictureInfoMPEG4Part2(&obj_context->vdp_picture_info.mpeg4);
1222 break;
1223#endif
1224 case VDP_CODEC_H264:
1225 dump_VdpPictureInfoH264(&obj_context->vdp_picture_info.h264);
1226 break;
1227 case VDP_CODEC_VC1:
1228 dump_VdpPictureInfoVC1(&obj_context->vdp_picture_info.vc1);
1229 break;
1230 default:
1231 break;
1232 }
1233 for (i = 0; i < obj_context->vdp_bitstream_buffers_count; i++)
1234 dump_VdpBitstreamBuffer(&obj_context->vdp_bitstream_buffers[i]);
1235 }
1236
1237 VAStatus va_status;
1238 VdpStatus vdp_status;
1239 vdp_status = ensure_decoder_with_max_refs(
1240 driver_data,
1241 obj_context,
1242 get_num_ref_frames(obj_context)
1243 );
1244 if (vdp_status == VDP_STATUS_OK)
1245 vdp_status = vdpau_decoder_render(
1246 driver_data,
1247 obj_context->vdp_decoder,
1248 obj_surface->vdp_surface,
1249 (VdpPictureInfo)&obj_context->vdp_picture_info,
1250 obj_context->vdp_bitstream_buffers_count,
1251 obj_context->vdp_bitstream_buffers
1252 );
1253 va_status = vdpau_get_VAStatus(vdp_status);
1254
1255 /* XXX: assume we are done with rendering right away */
1256 obj_context->current_render_target = VA_INVALID_SURFACE;
1257
1258 /* Release pending buffers */
1259 if (obj_context->dead_buffers_count > 0) {
1260 ASSERT(obj_context->dead_buffers);
1261 int i;
1262 for (i = 0; i < obj_context->dead_buffers_count; i++) {
1263 object_buffer_p obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]);
1264 ASSERT(obj_buffer);
1265 destroy_va_buffer(driver_data, obj_buffer);
1266 }
1267 obj_context->dead_buffers_count = 0;
1268 }
1269
1270 return va_status;
1271}
01272
=== added file '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_video.c'
--- .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_video.c 1970-01-01 00:00:00 +0000
+++ .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_video.c 2014-05-06 21:31:51 +0000
@@ -0,0 +1,995 @@
1/*
2 * vdpau_video.c - VDPAU backend for VA-API
3 *
4 * vdpau-video (C) 2009-2011 Splitted-Desktop Systems
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "sysdeps.h"
22#include "vdpau_video.h"
23#include "vdpau_video_x11.h"
24#include "vdpau_decode.h"
25#include "vdpau_subpic.h"
26#include "vdpau_mixer.h"
27#include "utils.h"
28
29#define DEBUG 1
30#include "debug.h"
31
32
33/* Define wait delay (in microseconds) for vaSyncSurface() implementation
34 with polling. */
35#define VDPAU_SYNC_DELAY 5000
36
37// Translates VA-API chroma format to VdpChromaType
38static VdpChromaType get_VdpChromaType(int format)
39{
40 switch (format) {
41 case VA_RT_FORMAT_YUV420: return VDP_CHROMA_TYPE_420;
42 case VA_RT_FORMAT_YUV422: return VDP_CHROMA_TYPE_422;
43 case VA_RT_FORMAT_YUV444: return VDP_CHROMA_TYPE_444;
44 }
45 return (VdpChromaType)-1;
46}
47
48
49/* ====================================================================== */
50/* === VA-API Implementation with VDPAU === */
51/* ====================================================================== */
52
53// Returns the maximum dimensions supported by the VDPAU implementation for that profile
54static inline VdpBool
55get_max_surface_size(
56 vdpau_driver_data_t *driver_data,
57 VdpDecoderProfile profile,
58 uint32_t *pmax_width,
59 uint32_t *pmax_height
60)
61{
62 VdpBool is_supported = VDP_FALSE;
63 VdpStatus vdp_status;
64 uint32_t max_level, max_references, max_width, max_height;
65
66 if (pmax_width)
67 *pmax_width = 0;
68 if (pmax_height)
69 *pmax_height = 0;
70
71 vdp_status = vdpau_decoder_query_capabilities(
72 driver_data,
73 driver_data->vdp_device,
74 profile,
75 &is_supported,
76 &max_level,
77 &max_references,
78 &max_width,
79 &max_height
80 );
81 if (!VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderQueryCapabilities()"))
82 return VDP_FALSE;
83
84 if (!is_supported)
85 return VDP_FALSE;
86
87 if (pmax_width)
88 *pmax_width = max_width;
89 if (max_height)
90 *pmax_height = max_height;
91
92 return VDP_TRUE;
93}
94
95// vaGetConfigAttributes
96VAStatus
97vdpau_GetConfigAttributes(
98 VADriverContextP ctx,
99 VAProfile profile,
100 VAEntrypoint entrypoint,
101 VAConfigAttrib *attrib_list,
102 int num_attribs
103)
104{
105 VDPAU_DRIVER_DATA_INIT;
106
107 VAStatus va_status = check_decoder(driver_data, profile, entrypoint);
108 if (va_status != VA_STATUS_SUCCESS)
109 return va_status;
110
111 int i;
112 for (i = 0; i < num_attribs; i++) {
113 switch (attrib_list[i].type) {
114 case VAConfigAttribRTFormat:
115 attrib_list[i].value = VA_RT_FORMAT_YUV420;
116 break;
117 default:
118 attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
119 break;
120 }
121 }
122 return VA_STATUS_SUCCESS;
123}
124
125static VAStatus
126vdpau_update_attribute(object_config_p obj_config, VAConfigAttrib *attrib)
127{
128 int i;
129
130 /* Check existing attrbiutes */
131 for (i = 0; obj_config->attrib_count < i; i++) {
132 if (obj_config->attrib_list[i].type == attrib->type) {
133 /* Update existing attribute */
134 obj_config->attrib_list[i].value = attrib->value;
135 return VA_STATUS_SUCCESS;
136 }
137 }
138 if (obj_config->attrib_count < VDPAU_MAX_CONFIG_ATTRIBUTES) {
139 i = obj_config->attrib_count;
140 obj_config->attrib_list[i].type = attrib->type;
141 obj_config->attrib_list[i].value = attrib->value;
142 obj_config->attrib_count++;
143 return VA_STATUS_SUCCESS;
144 }
145 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
146}
147
148// vaDestroyConfig
149VAStatus vdpau_DestroyConfig(VADriverContextP ctx, VAConfigID config_id)
150{
151 VDPAU_DRIVER_DATA_INIT;
152
153 object_config_p obj_config = VDPAU_CONFIG(config_id);
154 if (!obj_config)
155 return VA_STATUS_ERROR_INVALID_CONFIG;
156
157 object_heap_free(&driver_data->config_heap, (object_base_p)obj_config);
158 return VA_STATUS_SUCCESS;
159}
160
161// vaCreateConfig
162VAStatus
163vdpau_CreateConfig(
164 VADriverContextP ctx,
165 VAProfile profile,
166 VAEntrypoint entrypoint,
167 VAConfigAttrib *attrib_list,
168 int num_attribs,
169 VAConfigID *config_id
170)
171{
172 VDPAU_DRIVER_DATA_INIT;
173
174 VAStatus va_status;
175 int configID;
176 object_config_p obj_config;
177 int i;
178
179 /* Validate profile and entrypoint */
180 va_status = check_decoder(driver_data, profile, entrypoint);
181 if (va_status != VA_STATUS_SUCCESS)
182 return va_status;
183
184 configID = object_heap_allocate(&driver_data->config_heap);
185 if ((obj_config = VDPAU_CONFIG(configID)) == NULL)
186 return VA_STATUS_ERROR_ALLOCATION_FAILED;
187
188 obj_config->profile = profile;
189 obj_config->entrypoint = entrypoint;
190 obj_config->attrib_list[0].type = VAConfigAttribRTFormat;
191 obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420;
192 obj_config->attrib_count = 1;
193
194 for(i = 0; i < num_attribs; i++) {
195 va_status = vdpau_update_attribute(obj_config, &attrib_list[i]);
196 if (va_status != VA_STATUS_SUCCESS) {
197 vdpau_DestroyConfig(ctx, configID);
198 return va_status;
199 }
200 }
201
202 if (config_id)
203 *config_id = configID;
204
205 return va_status;
206}
207
208// vaQueryConfigAttributes
209VAStatus
210vdpau_QueryConfigAttributes(
211 VADriverContextP ctx,
212 VAConfigID config_id,
213 VAProfile *profile,
214 VAEntrypoint *entrypoint,
215 VAConfigAttrib *attrib_list,
216 int *num_attribs
217)
218{
219 VDPAU_DRIVER_DATA_INIT;
220
221 VAStatus va_status = VA_STATUS_SUCCESS;
222 object_config_p obj_config;
223 int i;
224
225 obj_config = VDPAU_CONFIG(config_id);
226 if (!obj_config)
227 return VA_STATUS_ERROR_INVALID_CONFIG;
228
229 if (profile)
230 *profile = obj_config->profile;
231
232 if (entrypoint)
233 *entrypoint = obj_config->entrypoint;
234
235 if (num_attribs)
236 *num_attribs = obj_config->attrib_count;
237
238 if (attrib_list) {
239 for (i = 0; i < obj_config->attrib_count; i++)
240 attrib_list[i] = obj_config->attrib_list[i];
241 }
242
243 return va_status;
244}
245
246// Add subpicture association to surface
247// NOTE: the subpicture owns the SubpictureAssociation object
248int surface_add_association(
249 object_surface_p obj_surface,
250 SubpictureAssociationP assoc
251)
252{
253 /* Check that we don't already have this association */
254 if (obj_surface->assocs) {
255 unsigned int i;
256 for (i = 0; i < obj_surface->assocs_count; i++) {
257 if (obj_surface->assocs[i] == assoc)
258 return 0;
259 if (obj_surface->assocs[i]->subpicture == assoc->subpicture) {
260 /* XXX: this should not happen, but replace it in the interim */
261 ASSERT(obj_surface->assocs[i]->surface == assoc->surface);
262 obj_surface->assocs[i] = assoc;
263 return 0;
264 }
265 }
266 }
267
268 /* Check that we have not reached the maximum subpictures capacity yet */
269 if (obj_surface->assocs_count >= VDPAU_MAX_SUBPICTURES)
270 return -1;
271
272 /* Append this subpicture association */
273 SubpictureAssociationP *assocs;
274 assocs = realloc_buffer(
275 &obj_surface->assocs,
276 &obj_surface->assocs_count_max,
277 1 + obj_surface->assocs_count,
278 sizeof(obj_surface->assocs[0])
279 );
280 if (!assocs)
281 return -1;
282
283 assocs[obj_surface->assocs_count++] = assoc;
284 return 0;
285}
286
287// Remove subpicture association from surface
288// NOTE: the subpicture owns the SubpictureAssociation object
289int surface_remove_association(
290 object_surface_p obj_surface,
291 SubpictureAssociationP assoc
292)
293{
294 if (!obj_surface->assocs || obj_surface->assocs_count == 0)
295 return -1;
296
297 unsigned int i;
298 const unsigned int last = obj_surface->assocs_count - 1;
299 for (i = 0; i <= last; i++) {
300 if (obj_surface->assocs[i] == assoc) {
301 /* Swap with the last subpicture */
302 obj_surface->assocs[i] = obj_surface->assocs[last];
303 obj_surface->assocs[last] = NULL;
304 obj_surface->assocs_count--;
305 return 0;
306 }
307 }
308 return -1;
309}
310
311// vaDestroySurfaces
312VAStatus
313vdpau_DestroySurfaces(
314 VADriverContextP ctx,
315 VASurfaceID *surface_list,
316 int num_surfaces
317)
318{
319 VDPAU_DRIVER_DATA_INIT;
320
321 int i, j, n;
322 for (i = num_surfaces - 1; i >= 0; i--) {
323 object_surface_p obj_surface = VDPAU_SURFACE(surface_list[i]);
324 ASSERT(obj_surface);
325 if (!obj_surface)
326 continue;
327
328 if (obj_surface->vdp_surface != VDP_INVALID_HANDLE) {
329 vdpau_video_surface_destroy(driver_data, obj_surface->vdp_surface);
330 obj_surface->vdp_surface = VDP_INVALID_HANDLE;
331 }
332
333 for (j = 0; j < obj_surface->output_surfaces_count; j++) {
334 output_surface_unref(driver_data, obj_surface->output_surfaces[j]);
335 obj_surface->output_surfaces[j] = NULL;
336 }
337 free(obj_surface->output_surfaces);
338 obj_surface->output_surfaces_count = 0;
339 obj_surface->output_surfaces_count_max = 0;
340
341 if (obj_surface->video_mixer) {
342 video_mixer_unref(driver_data, obj_surface->video_mixer);
343 obj_surface->video_mixer = NULL;
344 }
345
346 if (obj_surface->assocs) {
347 object_subpicture_p obj_subpicture;
348 VAStatus status;
349 const unsigned int n_assocs = obj_surface->assocs_count;
350
351 for (j = 0, n = 0; j < n_assocs; j++) {
352 SubpictureAssociationP const assoc = obj_surface->assocs[0];
353 ASSERT(assoc);
354 if (!assoc)
355 continue;
356 obj_subpicture = VDPAU_SUBPICTURE(assoc->subpicture);
357 ASSERT(obj_subpicture);
358 if (!obj_subpicture)
359 continue;
360 status = subpicture_deassociate_1(obj_subpicture, obj_surface);
361 if (status == VA_STATUS_SUCCESS)
362 ++n;
363 }
364 if (n != n_assocs)
365 vdpau_error_message("vaDestroySurfaces(): surface 0x%08x still "
366 "has %d subpictures associated to it\n",
367 obj_surface->base.id, n_assocs - n);
368 free(obj_surface->assocs);
369 obj_surface->assocs = NULL;
370 }
371 obj_surface->assocs_count = 0;
372 obj_surface->assocs_count_max = 0;
373
374 object_heap_free(&driver_data->surface_heap, (object_base_p)obj_surface);
375 }
376 return VA_STATUS_SUCCESS;
377}
378
379// vaCreateSurfaces
380VAStatus
381vdpau_CreateSurfaces(
382 VADriverContextP ctx,
383 int width,
384 int height,
385 int format,
386 int num_surfaces,
387 VASurfaceID *surfaces
388)
389{
390 VDPAU_DRIVER_DATA_INIT;
391
392 VAStatus va_status = VA_STATUS_SUCCESS;
393 VdpVideoSurface vdp_surface = VDP_INVALID_HANDLE;
394 VdpChromaType vdp_chroma_type = get_VdpChromaType(format);
395 VdpStatus vdp_status;
396 int i;
397
398 /* We only support one format */
399 if (format != VA_RT_FORMAT_YUV420)
400 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
401
402 for (i = 0; i < num_surfaces; i++) {
403 vdp_status = vdpau_video_surface_create(
404 driver_data,
405 driver_data->vdp_device,
406 vdp_chroma_type,
407 width, height,
408 &vdp_surface
409 );
410 if (!VDPAU_CHECK_STATUS(vdp_status, "VdpVideoSurfaceCreate()")) {
411 va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
412 break;
413 }
414
415 int va_surface = object_heap_allocate(&driver_data->surface_heap);
416 object_surface_p obj_surface = VDPAU_SURFACE(va_surface);
417 if (!obj_surface) {
418 va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
419 break;
420 }
421 obj_surface->va_context = VA_INVALID_ID;
422 obj_surface->va_surface_status = VASurfaceReady;
423 obj_surface->vdp_surface = vdp_surface;
424 obj_surface->width = width;
425 obj_surface->height = height;
426 obj_surface->assocs = NULL;
427 obj_surface->assocs_count = 0;
428 obj_surface->assocs_count_max = 0;
429 obj_surface->vdp_chroma_type = vdp_chroma_type;
430 obj_surface->output_surfaces = NULL;
431 obj_surface->output_surfaces_count = 0;
432 obj_surface->output_surfaces_count_max = 0;
433 obj_surface->video_mixer = NULL;
434 surfaces[i] = va_surface;
435 vdp_surface = VDP_INVALID_HANDLE;
436
437 object_mixer_p obj_mixer;
438 obj_mixer = video_mixer_create_cached(driver_data, obj_surface);
439 if (!obj_mixer) {
440 va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
441 break;
442 }
443 obj_surface->video_mixer = obj_mixer;
444 }
445
446 /* Error recovery */
447 if (va_status != VA_STATUS_SUCCESS) {
448 if (vdp_surface != VDP_INVALID_HANDLE)
449 vdpau_video_surface_destroy(driver_data, vdp_surface);
450 vdpau_DestroySurfaces(ctx, surfaces, i);
451 }
452 return va_status;
453}
454
455// vaDestroyContext
456VAStatus vdpau_DestroyContext(VADriverContextP ctx, VAContextID context)
457{
458 VDPAU_DRIVER_DATA_INIT;
459 int i;
460
461 object_context_p obj_context = VDPAU_CONTEXT(context);
462 if (!obj_context)
463 return VA_STATUS_ERROR_INVALID_CONTEXT;
464
465 if (obj_context->gen_slice_data) {
466 free(obj_context->gen_slice_data);
467 obj_context->gen_slice_data = NULL;
468 obj_context->gen_slice_data_size = 0;
469 obj_context->gen_slice_data_size_max = 0;
470 }
471
472 if (obj_context->vdp_bitstream_buffers) {
473 free(obj_context->vdp_bitstream_buffers);
474 obj_context->vdp_bitstream_buffers = NULL;
475 obj_context->vdp_bitstream_buffers_count = 0;
476 obj_context->vdp_bitstream_buffers_count_max = 0;
477 }
478
479 if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) {
480 vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder);
481 obj_context->vdp_decoder = VDP_INVALID_HANDLE;
482 }
483
484 if (obj_context->dead_buffers) {
485 free(obj_context->dead_buffers);
486 obj_context->dead_buffers = NULL;
487 }
488
489 if (obj_context->render_targets) {
490 for (i = 0; i < obj_context->num_render_targets; i++) {
491 object_surface_p obj_surface;
492 obj_surface = VDPAU_SURFACE(obj_context->render_targets[i]);
493 if (obj_surface)
494 obj_surface->va_context = VA_INVALID_ID;
495 }
496 free(obj_context->render_targets);
497 obj_context->render_targets = NULL;
498 }
499
500 obj_context->context_id = VA_INVALID_ID;
501 obj_context->config_id = VA_INVALID_ID;
502 obj_context->current_render_target = VA_INVALID_SURFACE;
503 obj_context->picture_width = 0;
504 obj_context->picture_height = 0;
505 obj_context->num_render_targets = 0;
506 obj_context->flags = 0;
507 obj_context->dead_buffers_count = 0;
508 obj_context->dead_buffers_count_max = 0;
509
510 object_heap_free(&driver_data->context_heap, (object_base_p)obj_context);
511 return VA_STATUS_SUCCESS;
512}
513
514// vaCreateContext
515VAStatus
516vdpau_CreateContext(
517 VADriverContextP ctx,
518 VAConfigID config_id,
519 int picture_width,
520 int picture_height,
521 int flag,
522 VASurfaceID *render_targets,
523 int num_render_targets,
524 VAContextID *context
525)
526{
527 VDPAU_DRIVER_DATA_INIT;
528
529 if (context)
530 *context = VA_INVALID_ID;
531
532 object_config_p obj_config;
533 if ((obj_config = VDPAU_CONFIG(config_id)) == NULL)
534 return VA_STATUS_ERROR_INVALID_CONFIG;
535
536 /* XXX: validate flag */
537
538 VdpDecoderProfile vdp_profile;
539 uint32_t max_width, max_height;
540 int i;
541 vdp_profile = get_VdpDecoderProfile(obj_config->profile);
542 if (!get_max_surface_size(driver_data, vdp_profile, &max_width, &max_height))
543 return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
544 if (picture_width > max_width || picture_height > max_height)
545 return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
546
547 VAContextID context_id = object_heap_allocate(&driver_data->context_heap);
548 if (context_id == VA_INVALID_ID)
549 return VA_STATUS_ERROR_ALLOCATION_FAILED;
550
551 object_context_p obj_context = VDPAU_CONTEXT(context_id);
552 if (!obj_context)
553 return VA_STATUS_ERROR_ALLOCATION_FAILED;
554 if (context)
555 *context = context_id;
556
557 obj_context->context_id = context_id;
558 obj_context->config_id = config_id;
559 obj_context->current_render_target = VA_INVALID_SURFACE;
560 obj_context->picture_width = picture_width;
561 obj_context->picture_height = picture_height;
562 obj_context->num_render_targets = num_render_targets;
563 obj_context->flags = flag;
564 obj_context->max_ref_frames = -1;
565 obj_context->render_targets = (VASurfaceID *)
566 calloc(num_render_targets, sizeof(VASurfaceID));
567 obj_context->dead_buffers = NULL;
568 obj_context->dead_buffers_count = 0;
569 obj_context->dead_buffers_count_max = 0;
570 obj_context->vdp_codec = get_VdpCodec(vdp_profile);
571 obj_context->vdp_profile = vdp_profile;
572 obj_context->vdp_decoder = VDP_INVALID_HANDLE;
573 obj_context->gen_slice_data = NULL;
574 obj_context->gen_slice_data_size = 0;
575 obj_context->gen_slice_data_size_max = 0;
576 obj_context->vdp_bitstream_buffers = NULL;
577 obj_context->vdp_bitstream_buffers_count = 0;
578 obj_context->vdp_bitstream_buffers_count_max = 0;
579
580 if (!obj_context->render_targets) {
581 vdpau_DestroyContext(ctx, context_id);
582 return VA_STATUS_ERROR_ALLOCATION_FAILED;
583 }
584
585 for (i = 0; i < num_render_targets; i++) {
586 object_surface_t *obj_surface;
587 if ((obj_surface = VDPAU_SURFACE(render_targets[i])) == NULL) {
588 vdpau_DestroyContext(ctx, context_id);
589 return VA_STATUS_ERROR_INVALID_SURFACE;
590 }
591 obj_context->render_targets[i] = render_targets[i];
592 /* XXX: assume we can only associate a surface to a single context */
593 ASSERT(obj_surface->va_context == VA_INVALID_ID);
594 obj_surface->va_context = context_id;
595 }
596 return VA_STATUS_SUCCESS;
597}
598
599// Query surface status
600VAStatus
601query_surface_status(
602 vdpau_driver_data_t *driver_data,
603 object_surface_p obj_surface,
604 VASurfaceStatus *status
605)
606{
607 VAStatus va_status = VA_STATUS_SUCCESS;
608
609 if (obj_surface->va_surface_status == VASurfaceDisplaying) {
610 unsigned int i, num_output_surfaces_displaying = 0;
611 for (i = 0; i < obj_surface->output_surfaces_count; i++) {
612 object_output_p obj_output = obj_surface->output_surfaces[i];
613 if (!obj_output)
614 return VA_STATUS_ERROR_INVALID_SURFACE;
615
616 VdpOutputSurface vdp_output_surface;
617 vdp_output_surface = obj_output->vdp_output_surfaces[obj_output->displayed_output_surface];
618 if (vdp_output_surface == VDP_INVALID_HANDLE)
619 continue;
620
621 VdpPresentationQueueStatus vdp_queue_status;
622 VdpTime vdp_dummy_time;
623 VdpStatus vdp_status;
624 vdp_status = vdpau_presentation_queue_query_surface_status(
625 driver_data,
626 obj_output->vdp_flip_queue,
627 vdp_output_surface,
628 &vdp_queue_status,
629 &vdp_dummy_time
630 );
631 va_status = vdpau_get_VAStatus(vdp_status);
632
633 if (vdp_queue_status != VDP_PRESENTATION_QUEUE_STATUS_VISIBLE)
634 ++num_output_surfaces_displaying;
635 }
636
637 if (num_output_surfaces_displaying == 0)
638 obj_surface->va_surface_status = VASurfaceReady;
639 }
640
641 if (status)
642 *status = obj_surface->va_surface_status;
643
644 return va_status;
645}
646
647// vaQuerySurfaceStatus
648VAStatus
649vdpau_QuerySurfaceStatus(
650 VADriverContextP ctx,
651 VASurfaceID render_target,
652 VASurfaceStatus *status
653)
654{
655 VDPAU_DRIVER_DATA_INIT;
656
657 object_surface_p obj_surface = VDPAU_SURFACE(render_target);
658 if (!obj_surface)
659 return VA_STATUS_ERROR_INVALID_SURFACE;
660
661 return query_surface_status(driver_data, obj_surface, status);
662}
663
664// Wait for the surface to complete pending operations
665VAStatus
666sync_surface(
667 vdpau_driver_data_t *driver_data,
668 object_surface_p obj_surface
669)
670{
671 /* VDPAU only supports status interface for in-progress display */
672 /* XXX: polling is bad but there currently is no alternative */
673 for (;;) {
674 VASurfaceStatus va_surface_status;
675 VAStatus va_status;
676
677 va_status = query_surface_status(
678 driver_data,
679 obj_surface,
680 &va_surface_status
681 );
682 if (va_status != VA_STATUS_SUCCESS)
683 return va_status;
684
685 if (va_surface_status != VASurfaceDisplaying)
686 break;
687 delay_usec(VDPAU_SYNC_DELAY);
688 }
689 return VA_STATUS_SUCCESS;
690}
691
692// vaSyncSurface
693VAStatus
694vdpau_SyncSurface2(
695 VADriverContextP ctx,
696 VASurfaceID render_target
697)
698{
699 VDPAU_DRIVER_DATA_INIT;
700
701 object_surface_p obj_surface = VDPAU_SURFACE(render_target);
702 if (!obj_surface)
703 return VA_STATUS_ERROR_INVALID_SURFACE;
704
705 /* Assume that this shouldn't be called before vaEndPicture() */
706 object_context_p obj_context = VDPAU_CONTEXT(obj_surface->va_context);
707 if (obj_context) {
708 ASSERT(obj_context->current_render_target != obj_surface->base.id);
709 if (obj_context->current_render_target == obj_surface->base.id)
710 return VA_STATUS_ERROR_INVALID_CONTEXT;
711 }
712
713 return sync_surface(driver_data, obj_surface);
714}
715
716VAStatus
717vdpau_SyncSurface3(
718 VADriverContextP ctx,
719 VAContextID context,
720 VASurfaceID render_target
721)
722{
723 VDPAU_DRIVER_DATA_INIT;
724
725 object_surface_p obj_surface = VDPAU_SURFACE(render_target);
726 if (!obj_surface)
727 return VA_STATUS_ERROR_INVALID_SURFACE;
728
729 /* Assume that this shouldn't be called before vaEndPicture() */
730 object_context_p obj_context = VDPAU_CONTEXT(context);
731 if (obj_context) {
732 ASSERT(obj_context->current_render_target != obj_surface->base.id);
733 if (obj_context->current_render_target == obj_surface->base.id)
734 return VA_STATUS_ERROR_INVALID_CONTEXT;
735 }
736 return sync_surface(driver_data, obj_surface);
737}
738
739// Ensure VA Display Attributes are initialized
740static int ensure_display_attributes(vdpau_driver_data_t *driver_data)
741{
742 VADisplayAttribute *attr;
743
744 if (driver_data->va_display_attrs_count > 0)
745 return 0;
746
747 memset(driver_data->va_display_attrs_mtime, 0, sizeof(driver_data->va_display_attrs_mtime));
748
749 attr = &driver_data->va_display_attrs[0];
750
751 attr->type = VADisplayAttribDirectSurface;
752 attr->value = 0; /* VdpVideoSurface is copied into VdpOutputSurface */
753 attr->min_value = attr->value;
754 attr->max_value = attr->value;
755 attr->flags = VA_DISPLAY_ATTRIB_GETTABLE;
756 attr++;
757
758 attr->type = VADisplayAttribBrightness;
759 attr->value = 0;
760 attr->min_value = -100;
761 attr->max_value = 100;
762 attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
763 attr++;
764
765 attr->type = VADisplayAttribContrast;
766 attr->value = 0;
767 attr->min_value = -100;
768 attr->max_value = 100;
769 attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
770 attr++;
771
772 attr->type = VADisplayAttribHue;
773 attr->value = 0;
774 attr->min_value = -100;
775 attr->max_value = 100;
776 attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
777 attr++;
778
779 attr->type = VADisplayAttribSaturation;
780 attr->value = 0;
781 attr->min_value = -100;
782 attr->max_value = 100;
783 attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
784 attr++;
785
786 attr->type = VADisplayAttribBackgroundColor;
787 attr->value = 0;
788 attr->min_value = 0;
789 attr->max_value = 0xffffff;
790 attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
791 attr++;
792
793 driver_data->va_display_attrs_count = attr - driver_data->va_display_attrs;
794 ASSERT(driver_data->va_display_attrs_count <= VDPAU_MAX_DISPLAY_ATTRIBUTES);
795 return 0;
796}
797
798// Look up for the specified VA display attribute
799static VADisplayAttribute *
800get_display_attribute(
801 vdpau_driver_data_t *driver_data,
802 VADisplayAttribType type
803)
804{
805 if (ensure_display_attributes(driver_data) < 0)
806 return NULL;
807
808 unsigned int i;
809 for (i = 0; i < driver_data->va_display_attrs_count; i++) {
810 if (driver_data->va_display_attrs[i].type == type)
811 return &driver_data->va_display_attrs[i];
812 }
813 return NULL;
814}
815
816// vaQueryDisplayAttributes
817VAStatus
818vdpau_QueryDisplayAttributes(
819 VADriverContextP ctx,
820 VADisplayAttribute *attr_list,
821 int *num_attributes
822)
823{
824 VDPAU_DRIVER_DATA_INIT;
825
826 if (ensure_display_attributes(driver_data) < 0)
827 return VA_STATUS_ERROR_OPERATION_FAILED;
828
829 if (attr_list)
830 memcpy(attr_list, driver_data->va_display_attrs,
831 driver_data->va_display_attrs_count * sizeof(attr_list[0]));
832
833 if (num_attributes)
834 *num_attributes = driver_data->va_display_attrs_count;
835
836 return VA_STATUS_SUCCESS;
837}
838
839// vaGetDisplayAttributes
840VAStatus
841vdpau_GetDisplayAttributes(
842 VADriverContextP ctx,
843 VADisplayAttribute *attr_list,
844 int num_attributes
845)
846{
847 VDPAU_DRIVER_DATA_INIT;
848
849 unsigned int i;
850 for (i = 0; i < num_attributes; i++) {
851 VADisplayAttribute * const dst_attr = &attr_list[i];
852 VADisplayAttribute *src_attr;
853
854 src_attr = get_display_attribute(driver_data, dst_attr->type);
855 if (src_attr && (src_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) != 0) {
856 dst_attr->min_value = src_attr->min_value;
857 dst_attr->max_value = src_attr->max_value;
858 dst_attr->value = src_attr->value;
859 }
860 else
861 dst_attr->flags &= ~VA_DISPLAY_ATTRIB_GETTABLE;
862 }
863 return VA_STATUS_SUCCESS;
864}
865
866// vaSetDisplayAttributes
867VAStatus
868vdpau_SetDisplayAttributes(
869 VADriverContextP ctx,
870 VADisplayAttribute *attr_list,
871 int num_attributes
872)
873{
874 VDPAU_DRIVER_DATA_INIT;
875
876 unsigned int i;
877 for (i = 0; i < num_attributes; i++) {
878 VADisplayAttribute * const src_attr = &attr_list[i];
879 VADisplayAttribute *dst_attr;
880
881 dst_attr = get_display_attribute(driver_data, src_attr->type);
882 if (!dst_attr)
883 return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
884
885 if ((dst_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) != 0) {
886 dst_attr->value = src_attr->value;
887
888 static uint64_t mtime;
889 const int display_attr_index = dst_attr - driver_data->va_display_attrs;
890 ASSERT(display_attr_index < VDPAU_MAX_DISPLAY_ATTRIBUTES);
891 driver_data->va_display_attrs_mtime[display_attr_index] = ++mtime;
892 }
893 }
894 return VA_STATUS_SUCCESS;
895}
896
897// vaDbgCopySurfaceToBuffer (not a PUBLIC interface)
898VAStatus
899vdpau_DbgCopySurfaceToBuffer(
900 VADriverContextP ctx,
901 VASurfaceID surface,
902 void **buffer,
903 unsigned int *stride
904)
905{
906 /* TODO */
907 return VA_STATUS_ERROR_UNKNOWN;
908}
909
910#if VA_CHECK_VERSION(0,30,0)
911// vaCreateSurfaceFromCIFrame
912VAStatus
913vdpau_CreateSurfaceFromCIFrame(
914 VADriverContextP ctx,
915 unsigned long frame_id,
916 VASurfaceID *surface
917)
918{
919 /* TODO */
920 return VA_STATUS_ERROR_UNKNOWN;
921}
922
923// vaCreateSurfaceFromV4L2Buf
924VAStatus
925vdpau_CreateSurfaceFromV4L2Buf(
926 VADriverContextP ctx,
927 int v4l2_fd,
928 struct v4l2_format *v4l2_fmt,
929 struct v4l2_buffer *v4l2_buf,
930 VASurfaceID *surface
931)
932{
933 /* TODO */
934 return VA_STATUS_ERROR_UNKNOWN;
935}
936
937// vaCopySurfaceToBuffer
938VAStatus
939vdpau_CopySurfaceToBuffer(
940 VADriverContextP ctx,
941 VASurfaceID surface,
942 unsigned int *fourcc,
943 unsigned int *luma_stride,
944 unsigned int *chroma_u_stride,
945 unsigned int *chroma_v_stride,
946 unsigned int *luma_offset,
947 unsigned int *chroma_u_offset,
948 unsigned int *chroma_v_offset,
949 void **buffer
950)
951{
952 /* TODO */
953 return VA_STATUS_ERROR_UNKNOWN;
954}
955#endif
956
957#if VA_CHECK_VERSION(0,31,1)
958// vaLockSurface
959VAStatus
960vdpau_LockSurface(
961 VADriverContextP ctx,
962 VASurfaceID surface,
963 unsigned int *fourcc,
964 unsigned int *luma_stride,
965 unsigned int *chroma_u_stride,
966 unsigned int *chroma_v_stride,
967 unsigned int *luma_offset,
968 unsigned int *chroma_u_offset,
969 unsigned int *chroma_v_offset,
970 unsigned int *buffer_name,
971 void **buffer
972)
973{
974 if (fourcc) *fourcc = VA_FOURCC('N','V','1','2');
975 if (luma_stride) *luma_stride = 0;
976 if (chroma_u_stride) *chroma_u_stride = 0;
977 if (chroma_v_stride) *chroma_v_stride = 0;
978 if (luma_offset) *luma_offset = 0;
979 if (chroma_u_offset) *chroma_u_offset = 0;
980 if (chroma_v_offset) *chroma_v_offset = 0;
981 if (buffer_name) *buffer_name = 0;
982 if (buffer) *buffer = NULL;
983 return VA_STATUS_SUCCESS;
984}
985
986// vaUnlockSurface
987VAStatus
988vdpau_UnlockSurface(
989 VADriverContextP ctx,
990 VASurfaceID surface
991)
992{
993 return VA_STATUS_SUCCESS;
994}
995#endif
0996
=== added directory '.pc/03_mark_destroyed_buffers_as_deleted.patch'
=== added directory '.pc/03_mark_destroyed_buffers_as_deleted.patch/src'
=== added file '.pc/03_mark_destroyed_buffers_as_deleted.patch/src/vdpau_decode.c'
--- .pc/03_mark_destroyed_buffers_as_deleted.patch/src/vdpau_decode.c 1970-01-01 00:00:00 +0000
+++ .pc/03_mark_destroyed_buffers_as_deleted.patch/src/vdpau_decode.c 2014-05-06 21:31:51 +0000
@@ -0,0 +1,1264 @@
1/*
2 * vdpau_decode.c - VDPAU backend for VA-API (decoder)
3 *
4 * vdpau-video (C) 2009-2011 Splitted-Desktop Systems
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "sysdeps.h"
22#include "vdpau_decode.h"
23#include "vdpau_driver.h"
24#include "vdpau_buffer.h"
25#include "vdpau_video.h"
26#include "vdpau_dump.h"
27#include "utils.h"
28#include "put_bits.h"
29
30#define DEBUG 1
31#include "debug.h"
32
33
34// Translates VdpDecoderProfile to VdpCodec
35VdpCodec get_VdpCodec(VdpDecoderProfile profile)
36{
37 switch (profile) {
38 case VDP_DECODER_PROFILE_MPEG1:
39 return VDP_CODEC_MPEG1;
40 case VDP_DECODER_PROFILE_MPEG2_SIMPLE:
41 case VDP_DECODER_PROFILE_MPEG2_MAIN:
42 return VDP_CODEC_MPEG2;
43#if USE_VDPAU_MPEG4
44 case VDP_DECODER_PROFILE_MPEG4_PART2_SP:
45 case VDP_DECODER_PROFILE_MPEG4_PART2_ASP:
46 case VDP_DECODER_PROFILE_DIVX4_QMOBILE:
47 case VDP_DECODER_PROFILE_DIVX4_MOBILE:
48 case VDP_DECODER_PROFILE_DIVX4_HOME_THEATER:
49 case VDP_DECODER_PROFILE_DIVX4_HD_1080P:
50 case VDP_DECODER_PROFILE_DIVX5_QMOBILE:
51 case VDP_DECODER_PROFILE_DIVX5_MOBILE:
52 case VDP_DECODER_PROFILE_DIVX5_HOME_THEATER:
53 case VDP_DECODER_PROFILE_DIVX5_HD_1080P:
54 return VDP_CODEC_MPEG4;
55#endif
56 case VDP_DECODER_PROFILE_H264_BASELINE:
57 case VDP_DECODER_PROFILE_H264_MAIN:
58 case VDP_DECODER_PROFILE_H264_HIGH:
59 return VDP_CODEC_H264;
60 case VDP_DECODER_PROFILE_VC1_SIMPLE:
61 case VDP_DECODER_PROFILE_VC1_MAIN:
62 case VDP_DECODER_PROFILE_VC1_ADVANCED:
63 return VDP_CODEC_VC1;
64 }
65 return 0;
66}
67
68// Translates VAProfile to VdpDecoderProfile
69VdpDecoderProfile get_VdpDecoderProfile(VAProfile profile)
70{
71 switch (profile) {
72 case VAProfileMPEG2Simple: return VDP_DECODER_PROFILE_MPEG2_SIMPLE;
73 case VAProfileMPEG2Main: return VDP_DECODER_PROFILE_MPEG2_MAIN;
74#if USE_VDPAU_MPEG4
75 case VAProfileMPEG4Simple: return VDP_DECODER_PROFILE_MPEG4_PART2_SP;
76 case VAProfileMPEG4AdvancedSimple: return VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
77#endif
78 case VAProfileH264Baseline: return VDP_DECODER_PROFILE_H264_BASELINE;
79 case VAProfileH264Main: return VDP_DECODER_PROFILE_H264_MAIN;
80 case VAProfileH264High: return VDP_DECODER_PROFILE_H264_HIGH;
81 case VAProfileVC1Simple: return VDP_DECODER_PROFILE_VC1_SIMPLE;
82 case VAProfileVC1Main: return VDP_DECODER_PROFILE_VC1_MAIN;
83 case VAProfileVC1Advanced: return VDP_DECODER_PROFILE_VC1_ADVANCED;
84 default: break;
85 }
86 return (VdpDecoderProfile)-1;
87}
88
89// Checks whether the VDPAU implementation supports the specified profile
90static inline VdpBool
91is_supported_profile(
92 vdpau_driver_data_t *driver_data,
93 VdpDecoderProfile profile
94)
95{
96 VdpBool is_supported = VDP_FALSE;
97 VdpStatus vdp_status;
98 uint32_t max_level, max_references, max_width, max_height;
99
100 if (profile == (VdpDecoderProfile)-1)
101 return VDP_FALSE;
102
103 vdp_status = vdpau_decoder_query_capabilities(
104 driver_data,
105 driver_data->vdp_device,
106 profile,
107 &is_supported,
108 &max_level,
109 &max_references,
110 &max_width,
111 &max_height
112 );
113 return (VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderQueryCapabilities()") &&
114 is_supported);
115}
116
117// Checks decoder for profile/entrypoint is available
118VAStatus
119check_decoder(
120 vdpau_driver_data_t *driver_data,
121 VAProfile profile,
122 VAEntrypoint entrypoint
123)
124{
125 if (!is_supported_profile(driver_data, get_VdpDecoderProfile(profile)))
126 return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
127
128 /* VDPAU only supports VLD */
129 if (entrypoint != VAEntrypointVLD)
130 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
131
132 return VA_STATUS_SUCCESS;
133}
134
135// Computes value for VdpDecoderCreate()::max_references parameter
136static int
137get_max_ref_frames(
138 VdpDecoderProfile profile,
139 unsigned int width,
140 unsigned int height
141)
142{
143 int max_ref_frames = 2;
144
145 switch (profile) {
146 case VDP_DECODER_PROFILE_H264_MAIN:
147 case VDP_DECODER_PROFILE_H264_HIGH:
148 {
149 /* level 4.1 limits */
150 unsigned int aligned_width = (width + 15) & -16;
151 unsigned int aligned_height = (height + 15) & -16;
152 unsigned int surface_size = (aligned_width * aligned_height * 3) / 2;
153 if ((max_ref_frames = (12 * 1024 * 1024) / surface_size) > 16)
154 max_ref_frames = 16;
155 break;
156 }
157 }
158 return max_ref_frames;
159}
160
161// Returns the maximum number of reference frames of a decode session
162static inline int get_num_ref_frames(object_context_p obj_context)
163{
164 if (obj_context->vdp_codec == VDP_CODEC_H264)
165 return obj_context->vdp_picture_info.h264.num_ref_frames;
166 return 2;
167}
168
169// Ensure VDPAU decoder is created for the specified number of reference frames
170static VdpStatus
171ensure_decoder_with_max_refs(
172 vdpau_driver_data_t *driver_data,
173 object_context_p obj_context,
174 int max_ref_frames
175)
176{
177 VdpStatus vdp_status;
178
179 if (max_ref_frames < 0)
180 max_ref_frames =
181 get_max_ref_frames(obj_context->vdp_profile,
182 obj_context->picture_width,
183 obj_context->picture_height);
184
185 if (obj_context->vdp_decoder == VDP_INVALID_HANDLE ||
186 obj_context->max_ref_frames < max_ref_frames) {
187 obj_context->max_ref_frames = max_ref_frames;
188
189 if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) {
190 vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder);
191 obj_context->vdp_decoder = VDP_INVALID_HANDLE;
192 }
193
194 vdp_status = vdpau_decoder_create(
195 driver_data,
196 driver_data->vdp_device,
197 obj_context->vdp_profile,
198 obj_context->picture_width,
199 obj_context->picture_height,
200 max_ref_frames,
201 &obj_context->vdp_decoder
202 );
203 if (!VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderCreate()"))
204 return vdp_status;
205 }
206 return VDP_STATUS_OK;
207}
208
209// Lazy allocate (generated) slice data buffer. Buffer lives until vaDestroyContext()
210static uint8_t *
211alloc_gen_slice_data(object_context_p obj_context, unsigned int size)
212{
213 uint8_t *gen_slice_data = obj_context->gen_slice_data;
214
215 if (obj_context->gen_slice_data_size + size > obj_context->gen_slice_data_size_max) {
216 obj_context->gen_slice_data_size_max += size;
217 gen_slice_data = realloc(obj_context->gen_slice_data,
218 obj_context->gen_slice_data_size_max);
219 if (!gen_slice_data)
220 return NULL;
221 obj_context->gen_slice_data = gen_slice_data;
222 }
223 gen_slice_data += obj_context->gen_slice_data_size;
224 obj_context->gen_slice_data_size += size;
225 return gen_slice_data;
226}
227
228// Lazy allocate VdpBitstreamBuffer. Buffer lives until vaDestroyContext()
229static VdpBitstreamBuffer *
230alloc_VdpBitstreamBuffer(object_context_p obj_context)
231{
232 VdpBitstreamBuffer *vdp_bitstream_buffers;
233
234 vdp_bitstream_buffers = realloc_buffer(
235 &obj_context->vdp_bitstream_buffers,
236 &obj_context->vdp_bitstream_buffers_count_max,
237 1 + obj_context->vdp_bitstream_buffers_count,
238 sizeof(*obj_context->vdp_bitstream_buffers)
239 );
240 if (!vdp_bitstream_buffers)
241 return NULL;
242
243 return &vdp_bitstream_buffers[obj_context->vdp_bitstream_buffers_count++];
244}
245
246// Append VASliceDataBuffer hunk into VDPAU buffer
247static int
248append_VdpBitstreamBuffer(
249 object_context_p obj_context,
250 const uint8_t *buffer,
251 uint32_t buffer_size
252)
253{
254 VdpBitstreamBuffer *bitstream_buffer;
255
256 bitstream_buffer = alloc_VdpBitstreamBuffer(obj_context);
257 if (!bitstream_buffer)
258 return -1;
259
260 bitstream_buffer->struct_version = VDP_BITSTREAM_BUFFER_VERSION;
261 bitstream_buffer->bitstream = buffer;
262 bitstream_buffer->bitstream_bytes = buffer_size;
263 return 0;
264}
265
266// Initialize VdpReferenceFrameH264 to default values
267static void init_VdpReferenceFrameH264(VdpReferenceFrameH264 *rf)
268{
269 rf->surface = VDP_INVALID_HANDLE;
270 rf->is_long_term = VDP_FALSE;
271 rf->top_is_reference = VDP_FALSE;
272 rf->bottom_is_reference = VDP_FALSE;
273 rf->field_order_cnt[0] = 0;
274 rf->field_order_cnt[1] = 0;
275 rf->frame_idx = 0;
276}
277
278static const uint8_t ff_identity[64] = {
279 0, 1, 2, 3, 4, 5, 6, 7,
280 8, 9, 10, 11, 12, 13, 14, 15,
281 16, 17, 18, 19, 20, 21, 22, 23,
282 24, 25, 26, 27, 28, 29, 30, 31,
283 32, 33, 34, 35, 36, 37, 38, 39,
284 40, 41, 42, 43, 44, 45, 46, 47,
285 48, 49, 50, 51, 52, 53, 54, 55,
286 56, 57, 58, 59, 60, 61, 62, 63
287};
288
289static const uint8_t ff_zigzag_direct[64] = {
290 0, 1, 8, 16, 9, 2, 3, 10,
291 17, 24, 32, 25, 18, 11, 4, 5,
292 12, 19, 26, 33, 40, 48, 41, 34,
293 27, 20, 13, 6, 7, 14, 21, 28,
294 35, 42, 49, 56, 57, 50, 43, 36,
295 29, 22, 15, 23, 30, 37, 44, 51,
296 58, 59, 52, 45, 38, 31, 39, 46,
297 53, 60, 61, 54, 47, 55, 62, 63
298};
299
300static const uint8_t ff_mpeg1_default_intra_matrix[64] = {
301 8, 16, 19, 22, 26, 27, 29, 34,
302 16, 16, 22, 24, 27, 29, 34, 37,
303 19, 22, 26, 27, 29, 34, 34, 38,
304 22, 22, 26, 27, 29, 34, 37, 40,
305 22, 26, 27, 29, 32, 35, 40, 48,
306 26, 27, 29, 32, 35, 40, 48, 58,
307 26, 27, 29, 34, 38, 46, 56, 69,
308 27, 29, 35, 38, 46, 56, 69, 83
309};
310
311static const uint8_t ff_mpeg1_default_non_intra_matrix[64] = {
312 16, 16, 16, 16, 16, 16, 16, 16,
313 16, 16, 16, 16, 16, 16, 16, 16,
314 16, 16, 16, 16, 16, 16, 16, 16,
315 16, 16, 16, 16, 16, 16, 16, 16,
316 16, 16, 16, 16, 16, 16, 16, 16,
317 16, 16, 16, 16, 16, 16, 16, 16,
318 16, 16, 16, 16, 16, 16, 16, 16,
319 16, 16, 16, 16, 16, 16, 16, 16
320};
321
322static const uint8_t ff_mpeg4_default_intra_matrix[64] = {
323 8, 17, 18, 19, 21, 23, 25, 27,
324 17, 18, 19, 21, 23, 25, 27, 28,
325 20, 21, 22, 23, 24, 26, 28, 30,
326 21, 22, 23, 24, 26, 28, 30, 32,
327 22, 23, 24, 26, 28, 30, 32, 35,
328 23, 24, 26, 28, 30, 32, 35, 38,
329 25, 26, 28, 30, 32, 35, 38, 41,
330 27, 28, 30, 32, 35, 38, 41, 45,
331};
332
333static const uint8_t ff_mpeg4_default_non_intra_matrix[64] = {
334 16, 17, 18, 19, 20, 21, 22, 23,
335 17, 18, 19, 20, 21, 22, 23, 24,
336 18, 19, 20, 21, 22, 23, 24, 25,
337 19, 20, 21, 22, 23, 24, 26, 27,
338 20, 21, 22, 23, 25, 26, 27, 28,
339 21, 22, 23, 24, 26, 27, 28, 30,
340 22, 23, 24, 26, 27, 28, 30, 31,
341 23, 24, 25, 27, 28, 30, 31, 33,
342};
343
344// Compute integer log2
345static inline int ilog2(uint32_t v)
346{
347 /* From <http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog> */
348 uint32_t r, shift;
349 r = (v > 0xffff) << 4; v >>= r;
350 shift = (v > 0xff ) << 3; v >>= shift; r |= shift;
351 shift = (v > 0xf ) << 2; v >>= shift; r |= shift;
352 shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
353 return r | (v >> 1);
354}
355
356// Translate VASurfaceID
357static int
358translate_VASurfaceID(
359 vdpau_driver_data_t *driver_data,
360 VASurfaceID va_surface,
361 VdpVideoSurface *vdp_surface
362)
363{
364 object_surface_p obj_surface;
365
366 if (va_surface == VA_INVALID_SURFACE) {
367 *vdp_surface = VDP_INVALID_HANDLE;
368 return 1;
369 }
370
371 obj_surface = VDPAU_SURFACE(va_surface);
372 if (!obj_surface)
373 return 0;
374
375 *vdp_surface = obj_surface->vdp_surface;
376 return 1;
377}
378
379// Translate VAPictureH264
380static int
381translate_VAPictureH264(
382 vdpau_driver_data_t *driver_data,
383 const VAPictureH264 *va_pic,
384 VdpReferenceFrameH264 *rf
385)
386{
387 // Handle invalid surfaces specifically
388 if (va_pic->picture_id == VA_INVALID_SURFACE) {
389 init_VdpReferenceFrameH264(rf);
390 return 1;
391 }
392
393 if (!translate_VASurfaceID(driver_data, va_pic->picture_id, &rf->surface))
394 return 0;
395 rf->is_long_term = (va_pic->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE) != 0;
396 if ((va_pic->flags & (VA_PICTURE_H264_TOP_FIELD|VA_PICTURE_H264_BOTTOM_FIELD)) == 0) {
397 rf->top_is_reference = VDP_TRUE;
398 rf->bottom_is_reference = VDP_TRUE;
399 }
400 else {
401 rf->top_is_reference = (va_pic->flags & VA_PICTURE_H264_TOP_FIELD) != 0;
402 rf->bottom_is_reference = (va_pic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0;
403 }
404 rf->field_order_cnt[0] = va_pic->TopFieldOrderCnt;
405 rf->field_order_cnt[1] = va_pic->BottomFieldOrderCnt;
406 rf->frame_idx = va_pic->frame_idx;
407 return 1;
408}
409
410// Translate no buffer
411static int
412translate_nothing(
413 vdpau_driver_data_t *driver_data,
414 object_context_p obj_context,
415 object_buffer_p obj_buffer
416)
417{
418 return 1;
419}
420
421// Translate VASliceDataBuffer
422static int
423translate_VASliceDataBuffer(
424 vdpau_driver_data_t *driver_data,
425 object_context_p obj_context,
426 object_buffer_p obj_buffer
427)
428{
429 if (obj_context->vdp_codec == VDP_CODEC_H264) {
430 /* Check we have the start code */
431 /* XXX: check for other codecs too? */
432 /* XXX: this assumes we get SliceParams before SliceData */
433 static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 };
434 VASliceParameterBufferH264 * const slice_params = obj_context->last_slice_params;
435 unsigned int i;
436 for (i = 0; i < obj_context->last_slice_params_count; i++) {
437 VASliceParameterBufferH264 * const slice_param = &slice_params[i];
438 uint8_t *buf = (uint8_t *)obj_buffer->buffer_data + slice_param->slice_data_offset;
439 if (memcmp(buf, start_code_prefix, sizeof(start_code_prefix)) != 0) {
440 if (append_VdpBitstreamBuffer(obj_context,
441 start_code_prefix,
442 sizeof(start_code_prefix)) < 0)
443 return 0;
444 }
445 if (append_VdpBitstreamBuffer(obj_context,
446 buf,
447 slice_param->slice_data_size) < 0)
448 return 0;
449 }
450 return 1;
451 }
452
453#if USE_VDPAU_MPEG4
454 if (obj_context->vdp_codec == VDP_CODEC_MPEG4 &&
455 obj_context->vdp_bitstream_buffers_count == 0) {
456 PutBitContext pb;
457 uint8_t slice_header_buffer[32];
458 uint8_t *slice_header;
459 int slice_header_size;
460 const uint8_t *slice_data = obj_buffer->buffer_data;
461 uint32_t slice_data_size = obj_buffer->buffer_size;
462 VAPictureParameterBufferMPEG4 * const pic_param = obj_context->last_pic_param;
463 VASliceParameterBufferMPEG4 * const slice_param = obj_context->last_slice_params;
464
465 int time_incr = 1 + ilog2(pic_param->vop_time_increment_resolution - 1);
466 if (time_incr < 1)
467 time_incr = 1;
468
469 static const uint16_t VOP_STARTCODE = 0x01b6;
470 enum {
471 VOP_I_TYPE = 0,
472 VOP_P_TYPE,
473 VOP_B_TYPE,
474 VOP_S_TYPE
475 };
476
477 /* XXX: this is a hack to compute the length of
478 modulo_time_base "1" sequence. We probably should be
479 reconstructing through an extra VOP field in VA-API? */
480 int nbits = (32 + /* VOP start code */
481 2 + /* vop_coding_type */
482 1 + /* modulo_time_base "0" */
483 1 + /* marker_bit */
484 time_incr + /* vop_time_increment */
485 1 + /* marker_bit */
486 1 + /* vop_coded */
487 (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE ? 1 : 0) +
488 3 + /* intra_dc_vlc_thr */
489 (pic_param->vol_fields.bits.interlaced ? 2 : 0) +
490 5 + /* vop_quant */
491 (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE ? 3 : 0) +
492 (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE ? 3 : 0));
493 if ((nbits = slice_param->macroblock_offset - (nbits % 8)) < 0)
494 nbits += 8;
495
496 /* Reconstruct the VOP header */
497 init_put_bits(&pb, slice_header_buffer, sizeof(slice_header_buffer));
498 put_bits(&pb, 16, 0); /* vop header */
499 put_bits(&pb, 16, VOP_STARTCODE); /* vop header */
500 put_bits(&pb, 2, pic_param->vop_fields.bits.vop_coding_type);
501 while (nbits-- > 0)
502 put_bits(&pb, 1, 1); /* modulo_time_base "1" */
503 put_bits(&pb, 1, 0); /* modulo_time_base "0" */
504 put_bits(&pb, 1, 1); /* marker */
505 put_bits(&pb, time_incr, 0); /* time increment */
506 put_bits(&pb, 1, 1); /* marker */
507 put_bits(&pb, 1, 1); /* vop coded */
508 if (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE)
509 put_bits(&pb, 1, pic_param->vop_fields.bits.vop_rounding_type);
510 put_bits(&pb, 3, pic_param->vop_fields.bits.intra_dc_vlc_thr);
511 if (pic_param->vol_fields.bits.interlaced) {
512 put_bits(&pb, 1, pic_param->vop_fields.bits.top_field_first);
513 put_bits(&pb, 1, pic_param->vop_fields.bits.alternate_vertical_scan_flag);
514 }
515 put_bits(&pb, 5, slice_param->quant_scale);
516 if (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE)
517 put_bits(&pb, 3, pic_param->vop_fcode_forward);
518 if (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE)
519 put_bits(&pb, 3, pic_param->vop_fcode_backward);
520
521 /* Merge in bits from the first byte of the slice */
522 ASSERT((put_bits_count(&pb) % 8) == slice_param->macroblock_offset);
523 if ((put_bits_count(&pb) % 8) != slice_param->macroblock_offset)
524 return 0;
525 const int r = 8 - (put_bits_count(&pb) % 8);
526 if (r > 0)
527 put_bits(&pb, r, slice_data[0] & ((1U << r) - 1));
528 flush_put_bits(&pb);
529
530 ASSERT((put_bits_count(&pb) % 8) == 0);
531 slice_header_size = put_bits_count(&pb) / 8;
532 ASSERT(slice_header_size <= sizeof(slice_header_buffer));
533 slice_header = alloc_gen_slice_data(obj_context, slice_header_size);
534 if (!slice_header)
535 return 0;
536 memcpy(slice_header, slice_header_buffer, slice_header_size);
537 if (append_VdpBitstreamBuffer(obj_context, slice_header, slice_header_size) < 0)
538 return 0;
539 if (append_VdpBitstreamBuffer(obj_context, slice_data + 1, slice_data_size - 1) < 0)
540 return 0;
541 return 1;
542 }
543#endif
544
545 if (append_VdpBitstreamBuffer(obj_context,
546 obj_buffer->buffer_data,
547 obj_buffer->buffer_size) < 0)
548 return 0;
549 return 1;
550}
551
552// Translate VAPictureParameterBufferMPEG2
553static int
554translate_VAPictureParameterBufferMPEG2(
555 vdpau_driver_data_t *driver_data,
556 object_context_p obj_context,
557 object_buffer_p obj_buffer
558)
559{
560 VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2;
561 VAPictureParameterBufferMPEG2 * const pic_param = obj_buffer->buffer_data;
562
563 if (!translate_VASurfaceID(driver_data,
564 pic_param->forward_reference_picture,
565 &pic_info->forward_reference))
566 return 0;
567
568 if (!translate_VASurfaceID(driver_data,
569 pic_param->backward_reference_picture,
570 &pic_info->backward_reference))
571 return 0;
572
573 pic_info->picture_structure = pic_param->picture_coding_extension.bits.picture_structure;
574 pic_info->picture_coding_type = pic_param->picture_coding_type;
575 pic_info->intra_dc_precision = pic_param->picture_coding_extension.bits.intra_dc_precision;
576 pic_info->frame_pred_frame_dct = pic_param->picture_coding_extension.bits.frame_pred_frame_dct;
577 pic_info->concealment_motion_vectors = pic_param->picture_coding_extension.bits.concealment_motion_vectors;
578 pic_info->intra_vlc_format = pic_param->picture_coding_extension.bits.intra_vlc_format;
579 pic_info->alternate_scan = pic_param->picture_coding_extension.bits.alternate_scan;
580 pic_info->q_scale_type = pic_param->picture_coding_extension.bits.q_scale_type;
581 pic_info->top_field_first = pic_param->picture_coding_extension.bits.top_field_first;
582 pic_info->full_pel_forward_vector = 0;
583 pic_info->full_pel_backward_vector = 0;
584 pic_info->f_code[0][0] = (pic_param->f_code >> 12) & 0xf;
585 pic_info->f_code[0][1] = (pic_param->f_code >> 8) & 0xf;
586 pic_info->f_code[1][0] = (pic_param->f_code >> 4) & 0xf;
587 pic_info->f_code[1][1] = pic_param->f_code & 0xf;
588 return 1;
589}
590
591// Translate VAIQMatrixBufferMPEG2
592static int
593translate_VAIQMatrixBufferMPEG2(
594 vdpau_driver_data_t *driver_data,
595 object_context_p obj_context,
596 object_buffer_p obj_buffer
597)
598{
599 VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2;
600 VAIQMatrixBufferMPEG2 * const iq_matrix = obj_buffer->buffer_data;
601 const uint8_t *intra_matrix;
602 const uint8_t *intra_matrix_lookup;
603 const uint8_t *inter_matrix;
604 const uint8_t *inter_matrix_lookup;
605 int i;
606
607 if (iq_matrix->load_intra_quantiser_matrix) {
608 intra_matrix = iq_matrix->intra_quantiser_matrix;
609 intra_matrix_lookup = ff_zigzag_direct;
610 }
611 else {
612 intra_matrix = ff_mpeg1_default_intra_matrix;
613 intra_matrix_lookup = ff_identity;
614 }
615
616 if (iq_matrix->load_non_intra_quantiser_matrix) {
617 inter_matrix = iq_matrix->non_intra_quantiser_matrix;
618 inter_matrix_lookup = ff_zigzag_direct;
619 }
620 else {
621 inter_matrix = ff_mpeg1_default_non_intra_matrix;
622 inter_matrix_lookup = ff_identity;
623 }
624
625 for (i = 0; i < 64; i++) {
626 pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] =
627 intra_matrix[i];
628 pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] =
629 inter_matrix[i];
630 }
631 return 1;
632}
633
634// Translate VASliceParameterBufferMPEG2
635static int
636translate_VASliceParameterBufferMPEG2(
637 vdpau_driver_data_t *driver_data,
638 object_context_p obj_context,
639 object_buffer_p obj_buffer
640 )
641{
642 VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2;
643
644 pic_info->slice_count += obj_buffer->num_elements;
645 obj_context->last_slice_params = obj_buffer->buffer_data;
646 obj_context->last_slice_params_count = obj_buffer->num_elements;
647 return 1;
648}
649
650#if USE_VDPAU_MPEG4
651// Translate VAPictureParameterBufferMPEG4
652static int
653translate_VAPictureParameterBufferMPEG4(
654 vdpau_driver_data_p driver_data,
655 object_context_p obj_context,
656 object_buffer_p obj_buffer
657)
658{
659 VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4;
660 VAPictureParameterBufferMPEG4 * const pic_param = obj_buffer->buffer_data;
661
662 /* XXX: we don't support short-video-header formats */
663 if (pic_param->vol_fields.bits.short_video_header)
664 return 0;
665
666 if (!translate_VASurfaceID(driver_data,
667 pic_param->forward_reference_picture,
668 &pic_info->forward_reference))
669 return 0;
670
671 if (!translate_VASurfaceID(driver_data,
672 pic_param->backward_reference_picture,
673 &pic_info->backward_reference))
674 return 0;
675
676 if (pic_param->vol_fields.bits.interlaced) {
677 vdpau_information_message("unsupported MPEG-4 video with interlaced "
678 "content, please report this video\n");
679 pic_info->trd[0] = 2*pic_param->TRD; /* XXX: + d(0) */
680 pic_info->trb[0] = 2*pic_param->TRB; /* XXX: + d(0) */
681 pic_info->trd[1] = 2*pic_param->TRD; /* XXX: + d(1) */
682 pic_info->trb[1] = 2*pic_param->TRB; /* XXX: + d(1) */
683 }
684 else {
685 pic_info->trd[0] = pic_param->TRD;
686 pic_info->trb[0] = pic_param->TRB;
687 pic_info->trd[1] = 0;
688 pic_info->trb[1] = 0;
689 }
690
691 pic_info->vop_time_increment_resolution = pic_param->vop_time_increment_resolution;
692 pic_info->vop_coding_type = pic_param->vop_fields.bits.vop_coding_type;
693 pic_info->vop_fcode_forward = pic_param->vop_fcode_forward;
694 pic_info->vop_fcode_backward = pic_param->vop_fcode_backward;
695 pic_info->resync_marker_disable = pic_param->vol_fields.bits.resync_marker_disable;
696 pic_info->interlaced = pic_param->vol_fields.bits.interlaced;
697 pic_info->quant_type = pic_param->vol_fields.bits.quant_type;
698 pic_info->quarter_sample = pic_param->vol_fields.bits.quarter_sample;
699 pic_info->short_video_header = pic_param->vol_fields.bits.short_video_header;
700 pic_info->rounding_control = pic_param->vop_fields.bits.vop_rounding_type;
701 pic_info->alternate_vertical_scan_flag = pic_param->vop_fields.bits.alternate_vertical_scan_flag;
702 pic_info->top_field_first = pic_param->vop_fields.bits.top_field_first;
703
704 obj_context->last_pic_param = obj_buffer->buffer_data;
705 return 1;
706}
707
708// Translate VAIQMatrixBufferMPEG4
709static int
710translate_VAIQMatrixBufferMPEG4(
711 vdpau_driver_data_p driver_data,
712 object_context_p obj_context,
713 object_buffer_p obj_buffer
714)
715{
716 VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4;
717 VAIQMatrixBufferMPEG4 * const iq_matrix = obj_buffer->buffer_data;
718 const uint8_t *intra_matrix;
719 const uint8_t *intra_matrix_lookup;
720 const uint8_t *inter_matrix;
721 const uint8_t *inter_matrix_lookup;
722 int i;
723
724 if (iq_matrix->load_intra_quant_mat) {
725 intra_matrix = iq_matrix->intra_quant_mat;
726 intra_matrix_lookup = ff_zigzag_direct;
727 }
728 else {
729 intra_matrix = ff_mpeg4_default_intra_matrix;
730 intra_matrix_lookup = ff_identity;
731 }
732
733 if (iq_matrix->load_non_intra_quant_mat) {
734 inter_matrix = iq_matrix->non_intra_quant_mat;
735 inter_matrix_lookup = ff_zigzag_direct;
736 }
737 else {
738 inter_matrix = ff_mpeg4_default_non_intra_matrix;
739 inter_matrix_lookup = ff_identity;
740 }
741
742 for (i = 0; i < 64; i++) {
743 pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] =
744 intra_matrix[i];
745 pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] =
746 inter_matrix[i];
747 }
748 return 1;
749}
750
751// Translate VASliceParameterBufferMPEG4
752static int
753translate_VASliceParameterBufferMPEG4(
754 vdpau_driver_data_p driver_data,
755 object_context_p obj_context,
756 object_buffer_p obj_buffer
757 )
758{
759 obj_context->last_slice_params = obj_buffer->buffer_data;
760 obj_context->last_slice_params_count = obj_buffer->num_elements;
761 return 1;
762}
763#endif
764
765// Translate VAPictureParameterBufferH264
766static int
767translate_VAPictureParameterBufferH264(
768 vdpau_driver_data_t *driver_data,
769 object_context_p obj_context,
770 object_buffer_p obj_buffer
771)
772{
773 VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264;
774 VAPictureParameterBufferH264 * const pic_param = obj_buffer->buffer_data;
775 VAPictureH264 * const CurrPic = &pic_param->CurrPic;
776 unsigned int i;
777
778 pic_info->field_order_cnt[0] = CurrPic->TopFieldOrderCnt;
779 pic_info->field_order_cnt[1] = CurrPic->BottomFieldOrderCnt;
780 pic_info->is_reference = pic_param->pic_fields.bits.reference_pic_flag;
781
782 pic_info->frame_num = pic_param->frame_num;
783 pic_info->field_pic_flag = pic_param->pic_fields.bits.field_pic_flag;
784 pic_info->bottom_field_flag = pic_param->pic_fields.bits.field_pic_flag && (CurrPic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0;
785 pic_info->num_ref_frames = pic_param->num_ref_frames;
786 pic_info->mb_adaptive_frame_field_flag = pic_param->seq_fields.bits.mb_adaptive_frame_field_flag && !pic_info->field_pic_flag;
787 pic_info->constrained_intra_pred_flag = pic_param->pic_fields.bits.constrained_intra_pred_flag;
788 pic_info->weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag;
789 pic_info->weighted_bipred_idc = pic_param->pic_fields.bits.weighted_bipred_idc;
790 pic_info->frame_mbs_only_flag = pic_param->seq_fields.bits.frame_mbs_only_flag;
791 pic_info->transform_8x8_mode_flag = pic_param->pic_fields.bits.transform_8x8_mode_flag;
792 pic_info->chroma_qp_index_offset = pic_param->chroma_qp_index_offset;
793 pic_info->second_chroma_qp_index_offset = pic_param->second_chroma_qp_index_offset;
794 pic_info->pic_init_qp_minus26 = pic_param->pic_init_qp_minus26;
795 pic_info->log2_max_frame_num_minus4 = pic_param->seq_fields.bits.log2_max_frame_num_minus4;
796 pic_info->pic_order_cnt_type = pic_param->seq_fields.bits.pic_order_cnt_type;
797 pic_info->log2_max_pic_order_cnt_lsb_minus4 = pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4;
798 pic_info->delta_pic_order_always_zero_flag = pic_param->seq_fields.bits.delta_pic_order_always_zero_flag;
799 pic_info->direct_8x8_inference_flag = pic_param->seq_fields.bits.direct_8x8_inference_flag;
800 pic_info->entropy_coding_mode_flag = pic_param->pic_fields.bits.entropy_coding_mode_flag;
801 pic_info->pic_order_present_flag = pic_param->pic_fields.bits.pic_order_present_flag;
802 pic_info->deblocking_filter_control_present_flag = pic_param->pic_fields.bits.deblocking_filter_control_present_flag;
803 pic_info->redundant_pic_cnt_present_flag = pic_param->pic_fields.bits.redundant_pic_cnt_present_flag;
804
805 for (i = 0; i < 16; i++) {
806 if (!translate_VAPictureH264(driver_data,
807 &pic_param->ReferenceFrames[i],
808 &pic_info->referenceFrames[i]))
809 return 0;
810 }
811 return 1;
812}
813
814// Translate VAIQMatrixBufferH264
815static int
816translate_VAIQMatrixBufferH264(
817 vdpau_driver_data_t *driver_data,
818 object_context_p obj_context,
819 object_buffer_p obj_buffer
820)
821{
822 VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264;
823 VAIQMatrixBufferH264 * const iq_matrix = obj_buffer->buffer_data;
824 int i, j;
825
826 if (sizeof(pic_info->scaling_lists_4x4) == sizeof(iq_matrix->ScalingList4x4))
827 memcpy(pic_info->scaling_lists_4x4, iq_matrix->ScalingList4x4,
828 sizeof(pic_info->scaling_lists_4x4));
829 else {
830 for (j = 0; j < 6; j++) {
831 for (i = 0; i < 16; i++)
832 pic_info->scaling_lists_4x4[j][i] = iq_matrix->ScalingList4x4[j][i];
833 }
834 }
835
836 if (sizeof(pic_info->scaling_lists_8x8) == sizeof(iq_matrix->ScalingList8x8))
837 memcpy(pic_info->scaling_lists_8x8, iq_matrix->ScalingList8x8,
838 sizeof(pic_info->scaling_lists_8x8));
839 else {
840 for (j = 0; j < 2; j++) {
841 for (i = 0; i < 64; i++)
842 pic_info->scaling_lists_8x8[j][i] = iq_matrix->ScalingList8x8[j][i];
843 }
844 }
845 return 1;
846}
847
848// Translate VASliceParameterBufferH264
849static int
850translate_VASliceParameterBufferH264(
851 vdpau_driver_data_t *driver_data,
852 object_context_p obj_context,
853 object_buffer_p obj_buffer
854)
855{
856 VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264;
857 VASliceParameterBufferH264 * const slice_params = obj_buffer->buffer_data;
858 VASliceParameterBufferH264 * const slice_param = &slice_params[obj_buffer->num_elements - 1];
859
860 pic_info->slice_count += obj_buffer->num_elements;
861 pic_info->num_ref_idx_l0_active_minus1 = slice_param->num_ref_idx_l0_active_minus1;
862 pic_info->num_ref_idx_l1_active_minus1 = slice_param->num_ref_idx_l1_active_minus1;
863 obj_context->last_slice_params = obj_buffer->buffer_data;
864 obj_context->last_slice_params_count = obj_buffer->num_elements;
865 return 1;
866}
867
868// Translate VAPictureParameterBufferVC1
869static int
870translate_VAPictureParameterBufferVC1(
871 vdpau_driver_data_t *driver_data,
872 object_context_p obj_context,
873 object_buffer_p obj_buffer
874)
875{
876 VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1;
877 VAPictureParameterBufferVC1 * const pic_param = obj_buffer->buffer_data;
878 int picture_type, major_version, minor_version;
879
880 if (!translate_VASurfaceID(driver_data,
881 pic_param->forward_reference_picture,
882 &pic_info->forward_reference))
883 return 0;
884
885 if (!translate_VASurfaceID(driver_data,
886 pic_param->backward_reference_picture,
887 &pic_info->backward_reference))
888 return 0;
889
890 switch (pic_param->picture_fields.bits.picture_type) {
891 case 0: picture_type = 0; break; /* I */
892 case 1: picture_type = 1; break; /* P */
893 case 2: picture_type = 3; break; /* B */
894 case 3: picture_type = 4; break; /* BI */
895 case 4: picture_type = 1; break; /* P "skipped" */
896 default: return 0;
897 }
898
899 pic_info->picture_type = picture_type;
900 pic_info->frame_coding_mode = pic_param->picture_fields.bits.frame_coding_mode;
901 pic_info->postprocflag = pic_param->post_processing != 0;
902 pic_info->pulldown = pic_param->sequence_fields.bits.pulldown;
903 pic_info->interlace = pic_param->sequence_fields.bits.interlace;
904 pic_info->tfcntrflag = pic_param->sequence_fields.bits.tfcntrflag;
905 pic_info->finterpflag = pic_param->sequence_fields.bits.finterpflag;
906 pic_info->psf = pic_param->sequence_fields.bits.psf;
907 pic_info->dquant = pic_param->pic_quantizer_fields.bits.dquant;
908 pic_info->panscan_flag = pic_param->entrypoint_fields.bits.panscan_flag;
909 pic_info->refdist_flag = pic_param->reference_fields.bits.reference_distance_flag;
910 pic_info->quantizer = pic_param->pic_quantizer_fields.bits.quantizer;
911 pic_info->extended_mv = pic_param->mv_fields.bits.extended_mv_flag;
912 pic_info->extended_dmv = pic_param->mv_fields.bits.extended_dmv_flag;
913 pic_info->overlap = pic_param->sequence_fields.bits.overlap;
914 pic_info->vstransform = pic_param->transform_fields.bits.variable_sized_transform_flag;
915 pic_info->loopfilter = pic_param->entrypoint_fields.bits.loopfilter;
916 pic_info->fastuvmc = pic_param->fast_uvmc_flag;
917 pic_info->range_mapy_flag = pic_param->range_mapping_fields.bits.luma_flag;
918 pic_info->range_mapy = pic_param->range_mapping_fields.bits.luma;
919 pic_info->range_mapuv_flag = pic_param->range_mapping_fields.bits.chroma_flag;
920 pic_info->range_mapuv = pic_param->range_mapping_fields.bits.chroma;
921 pic_info->multires = pic_param->sequence_fields.bits.multires;
922 pic_info->syncmarker = pic_param->sequence_fields.bits.syncmarker;
923 pic_info->rangered = pic_param->sequence_fields.bits.rangered;
924 if (!vdpau_is_nvidia(driver_data, &major_version, &minor_version) ||
925 (major_version > 180 || minor_version >= 35))
926 pic_info->rangered |= pic_param->range_reduction_frame << 1;
927 pic_info->maxbframes = pic_param->sequence_fields.bits.max_b_frames;
928 pic_info->deblockEnable = pic_param->post_processing != 0; /* XXX: this is NVIDIA's vdpau.c semantics (postprocflag & 1) */
929 pic_info->pquant = pic_param->pic_quantizer_fields.bits.pic_quantizer_scale;
930 return 1;
931}
932
933// Translate VASliceParameterBufferVC1
934static int
935translate_VASliceParameterBufferVC1(
936 vdpau_driver_data_t *driver_data,
937 object_context_p obj_context,
938 object_buffer_p obj_buffer
939)
940{
941 VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1;
942
943 pic_info->slice_count += obj_buffer->num_elements;
944 obj_context->last_slice_params = obj_buffer->buffer_data;
945 obj_context->last_slice_params_count = obj_buffer->num_elements;
946 return 1;
947}
948
949// Translate VA buffer
950typedef int
951(*translate_buffer_func_t)(vdpau_driver_data_t *driver_data,
952 object_context_p obj_context,
953 object_buffer_p obj_buffer);
954
955typedef struct translate_buffer_info translate_buffer_info_t;
956struct translate_buffer_info {
957 VdpCodec codec;
958 VABufferType type;
959 translate_buffer_func_t func;
960};
961
962static int
963translate_buffer(
964 vdpau_driver_data_t *driver_data,
965 object_context_p obj_context,
966 object_buffer_p obj_buffer
967)
968{
969 static const translate_buffer_info_t translate_info[] = {
970#define _(CODEC, TYPE) \
971 { VDP_CODEC_##CODEC, VA##TYPE##BufferType, \
972 translate_VA##TYPE##Buffer##CODEC }
973 _(MPEG2, PictureParameter),
974 _(MPEG2, IQMatrix),
975 _(MPEG2, SliceParameter),
976#if USE_VDPAU_MPEG4
977 _(MPEG4, PictureParameter),
978 _(MPEG4, IQMatrix),
979 _(MPEG4, SliceParameter),
980#endif
981 _(H264, PictureParameter),
982 _(H264, IQMatrix),
983 _(H264, SliceParameter),
984 _(VC1, PictureParameter),
985 _(VC1, SliceParameter),
986#undef _
987 { VDP_CODEC_VC1, VABitPlaneBufferType, translate_nothing },
988 { 0, VASliceDataBufferType, translate_VASliceDataBuffer },
989 { 0, 0, NULL }
990 };
991 const translate_buffer_info_t *tbip;
992 for (tbip = translate_info; tbip->func != NULL; tbip++) {
993 if (tbip->codec && tbip->codec != obj_context->vdp_codec)
994 continue;
995 if (tbip->type != obj_buffer->type)
996 continue;
997 return tbip->func(driver_data, obj_context, obj_buffer);
998 }
999 D(bug("ERROR: no translate function found for %s%s\n",
1000 string_of_VABufferType(obj_buffer->type),
1001 obj_context->vdp_codec ? string_of_VdpCodec(obj_context->vdp_codec) : NULL));
1002 return 0;
1003}
1004
1005// vaQueryConfigProfiles
1006VAStatus
1007vdpau_QueryConfigProfiles(
1008 VADriverContextP ctx,
1009 VAProfile *profile_list,
1010 int *num_profiles
1011)
1012{
1013 VDPAU_DRIVER_DATA_INIT;
1014
1015 static const VAProfile va_profiles[] = {
1016 VAProfileMPEG2Simple,
1017 VAProfileMPEG2Main,
1018 VAProfileMPEG4Simple,
1019 VAProfileMPEG4AdvancedSimple,
1020 VAProfileMPEG4Main,
1021 VAProfileH264Baseline,
1022 VAProfileH264Main,
1023 VAProfileH264High,
1024 VAProfileVC1Simple,
1025 VAProfileVC1Main,
1026 VAProfileVC1Advanced
1027 };
1028
1029 int i, n = 0;
1030 for (i = 0; i < ARRAY_ELEMS(va_profiles); i++) {
1031 VAProfile profile = va_profiles[i];
1032 VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile);
1033 if (is_supported_profile(driver_data, vdp_profile))
1034 profile_list[n++] = profile;
1035 }
1036
1037 /* If the assert fails then VDPAU_MAX_PROFILES needs to be bigger */
1038 ASSERT(n <= VDPAU_MAX_PROFILES);
1039 if (num_profiles)
1040 *num_profiles = n;
1041
1042 return VA_STATUS_SUCCESS;
1043}
1044
1045// vaQueryConfigEntrypoints
1046VAStatus
1047vdpau_QueryConfigEntrypoints(
1048 VADriverContextP ctx,
1049 VAProfile profile,
1050 VAEntrypoint *entrypoint_list,
1051 int *num_entrypoints
1052)
1053{
1054 VDPAU_DRIVER_DATA_INIT;
1055
1056 VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile);
1057 if (!is_supported_profile(driver_data, vdp_profile))
1058 return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1059
1060 VAEntrypoint entrypoint;
1061 switch (profile) {
1062 case VAProfileMPEG2Simple:
1063 case VAProfileMPEG2Main:
1064 entrypoint = VAEntrypointVLD;
1065 break;
1066 case VAProfileMPEG4Simple:
1067 case VAProfileMPEG4AdvancedSimple:
1068 case VAProfileMPEG4Main:
1069 entrypoint = VAEntrypointVLD;
1070 break;
1071 case VAProfileH264Baseline:
1072 case VAProfileH264Main:
1073 case VAProfileH264High:
1074 entrypoint = VAEntrypointVLD;
1075 break;
1076 case VAProfileVC1Simple:
1077 case VAProfileVC1Main:
1078 case VAProfileVC1Advanced:
1079 entrypoint = VAEntrypointVLD;
1080 break;
1081 default:
1082 entrypoint = 0;
1083 break;
1084 }
1085
1086 if (entrypoint_list)
1087 *entrypoint_list = entrypoint;
1088
1089 if (num_entrypoints)
1090 *num_entrypoints = entrypoint != 0;
1091
1092 return VA_STATUS_SUCCESS;
1093}
1094
1095// vaBeginPicture
1096VAStatus
1097vdpau_BeginPicture(
1098 VADriverContextP ctx,
1099 VAContextID context,
1100 VASurfaceID render_target
1101)
1102{
1103 VDPAU_DRIVER_DATA_INIT;
1104
1105 object_context_p obj_context = VDPAU_CONTEXT(context);
1106 if (!obj_context)
1107 return VA_STATUS_ERROR_INVALID_CONTEXT;
1108
1109 object_surface_p obj_surface = VDPAU_SURFACE(render_target);
1110 if (!obj_surface)
1111 return VA_STATUS_ERROR_INVALID_SURFACE;
1112
1113 obj_surface->va_surface_status = VASurfaceRendering;
1114 obj_context->last_pic_param = NULL;
1115 obj_context->last_slice_params = NULL;
1116 obj_context->last_slice_params_count = 0;
1117 obj_context->current_render_target = obj_surface->base.id;
1118 obj_context->gen_slice_data_size = 0;
1119 obj_context->vdp_bitstream_buffers_count = 0;
1120
1121 switch (obj_context->vdp_codec) {
1122 case VDP_CODEC_MPEG1:
1123 case VDP_CODEC_MPEG2:
1124 obj_context->vdp_picture_info.mpeg2.slice_count = 0;
1125 break;
1126 case VDP_CODEC_MPEG4:
1127 break;
1128 case VDP_CODEC_H264:
1129 obj_context->vdp_picture_info.h264.slice_count = 0;
1130 break;
1131 case VDP_CODEC_VC1:
1132 obj_context->vdp_picture_info.vc1.slice_count = 0;
1133 break;
1134 default:
1135 return VA_STATUS_ERROR_UNKNOWN;
1136 }
1137
1138 destroy_dead_va_buffers(driver_data, obj_context);
1139 return VA_STATUS_SUCCESS;
1140}
1141
1142// vaRenderPicture
1143VAStatus
1144vdpau_RenderPicture(
1145 VADriverContextP ctx,
1146 VAContextID context,
1147 VABufferID *buffers,
1148 int num_buffers
1149)
1150{
1151 VDPAU_DRIVER_DATA_INIT;
1152 int i;
1153
1154 object_context_p obj_context = VDPAU_CONTEXT(context);
1155 if (!obj_context)
1156 return VA_STATUS_ERROR_INVALID_CONTEXT;
1157
1158 object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target);
1159 if (!obj_surface)
1160 return VA_STATUS_ERROR_INVALID_SURFACE;
1161
1162 /* Verify that we got valid buffer references */
1163 for (i = 0; i < num_buffers; i++) {
1164 object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]);
1165 if (!obj_buffer)
1166 return VA_STATUS_ERROR_INVALID_BUFFER;
1167 }
1168
1169 /* Translate buffers */
1170 for (i = 0; i < num_buffers; i++) {
1171 object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]);
1172 if (!translate_buffer(driver_data, obj_context, obj_buffer))
1173 return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1174 /* Release any buffer that is not VASliceDataBuffer */
1175 /* VASliceParameterBuffer is also needed to check for start_codes */
1176 switch (obj_buffer->type) {
1177 case VASliceParameterBufferType:
1178 case VASliceDataBufferType:
1179 schedule_destroy_va_buffer(driver_data, obj_buffer);
1180 break;
1181 case VAPictureParameterBufferType:
1182 /* Preserve VAPictureParameterBufferMPEG4 */
1183 if (obj_context->vdp_codec == VDP_CODEC_MPEG4) {
1184 schedule_destroy_va_buffer(driver_data, obj_buffer);
1185 break;
1186 }
1187 /* fall-through */
1188 default:
1189 destroy_va_buffer(driver_data, obj_buffer);
1190 break;
1191 }
1192 }
1193
1194 return VA_STATUS_SUCCESS;
1195}
1196
1197// vaEndPicture
1198VAStatus
1199vdpau_EndPicture(
1200 VADriverContextP ctx,
1201 VAContextID context
1202)
1203{
1204 VDPAU_DRIVER_DATA_INIT;
1205 unsigned int i;
1206
1207 object_context_p obj_context = VDPAU_CONTEXT(context);
1208 if (!obj_context)
1209 return VA_STATUS_ERROR_INVALID_CONTEXT;
1210
1211 object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target);
1212 if (!obj_surface)
1213 return VA_STATUS_ERROR_INVALID_SURFACE;
1214
1215 if (trace_enabled()) {
1216 switch (obj_context->vdp_codec) {
1217 case VDP_CODEC_MPEG1:
1218 case VDP_CODEC_MPEG2:
1219 dump_VdpPictureInfoMPEG1Or2(&obj_context->vdp_picture_info.mpeg2);
1220 break;
1221#if HAVE_VDPAU_MPEG4
1222 case VDP_CODEC_MPEG4:
1223 dump_VdpPictureInfoMPEG4Part2(&obj_context->vdp_picture_info.mpeg4);
1224 break;
1225#endif
1226 case VDP_CODEC_H264:
1227 dump_VdpPictureInfoH264(&obj_context->vdp_picture_info.h264);
1228 break;
1229 case VDP_CODEC_VC1:
1230 dump_VdpPictureInfoVC1(&obj_context->vdp_picture_info.vc1);
1231 break;
1232 default:
1233 break;
1234 }
1235 for (i = 0; i < obj_context->vdp_bitstream_buffers_count; i++)
1236 dump_VdpBitstreamBuffer(&obj_context->vdp_bitstream_buffers[i]);
1237 }
1238
1239 VAStatus va_status;
1240 VdpStatus vdp_status;
1241 vdp_status = ensure_decoder_with_max_refs(
1242 driver_data,
1243 obj_context,
1244 get_num_ref_frames(obj_context)
1245 );
1246 if (vdp_status == VDP_STATUS_OK)
1247 vdp_status = vdpau_decoder_render(
1248 driver_data,
1249 obj_context->vdp_decoder,
1250 obj_surface->vdp_surface,
1251 (VdpPictureInfo)&obj_context->vdp_picture_info,
1252 obj_context->vdp_bitstream_buffers_count,
1253 obj_context->vdp_bitstream_buffers
1254 );
1255 va_status = vdpau_get_VAStatus(vdp_status);
1256
1257 /* XXX: assume we are done with rendering right away */
1258 obj_context->current_render_target = VA_INVALID_SURFACE;
1259
1260 /* Release pending buffers */
1261 destroy_dead_va_buffers(driver_data, obj_context);
1262
1263 return va_status;
1264}
01265
=== modified file '.pc/applied-patches'
--- .pc/applied-patches 2013-04-13 09:39:54 +0000
+++ .pc/applied-patches 2014-05-06 21:31:51 +0000
@@ -1,2 +1,5 @@
1autoreconf.patch1autoreconf.patch
2GL_VER_1_3.patch2GL_VER_1_3.patch
301_dont_clear_va_buffer_too_early.patch
402_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch
503_mark_destroyed_buffers_as_deleted.patch
36
=== modified file 'debian/changelog'
--- debian/changelog 2013-04-13 09:39:54 +0000
+++ debian/changelog 2014-05-06 21:31:51 +0000
@@ -1,3 +1,10 @@
1vdpau-video (0.7.3-2ubuntu2) UNRELEASED; urgency=medium
2
3 * Added patch-set from upstream to fix crash when using
4 gstreamer-vaapi (LP: #1222790)
5
6 -- Marco Trevisan (Treviño) <marco@ubuntu.com> Tue, 06 May 2014 23:15:53 +0200
7
1vdpau-video (0.7.3-2ubuntu1) raring; urgency=low8vdpau-video (0.7.3-2ubuntu1) raring; urgency=low
29
3 * Added patch from Gentoo bug #438180 (backported from upstream10 * Added patch from Gentoo bug #438180 (backported from upstream
411
=== added file 'debian/patches/01_dont_clear_va_buffer_too_early.patch'
--- debian/patches/01_dont_clear_va_buffer_too_early.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/01_dont_clear_va_buffer_too_early.patch 2014-05-06 21:31:51 +0000
@@ -0,0 +1,56 @@
1Description: Don't clear VA buffers too early.
2 vaRenderPicture() is supposed to destroy a VA buffer implicitly. However,
3 some buffers need to be kept until vaEndPicture() is reached. Besides, if
4 user calls vaDestroyBuffer() in between, we still have to keep the buffer
5 live for vaEndPicture().
6
7Origin: upstream, http://cgit.freedesktop.org/vaapi/vdpau-driver/commit/?id=d26b5b3
8Bug-Ubuntu: https://bugs.launchpad.net/bugs/1222790
9Forwarded: yes
10Applied-Upstream: 0.7.4
11Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
12
13---
14diff --git a/src/vdpau_buffer.c b/src/vdpau_buffer.c
15index f1171f3..540713f 100644
16--- a/src/vdpau_buffer.c
17+++ b/src/vdpau_buffer.c
18@@ -57,6 +57,7 @@ create_va_buffer(
19 obj_buffer->buffer_size = size * num_elements;
20 obj_buffer->buffer_data = malloc(obj_buffer->buffer_size);
21 obj_buffer->mtime = 0;
22+ obj_buffer->delayed_destroy = 0;
23
24 if (!obj_buffer->buffer_data) {
25 destroy_va_buffer(driver_data, obj_buffer);
26@@ -103,6 +104,7 @@ schedule_destroy_va_buffer(
27 ASSERT(obj_context->dead_buffers);
28 obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id;
29 obj_context->dead_buffers_count++;
30+ obj_buffer->delayed_destroy = 1;
31 }
32
33 // vaCreateBuffer
34@@ -162,7 +164,7 @@ vdpau_DestroyBuffer(
35
36 object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id);
37
38- if (obj_buffer)
39+ if (obj_buffer && !obj_buffer->delayed_destroy)
40 destroy_va_buffer(driver_data, obj_buffer);
41
42 return VA_STATUS_SUCCESS;
43diff --git a/src/vdpau_buffer.h b/src/vdpau_buffer.h
44index 7790f54..0168df9 100644
45--- a/src/vdpau_buffer.h
46+++ b/src/vdpau_buffer.h
47@@ -33,6 +33,7 @@ struct object_buffer {
48 unsigned int max_num_elements;
49 unsigned int num_elements;
50 uint64_t mtime;
51+ unsigned int delayed_destroy : 1;
52 };
53
54 // Create VA buffer object
55--
56cgit v0.9.0.2-2-gbebe
057
=== added file 'debian/patches/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch'
--- debian/patches/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch 2014-05-06 21:31:51 +0000
@@ -0,0 +1,111 @@
1Description: Purge VA buffers on context destroy or new picture decdode sequence.
2Origin: upstream, http://cgit.freedesktop.org/vaapi/vdpau-driver/commit/?id=2630695
3Bug-Ubuntu: https://bugs.launchpad.net/bugs/1222790
4Forwarded: yes
5Applied-Upstream: 0.7.4
6Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
7
8---
9diff --git a/src/vdpau_buffer.c b/src/vdpau_buffer.c
10index 540713f..8766046 100644
11--- a/src/vdpau_buffer.c
12+++ b/src/vdpau_buffer.c
13@@ -28,6 +28,27 @@
14 #define DEBUG 1
15 #include "debug.h"
16
17+// Destroy dead VA buffers
18+void
19+destroy_dead_va_buffers(
20+ vdpau_driver_data_t *driver_data,
21+ object_context_p obj_context
22+)
23+{
24+ object_buffer_p obj_buffer;
25+ unsigned int i;
26+
27+ if (obj_context->dead_buffers_count < 1)
28+ return;
29+
30+ ASSERT(obj_context->dead_buffers);
31+ for (i = 0; i < obj_context->dead_buffers_count; i++) {
32+ obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]);
33+ ASSERT(obj_buffer);
34+ destroy_va_buffer(driver_data, obj_buffer);
35+ }
36+ obj_context->dead_buffers_count = 0;
37+}
38
39 // Create VA buffer object
40 object_buffer_p
41diff --git a/src/vdpau_buffer.h b/src/vdpau_buffer.h
42index 0168df9..42672aa 100644
43--- a/src/vdpau_buffer.h
44+++ b/src/vdpau_buffer.h
45@@ -36,6 +36,13 @@ struct object_buffer {
46 unsigned int delayed_destroy : 1;
47 };
48
49+// Destroy dead VA buffers
50+void
51+destroy_dead_va_buffers(
52+ vdpau_driver_data_t *driver_data,
53+ object_context_p obj_context
54+) attribute_hidden;
55+
56 // Create VA buffer object
57 object_buffer_p
58 create_va_buffer(
59diff --git a/src/vdpau_decode.c b/src/vdpau_decode.c
60index 08dfbf0..dee3993 100644
61--- a/src/vdpau_decode.c
62+++ b/src/vdpau_decode.c
63@@ -1134,6 +1134,8 @@ vdpau_BeginPicture(
64 default:
65 return VA_STATUS_ERROR_UNKNOWN;
66 }
67+
68+ destroy_dead_va_buffers(driver_data, obj_context);
69 return VA_STATUS_SUCCESS;
70 }
71
72@@ -1256,16 +1258,7 @@ vdpau_EndPicture(
73 obj_context->current_render_target = VA_INVALID_SURFACE;
74
75 /* Release pending buffers */
76- if (obj_context->dead_buffers_count > 0) {
77- ASSERT(obj_context->dead_buffers);
78- int i;
79- for (i = 0; i < obj_context->dead_buffers_count; i++) {
80- object_buffer_p obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]);
81- ASSERT(obj_buffer);
82- destroy_va_buffer(driver_data, obj_buffer);
83- }
84- obj_context->dead_buffers_count = 0;
85- }
86+ destroy_dead_va_buffers(driver_data, obj_context);
87
88 return va_status;
89 }
90diff --git a/src/vdpau_video.c b/src/vdpau_video.c
91index 3821879..05d1f5e 100644
92--- a/src/vdpau_video.c
93+++ b/src/vdpau_video.c
94@@ -24,6 +24,7 @@
95 #include "vdpau_decode.h"
96 #include "vdpau_subpic.h"
97 #include "vdpau_mixer.h"
98+#include "vdpau_buffer.h"
99 #include "utils.h"
100
101 #define DEBUG 1
102@@ -481,6 +482,7 @@ VAStatus vdpau_DestroyContext(VADriverContextP ctx, VAContextID context)
103 obj_context->vdp_decoder = VDP_INVALID_HANDLE;
104 }
105
106+ destroy_dead_va_buffers(driver_data, obj_context);
107 if (obj_context->dead_buffers) {
108 free(obj_context->dead_buffers);
109 obj_context->dead_buffers = NULL;
110--
111cgit v0.9.0.2-2-gbebe
0112
=== added file 'debian/patches/03_mark_destroyed_buffers_as_deleted.patch'
--- debian/patches/03_mark_destroyed_buffers_as_deleted.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/03_mark_destroyed_buffers_as_deleted.patch 2014-05-06 21:31:51 +0000
@@ -0,0 +1,28 @@
1Description: decode: mark destroyed buffers as deleted
2 In multi-threaded scenarios destroying a buffer via destroy_va_buffer()
3 will allow other threads to claim the freed buffer object. If the
4 calling code does not know whether the buffer object was freed it may
5 attempt to vaDestroyBuffer, essentially destroying a buffer object which
6 is in use by another thread.
7
8Origin: upstream, http://cgit.freedesktop.org/vaapi/vdpau-driver/commit/?id=e4fd3b
9Bug-Ubuntu: https://bugs.launchpad.net/bugs/1222790
10Forwarded: yes
11Applied-Upstream: 0.7.4
12Author: Philip Lorenz <philip@bithub.de>
13
14---
15diff --git a/src/vdpau_decode.c b/src/vdpau_decode.c
16index b9f1419..22d9cd9 100644
17--- a/src/vdpau_decode.c
18+++ b/src/vdpau_decode.c
19@@ -1229,6 +1229,7 @@ vdpau_RenderPicture(
20 destroy_va_buffer(driver_data, obj_buffer);
21 break;
22 }
23+ buffers[i] = VA_INVALID_BUFFER;
24 }
25
26 return VA_STATUS_SUCCESS;
27--
28cgit v0.9.0.2-2-gbebe
029
=== modified file 'debian/patches/series'
--- debian/patches/series 2013-04-13 09:39:54 +0000
+++ debian/patches/series 2014-05-06 21:31:51 +0000
@@ -1,2 +1,5 @@
1autoreconf.patch1autoreconf.patch
2GL_VER_1_3.patch2GL_VER_1_3.patch
301_dont_clear_va_buffer_too_early.patch
402_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch
503_mark_destroyed_buffers_as_deleted.patch
36
=== modified file 'src/vdpau_buffer.c'
--- src/vdpau_buffer.c 2011-09-22 11:35:45 +0000
+++ src/vdpau_buffer.c 2014-05-06 21:31:51 +0000
@@ -28,6 +28,27 @@
28#define DEBUG 128#define DEBUG 1
29#include "debug.h"29#include "debug.h"
3030
31// Destroy dead VA buffers
32void
33destroy_dead_va_buffers(
34 vdpau_driver_data_t *driver_data,
35 object_context_p obj_context
36)
37{
38 object_buffer_p obj_buffer;
39 unsigned int i;
40
41 if (obj_context->dead_buffers_count < 1)
42 return;
43
44 ASSERT(obj_context->dead_buffers);
45 for (i = 0; i < obj_context->dead_buffers_count; i++) {
46 obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]);
47 ASSERT(obj_buffer);
48 destroy_va_buffer(driver_data, obj_buffer);
49 }
50 obj_context->dead_buffers_count = 0;
51}
3152
32// Create VA buffer object53// Create VA buffer object
33object_buffer_p54object_buffer_p
@@ -57,6 +78,7 @@
57 obj_buffer->buffer_size = size * num_elements;78 obj_buffer->buffer_size = size * num_elements;
58 obj_buffer->buffer_data = malloc(obj_buffer->buffer_size);79 obj_buffer->buffer_data = malloc(obj_buffer->buffer_size);
59 obj_buffer->mtime = 0;80 obj_buffer->mtime = 0;
81 obj_buffer->delayed_destroy = 0;
6082
61 if (!obj_buffer->buffer_data) {83 if (!obj_buffer->buffer_data) {
62 destroy_va_buffer(driver_data, obj_buffer);84 destroy_va_buffer(driver_data, obj_buffer);
@@ -103,6 +125,7 @@
103 ASSERT(obj_context->dead_buffers);125 ASSERT(obj_context->dead_buffers);
104 obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id;126 obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id;
105 obj_context->dead_buffers_count++;127 obj_context->dead_buffers_count++;
128 obj_buffer->delayed_destroy = 1;
106}129}
107130
108// vaCreateBuffer131// vaCreateBuffer
@@ -162,7 +185,7 @@
162185
163 object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id);186 object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id);
164187
165 if (obj_buffer)188 if (obj_buffer && !obj_buffer->delayed_destroy)
166 destroy_va_buffer(driver_data, obj_buffer);189 destroy_va_buffer(driver_data, obj_buffer);
167190
168 return VA_STATUS_SUCCESS;191 return VA_STATUS_SUCCESS;
169192
=== modified file 'src/vdpau_buffer.h'
--- src/vdpau_buffer.h 2011-09-22 11:35:45 +0000
+++ src/vdpau_buffer.h 2014-05-06 21:31:51 +0000
@@ -33,8 +33,16 @@
33 unsigned int max_num_elements;33 unsigned int max_num_elements;
34 unsigned int num_elements;34 unsigned int num_elements;
35 uint64_t mtime;35 uint64_t mtime;
36 unsigned int delayed_destroy : 1;
36};37};
3738
39// Destroy dead VA buffers
40void
41destroy_dead_va_buffers(
42 vdpau_driver_data_t *driver_data,
43 object_context_p obj_context
44) attribute_hidden;
45
38// Create VA buffer object46// Create VA buffer object
39object_buffer_p47object_buffer_p
40create_va_buffer(48create_va_buffer(
4149
=== modified file 'src/vdpau_decode.c'
--- src/vdpau_decode.c 2011-09-22 11:35:45 +0000
+++ src/vdpau_decode.c 2014-05-06 21:31:51 +0000
@@ -1134,6 +1134,8 @@
1134 default:1134 default:
1135 return VA_STATUS_ERROR_UNKNOWN;1135 return VA_STATUS_ERROR_UNKNOWN;
1136 }1136 }
1137
1138 destroy_dead_va_buffers(driver_data, obj_context);
1137 return VA_STATUS_SUCCESS;1139 return VA_STATUS_SUCCESS;
1138}1140}
11391141
@@ -1187,6 +1189,7 @@
1187 destroy_va_buffer(driver_data, obj_buffer);1189 destroy_va_buffer(driver_data, obj_buffer);
1188 break;1190 break;
1189 }1191 }
1192 buffers[i] = VA_INVALID_BUFFER;
1190 }1193 }
11911194
1192 return VA_STATUS_SUCCESS;1195 return VA_STATUS_SUCCESS;
@@ -1256,16 +1259,7 @@
1256 obj_context->current_render_target = VA_INVALID_SURFACE;1259 obj_context->current_render_target = VA_INVALID_SURFACE;
12571260
1258 /* Release pending buffers */1261 /* Release pending buffers */
1259 if (obj_context->dead_buffers_count > 0) {1262 destroy_dead_va_buffers(driver_data, obj_context);
1260 ASSERT(obj_context->dead_buffers);
1261 int i;
1262 for (i = 0; i < obj_context->dead_buffers_count; i++) {
1263 object_buffer_p obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]);
1264 ASSERT(obj_buffer);
1265 destroy_va_buffer(driver_data, obj_buffer);
1266 }
1267 obj_context->dead_buffers_count = 0;
1268 }
12691263
1270 return va_status;1264 return va_status;
1271}1265}
12721266
=== modified file 'src/vdpau_video.c'
--- src/vdpau_video.c 2011-09-22 11:35:45 +0000
+++ src/vdpau_video.c 2014-05-06 21:31:51 +0000
@@ -24,6 +24,7 @@
24#include "vdpau_decode.h"24#include "vdpau_decode.h"
25#include "vdpau_subpic.h"25#include "vdpau_subpic.h"
26#include "vdpau_mixer.h"26#include "vdpau_mixer.h"
27#include "vdpau_buffer.h"
27#include "utils.h"28#include "utils.h"
2829
29#define DEBUG 130#define DEBUG 1
@@ -481,6 +482,7 @@
481 obj_context->vdp_decoder = VDP_INVALID_HANDLE;482 obj_context->vdp_decoder = VDP_INVALID_HANDLE;
482 }483 }
483484
485 destroy_dead_va_buffers(driver_data, obj_context);
484 if (obj_context->dead_buffers) {486 if (obj_context->dead_buffers) {
485 free(obj_context->dead_buffers);487 free(obj_context->dead_buffers);
486 obj_context->dead_buffers = NULL;488 obj_context->dead_buffers = NULL;

Subscribers

People subscribed via source and target branches