Merge lp:~3v1n0/ubuntu/utopic/vdpau-video/fix-buffers into lp:ubuntu/utopic/vdpau-video
- Utopic (14.10)
- fix-buffers
- Merge into utopic
Proposed by
Marco Trevisan (Treviño)
Status: | Merged |
---|---|
Merge reported by: | Martin Pitt |
Merged at revision: | not available |
Proposed branch: | lp:~3v1n0/ubuntu/utopic/vdpau-video/fix-buffers |
Merge into: | lp:ubuntu/utopic/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/utopic/vdpau-video/fix-buffers |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Pitt | Approve | ||
Review via email: mp+218515@code.launchpad.net |
Commit message
Added patch-set from upstream to fix crash when using gstreamer-vaapi
Description of the change
Backported upstream commits:
- http://
- http://
- http://
They fixes a crash when using gstreamer-vaapi.
To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote : | # |
this FTBFSed in utopic, so you'll need a followup upload to fix that.
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
I think for utopic we should probably move to the upstream 0.7.4 version.
By the way, I guess the FTBFS is caused by this libva change [1], that is fixable with this vdpau-driver patch [1].
[1] http://
[2] http://
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory '.pc/01_dont_clear_va_buffer_too_early.patch' |
2 | === added directory '.pc/01_dont_clear_va_buffer_too_early.patch/src' |
3 | === added file '.pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.c' |
4 | --- .pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.c 1970-01-01 00:00:00 +0000 |
5 | +++ .pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.c 2014-05-06 21:30:45 +0000 |
6 | @@ -0,0 +1,257 @@ |
7 | +/* |
8 | + * vdpau_buffer.c - VDPAU backend for VA-API (VA buffers) |
9 | + * |
10 | + * vdpau-video (C) 2009-2011 Splitted-Desktop Systems |
11 | + * |
12 | + * This program is free software; you can redistribute it and/or modify |
13 | + * it under the terms of the GNU General Public License as published by |
14 | + * the Free Software Foundation; either version 2 of the License, or |
15 | + * (at your option) any later version. |
16 | + * |
17 | + * This program is distributed in the hope that it will be useful, |
18 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | + * GNU General Public License for more details. |
21 | + * |
22 | + * You should have received a copy of the GNU General Public License |
23 | + * along with this program; if not, write to the Free Software |
24 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
25 | + */ |
26 | + |
27 | +#include "sysdeps.h" |
28 | +#include "vdpau_buffer.h" |
29 | +#include "vdpau_driver.h" |
30 | +#include "vdpau_video.h" |
31 | +#include "vdpau_dump.h" |
32 | +#include "utils.h" |
33 | + |
34 | +#define DEBUG 1 |
35 | +#include "debug.h" |
36 | + |
37 | + |
38 | +// Create VA buffer object |
39 | +object_buffer_p |
40 | +create_va_buffer( |
41 | + vdpau_driver_data_t *driver_data, |
42 | + VAContextID context, |
43 | + VABufferType buffer_type, |
44 | + unsigned int num_elements, |
45 | + unsigned int size |
46 | +) |
47 | +{ |
48 | + VABufferID buffer_id; |
49 | + object_buffer_p obj_buffer; |
50 | + |
51 | + buffer_id = object_heap_allocate(&driver_data->buffer_heap); |
52 | + if (buffer_id == VA_INVALID_BUFFER) |
53 | + return NULL; |
54 | + |
55 | + obj_buffer = VDPAU_BUFFER(buffer_id); |
56 | + if (!obj_buffer) |
57 | + return NULL; |
58 | + |
59 | + obj_buffer->va_context = context; |
60 | + obj_buffer->type = buffer_type; |
61 | + obj_buffer->max_num_elements = num_elements; |
62 | + obj_buffer->num_elements = num_elements; |
63 | + obj_buffer->buffer_size = size * num_elements; |
64 | + obj_buffer->buffer_data = malloc(obj_buffer->buffer_size); |
65 | + obj_buffer->mtime = 0; |
66 | + |
67 | + if (!obj_buffer->buffer_data) { |
68 | + destroy_va_buffer(driver_data, obj_buffer); |
69 | + return NULL; |
70 | + } |
71 | + return obj_buffer; |
72 | +} |
73 | + |
74 | +// Destroy VA buffer object |
75 | +void |
76 | +destroy_va_buffer( |
77 | + vdpau_driver_data_t *driver_data, |
78 | + object_buffer_p obj_buffer |
79 | +) |
80 | +{ |
81 | + if (!obj_buffer) |
82 | + return; |
83 | + |
84 | + if (obj_buffer->buffer_data) { |
85 | + free(obj_buffer->buffer_data); |
86 | + obj_buffer->buffer_data = NULL; |
87 | + } |
88 | + object_heap_free(&driver_data->buffer_heap, (object_base_p)obj_buffer); |
89 | +} |
90 | + |
91 | +// Schedule VA buffer object for destruction |
92 | +void |
93 | +schedule_destroy_va_buffer( |
94 | + vdpau_driver_data_p driver_data, |
95 | + object_buffer_p obj_buffer |
96 | +) |
97 | +{ |
98 | + object_context_p obj_context = VDPAU_CONTEXT(obj_buffer->va_context); |
99 | + if (!obj_context) |
100 | + return; |
101 | + |
102 | + realloc_buffer( |
103 | + &obj_context->dead_buffers, |
104 | + &obj_context->dead_buffers_count_max, |
105 | + 16 + obj_context->dead_buffers_count, |
106 | + sizeof(*obj_context->dead_buffers) |
107 | + ); |
108 | + |
109 | + ASSERT(obj_context->dead_buffers); |
110 | + obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id; |
111 | + obj_context->dead_buffers_count++; |
112 | +} |
113 | + |
114 | +// vaCreateBuffer |
115 | +VAStatus |
116 | +vdpau_CreateBuffer( |
117 | + VADriverContextP ctx, |
118 | + VAContextID context, |
119 | + VABufferType type, |
120 | + unsigned int size, |
121 | + unsigned int num_elements, |
122 | + void *data, |
123 | + VABufferID *buf_id |
124 | +) |
125 | +{ |
126 | + VDPAU_DRIVER_DATA_INIT; |
127 | + |
128 | + if (buf_id) |
129 | + *buf_id = VA_INVALID_BUFFER; |
130 | + |
131 | + /* Validate type */ |
132 | + switch (type) { |
133 | + case VAPictureParameterBufferType: |
134 | + case VAIQMatrixBufferType: |
135 | + case VASliceParameterBufferType: |
136 | + case VASliceDataBufferType: |
137 | + case VABitPlaneBufferType: |
138 | + case VAImageBufferType: |
139 | + /* Ok */ |
140 | + break; |
141 | + default: |
142 | + D(bug("ERROR: unsupported buffer type %d\n", type)); |
143 | + return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; |
144 | + } |
145 | + |
146 | + object_buffer_p obj_buffer; |
147 | + obj_buffer = create_va_buffer(driver_data, context, type, num_elements, size); |
148 | + if (!obj_buffer) |
149 | + return VA_STATUS_ERROR_ALLOCATION_FAILED; |
150 | + |
151 | + if (data) |
152 | + memcpy(obj_buffer->buffer_data, data, obj_buffer->buffer_size); |
153 | + |
154 | + if (buf_id) |
155 | + *buf_id = obj_buffer->base.id; |
156 | + |
157 | + return VA_STATUS_SUCCESS; |
158 | +} |
159 | + |
160 | +// vaDestroyBuffer |
161 | +VAStatus |
162 | +vdpau_DestroyBuffer( |
163 | + VADriverContextP ctx, |
164 | + VABufferID buffer_id |
165 | +) |
166 | +{ |
167 | + VDPAU_DRIVER_DATA_INIT; |
168 | + |
169 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id); |
170 | + |
171 | + if (obj_buffer) |
172 | + destroy_va_buffer(driver_data, obj_buffer); |
173 | + |
174 | + return VA_STATUS_SUCCESS; |
175 | +} |
176 | + |
177 | +// vaBufferSetNumElements |
178 | +VAStatus |
179 | +vdpau_BufferSetNumElements( |
180 | + VADriverContextP ctx, |
181 | + VABufferID buf_id, |
182 | + unsigned int num_elements |
183 | +) |
184 | +{ |
185 | + VDPAU_DRIVER_DATA_INIT; |
186 | + |
187 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); |
188 | + if (!obj_buffer) |
189 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
190 | + |
191 | + if (num_elements < 0 || num_elements > obj_buffer->max_num_elements) |
192 | + return VA_STATUS_ERROR_UNKNOWN; |
193 | + |
194 | + obj_buffer->num_elements = num_elements; |
195 | + return VA_STATUS_SUCCESS; |
196 | +} |
197 | + |
198 | +// vaMapBuffer |
199 | +VAStatus |
200 | +vdpau_MapBuffer( |
201 | + VADriverContextP ctx, |
202 | + VABufferID buf_id, |
203 | + void **pbuf |
204 | +) |
205 | +{ |
206 | + VDPAU_DRIVER_DATA_INIT; |
207 | + |
208 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); |
209 | + if (!obj_buffer) |
210 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
211 | + |
212 | + if (pbuf) |
213 | + *pbuf = obj_buffer->buffer_data; |
214 | + |
215 | + if (obj_buffer->buffer_data == NULL) |
216 | + return VA_STATUS_ERROR_UNKNOWN; |
217 | + |
218 | + ++obj_buffer->mtime; |
219 | + return VA_STATUS_SUCCESS; |
220 | +} |
221 | + |
222 | +// vaUnmapBuffer |
223 | +VAStatus |
224 | +vdpau_UnmapBuffer( |
225 | + VADriverContextP ctx, |
226 | + VABufferID buf_id |
227 | +) |
228 | +{ |
229 | + VDPAU_DRIVER_DATA_INIT; |
230 | + |
231 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); |
232 | + if (!obj_buffer) |
233 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
234 | + |
235 | + ++obj_buffer->mtime; |
236 | + return VA_STATUS_SUCCESS; |
237 | +} |
238 | + |
239 | +// vaBufferInfo |
240 | +VAStatus |
241 | +vdpau_BufferInfo( |
242 | + VADriverContextP ctx, |
243 | + VAContextID context, |
244 | + VABufferID buf_id, |
245 | + VABufferType *type, |
246 | + unsigned int *size, |
247 | + unsigned int *num_elements |
248 | +) |
249 | +{ |
250 | + VDPAU_DRIVER_DATA_INIT; |
251 | + |
252 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); |
253 | + if (!obj_buffer) |
254 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
255 | + |
256 | + if (type) |
257 | + *type = obj_buffer->type; |
258 | + if (size) |
259 | + *size = obj_buffer->buffer_size / obj_buffer->num_elements; |
260 | + if (num_elements) |
261 | + *num_elements = obj_buffer->num_elements; |
262 | + return VA_STATUS_SUCCESS; |
263 | +} |
264 | |
265 | === added file '.pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.h' |
266 | --- .pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.h 1970-01-01 00:00:00 +0000 |
267 | +++ .pc/01_dont_clear_va_buffer_too_early.patch/src/vdpau_buffer.h 2014-05-06 21:30:45 +0000 |
268 | @@ -0,0 +1,115 @@ |
269 | +/* |
270 | + * vdpau_buffer.h - VDPAU backend for VA-API (VA buffers) |
271 | + * |
272 | + * vdpau-video (C) 2009-2011 Splitted-Desktop Systems |
273 | + * |
274 | + * This program is free software; you can redistribute it and/or modify |
275 | + * it under the terms of the GNU General Public License as published by |
276 | + * the Free Software Foundation; either version 2 of the License, or |
277 | + * (at your option) any later version. |
278 | + * |
279 | + * This program is distributed in the hope that it will be useful, |
280 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
281 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
282 | + * GNU General Public License for more details. |
283 | + * |
284 | + * You should have received a copy of the GNU General Public License |
285 | + * along with this program; if not, write to the Free Software |
286 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
287 | + */ |
288 | + |
289 | +#ifndef VDPAU_BUFFER_H |
290 | +#define VDPAU_BUFFER_H |
291 | + |
292 | +#include "vdpau_driver.h" |
293 | + |
294 | +typedef struct object_buffer object_buffer_t; |
295 | +struct object_buffer { |
296 | + struct object_base base; |
297 | + VAContextID va_context; |
298 | + VABufferType type; |
299 | + void *buffer_data; |
300 | + unsigned int buffer_size; |
301 | + unsigned int max_num_elements; |
302 | + unsigned int num_elements; |
303 | + uint64_t mtime; |
304 | +}; |
305 | + |
306 | +// Create VA buffer object |
307 | +object_buffer_p |
308 | +create_va_buffer( |
309 | + vdpau_driver_data_p driver_data, |
310 | + VAContextID context, |
311 | + VABufferType buffer_type, |
312 | + unsigned int num_elements, |
313 | + unsigned int size |
314 | +) attribute_hidden; |
315 | + |
316 | +// Destroy VA buffer object |
317 | +void |
318 | +destroy_va_buffer( |
319 | + vdpau_driver_data_p driver_data, |
320 | + object_buffer_p obj_buffer |
321 | +) attribute_hidden; |
322 | + |
323 | +// Schedule VA buffer object for destruction |
324 | +void |
325 | +schedule_destroy_va_buffer( |
326 | + vdpau_driver_data_p driver_data, |
327 | + object_buffer_p obj_buffer |
328 | +) attribute_hidden; |
329 | + |
330 | +// vaCreateBuffer |
331 | +VAStatus |
332 | +vdpau_CreateBuffer( |
333 | + VADriverContextP ctx, |
334 | + VAContextID context, |
335 | + VABufferType type, |
336 | + unsigned int size, |
337 | + unsigned int num_elements, |
338 | + void *data, |
339 | + VABufferID *buf_id |
340 | +) attribute_hidden; |
341 | + |
342 | +// vaDestroyBuffer |
343 | +VAStatus |
344 | +vdpau_DestroyBuffer( |
345 | + VADriverContextP ctx, |
346 | + VABufferID buffer_id |
347 | +) attribute_hidden; |
348 | + |
349 | +// vaBufferSetNumElements |
350 | +VAStatus |
351 | +vdpau_BufferSetNumElements( |
352 | + VADriverContextP ctx, |
353 | + VABufferID buf_id, |
354 | + unsigned int num_elements |
355 | +) attribute_hidden; |
356 | + |
357 | +// vaMapBuffer |
358 | +VAStatus |
359 | +vdpau_MapBuffer( |
360 | + VADriverContextP ctx, |
361 | + VABufferID buf_id, |
362 | + void **pbuf |
363 | +) attribute_hidden; |
364 | + |
365 | +// vaUnmapBuffer |
366 | +VAStatus |
367 | +vdpau_UnmapBuffer( |
368 | + VADriverContextP ctx, |
369 | + VABufferID buf_id |
370 | +) attribute_hidden; |
371 | + |
372 | +// vaBufferInfo |
373 | +VAStatus |
374 | +vdpau_BufferInfo( |
375 | + VADriverContextP ctx, |
376 | + VAContextID context, |
377 | + VABufferID buf_id, |
378 | + VABufferType *type, |
379 | + unsigned int *size, |
380 | + unsigned int *num_elements |
381 | +) attribute_hidden; |
382 | + |
383 | +#endif /* VDPAU_BUFFER_H */ |
384 | |
385 | === added directory '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch' |
386 | === added directory '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src' |
387 | === added file '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.c' |
388 | --- .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 |
389 | +++ .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.c 2014-05-06 21:30:45 +0000 |
390 | @@ -0,0 +1,259 @@ |
391 | +/* |
392 | + * vdpau_buffer.c - VDPAU backend for VA-API (VA buffers) |
393 | + * |
394 | + * vdpau-video (C) 2009-2011 Splitted-Desktop Systems |
395 | + * |
396 | + * This program is free software; you can redistribute it and/or modify |
397 | + * it under the terms of the GNU General Public License as published by |
398 | + * the Free Software Foundation; either version 2 of the License, or |
399 | + * (at your option) any later version. |
400 | + * |
401 | + * This program is distributed in the hope that it will be useful, |
402 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
403 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
404 | + * GNU General Public License for more details. |
405 | + * |
406 | + * You should have received a copy of the GNU General Public License |
407 | + * along with this program; if not, write to the Free Software |
408 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
409 | + */ |
410 | + |
411 | +#include "sysdeps.h" |
412 | +#include "vdpau_buffer.h" |
413 | +#include "vdpau_driver.h" |
414 | +#include "vdpau_video.h" |
415 | +#include "vdpau_dump.h" |
416 | +#include "utils.h" |
417 | + |
418 | +#define DEBUG 1 |
419 | +#include "debug.h" |
420 | + |
421 | + |
422 | +// Create VA buffer object |
423 | +object_buffer_p |
424 | +create_va_buffer( |
425 | + vdpau_driver_data_t *driver_data, |
426 | + VAContextID context, |
427 | + VABufferType buffer_type, |
428 | + unsigned int num_elements, |
429 | + unsigned int size |
430 | +) |
431 | +{ |
432 | + VABufferID buffer_id; |
433 | + object_buffer_p obj_buffer; |
434 | + |
435 | + buffer_id = object_heap_allocate(&driver_data->buffer_heap); |
436 | + if (buffer_id == VA_INVALID_BUFFER) |
437 | + return NULL; |
438 | + |
439 | + obj_buffer = VDPAU_BUFFER(buffer_id); |
440 | + if (!obj_buffer) |
441 | + return NULL; |
442 | + |
443 | + obj_buffer->va_context = context; |
444 | + obj_buffer->type = buffer_type; |
445 | + obj_buffer->max_num_elements = num_elements; |
446 | + obj_buffer->num_elements = num_elements; |
447 | + obj_buffer->buffer_size = size * num_elements; |
448 | + obj_buffer->buffer_data = malloc(obj_buffer->buffer_size); |
449 | + obj_buffer->mtime = 0; |
450 | + obj_buffer->delayed_destroy = 0; |
451 | + |
452 | + if (!obj_buffer->buffer_data) { |
453 | + destroy_va_buffer(driver_data, obj_buffer); |
454 | + return NULL; |
455 | + } |
456 | + return obj_buffer; |
457 | +} |
458 | + |
459 | +// Destroy VA buffer object |
460 | +void |
461 | +destroy_va_buffer( |
462 | + vdpau_driver_data_t *driver_data, |
463 | + object_buffer_p obj_buffer |
464 | +) |
465 | +{ |
466 | + if (!obj_buffer) |
467 | + return; |
468 | + |
469 | + if (obj_buffer->buffer_data) { |
470 | + free(obj_buffer->buffer_data); |
471 | + obj_buffer->buffer_data = NULL; |
472 | + } |
473 | + object_heap_free(&driver_data->buffer_heap, (object_base_p)obj_buffer); |
474 | +} |
475 | + |
476 | +// Schedule VA buffer object for destruction |
477 | +void |
478 | +schedule_destroy_va_buffer( |
479 | + vdpau_driver_data_p driver_data, |
480 | + object_buffer_p obj_buffer |
481 | +) |
482 | +{ |
483 | + object_context_p obj_context = VDPAU_CONTEXT(obj_buffer->va_context); |
484 | + if (!obj_context) |
485 | + return; |
486 | + |
487 | + realloc_buffer( |
488 | + &obj_context->dead_buffers, |
489 | + &obj_context->dead_buffers_count_max, |
490 | + 16 + obj_context->dead_buffers_count, |
491 | + sizeof(*obj_context->dead_buffers) |
492 | + ); |
493 | + |
494 | + ASSERT(obj_context->dead_buffers); |
495 | + obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id; |
496 | + obj_context->dead_buffers_count++; |
497 | + obj_buffer->delayed_destroy = 1; |
498 | +} |
499 | + |
500 | +// vaCreateBuffer |
501 | +VAStatus |
502 | +vdpau_CreateBuffer( |
503 | + VADriverContextP ctx, |
504 | + VAContextID context, |
505 | + VABufferType type, |
506 | + unsigned int size, |
507 | + unsigned int num_elements, |
508 | + void *data, |
509 | + VABufferID *buf_id |
510 | +) |
511 | +{ |
512 | + VDPAU_DRIVER_DATA_INIT; |
513 | + |
514 | + if (buf_id) |
515 | + *buf_id = VA_INVALID_BUFFER; |
516 | + |
517 | + /* Validate type */ |
518 | + switch (type) { |
519 | + case VAPictureParameterBufferType: |
520 | + case VAIQMatrixBufferType: |
521 | + case VASliceParameterBufferType: |
522 | + case VASliceDataBufferType: |
523 | + case VABitPlaneBufferType: |
524 | + case VAImageBufferType: |
525 | + /* Ok */ |
526 | + break; |
527 | + default: |
528 | + D(bug("ERROR: unsupported buffer type %d\n", type)); |
529 | + return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; |
530 | + } |
531 | + |
532 | + object_buffer_p obj_buffer; |
533 | + obj_buffer = create_va_buffer(driver_data, context, type, num_elements, size); |
534 | + if (!obj_buffer) |
535 | + return VA_STATUS_ERROR_ALLOCATION_FAILED; |
536 | + |
537 | + if (data) |
538 | + memcpy(obj_buffer->buffer_data, data, obj_buffer->buffer_size); |
539 | + |
540 | + if (buf_id) |
541 | + *buf_id = obj_buffer->base.id; |
542 | + |
543 | + return VA_STATUS_SUCCESS; |
544 | +} |
545 | + |
546 | +// vaDestroyBuffer |
547 | +VAStatus |
548 | +vdpau_DestroyBuffer( |
549 | + VADriverContextP ctx, |
550 | + VABufferID buffer_id |
551 | +) |
552 | +{ |
553 | + VDPAU_DRIVER_DATA_INIT; |
554 | + |
555 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id); |
556 | + |
557 | + if (obj_buffer && !obj_buffer->delayed_destroy) |
558 | + destroy_va_buffer(driver_data, obj_buffer); |
559 | + |
560 | + return VA_STATUS_SUCCESS; |
561 | +} |
562 | + |
563 | +// vaBufferSetNumElements |
564 | +VAStatus |
565 | +vdpau_BufferSetNumElements( |
566 | + VADriverContextP ctx, |
567 | + VABufferID buf_id, |
568 | + unsigned int num_elements |
569 | +) |
570 | +{ |
571 | + VDPAU_DRIVER_DATA_INIT; |
572 | + |
573 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); |
574 | + if (!obj_buffer) |
575 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
576 | + |
577 | + if (num_elements < 0 || num_elements > obj_buffer->max_num_elements) |
578 | + return VA_STATUS_ERROR_UNKNOWN; |
579 | + |
580 | + obj_buffer->num_elements = num_elements; |
581 | + return VA_STATUS_SUCCESS; |
582 | +} |
583 | + |
584 | +// vaMapBuffer |
585 | +VAStatus |
586 | +vdpau_MapBuffer( |
587 | + VADriverContextP ctx, |
588 | + VABufferID buf_id, |
589 | + void **pbuf |
590 | +) |
591 | +{ |
592 | + VDPAU_DRIVER_DATA_INIT; |
593 | + |
594 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); |
595 | + if (!obj_buffer) |
596 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
597 | + |
598 | + if (pbuf) |
599 | + *pbuf = obj_buffer->buffer_data; |
600 | + |
601 | + if (obj_buffer->buffer_data == NULL) |
602 | + return VA_STATUS_ERROR_UNKNOWN; |
603 | + |
604 | + ++obj_buffer->mtime; |
605 | + return VA_STATUS_SUCCESS; |
606 | +} |
607 | + |
608 | +// vaUnmapBuffer |
609 | +VAStatus |
610 | +vdpau_UnmapBuffer( |
611 | + VADriverContextP ctx, |
612 | + VABufferID buf_id |
613 | +) |
614 | +{ |
615 | + VDPAU_DRIVER_DATA_INIT; |
616 | + |
617 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); |
618 | + if (!obj_buffer) |
619 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
620 | + |
621 | + ++obj_buffer->mtime; |
622 | + return VA_STATUS_SUCCESS; |
623 | +} |
624 | + |
625 | +// vaBufferInfo |
626 | +VAStatus |
627 | +vdpau_BufferInfo( |
628 | + VADriverContextP ctx, |
629 | + VAContextID context, |
630 | + VABufferID buf_id, |
631 | + VABufferType *type, |
632 | + unsigned int *size, |
633 | + unsigned int *num_elements |
634 | +) |
635 | +{ |
636 | + VDPAU_DRIVER_DATA_INIT; |
637 | + |
638 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); |
639 | + if (!obj_buffer) |
640 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
641 | + |
642 | + if (type) |
643 | + *type = obj_buffer->type; |
644 | + if (size) |
645 | + *size = obj_buffer->buffer_size / obj_buffer->num_elements; |
646 | + if (num_elements) |
647 | + *num_elements = obj_buffer->num_elements; |
648 | + return VA_STATUS_SUCCESS; |
649 | +} |
650 | |
651 | === added file '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.h' |
652 | --- .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 |
653 | +++ .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_buffer.h 2014-05-06 21:30:45 +0000 |
654 | @@ -0,0 +1,116 @@ |
655 | +/* |
656 | + * vdpau_buffer.h - VDPAU backend for VA-API (VA buffers) |
657 | + * |
658 | + * vdpau-video (C) 2009-2011 Splitted-Desktop Systems |
659 | + * |
660 | + * This program is free software; you can redistribute it and/or modify |
661 | + * it under the terms of the GNU General Public License as published by |
662 | + * the Free Software Foundation; either version 2 of the License, or |
663 | + * (at your option) any later version. |
664 | + * |
665 | + * This program is distributed in the hope that it will be useful, |
666 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
667 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
668 | + * GNU General Public License for more details. |
669 | + * |
670 | + * You should have received a copy of the GNU General Public License |
671 | + * along with this program; if not, write to the Free Software |
672 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
673 | + */ |
674 | + |
675 | +#ifndef VDPAU_BUFFER_H |
676 | +#define VDPAU_BUFFER_H |
677 | + |
678 | +#include "vdpau_driver.h" |
679 | + |
680 | +typedef struct object_buffer object_buffer_t; |
681 | +struct object_buffer { |
682 | + struct object_base base; |
683 | + VAContextID va_context; |
684 | + VABufferType type; |
685 | + void *buffer_data; |
686 | + unsigned int buffer_size; |
687 | + unsigned int max_num_elements; |
688 | + unsigned int num_elements; |
689 | + uint64_t mtime; |
690 | + unsigned int delayed_destroy : 1; |
691 | +}; |
692 | + |
693 | +// Create VA buffer object |
694 | +object_buffer_p |
695 | +create_va_buffer( |
696 | + vdpau_driver_data_p driver_data, |
697 | + VAContextID context, |
698 | + VABufferType buffer_type, |
699 | + unsigned int num_elements, |
700 | + unsigned int size |
701 | +) attribute_hidden; |
702 | + |
703 | +// Destroy VA buffer object |
704 | +void |
705 | +destroy_va_buffer( |
706 | + vdpau_driver_data_p driver_data, |
707 | + object_buffer_p obj_buffer |
708 | +) attribute_hidden; |
709 | + |
710 | +// Schedule VA buffer object for destruction |
711 | +void |
712 | +schedule_destroy_va_buffer( |
713 | + vdpau_driver_data_p driver_data, |
714 | + object_buffer_p obj_buffer |
715 | +) attribute_hidden; |
716 | + |
717 | +// vaCreateBuffer |
718 | +VAStatus |
719 | +vdpau_CreateBuffer( |
720 | + VADriverContextP ctx, |
721 | + VAContextID context, |
722 | + VABufferType type, |
723 | + unsigned int size, |
724 | + unsigned int num_elements, |
725 | + void *data, |
726 | + VABufferID *buf_id |
727 | +) attribute_hidden; |
728 | + |
729 | +// vaDestroyBuffer |
730 | +VAStatus |
731 | +vdpau_DestroyBuffer( |
732 | + VADriverContextP ctx, |
733 | + VABufferID buffer_id |
734 | +) attribute_hidden; |
735 | + |
736 | +// vaBufferSetNumElements |
737 | +VAStatus |
738 | +vdpau_BufferSetNumElements( |
739 | + VADriverContextP ctx, |
740 | + VABufferID buf_id, |
741 | + unsigned int num_elements |
742 | +) attribute_hidden; |
743 | + |
744 | +// vaMapBuffer |
745 | +VAStatus |
746 | +vdpau_MapBuffer( |
747 | + VADriverContextP ctx, |
748 | + VABufferID buf_id, |
749 | + void **pbuf |
750 | +) attribute_hidden; |
751 | + |
752 | +// vaUnmapBuffer |
753 | +VAStatus |
754 | +vdpau_UnmapBuffer( |
755 | + VADriverContextP ctx, |
756 | + VABufferID buf_id |
757 | +) attribute_hidden; |
758 | + |
759 | +// vaBufferInfo |
760 | +VAStatus |
761 | +vdpau_BufferInfo( |
762 | + VADriverContextP ctx, |
763 | + VAContextID context, |
764 | + VABufferID buf_id, |
765 | + VABufferType *type, |
766 | + unsigned int *size, |
767 | + unsigned int *num_elements |
768 | +) attribute_hidden; |
769 | + |
770 | +#endif /* VDPAU_BUFFER_H */ |
771 | |
772 | === added file '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_decode.c' |
773 | --- .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 |
774 | +++ .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_decode.c 2014-05-06 21:30:45 +0000 |
775 | @@ -0,0 +1,1271 @@ |
776 | +/* |
777 | + * vdpau_decode.c - VDPAU backend for VA-API (decoder) |
778 | + * |
779 | + * vdpau-video (C) 2009-2011 Splitted-Desktop Systems |
780 | + * |
781 | + * This program is free software; you can redistribute it and/or modify |
782 | + * it under the terms of the GNU General Public License as published by |
783 | + * the Free Software Foundation; either version 2 of the License, or |
784 | + * (at your option) any later version. |
785 | + * |
786 | + * This program is distributed in the hope that it will be useful, |
787 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
788 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
789 | + * GNU General Public License for more details. |
790 | + * |
791 | + * You should have received a copy of the GNU General Public License |
792 | + * along with this program; if not, write to the Free Software |
793 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
794 | + */ |
795 | + |
796 | +#include "sysdeps.h" |
797 | +#include "vdpau_decode.h" |
798 | +#include "vdpau_driver.h" |
799 | +#include "vdpau_buffer.h" |
800 | +#include "vdpau_video.h" |
801 | +#include "vdpau_dump.h" |
802 | +#include "utils.h" |
803 | +#include "put_bits.h" |
804 | + |
805 | +#define DEBUG 1 |
806 | +#include "debug.h" |
807 | + |
808 | + |
809 | +// Translates VdpDecoderProfile to VdpCodec |
810 | +VdpCodec get_VdpCodec(VdpDecoderProfile profile) |
811 | +{ |
812 | + switch (profile) { |
813 | + case VDP_DECODER_PROFILE_MPEG1: |
814 | + return VDP_CODEC_MPEG1; |
815 | + case VDP_DECODER_PROFILE_MPEG2_SIMPLE: |
816 | + case VDP_DECODER_PROFILE_MPEG2_MAIN: |
817 | + return VDP_CODEC_MPEG2; |
818 | +#if USE_VDPAU_MPEG4 |
819 | + case VDP_DECODER_PROFILE_MPEG4_PART2_SP: |
820 | + case VDP_DECODER_PROFILE_MPEG4_PART2_ASP: |
821 | + case VDP_DECODER_PROFILE_DIVX4_QMOBILE: |
822 | + case VDP_DECODER_PROFILE_DIVX4_MOBILE: |
823 | + case VDP_DECODER_PROFILE_DIVX4_HOME_THEATER: |
824 | + case VDP_DECODER_PROFILE_DIVX4_HD_1080P: |
825 | + case VDP_DECODER_PROFILE_DIVX5_QMOBILE: |
826 | + case VDP_DECODER_PROFILE_DIVX5_MOBILE: |
827 | + case VDP_DECODER_PROFILE_DIVX5_HOME_THEATER: |
828 | + case VDP_DECODER_PROFILE_DIVX5_HD_1080P: |
829 | + return VDP_CODEC_MPEG4; |
830 | +#endif |
831 | + case VDP_DECODER_PROFILE_H264_BASELINE: |
832 | + case VDP_DECODER_PROFILE_H264_MAIN: |
833 | + case VDP_DECODER_PROFILE_H264_HIGH: |
834 | + return VDP_CODEC_H264; |
835 | + case VDP_DECODER_PROFILE_VC1_SIMPLE: |
836 | + case VDP_DECODER_PROFILE_VC1_MAIN: |
837 | + case VDP_DECODER_PROFILE_VC1_ADVANCED: |
838 | + return VDP_CODEC_VC1; |
839 | + } |
840 | + return 0; |
841 | +} |
842 | + |
843 | +// Translates VAProfile to VdpDecoderProfile |
844 | +VdpDecoderProfile get_VdpDecoderProfile(VAProfile profile) |
845 | +{ |
846 | + switch (profile) { |
847 | + case VAProfileMPEG2Simple: return VDP_DECODER_PROFILE_MPEG2_SIMPLE; |
848 | + case VAProfileMPEG2Main: return VDP_DECODER_PROFILE_MPEG2_MAIN; |
849 | +#if USE_VDPAU_MPEG4 |
850 | + case VAProfileMPEG4Simple: return VDP_DECODER_PROFILE_MPEG4_PART2_SP; |
851 | + case VAProfileMPEG4AdvancedSimple: return VDP_DECODER_PROFILE_MPEG4_PART2_ASP; |
852 | +#endif |
853 | + case VAProfileH264Baseline: return VDP_DECODER_PROFILE_H264_BASELINE; |
854 | + case VAProfileH264Main: return VDP_DECODER_PROFILE_H264_MAIN; |
855 | + case VAProfileH264High: return VDP_DECODER_PROFILE_H264_HIGH; |
856 | + case VAProfileVC1Simple: return VDP_DECODER_PROFILE_VC1_SIMPLE; |
857 | + case VAProfileVC1Main: return VDP_DECODER_PROFILE_VC1_MAIN; |
858 | + case VAProfileVC1Advanced: return VDP_DECODER_PROFILE_VC1_ADVANCED; |
859 | + default: break; |
860 | + } |
861 | + return (VdpDecoderProfile)-1; |
862 | +} |
863 | + |
864 | +// Checks whether the VDPAU implementation supports the specified profile |
865 | +static inline VdpBool |
866 | +is_supported_profile( |
867 | + vdpau_driver_data_t *driver_data, |
868 | + VdpDecoderProfile profile |
869 | +) |
870 | +{ |
871 | + VdpBool is_supported = VDP_FALSE; |
872 | + VdpStatus vdp_status; |
873 | + uint32_t max_level, max_references, max_width, max_height; |
874 | + |
875 | + if (profile == (VdpDecoderProfile)-1) |
876 | + return VDP_FALSE; |
877 | + |
878 | + vdp_status = vdpau_decoder_query_capabilities( |
879 | + driver_data, |
880 | + driver_data->vdp_device, |
881 | + profile, |
882 | + &is_supported, |
883 | + &max_level, |
884 | + &max_references, |
885 | + &max_width, |
886 | + &max_height |
887 | + ); |
888 | + return (VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderQueryCapabilities()") && |
889 | + is_supported); |
890 | +} |
891 | + |
892 | +// Checks decoder for profile/entrypoint is available |
893 | +VAStatus |
894 | +check_decoder( |
895 | + vdpau_driver_data_t *driver_data, |
896 | + VAProfile profile, |
897 | + VAEntrypoint entrypoint |
898 | +) |
899 | +{ |
900 | + if (!is_supported_profile(driver_data, get_VdpDecoderProfile(profile))) |
901 | + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; |
902 | + |
903 | + /* VDPAU only supports VLD */ |
904 | + if (entrypoint != VAEntrypointVLD) |
905 | + return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; |
906 | + |
907 | + return VA_STATUS_SUCCESS; |
908 | +} |
909 | + |
910 | +// Computes value for VdpDecoderCreate()::max_references parameter |
911 | +static int |
912 | +get_max_ref_frames( |
913 | + VdpDecoderProfile profile, |
914 | + unsigned int width, |
915 | + unsigned int height |
916 | +) |
917 | +{ |
918 | + int max_ref_frames = 2; |
919 | + |
920 | + switch (profile) { |
921 | + case VDP_DECODER_PROFILE_H264_MAIN: |
922 | + case VDP_DECODER_PROFILE_H264_HIGH: |
923 | + { |
924 | + /* level 4.1 limits */ |
925 | + unsigned int aligned_width = (width + 15) & -16; |
926 | + unsigned int aligned_height = (height + 15) & -16; |
927 | + unsigned int surface_size = (aligned_width * aligned_height * 3) / 2; |
928 | + if ((max_ref_frames = (12 * 1024 * 1024) / surface_size) > 16) |
929 | + max_ref_frames = 16; |
930 | + break; |
931 | + } |
932 | + } |
933 | + return max_ref_frames; |
934 | +} |
935 | + |
936 | +// Returns the maximum number of reference frames of a decode session |
937 | +static inline int get_num_ref_frames(object_context_p obj_context) |
938 | +{ |
939 | + if (obj_context->vdp_codec == VDP_CODEC_H264) |
940 | + return obj_context->vdp_picture_info.h264.num_ref_frames; |
941 | + return 2; |
942 | +} |
943 | + |
944 | +// Ensure VDPAU decoder is created for the specified number of reference frames |
945 | +static VdpStatus |
946 | +ensure_decoder_with_max_refs( |
947 | + vdpau_driver_data_t *driver_data, |
948 | + object_context_p obj_context, |
949 | + int max_ref_frames |
950 | +) |
951 | +{ |
952 | + VdpStatus vdp_status; |
953 | + |
954 | + if (max_ref_frames < 0) |
955 | + max_ref_frames = |
956 | + get_max_ref_frames(obj_context->vdp_profile, |
957 | + obj_context->picture_width, |
958 | + obj_context->picture_height); |
959 | + |
960 | + if (obj_context->vdp_decoder == VDP_INVALID_HANDLE || |
961 | + obj_context->max_ref_frames < max_ref_frames) { |
962 | + obj_context->max_ref_frames = max_ref_frames; |
963 | + |
964 | + if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) { |
965 | + vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder); |
966 | + obj_context->vdp_decoder = VDP_INVALID_HANDLE; |
967 | + } |
968 | + |
969 | + vdp_status = vdpau_decoder_create( |
970 | + driver_data, |
971 | + driver_data->vdp_device, |
972 | + obj_context->vdp_profile, |
973 | + obj_context->picture_width, |
974 | + obj_context->picture_height, |
975 | + max_ref_frames, |
976 | + &obj_context->vdp_decoder |
977 | + ); |
978 | + if (!VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderCreate()")) |
979 | + return vdp_status; |
980 | + } |
981 | + return VDP_STATUS_OK; |
982 | +} |
983 | + |
984 | +// Lazy allocate (generated) slice data buffer. Buffer lives until vaDestroyContext() |
985 | +static uint8_t * |
986 | +alloc_gen_slice_data(object_context_p obj_context, unsigned int size) |
987 | +{ |
988 | + uint8_t *gen_slice_data = obj_context->gen_slice_data; |
989 | + |
990 | + if (obj_context->gen_slice_data_size + size > obj_context->gen_slice_data_size_max) { |
991 | + obj_context->gen_slice_data_size_max += size; |
992 | + gen_slice_data = realloc(obj_context->gen_slice_data, |
993 | + obj_context->gen_slice_data_size_max); |
994 | + if (!gen_slice_data) |
995 | + return NULL; |
996 | + obj_context->gen_slice_data = gen_slice_data; |
997 | + } |
998 | + gen_slice_data += obj_context->gen_slice_data_size; |
999 | + obj_context->gen_slice_data_size += size; |
1000 | + return gen_slice_data; |
1001 | +} |
1002 | + |
1003 | +// Lazy allocate VdpBitstreamBuffer. Buffer lives until vaDestroyContext() |
1004 | +static VdpBitstreamBuffer * |
1005 | +alloc_VdpBitstreamBuffer(object_context_p obj_context) |
1006 | +{ |
1007 | + VdpBitstreamBuffer *vdp_bitstream_buffers; |
1008 | + |
1009 | + vdp_bitstream_buffers = realloc_buffer( |
1010 | + &obj_context->vdp_bitstream_buffers, |
1011 | + &obj_context->vdp_bitstream_buffers_count_max, |
1012 | + 1 + obj_context->vdp_bitstream_buffers_count, |
1013 | + sizeof(*obj_context->vdp_bitstream_buffers) |
1014 | + ); |
1015 | + if (!vdp_bitstream_buffers) |
1016 | + return NULL; |
1017 | + |
1018 | + return &vdp_bitstream_buffers[obj_context->vdp_bitstream_buffers_count++]; |
1019 | +} |
1020 | + |
1021 | +// Append VASliceDataBuffer hunk into VDPAU buffer |
1022 | +static int |
1023 | +append_VdpBitstreamBuffer( |
1024 | + object_context_p obj_context, |
1025 | + const uint8_t *buffer, |
1026 | + uint32_t buffer_size |
1027 | +) |
1028 | +{ |
1029 | + VdpBitstreamBuffer *bitstream_buffer; |
1030 | + |
1031 | + bitstream_buffer = alloc_VdpBitstreamBuffer(obj_context); |
1032 | + if (!bitstream_buffer) |
1033 | + return -1; |
1034 | + |
1035 | + bitstream_buffer->struct_version = VDP_BITSTREAM_BUFFER_VERSION; |
1036 | + bitstream_buffer->bitstream = buffer; |
1037 | + bitstream_buffer->bitstream_bytes = buffer_size; |
1038 | + return 0; |
1039 | +} |
1040 | + |
1041 | +// Initialize VdpReferenceFrameH264 to default values |
1042 | +static void init_VdpReferenceFrameH264(VdpReferenceFrameH264 *rf) |
1043 | +{ |
1044 | + rf->surface = VDP_INVALID_HANDLE; |
1045 | + rf->is_long_term = VDP_FALSE; |
1046 | + rf->top_is_reference = VDP_FALSE; |
1047 | + rf->bottom_is_reference = VDP_FALSE; |
1048 | + rf->field_order_cnt[0] = 0; |
1049 | + rf->field_order_cnt[1] = 0; |
1050 | + rf->frame_idx = 0; |
1051 | +} |
1052 | + |
1053 | +static const uint8_t ff_identity[64] = { |
1054 | + 0, 1, 2, 3, 4, 5, 6, 7, |
1055 | + 8, 9, 10, 11, 12, 13, 14, 15, |
1056 | + 16, 17, 18, 19, 20, 21, 22, 23, |
1057 | + 24, 25, 26, 27, 28, 29, 30, 31, |
1058 | + 32, 33, 34, 35, 36, 37, 38, 39, |
1059 | + 40, 41, 42, 43, 44, 45, 46, 47, |
1060 | + 48, 49, 50, 51, 52, 53, 54, 55, |
1061 | + 56, 57, 58, 59, 60, 61, 62, 63 |
1062 | +}; |
1063 | + |
1064 | +static const uint8_t ff_zigzag_direct[64] = { |
1065 | + 0, 1, 8, 16, 9, 2, 3, 10, |
1066 | + 17, 24, 32, 25, 18, 11, 4, 5, |
1067 | + 12, 19, 26, 33, 40, 48, 41, 34, |
1068 | + 27, 20, 13, 6, 7, 14, 21, 28, |
1069 | + 35, 42, 49, 56, 57, 50, 43, 36, |
1070 | + 29, 22, 15, 23, 30, 37, 44, 51, |
1071 | + 58, 59, 52, 45, 38, 31, 39, 46, |
1072 | + 53, 60, 61, 54, 47, 55, 62, 63 |
1073 | +}; |
1074 | + |
1075 | +static const uint8_t ff_mpeg1_default_intra_matrix[64] = { |
1076 | + 8, 16, 19, 22, 26, 27, 29, 34, |
1077 | + 16, 16, 22, 24, 27, 29, 34, 37, |
1078 | + 19, 22, 26, 27, 29, 34, 34, 38, |
1079 | + 22, 22, 26, 27, 29, 34, 37, 40, |
1080 | + 22, 26, 27, 29, 32, 35, 40, 48, |
1081 | + 26, 27, 29, 32, 35, 40, 48, 58, |
1082 | + 26, 27, 29, 34, 38, 46, 56, 69, |
1083 | + 27, 29, 35, 38, 46, 56, 69, 83 |
1084 | +}; |
1085 | + |
1086 | +static const uint8_t ff_mpeg1_default_non_intra_matrix[64] = { |
1087 | + 16, 16, 16, 16, 16, 16, 16, 16, |
1088 | + 16, 16, 16, 16, 16, 16, 16, 16, |
1089 | + 16, 16, 16, 16, 16, 16, 16, 16, |
1090 | + 16, 16, 16, 16, 16, 16, 16, 16, |
1091 | + 16, 16, 16, 16, 16, 16, 16, 16, |
1092 | + 16, 16, 16, 16, 16, 16, 16, 16, |
1093 | + 16, 16, 16, 16, 16, 16, 16, 16, |
1094 | + 16, 16, 16, 16, 16, 16, 16, 16 |
1095 | +}; |
1096 | + |
1097 | +static const uint8_t ff_mpeg4_default_intra_matrix[64] = { |
1098 | + 8, 17, 18, 19, 21, 23, 25, 27, |
1099 | + 17, 18, 19, 21, 23, 25, 27, 28, |
1100 | + 20, 21, 22, 23, 24, 26, 28, 30, |
1101 | + 21, 22, 23, 24, 26, 28, 30, 32, |
1102 | + 22, 23, 24, 26, 28, 30, 32, 35, |
1103 | + 23, 24, 26, 28, 30, 32, 35, 38, |
1104 | + 25, 26, 28, 30, 32, 35, 38, 41, |
1105 | + 27, 28, 30, 32, 35, 38, 41, 45, |
1106 | +}; |
1107 | + |
1108 | +static const uint8_t ff_mpeg4_default_non_intra_matrix[64] = { |
1109 | + 16, 17, 18, 19, 20, 21, 22, 23, |
1110 | + 17, 18, 19, 20, 21, 22, 23, 24, |
1111 | + 18, 19, 20, 21, 22, 23, 24, 25, |
1112 | + 19, 20, 21, 22, 23, 24, 26, 27, |
1113 | + 20, 21, 22, 23, 25, 26, 27, 28, |
1114 | + 21, 22, 23, 24, 26, 27, 28, 30, |
1115 | + 22, 23, 24, 26, 27, 28, 30, 31, |
1116 | + 23, 24, 25, 27, 28, 30, 31, 33, |
1117 | +}; |
1118 | + |
1119 | +// Compute integer log2 |
1120 | +static inline int ilog2(uint32_t v) |
1121 | +{ |
1122 | + /* From <http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog> */ |
1123 | + uint32_t r, shift; |
1124 | + r = (v > 0xffff) << 4; v >>= r; |
1125 | + shift = (v > 0xff ) << 3; v >>= shift; r |= shift; |
1126 | + shift = (v > 0xf ) << 2; v >>= shift; r |= shift; |
1127 | + shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; |
1128 | + return r | (v >> 1); |
1129 | +} |
1130 | + |
1131 | +// Translate VASurfaceID |
1132 | +static int |
1133 | +translate_VASurfaceID( |
1134 | + vdpau_driver_data_t *driver_data, |
1135 | + VASurfaceID va_surface, |
1136 | + VdpVideoSurface *vdp_surface |
1137 | +) |
1138 | +{ |
1139 | + object_surface_p obj_surface; |
1140 | + |
1141 | + if (va_surface == VA_INVALID_SURFACE) { |
1142 | + *vdp_surface = VDP_INVALID_HANDLE; |
1143 | + return 1; |
1144 | + } |
1145 | + |
1146 | + obj_surface = VDPAU_SURFACE(va_surface); |
1147 | + if (!obj_surface) |
1148 | + return 0; |
1149 | + |
1150 | + *vdp_surface = obj_surface->vdp_surface; |
1151 | + return 1; |
1152 | +} |
1153 | + |
1154 | +// Translate VAPictureH264 |
1155 | +static int |
1156 | +translate_VAPictureH264( |
1157 | + vdpau_driver_data_t *driver_data, |
1158 | + const VAPictureH264 *va_pic, |
1159 | + VdpReferenceFrameH264 *rf |
1160 | +) |
1161 | +{ |
1162 | + // Handle invalid surfaces specifically |
1163 | + if (va_pic->picture_id == VA_INVALID_SURFACE) { |
1164 | + init_VdpReferenceFrameH264(rf); |
1165 | + return 1; |
1166 | + } |
1167 | + |
1168 | + if (!translate_VASurfaceID(driver_data, va_pic->picture_id, &rf->surface)) |
1169 | + return 0; |
1170 | + rf->is_long_term = (va_pic->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE) != 0; |
1171 | + if ((va_pic->flags & (VA_PICTURE_H264_TOP_FIELD|VA_PICTURE_H264_BOTTOM_FIELD)) == 0) { |
1172 | + rf->top_is_reference = VDP_TRUE; |
1173 | + rf->bottom_is_reference = VDP_TRUE; |
1174 | + } |
1175 | + else { |
1176 | + rf->top_is_reference = (va_pic->flags & VA_PICTURE_H264_TOP_FIELD) != 0; |
1177 | + rf->bottom_is_reference = (va_pic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0; |
1178 | + } |
1179 | + rf->field_order_cnt[0] = va_pic->TopFieldOrderCnt; |
1180 | + rf->field_order_cnt[1] = va_pic->BottomFieldOrderCnt; |
1181 | + rf->frame_idx = va_pic->frame_idx; |
1182 | + return 1; |
1183 | +} |
1184 | + |
1185 | +// Translate no buffer |
1186 | +static int |
1187 | +translate_nothing( |
1188 | + vdpau_driver_data_t *driver_data, |
1189 | + object_context_p obj_context, |
1190 | + object_buffer_p obj_buffer |
1191 | +) |
1192 | +{ |
1193 | + return 1; |
1194 | +} |
1195 | + |
1196 | +// Translate VASliceDataBuffer |
1197 | +static int |
1198 | +translate_VASliceDataBuffer( |
1199 | + vdpau_driver_data_t *driver_data, |
1200 | + object_context_p obj_context, |
1201 | + object_buffer_p obj_buffer |
1202 | +) |
1203 | +{ |
1204 | + if (obj_context->vdp_codec == VDP_CODEC_H264) { |
1205 | + /* Check we have the start code */ |
1206 | + /* XXX: check for other codecs too? */ |
1207 | + /* XXX: this assumes we get SliceParams before SliceData */ |
1208 | + static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; |
1209 | + VASliceParameterBufferH264 * const slice_params = obj_context->last_slice_params; |
1210 | + unsigned int i; |
1211 | + for (i = 0; i < obj_context->last_slice_params_count; i++) { |
1212 | + VASliceParameterBufferH264 * const slice_param = &slice_params[i]; |
1213 | + uint8_t *buf = (uint8_t *)obj_buffer->buffer_data + slice_param->slice_data_offset; |
1214 | + if (memcmp(buf, start_code_prefix, sizeof(start_code_prefix)) != 0) { |
1215 | + if (append_VdpBitstreamBuffer(obj_context, |
1216 | + start_code_prefix, |
1217 | + sizeof(start_code_prefix)) < 0) |
1218 | + return 0; |
1219 | + } |
1220 | + if (append_VdpBitstreamBuffer(obj_context, |
1221 | + buf, |
1222 | + slice_param->slice_data_size) < 0) |
1223 | + return 0; |
1224 | + } |
1225 | + return 1; |
1226 | + } |
1227 | + |
1228 | +#if USE_VDPAU_MPEG4 |
1229 | + if (obj_context->vdp_codec == VDP_CODEC_MPEG4 && |
1230 | + obj_context->vdp_bitstream_buffers_count == 0) { |
1231 | + PutBitContext pb; |
1232 | + uint8_t slice_header_buffer[32]; |
1233 | + uint8_t *slice_header; |
1234 | + int slice_header_size; |
1235 | + const uint8_t *slice_data = obj_buffer->buffer_data; |
1236 | + uint32_t slice_data_size = obj_buffer->buffer_size; |
1237 | + VAPictureParameterBufferMPEG4 * const pic_param = obj_context->last_pic_param; |
1238 | + VASliceParameterBufferMPEG4 * const slice_param = obj_context->last_slice_params; |
1239 | + |
1240 | + int time_incr = 1 + ilog2(pic_param->vop_time_increment_resolution - 1); |
1241 | + if (time_incr < 1) |
1242 | + time_incr = 1; |
1243 | + |
1244 | + static const uint16_t VOP_STARTCODE = 0x01b6; |
1245 | + enum { |
1246 | + VOP_I_TYPE = 0, |
1247 | + VOP_P_TYPE, |
1248 | + VOP_B_TYPE, |
1249 | + VOP_S_TYPE |
1250 | + }; |
1251 | + |
1252 | + /* XXX: this is a hack to compute the length of |
1253 | + modulo_time_base "1" sequence. We probably should be |
1254 | + reconstructing through an extra VOP field in VA-API? */ |
1255 | + int nbits = (32 + /* VOP start code */ |
1256 | + 2 + /* vop_coding_type */ |
1257 | + 1 + /* modulo_time_base "0" */ |
1258 | + 1 + /* marker_bit */ |
1259 | + time_incr + /* vop_time_increment */ |
1260 | + 1 + /* marker_bit */ |
1261 | + 1 + /* vop_coded */ |
1262 | + (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE ? 1 : 0) + |
1263 | + 3 + /* intra_dc_vlc_thr */ |
1264 | + (pic_param->vol_fields.bits.interlaced ? 2 : 0) + |
1265 | + 5 + /* vop_quant */ |
1266 | + (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE ? 3 : 0) + |
1267 | + (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE ? 3 : 0)); |
1268 | + if ((nbits = slice_param->macroblock_offset - (nbits % 8)) < 0) |
1269 | + nbits += 8; |
1270 | + |
1271 | + /* Reconstruct the VOP header */ |
1272 | + init_put_bits(&pb, slice_header_buffer, sizeof(slice_header_buffer)); |
1273 | + put_bits(&pb, 16, 0); /* vop header */ |
1274 | + put_bits(&pb, 16, VOP_STARTCODE); /* vop header */ |
1275 | + put_bits(&pb, 2, pic_param->vop_fields.bits.vop_coding_type); |
1276 | + while (nbits-- > 0) |
1277 | + put_bits(&pb, 1, 1); /* modulo_time_base "1" */ |
1278 | + put_bits(&pb, 1, 0); /* modulo_time_base "0" */ |
1279 | + put_bits(&pb, 1, 1); /* marker */ |
1280 | + put_bits(&pb, time_incr, 0); /* time increment */ |
1281 | + put_bits(&pb, 1, 1); /* marker */ |
1282 | + put_bits(&pb, 1, 1); /* vop coded */ |
1283 | + if (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE) |
1284 | + put_bits(&pb, 1, pic_param->vop_fields.bits.vop_rounding_type); |
1285 | + put_bits(&pb, 3, pic_param->vop_fields.bits.intra_dc_vlc_thr); |
1286 | + if (pic_param->vol_fields.bits.interlaced) { |
1287 | + put_bits(&pb, 1, pic_param->vop_fields.bits.top_field_first); |
1288 | + put_bits(&pb, 1, pic_param->vop_fields.bits.alternate_vertical_scan_flag); |
1289 | + } |
1290 | + put_bits(&pb, 5, slice_param->quant_scale); |
1291 | + if (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE) |
1292 | + put_bits(&pb, 3, pic_param->vop_fcode_forward); |
1293 | + if (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE) |
1294 | + put_bits(&pb, 3, pic_param->vop_fcode_backward); |
1295 | + |
1296 | + /* Merge in bits from the first byte of the slice */ |
1297 | + ASSERT((put_bits_count(&pb) % 8) == slice_param->macroblock_offset); |
1298 | + if ((put_bits_count(&pb) % 8) != slice_param->macroblock_offset) |
1299 | + return 0; |
1300 | + const int r = 8 - (put_bits_count(&pb) % 8); |
1301 | + if (r > 0) |
1302 | + put_bits(&pb, r, slice_data[0] & ((1U << r) - 1)); |
1303 | + flush_put_bits(&pb); |
1304 | + |
1305 | + ASSERT((put_bits_count(&pb) % 8) == 0); |
1306 | + slice_header_size = put_bits_count(&pb) / 8; |
1307 | + ASSERT(slice_header_size <= sizeof(slice_header_buffer)); |
1308 | + slice_header = alloc_gen_slice_data(obj_context, slice_header_size); |
1309 | + if (!slice_header) |
1310 | + return 0; |
1311 | + memcpy(slice_header, slice_header_buffer, slice_header_size); |
1312 | + if (append_VdpBitstreamBuffer(obj_context, slice_header, slice_header_size) < 0) |
1313 | + return 0; |
1314 | + if (append_VdpBitstreamBuffer(obj_context, slice_data + 1, slice_data_size - 1) < 0) |
1315 | + return 0; |
1316 | + return 1; |
1317 | + } |
1318 | +#endif |
1319 | + |
1320 | + if (append_VdpBitstreamBuffer(obj_context, |
1321 | + obj_buffer->buffer_data, |
1322 | + obj_buffer->buffer_size) < 0) |
1323 | + return 0; |
1324 | + return 1; |
1325 | +} |
1326 | + |
1327 | +// Translate VAPictureParameterBufferMPEG2 |
1328 | +static int |
1329 | +translate_VAPictureParameterBufferMPEG2( |
1330 | + vdpau_driver_data_t *driver_data, |
1331 | + object_context_p obj_context, |
1332 | + object_buffer_p obj_buffer |
1333 | +) |
1334 | +{ |
1335 | + VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; |
1336 | + VAPictureParameterBufferMPEG2 * const pic_param = obj_buffer->buffer_data; |
1337 | + |
1338 | + if (!translate_VASurfaceID(driver_data, |
1339 | + pic_param->forward_reference_picture, |
1340 | + &pic_info->forward_reference)) |
1341 | + return 0; |
1342 | + |
1343 | + if (!translate_VASurfaceID(driver_data, |
1344 | + pic_param->backward_reference_picture, |
1345 | + &pic_info->backward_reference)) |
1346 | + return 0; |
1347 | + |
1348 | + pic_info->picture_structure = pic_param->picture_coding_extension.bits.picture_structure; |
1349 | + pic_info->picture_coding_type = pic_param->picture_coding_type; |
1350 | + pic_info->intra_dc_precision = pic_param->picture_coding_extension.bits.intra_dc_precision; |
1351 | + pic_info->frame_pred_frame_dct = pic_param->picture_coding_extension.bits.frame_pred_frame_dct; |
1352 | + pic_info->concealment_motion_vectors = pic_param->picture_coding_extension.bits.concealment_motion_vectors; |
1353 | + pic_info->intra_vlc_format = pic_param->picture_coding_extension.bits.intra_vlc_format; |
1354 | + pic_info->alternate_scan = pic_param->picture_coding_extension.bits.alternate_scan; |
1355 | + pic_info->q_scale_type = pic_param->picture_coding_extension.bits.q_scale_type; |
1356 | + pic_info->top_field_first = pic_param->picture_coding_extension.bits.top_field_first; |
1357 | + pic_info->full_pel_forward_vector = 0; |
1358 | + pic_info->full_pel_backward_vector = 0; |
1359 | + pic_info->f_code[0][0] = (pic_param->f_code >> 12) & 0xf; |
1360 | + pic_info->f_code[0][1] = (pic_param->f_code >> 8) & 0xf; |
1361 | + pic_info->f_code[1][0] = (pic_param->f_code >> 4) & 0xf; |
1362 | + pic_info->f_code[1][1] = pic_param->f_code & 0xf; |
1363 | + return 1; |
1364 | +} |
1365 | + |
1366 | +// Translate VAIQMatrixBufferMPEG2 |
1367 | +static int |
1368 | +translate_VAIQMatrixBufferMPEG2( |
1369 | + vdpau_driver_data_t *driver_data, |
1370 | + object_context_p obj_context, |
1371 | + object_buffer_p obj_buffer |
1372 | +) |
1373 | +{ |
1374 | + VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; |
1375 | + VAIQMatrixBufferMPEG2 * const iq_matrix = obj_buffer->buffer_data; |
1376 | + const uint8_t *intra_matrix; |
1377 | + const uint8_t *intra_matrix_lookup; |
1378 | + const uint8_t *inter_matrix; |
1379 | + const uint8_t *inter_matrix_lookup; |
1380 | + int i; |
1381 | + |
1382 | + if (iq_matrix->load_intra_quantiser_matrix) { |
1383 | + intra_matrix = iq_matrix->intra_quantiser_matrix; |
1384 | + intra_matrix_lookup = ff_zigzag_direct; |
1385 | + } |
1386 | + else { |
1387 | + intra_matrix = ff_mpeg1_default_intra_matrix; |
1388 | + intra_matrix_lookup = ff_identity; |
1389 | + } |
1390 | + |
1391 | + if (iq_matrix->load_non_intra_quantiser_matrix) { |
1392 | + inter_matrix = iq_matrix->non_intra_quantiser_matrix; |
1393 | + inter_matrix_lookup = ff_zigzag_direct; |
1394 | + } |
1395 | + else { |
1396 | + inter_matrix = ff_mpeg1_default_non_intra_matrix; |
1397 | + inter_matrix_lookup = ff_identity; |
1398 | + } |
1399 | + |
1400 | + for (i = 0; i < 64; i++) { |
1401 | + pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] = |
1402 | + intra_matrix[i]; |
1403 | + pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] = |
1404 | + inter_matrix[i]; |
1405 | + } |
1406 | + return 1; |
1407 | +} |
1408 | + |
1409 | +// Translate VASliceParameterBufferMPEG2 |
1410 | +static int |
1411 | +translate_VASliceParameterBufferMPEG2( |
1412 | + vdpau_driver_data_t *driver_data, |
1413 | + object_context_p obj_context, |
1414 | + object_buffer_p obj_buffer |
1415 | + ) |
1416 | +{ |
1417 | + VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; |
1418 | + |
1419 | + pic_info->slice_count += obj_buffer->num_elements; |
1420 | + obj_context->last_slice_params = obj_buffer->buffer_data; |
1421 | + obj_context->last_slice_params_count = obj_buffer->num_elements; |
1422 | + return 1; |
1423 | +} |
1424 | + |
1425 | +#if USE_VDPAU_MPEG4 |
1426 | +// Translate VAPictureParameterBufferMPEG4 |
1427 | +static int |
1428 | +translate_VAPictureParameterBufferMPEG4( |
1429 | + vdpau_driver_data_p driver_data, |
1430 | + object_context_p obj_context, |
1431 | + object_buffer_p obj_buffer |
1432 | +) |
1433 | +{ |
1434 | + VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4; |
1435 | + VAPictureParameterBufferMPEG4 * const pic_param = obj_buffer->buffer_data; |
1436 | + |
1437 | + /* XXX: we don't support short-video-header formats */ |
1438 | + if (pic_param->vol_fields.bits.short_video_header) |
1439 | + return 0; |
1440 | + |
1441 | + if (!translate_VASurfaceID(driver_data, |
1442 | + pic_param->forward_reference_picture, |
1443 | + &pic_info->forward_reference)) |
1444 | + return 0; |
1445 | + |
1446 | + if (!translate_VASurfaceID(driver_data, |
1447 | + pic_param->backward_reference_picture, |
1448 | + &pic_info->backward_reference)) |
1449 | + return 0; |
1450 | + |
1451 | + if (pic_param->vol_fields.bits.interlaced) { |
1452 | + vdpau_information_message("unsupported MPEG-4 video with interlaced " |
1453 | + "content, please report this video\n"); |
1454 | + pic_info->trd[0] = 2*pic_param->TRD; /* XXX: + d(0) */ |
1455 | + pic_info->trb[0] = 2*pic_param->TRB; /* XXX: + d(0) */ |
1456 | + pic_info->trd[1] = 2*pic_param->TRD; /* XXX: + d(1) */ |
1457 | + pic_info->trb[1] = 2*pic_param->TRB; /* XXX: + d(1) */ |
1458 | + } |
1459 | + else { |
1460 | + pic_info->trd[0] = pic_param->TRD; |
1461 | + pic_info->trb[0] = pic_param->TRB; |
1462 | + pic_info->trd[1] = 0; |
1463 | + pic_info->trb[1] = 0; |
1464 | + } |
1465 | + |
1466 | + pic_info->vop_time_increment_resolution = pic_param->vop_time_increment_resolution; |
1467 | + pic_info->vop_coding_type = pic_param->vop_fields.bits.vop_coding_type; |
1468 | + pic_info->vop_fcode_forward = pic_param->vop_fcode_forward; |
1469 | + pic_info->vop_fcode_backward = pic_param->vop_fcode_backward; |
1470 | + pic_info->resync_marker_disable = pic_param->vol_fields.bits.resync_marker_disable; |
1471 | + pic_info->interlaced = pic_param->vol_fields.bits.interlaced; |
1472 | + pic_info->quant_type = pic_param->vol_fields.bits.quant_type; |
1473 | + pic_info->quarter_sample = pic_param->vol_fields.bits.quarter_sample; |
1474 | + pic_info->short_video_header = pic_param->vol_fields.bits.short_video_header; |
1475 | + pic_info->rounding_control = pic_param->vop_fields.bits.vop_rounding_type; |
1476 | + pic_info->alternate_vertical_scan_flag = pic_param->vop_fields.bits.alternate_vertical_scan_flag; |
1477 | + pic_info->top_field_first = pic_param->vop_fields.bits.top_field_first; |
1478 | + |
1479 | + obj_context->last_pic_param = obj_buffer->buffer_data; |
1480 | + return 1; |
1481 | +} |
1482 | + |
1483 | +// Translate VAIQMatrixBufferMPEG4 |
1484 | +static int |
1485 | +translate_VAIQMatrixBufferMPEG4( |
1486 | + vdpau_driver_data_p driver_data, |
1487 | + object_context_p obj_context, |
1488 | + object_buffer_p obj_buffer |
1489 | +) |
1490 | +{ |
1491 | + VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4; |
1492 | + VAIQMatrixBufferMPEG4 * const iq_matrix = obj_buffer->buffer_data; |
1493 | + const uint8_t *intra_matrix; |
1494 | + const uint8_t *intra_matrix_lookup; |
1495 | + const uint8_t *inter_matrix; |
1496 | + const uint8_t *inter_matrix_lookup; |
1497 | + int i; |
1498 | + |
1499 | + if (iq_matrix->load_intra_quant_mat) { |
1500 | + intra_matrix = iq_matrix->intra_quant_mat; |
1501 | + intra_matrix_lookup = ff_zigzag_direct; |
1502 | + } |
1503 | + else { |
1504 | + intra_matrix = ff_mpeg4_default_intra_matrix; |
1505 | + intra_matrix_lookup = ff_identity; |
1506 | + } |
1507 | + |
1508 | + if (iq_matrix->load_non_intra_quant_mat) { |
1509 | + inter_matrix = iq_matrix->non_intra_quant_mat; |
1510 | + inter_matrix_lookup = ff_zigzag_direct; |
1511 | + } |
1512 | + else { |
1513 | + inter_matrix = ff_mpeg4_default_non_intra_matrix; |
1514 | + inter_matrix_lookup = ff_identity; |
1515 | + } |
1516 | + |
1517 | + for (i = 0; i < 64; i++) { |
1518 | + pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] = |
1519 | + intra_matrix[i]; |
1520 | + pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] = |
1521 | + inter_matrix[i]; |
1522 | + } |
1523 | + return 1; |
1524 | +} |
1525 | + |
1526 | +// Translate VASliceParameterBufferMPEG4 |
1527 | +static int |
1528 | +translate_VASliceParameterBufferMPEG4( |
1529 | + vdpau_driver_data_p driver_data, |
1530 | + object_context_p obj_context, |
1531 | + object_buffer_p obj_buffer |
1532 | + ) |
1533 | +{ |
1534 | + obj_context->last_slice_params = obj_buffer->buffer_data; |
1535 | + obj_context->last_slice_params_count = obj_buffer->num_elements; |
1536 | + return 1; |
1537 | +} |
1538 | +#endif |
1539 | + |
1540 | +// Translate VAPictureParameterBufferH264 |
1541 | +static int |
1542 | +translate_VAPictureParameterBufferH264( |
1543 | + vdpau_driver_data_t *driver_data, |
1544 | + object_context_p obj_context, |
1545 | + object_buffer_p obj_buffer |
1546 | +) |
1547 | +{ |
1548 | + VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; |
1549 | + VAPictureParameterBufferH264 * const pic_param = obj_buffer->buffer_data; |
1550 | + VAPictureH264 * const CurrPic = &pic_param->CurrPic; |
1551 | + unsigned int i; |
1552 | + |
1553 | + pic_info->field_order_cnt[0] = CurrPic->TopFieldOrderCnt; |
1554 | + pic_info->field_order_cnt[1] = CurrPic->BottomFieldOrderCnt; |
1555 | + pic_info->is_reference = pic_param->pic_fields.bits.reference_pic_flag; |
1556 | + |
1557 | + pic_info->frame_num = pic_param->frame_num; |
1558 | + pic_info->field_pic_flag = pic_param->pic_fields.bits.field_pic_flag; |
1559 | + pic_info->bottom_field_flag = pic_param->pic_fields.bits.field_pic_flag && (CurrPic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0; |
1560 | + pic_info->num_ref_frames = pic_param->num_ref_frames; |
1561 | + pic_info->mb_adaptive_frame_field_flag = pic_param->seq_fields.bits.mb_adaptive_frame_field_flag && !pic_info->field_pic_flag; |
1562 | + pic_info->constrained_intra_pred_flag = pic_param->pic_fields.bits.constrained_intra_pred_flag; |
1563 | + pic_info->weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag; |
1564 | + pic_info->weighted_bipred_idc = pic_param->pic_fields.bits.weighted_bipred_idc; |
1565 | + pic_info->frame_mbs_only_flag = pic_param->seq_fields.bits.frame_mbs_only_flag; |
1566 | + pic_info->transform_8x8_mode_flag = pic_param->pic_fields.bits.transform_8x8_mode_flag; |
1567 | + pic_info->chroma_qp_index_offset = pic_param->chroma_qp_index_offset; |
1568 | + pic_info->second_chroma_qp_index_offset = pic_param->second_chroma_qp_index_offset; |
1569 | + pic_info->pic_init_qp_minus26 = pic_param->pic_init_qp_minus26; |
1570 | + pic_info->log2_max_frame_num_minus4 = pic_param->seq_fields.bits.log2_max_frame_num_minus4; |
1571 | + pic_info->pic_order_cnt_type = pic_param->seq_fields.bits.pic_order_cnt_type; |
1572 | + pic_info->log2_max_pic_order_cnt_lsb_minus4 = pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4; |
1573 | + pic_info->delta_pic_order_always_zero_flag = pic_param->seq_fields.bits.delta_pic_order_always_zero_flag; |
1574 | + pic_info->direct_8x8_inference_flag = pic_param->seq_fields.bits.direct_8x8_inference_flag; |
1575 | + pic_info->entropy_coding_mode_flag = pic_param->pic_fields.bits.entropy_coding_mode_flag; |
1576 | + pic_info->pic_order_present_flag = pic_param->pic_fields.bits.pic_order_present_flag; |
1577 | + pic_info->deblocking_filter_control_present_flag = pic_param->pic_fields.bits.deblocking_filter_control_present_flag; |
1578 | + pic_info->redundant_pic_cnt_present_flag = pic_param->pic_fields.bits.redundant_pic_cnt_present_flag; |
1579 | + |
1580 | + for (i = 0; i < 16; i++) { |
1581 | + if (!translate_VAPictureH264(driver_data, |
1582 | + &pic_param->ReferenceFrames[i], |
1583 | + &pic_info->referenceFrames[i])) |
1584 | + return 0; |
1585 | + } |
1586 | + return 1; |
1587 | +} |
1588 | + |
1589 | +// Translate VAIQMatrixBufferH264 |
1590 | +static int |
1591 | +translate_VAIQMatrixBufferH264( |
1592 | + vdpau_driver_data_t *driver_data, |
1593 | + object_context_p obj_context, |
1594 | + object_buffer_p obj_buffer |
1595 | +) |
1596 | +{ |
1597 | + VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; |
1598 | + VAIQMatrixBufferH264 * const iq_matrix = obj_buffer->buffer_data; |
1599 | + int i, j; |
1600 | + |
1601 | + if (sizeof(pic_info->scaling_lists_4x4) == sizeof(iq_matrix->ScalingList4x4)) |
1602 | + memcpy(pic_info->scaling_lists_4x4, iq_matrix->ScalingList4x4, |
1603 | + sizeof(pic_info->scaling_lists_4x4)); |
1604 | + else { |
1605 | + for (j = 0; j < 6; j++) { |
1606 | + for (i = 0; i < 16; i++) |
1607 | + pic_info->scaling_lists_4x4[j][i] = iq_matrix->ScalingList4x4[j][i]; |
1608 | + } |
1609 | + } |
1610 | + |
1611 | + if (sizeof(pic_info->scaling_lists_8x8) == sizeof(iq_matrix->ScalingList8x8)) |
1612 | + memcpy(pic_info->scaling_lists_8x8, iq_matrix->ScalingList8x8, |
1613 | + sizeof(pic_info->scaling_lists_8x8)); |
1614 | + else { |
1615 | + for (j = 0; j < 2; j++) { |
1616 | + for (i = 0; i < 64; i++) |
1617 | + pic_info->scaling_lists_8x8[j][i] = iq_matrix->ScalingList8x8[j][i]; |
1618 | + } |
1619 | + } |
1620 | + return 1; |
1621 | +} |
1622 | + |
1623 | +// Translate VASliceParameterBufferH264 |
1624 | +static int |
1625 | +translate_VASliceParameterBufferH264( |
1626 | + vdpau_driver_data_t *driver_data, |
1627 | + object_context_p obj_context, |
1628 | + object_buffer_p obj_buffer |
1629 | +) |
1630 | +{ |
1631 | + VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; |
1632 | + VASliceParameterBufferH264 * const slice_params = obj_buffer->buffer_data; |
1633 | + VASliceParameterBufferH264 * const slice_param = &slice_params[obj_buffer->num_elements - 1]; |
1634 | + |
1635 | + pic_info->slice_count += obj_buffer->num_elements; |
1636 | + pic_info->num_ref_idx_l0_active_minus1 = slice_param->num_ref_idx_l0_active_minus1; |
1637 | + pic_info->num_ref_idx_l1_active_minus1 = slice_param->num_ref_idx_l1_active_minus1; |
1638 | + obj_context->last_slice_params = obj_buffer->buffer_data; |
1639 | + obj_context->last_slice_params_count = obj_buffer->num_elements; |
1640 | + return 1; |
1641 | +} |
1642 | + |
1643 | +// Translate VAPictureParameterBufferVC1 |
1644 | +static int |
1645 | +translate_VAPictureParameterBufferVC1( |
1646 | + vdpau_driver_data_t *driver_data, |
1647 | + object_context_p obj_context, |
1648 | + object_buffer_p obj_buffer |
1649 | +) |
1650 | +{ |
1651 | + VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1; |
1652 | + VAPictureParameterBufferVC1 * const pic_param = obj_buffer->buffer_data; |
1653 | + int picture_type, major_version, minor_version; |
1654 | + |
1655 | + if (!translate_VASurfaceID(driver_data, |
1656 | + pic_param->forward_reference_picture, |
1657 | + &pic_info->forward_reference)) |
1658 | + return 0; |
1659 | + |
1660 | + if (!translate_VASurfaceID(driver_data, |
1661 | + pic_param->backward_reference_picture, |
1662 | + &pic_info->backward_reference)) |
1663 | + return 0; |
1664 | + |
1665 | + switch (pic_param->picture_fields.bits.picture_type) { |
1666 | + case 0: picture_type = 0; break; /* I */ |
1667 | + case 1: picture_type = 1; break; /* P */ |
1668 | + case 2: picture_type = 3; break; /* B */ |
1669 | + case 3: picture_type = 4; break; /* BI */ |
1670 | + case 4: picture_type = 1; break; /* P "skipped" */ |
1671 | + default: return 0; |
1672 | + } |
1673 | + |
1674 | + pic_info->picture_type = picture_type; |
1675 | + pic_info->frame_coding_mode = pic_param->picture_fields.bits.frame_coding_mode; |
1676 | + pic_info->postprocflag = pic_param->post_processing != 0; |
1677 | + pic_info->pulldown = pic_param->sequence_fields.bits.pulldown; |
1678 | + pic_info->interlace = pic_param->sequence_fields.bits.interlace; |
1679 | + pic_info->tfcntrflag = pic_param->sequence_fields.bits.tfcntrflag; |
1680 | + pic_info->finterpflag = pic_param->sequence_fields.bits.finterpflag; |
1681 | + pic_info->psf = pic_param->sequence_fields.bits.psf; |
1682 | + pic_info->dquant = pic_param->pic_quantizer_fields.bits.dquant; |
1683 | + pic_info->panscan_flag = pic_param->entrypoint_fields.bits.panscan_flag; |
1684 | + pic_info->refdist_flag = pic_param->reference_fields.bits.reference_distance_flag; |
1685 | + pic_info->quantizer = pic_param->pic_quantizer_fields.bits.quantizer; |
1686 | + pic_info->extended_mv = pic_param->mv_fields.bits.extended_mv_flag; |
1687 | + pic_info->extended_dmv = pic_param->mv_fields.bits.extended_dmv_flag; |
1688 | + pic_info->overlap = pic_param->sequence_fields.bits.overlap; |
1689 | + pic_info->vstransform = pic_param->transform_fields.bits.variable_sized_transform_flag; |
1690 | + pic_info->loopfilter = pic_param->entrypoint_fields.bits.loopfilter; |
1691 | + pic_info->fastuvmc = pic_param->fast_uvmc_flag; |
1692 | + pic_info->range_mapy_flag = pic_param->range_mapping_fields.bits.luma_flag; |
1693 | + pic_info->range_mapy = pic_param->range_mapping_fields.bits.luma; |
1694 | + pic_info->range_mapuv_flag = pic_param->range_mapping_fields.bits.chroma_flag; |
1695 | + pic_info->range_mapuv = pic_param->range_mapping_fields.bits.chroma; |
1696 | + pic_info->multires = pic_param->sequence_fields.bits.multires; |
1697 | + pic_info->syncmarker = pic_param->sequence_fields.bits.syncmarker; |
1698 | + pic_info->rangered = pic_param->sequence_fields.bits.rangered; |
1699 | + if (!vdpau_is_nvidia(driver_data, &major_version, &minor_version) || |
1700 | + (major_version > 180 || minor_version >= 35)) |
1701 | + pic_info->rangered |= pic_param->range_reduction_frame << 1; |
1702 | + pic_info->maxbframes = pic_param->sequence_fields.bits.max_b_frames; |
1703 | + pic_info->deblockEnable = pic_param->post_processing != 0; /* XXX: this is NVIDIA's vdpau.c semantics (postprocflag & 1) */ |
1704 | + pic_info->pquant = pic_param->pic_quantizer_fields.bits.pic_quantizer_scale; |
1705 | + return 1; |
1706 | +} |
1707 | + |
1708 | +// Translate VASliceParameterBufferVC1 |
1709 | +static int |
1710 | +translate_VASliceParameterBufferVC1( |
1711 | + vdpau_driver_data_t *driver_data, |
1712 | + object_context_p obj_context, |
1713 | + object_buffer_p obj_buffer |
1714 | +) |
1715 | +{ |
1716 | + VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1; |
1717 | + |
1718 | + pic_info->slice_count += obj_buffer->num_elements; |
1719 | + obj_context->last_slice_params = obj_buffer->buffer_data; |
1720 | + obj_context->last_slice_params_count = obj_buffer->num_elements; |
1721 | + return 1; |
1722 | +} |
1723 | + |
1724 | +// Translate VA buffer |
1725 | +typedef int |
1726 | +(*translate_buffer_func_t)(vdpau_driver_data_t *driver_data, |
1727 | + object_context_p obj_context, |
1728 | + object_buffer_p obj_buffer); |
1729 | + |
1730 | +typedef struct translate_buffer_info translate_buffer_info_t; |
1731 | +struct translate_buffer_info { |
1732 | + VdpCodec codec; |
1733 | + VABufferType type; |
1734 | + translate_buffer_func_t func; |
1735 | +}; |
1736 | + |
1737 | +static int |
1738 | +translate_buffer( |
1739 | + vdpau_driver_data_t *driver_data, |
1740 | + object_context_p obj_context, |
1741 | + object_buffer_p obj_buffer |
1742 | +) |
1743 | +{ |
1744 | + static const translate_buffer_info_t translate_info[] = { |
1745 | +#define _(CODEC, TYPE) \ |
1746 | + { VDP_CODEC_##CODEC, VA##TYPE##BufferType, \ |
1747 | + translate_VA##TYPE##Buffer##CODEC } |
1748 | + _(MPEG2, PictureParameter), |
1749 | + _(MPEG2, IQMatrix), |
1750 | + _(MPEG2, SliceParameter), |
1751 | +#if USE_VDPAU_MPEG4 |
1752 | + _(MPEG4, PictureParameter), |
1753 | + _(MPEG4, IQMatrix), |
1754 | + _(MPEG4, SliceParameter), |
1755 | +#endif |
1756 | + _(H264, PictureParameter), |
1757 | + _(H264, IQMatrix), |
1758 | + _(H264, SliceParameter), |
1759 | + _(VC1, PictureParameter), |
1760 | + _(VC1, SliceParameter), |
1761 | +#undef _ |
1762 | + { VDP_CODEC_VC1, VABitPlaneBufferType, translate_nothing }, |
1763 | + { 0, VASliceDataBufferType, translate_VASliceDataBuffer }, |
1764 | + { 0, 0, NULL } |
1765 | + }; |
1766 | + const translate_buffer_info_t *tbip; |
1767 | + for (tbip = translate_info; tbip->func != NULL; tbip++) { |
1768 | + if (tbip->codec && tbip->codec != obj_context->vdp_codec) |
1769 | + continue; |
1770 | + if (tbip->type != obj_buffer->type) |
1771 | + continue; |
1772 | + return tbip->func(driver_data, obj_context, obj_buffer); |
1773 | + } |
1774 | + D(bug("ERROR: no translate function found for %s%s\n", |
1775 | + string_of_VABufferType(obj_buffer->type), |
1776 | + obj_context->vdp_codec ? string_of_VdpCodec(obj_context->vdp_codec) : NULL)); |
1777 | + return 0; |
1778 | +} |
1779 | + |
1780 | +// vaQueryConfigProfiles |
1781 | +VAStatus |
1782 | +vdpau_QueryConfigProfiles( |
1783 | + VADriverContextP ctx, |
1784 | + VAProfile *profile_list, |
1785 | + int *num_profiles |
1786 | +) |
1787 | +{ |
1788 | + VDPAU_DRIVER_DATA_INIT; |
1789 | + |
1790 | + static const VAProfile va_profiles[] = { |
1791 | + VAProfileMPEG2Simple, |
1792 | + VAProfileMPEG2Main, |
1793 | + VAProfileMPEG4Simple, |
1794 | + VAProfileMPEG4AdvancedSimple, |
1795 | + VAProfileMPEG4Main, |
1796 | + VAProfileH264Baseline, |
1797 | + VAProfileH264Main, |
1798 | + VAProfileH264High, |
1799 | + VAProfileVC1Simple, |
1800 | + VAProfileVC1Main, |
1801 | + VAProfileVC1Advanced |
1802 | + }; |
1803 | + |
1804 | + int i, n = 0; |
1805 | + for (i = 0; i < ARRAY_ELEMS(va_profiles); i++) { |
1806 | + VAProfile profile = va_profiles[i]; |
1807 | + VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile); |
1808 | + if (is_supported_profile(driver_data, vdp_profile)) |
1809 | + profile_list[n++] = profile; |
1810 | + } |
1811 | + |
1812 | + /* If the assert fails then VDPAU_MAX_PROFILES needs to be bigger */ |
1813 | + ASSERT(n <= VDPAU_MAX_PROFILES); |
1814 | + if (num_profiles) |
1815 | + *num_profiles = n; |
1816 | + |
1817 | + return VA_STATUS_SUCCESS; |
1818 | +} |
1819 | + |
1820 | +// vaQueryConfigEntrypoints |
1821 | +VAStatus |
1822 | +vdpau_QueryConfigEntrypoints( |
1823 | + VADriverContextP ctx, |
1824 | + VAProfile profile, |
1825 | + VAEntrypoint *entrypoint_list, |
1826 | + int *num_entrypoints |
1827 | +) |
1828 | +{ |
1829 | + VDPAU_DRIVER_DATA_INIT; |
1830 | + |
1831 | + VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile); |
1832 | + if (!is_supported_profile(driver_data, vdp_profile)) |
1833 | + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; |
1834 | + |
1835 | + VAEntrypoint entrypoint; |
1836 | + switch (profile) { |
1837 | + case VAProfileMPEG2Simple: |
1838 | + case VAProfileMPEG2Main: |
1839 | + entrypoint = VAEntrypointVLD; |
1840 | + break; |
1841 | + case VAProfileMPEG4Simple: |
1842 | + case VAProfileMPEG4AdvancedSimple: |
1843 | + case VAProfileMPEG4Main: |
1844 | + entrypoint = VAEntrypointVLD; |
1845 | + break; |
1846 | + case VAProfileH264Baseline: |
1847 | + case VAProfileH264Main: |
1848 | + case VAProfileH264High: |
1849 | + entrypoint = VAEntrypointVLD; |
1850 | + break; |
1851 | + case VAProfileVC1Simple: |
1852 | + case VAProfileVC1Main: |
1853 | + case VAProfileVC1Advanced: |
1854 | + entrypoint = VAEntrypointVLD; |
1855 | + break; |
1856 | + default: |
1857 | + entrypoint = 0; |
1858 | + break; |
1859 | + } |
1860 | + |
1861 | + if (entrypoint_list) |
1862 | + *entrypoint_list = entrypoint; |
1863 | + |
1864 | + if (num_entrypoints) |
1865 | + *num_entrypoints = entrypoint != 0; |
1866 | + |
1867 | + return VA_STATUS_SUCCESS; |
1868 | +} |
1869 | + |
1870 | +// vaBeginPicture |
1871 | +VAStatus |
1872 | +vdpau_BeginPicture( |
1873 | + VADriverContextP ctx, |
1874 | + VAContextID context, |
1875 | + VASurfaceID render_target |
1876 | +) |
1877 | +{ |
1878 | + VDPAU_DRIVER_DATA_INIT; |
1879 | + |
1880 | + object_context_p obj_context = VDPAU_CONTEXT(context); |
1881 | + if (!obj_context) |
1882 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
1883 | + |
1884 | + object_surface_p obj_surface = VDPAU_SURFACE(render_target); |
1885 | + if (!obj_surface) |
1886 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
1887 | + |
1888 | + obj_surface->va_surface_status = VASurfaceRendering; |
1889 | + obj_context->last_pic_param = NULL; |
1890 | + obj_context->last_slice_params = NULL; |
1891 | + obj_context->last_slice_params_count = 0; |
1892 | + obj_context->current_render_target = obj_surface->base.id; |
1893 | + obj_context->gen_slice_data_size = 0; |
1894 | + obj_context->vdp_bitstream_buffers_count = 0; |
1895 | + |
1896 | + switch (obj_context->vdp_codec) { |
1897 | + case VDP_CODEC_MPEG1: |
1898 | + case VDP_CODEC_MPEG2: |
1899 | + obj_context->vdp_picture_info.mpeg2.slice_count = 0; |
1900 | + break; |
1901 | + case VDP_CODEC_MPEG4: |
1902 | + break; |
1903 | + case VDP_CODEC_H264: |
1904 | + obj_context->vdp_picture_info.h264.slice_count = 0; |
1905 | + break; |
1906 | + case VDP_CODEC_VC1: |
1907 | + obj_context->vdp_picture_info.vc1.slice_count = 0; |
1908 | + break; |
1909 | + default: |
1910 | + return VA_STATUS_ERROR_UNKNOWN; |
1911 | + } |
1912 | + return VA_STATUS_SUCCESS; |
1913 | +} |
1914 | + |
1915 | +// vaRenderPicture |
1916 | +VAStatus |
1917 | +vdpau_RenderPicture( |
1918 | + VADriverContextP ctx, |
1919 | + VAContextID context, |
1920 | + VABufferID *buffers, |
1921 | + int num_buffers |
1922 | +) |
1923 | +{ |
1924 | + VDPAU_DRIVER_DATA_INIT; |
1925 | + int i; |
1926 | + |
1927 | + object_context_p obj_context = VDPAU_CONTEXT(context); |
1928 | + if (!obj_context) |
1929 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
1930 | + |
1931 | + object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target); |
1932 | + if (!obj_surface) |
1933 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
1934 | + |
1935 | + /* Verify that we got valid buffer references */ |
1936 | + for (i = 0; i < num_buffers; i++) { |
1937 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]); |
1938 | + if (!obj_buffer) |
1939 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
1940 | + } |
1941 | + |
1942 | + /* Translate buffers */ |
1943 | + for (i = 0; i < num_buffers; i++) { |
1944 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]); |
1945 | + if (!translate_buffer(driver_data, obj_context, obj_buffer)) |
1946 | + return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; |
1947 | + /* Release any buffer that is not VASliceDataBuffer */ |
1948 | + /* VASliceParameterBuffer is also needed to check for start_codes */ |
1949 | + switch (obj_buffer->type) { |
1950 | + case VASliceParameterBufferType: |
1951 | + case VASliceDataBufferType: |
1952 | + schedule_destroy_va_buffer(driver_data, obj_buffer); |
1953 | + break; |
1954 | + case VAPictureParameterBufferType: |
1955 | + /* Preserve VAPictureParameterBufferMPEG4 */ |
1956 | + if (obj_context->vdp_codec == VDP_CODEC_MPEG4) { |
1957 | + schedule_destroy_va_buffer(driver_data, obj_buffer); |
1958 | + break; |
1959 | + } |
1960 | + /* fall-through */ |
1961 | + default: |
1962 | + destroy_va_buffer(driver_data, obj_buffer); |
1963 | + break; |
1964 | + } |
1965 | + } |
1966 | + |
1967 | + return VA_STATUS_SUCCESS; |
1968 | +} |
1969 | + |
1970 | +// vaEndPicture |
1971 | +VAStatus |
1972 | +vdpau_EndPicture( |
1973 | + VADriverContextP ctx, |
1974 | + VAContextID context |
1975 | +) |
1976 | +{ |
1977 | + VDPAU_DRIVER_DATA_INIT; |
1978 | + unsigned int i; |
1979 | + |
1980 | + object_context_p obj_context = VDPAU_CONTEXT(context); |
1981 | + if (!obj_context) |
1982 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
1983 | + |
1984 | + object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target); |
1985 | + if (!obj_surface) |
1986 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
1987 | + |
1988 | + if (trace_enabled()) { |
1989 | + switch (obj_context->vdp_codec) { |
1990 | + case VDP_CODEC_MPEG1: |
1991 | + case VDP_CODEC_MPEG2: |
1992 | + dump_VdpPictureInfoMPEG1Or2(&obj_context->vdp_picture_info.mpeg2); |
1993 | + break; |
1994 | +#if HAVE_VDPAU_MPEG4 |
1995 | + case VDP_CODEC_MPEG4: |
1996 | + dump_VdpPictureInfoMPEG4Part2(&obj_context->vdp_picture_info.mpeg4); |
1997 | + break; |
1998 | +#endif |
1999 | + case VDP_CODEC_H264: |
2000 | + dump_VdpPictureInfoH264(&obj_context->vdp_picture_info.h264); |
2001 | + break; |
2002 | + case VDP_CODEC_VC1: |
2003 | + dump_VdpPictureInfoVC1(&obj_context->vdp_picture_info.vc1); |
2004 | + break; |
2005 | + default: |
2006 | + break; |
2007 | + } |
2008 | + for (i = 0; i < obj_context->vdp_bitstream_buffers_count; i++) |
2009 | + dump_VdpBitstreamBuffer(&obj_context->vdp_bitstream_buffers[i]); |
2010 | + } |
2011 | + |
2012 | + VAStatus va_status; |
2013 | + VdpStatus vdp_status; |
2014 | + vdp_status = ensure_decoder_with_max_refs( |
2015 | + driver_data, |
2016 | + obj_context, |
2017 | + get_num_ref_frames(obj_context) |
2018 | + ); |
2019 | + if (vdp_status == VDP_STATUS_OK) |
2020 | + vdp_status = vdpau_decoder_render( |
2021 | + driver_data, |
2022 | + obj_context->vdp_decoder, |
2023 | + obj_surface->vdp_surface, |
2024 | + (VdpPictureInfo)&obj_context->vdp_picture_info, |
2025 | + obj_context->vdp_bitstream_buffers_count, |
2026 | + obj_context->vdp_bitstream_buffers |
2027 | + ); |
2028 | + va_status = vdpau_get_VAStatus(vdp_status); |
2029 | + |
2030 | + /* XXX: assume we are done with rendering right away */ |
2031 | + obj_context->current_render_target = VA_INVALID_SURFACE; |
2032 | + |
2033 | + /* Release pending buffers */ |
2034 | + if (obj_context->dead_buffers_count > 0) { |
2035 | + ASSERT(obj_context->dead_buffers); |
2036 | + int i; |
2037 | + for (i = 0; i < obj_context->dead_buffers_count; i++) { |
2038 | + object_buffer_p obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]); |
2039 | + ASSERT(obj_buffer); |
2040 | + destroy_va_buffer(driver_data, obj_buffer); |
2041 | + } |
2042 | + obj_context->dead_buffers_count = 0; |
2043 | + } |
2044 | + |
2045 | + return va_status; |
2046 | +} |
2047 | |
2048 | === added file '.pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_video.c' |
2049 | --- .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 |
2050 | +++ .pc/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch/src/vdpau_video.c 2014-05-06 21:30:45 +0000 |
2051 | @@ -0,0 +1,995 @@ |
2052 | +/* |
2053 | + * vdpau_video.c - VDPAU backend for VA-API |
2054 | + * |
2055 | + * vdpau-video (C) 2009-2011 Splitted-Desktop Systems |
2056 | + * |
2057 | + * This program is free software; you can redistribute it and/or modify |
2058 | + * it under the terms of the GNU General Public License as published by |
2059 | + * the Free Software Foundation; either version 2 of the License, or |
2060 | + * (at your option) any later version. |
2061 | + * |
2062 | + * This program is distributed in the hope that it will be useful, |
2063 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2064 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2065 | + * GNU General Public License for more details. |
2066 | + * |
2067 | + * You should have received a copy of the GNU General Public License |
2068 | + * along with this program; if not, write to the Free Software |
2069 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
2070 | + */ |
2071 | + |
2072 | +#include "sysdeps.h" |
2073 | +#include "vdpau_video.h" |
2074 | +#include "vdpau_video_x11.h" |
2075 | +#include "vdpau_decode.h" |
2076 | +#include "vdpau_subpic.h" |
2077 | +#include "vdpau_mixer.h" |
2078 | +#include "utils.h" |
2079 | + |
2080 | +#define DEBUG 1 |
2081 | +#include "debug.h" |
2082 | + |
2083 | + |
2084 | +/* Define wait delay (in microseconds) for vaSyncSurface() implementation |
2085 | + with polling. */ |
2086 | +#define VDPAU_SYNC_DELAY 5000 |
2087 | + |
2088 | +// Translates VA-API chroma format to VdpChromaType |
2089 | +static VdpChromaType get_VdpChromaType(int format) |
2090 | +{ |
2091 | + switch (format) { |
2092 | + case VA_RT_FORMAT_YUV420: return VDP_CHROMA_TYPE_420; |
2093 | + case VA_RT_FORMAT_YUV422: return VDP_CHROMA_TYPE_422; |
2094 | + case VA_RT_FORMAT_YUV444: return VDP_CHROMA_TYPE_444; |
2095 | + } |
2096 | + return (VdpChromaType)-1; |
2097 | +} |
2098 | + |
2099 | + |
2100 | +/* ====================================================================== */ |
2101 | +/* === VA-API Implementation with VDPAU === */ |
2102 | +/* ====================================================================== */ |
2103 | + |
2104 | +// Returns the maximum dimensions supported by the VDPAU implementation for that profile |
2105 | +static inline VdpBool |
2106 | +get_max_surface_size( |
2107 | + vdpau_driver_data_t *driver_data, |
2108 | + VdpDecoderProfile profile, |
2109 | + uint32_t *pmax_width, |
2110 | + uint32_t *pmax_height |
2111 | +) |
2112 | +{ |
2113 | + VdpBool is_supported = VDP_FALSE; |
2114 | + VdpStatus vdp_status; |
2115 | + uint32_t max_level, max_references, max_width, max_height; |
2116 | + |
2117 | + if (pmax_width) |
2118 | + *pmax_width = 0; |
2119 | + if (pmax_height) |
2120 | + *pmax_height = 0; |
2121 | + |
2122 | + vdp_status = vdpau_decoder_query_capabilities( |
2123 | + driver_data, |
2124 | + driver_data->vdp_device, |
2125 | + profile, |
2126 | + &is_supported, |
2127 | + &max_level, |
2128 | + &max_references, |
2129 | + &max_width, |
2130 | + &max_height |
2131 | + ); |
2132 | + if (!VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderQueryCapabilities()")) |
2133 | + return VDP_FALSE; |
2134 | + |
2135 | + if (!is_supported) |
2136 | + return VDP_FALSE; |
2137 | + |
2138 | + if (pmax_width) |
2139 | + *pmax_width = max_width; |
2140 | + if (max_height) |
2141 | + *pmax_height = max_height; |
2142 | + |
2143 | + return VDP_TRUE; |
2144 | +} |
2145 | + |
2146 | +// vaGetConfigAttributes |
2147 | +VAStatus |
2148 | +vdpau_GetConfigAttributes( |
2149 | + VADriverContextP ctx, |
2150 | + VAProfile profile, |
2151 | + VAEntrypoint entrypoint, |
2152 | + VAConfigAttrib *attrib_list, |
2153 | + int num_attribs |
2154 | +) |
2155 | +{ |
2156 | + VDPAU_DRIVER_DATA_INIT; |
2157 | + |
2158 | + VAStatus va_status = check_decoder(driver_data, profile, entrypoint); |
2159 | + if (va_status != VA_STATUS_SUCCESS) |
2160 | + return va_status; |
2161 | + |
2162 | + int i; |
2163 | + for (i = 0; i < num_attribs; i++) { |
2164 | + switch (attrib_list[i].type) { |
2165 | + case VAConfigAttribRTFormat: |
2166 | + attrib_list[i].value = VA_RT_FORMAT_YUV420; |
2167 | + break; |
2168 | + default: |
2169 | + attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED; |
2170 | + break; |
2171 | + } |
2172 | + } |
2173 | + return VA_STATUS_SUCCESS; |
2174 | +} |
2175 | + |
2176 | +static VAStatus |
2177 | +vdpau_update_attribute(object_config_p obj_config, VAConfigAttrib *attrib) |
2178 | +{ |
2179 | + int i; |
2180 | + |
2181 | + /* Check existing attrbiutes */ |
2182 | + for (i = 0; obj_config->attrib_count < i; i++) { |
2183 | + if (obj_config->attrib_list[i].type == attrib->type) { |
2184 | + /* Update existing attribute */ |
2185 | + obj_config->attrib_list[i].value = attrib->value; |
2186 | + return VA_STATUS_SUCCESS; |
2187 | + } |
2188 | + } |
2189 | + if (obj_config->attrib_count < VDPAU_MAX_CONFIG_ATTRIBUTES) { |
2190 | + i = obj_config->attrib_count; |
2191 | + obj_config->attrib_list[i].type = attrib->type; |
2192 | + obj_config->attrib_list[i].value = attrib->value; |
2193 | + obj_config->attrib_count++; |
2194 | + return VA_STATUS_SUCCESS; |
2195 | + } |
2196 | + return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; |
2197 | +} |
2198 | + |
2199 | +// vaDestroyConfig |
2200 | +VAStatus vdpau_DestroyConfig(VADriverContextP ctx, VAConfigID config_id) |
2201 | +{ |
2202 | + VDPAU_DRIVER_DATA_INIT; |
2203 | + |
2204 | + object_config_p obj_config = VDPAU_CONFIG(config_id); |
2205 | + if (!obj_config) |
2206 | + return VA_STATUS_ERROR_INVALID_CONFIG; |
2207 | + |
2208 | + object_heap_free(&driver_data->config_heap, (object_base_p)obj_config); |
2209 | + return VA_STATUS_SUCCESS; |
2210 | +} |
2211 | + |
2212 | +// vaCreateConfig |
2213 | +VAStatus |
2214 | +vdpau_CreateConfig( |
2215 | + VADriverContextP ctx, |
2216 | + VAProfile profile, |
2217 | + VAEntrypoint entrypoint, |
2218 | + VAConfigAttrib *attrib_list, |
2219 | + int num_attribs, |
2220 | + VAConfigID *config_id |
2221 | +) |
2222 | +{ |
2223 | + VDPAU_DRIVER_DATA_INIT; |
2224 | + |
2225 | + VAStatus va_status; |
2226 | + int configID; |
2227 | + object_config_p obj_config; |
2228 | + int i; |
2229 | + |
2230 | + /* Validate profile and entrypoint */ |
2231 | + va_status = check_decoder(driver_data, profile, entrypoint); |
2232 | + if (va_status != VA_STATUS_SUCCESS) |
2233 | + return va_status; |
2234 | + |
2235 | + configID = object_heap_allocate(&driver_data->config_heap); |
2236 | + if ((obj_config = VDPAU_CONFIG(configID)) == NULL) |
2237 | + return VA_STATUS_ERROR_ALLOCATION_FAILED; |
2238 | + |
2239 | + obj_config->profile = profile; |
2240 | + obj_config->entrypoint = entrypoint; |
2241 | + obj_config->attrib_list[0].type = VAConfigAttribRTFormat; |
2242 | + obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420; |
2243 | + obj_config->attrib_count = 1; |
2244 | + |
2245 | + for(i = 0; i < num_attribs; i++) { |
2246 | + va_status = vdpau_update_attribute(obj_config, &attrib_list[i]); |
2247 | + if (va_status != VA_STATUS_SUCCESS) { |
2248 | + vdpau_DestroyConfig(ctx, configID); |
2249 | + return va_status; |
2250 | + } |
2251 | + } |
2252 | + |
2253 | + if (config_id) |
2254 | + *config_id = configID; |
2255 | + |
2256 | + return va_status; |
2257 | +} |
2258 | + |
2259 | +// vaQueryConfigAttributes |
2260 | +VAStatus |
2261 | +vdpau_QueryConfigAttributes( |
2262 | + VADriverContextP ctx, |
2263 | + VAConfigID config_id, |
2264 | + VAProfile *profile, |
2265 | + VAEntrypoint *entrypoint, |
2266 | + VAConfigAttrib *attrib_list, |
2267 | + int *num_attribs |
2268 | +) |
2269 | +{ |
2270 | + VDPAU_DRIVER_DATA_INIT; |
2271 | + |
2272 | + VAStatus va_status = VA_STATUS_SUCCESS; |
2273 | + object_config_p obj_config; |
2274 | + int i; |
2275 | + |
2276 | + obj_config = VDPAU_CONFIG(config_id); |
2277 | + if (!obj_config) |
2278 | + return VA_STATUS_ERROR_INVALID_CONFIG; |
2279 | + |
2280 | + if (profile) |
2281 | + *profile = obj_config->profile; |
2282 | + |
2283 | + if (entrypoint) |
2284 | + *entrypoint = obj_config->entrypoint; |
2285 | + |
2286 | + if (num_attribs) |
2287 | + *num_attribs = obj_config->attrib_count; |
2288 | + |
2289 | + if (attrib_list) { |
2290 | + for (i = 0; i < obj_config->attrib_count; i++) |
2291 | + attrib_list[i] = obj_config->attrib_list[i]; |
2292 | + } |
2293 | + |
2294 | + return va_status; |
2295 | +} |
2296 | + |
2297 | +// Add subpicture association to surface |
2298 | +// NOTE: the subpicture owns the SubpictureAssociation object |
2299 | +int surface_add_association( |
2300 | + object_surface_p obj_surface, |
2301 | + SubpictureAssociationP assoc |
2302 | +) |
2303 | +{ |
2304 | + /* Check that we don't already have this association */ |
2305 | + if (obj_surface->assocs) { |
2306 | + unsigned int i; |
2307 | + for (i = 0; i < obj_surface->assocs_count; i++) { |
2308 | + if (obj_surface->assocs[i] == assoc) |
2309 | + return 0; |
2310 | + if (obj_surface->assocs[i]->subpicture == assoc->subpicture) { |
2311 | + /* XXX: this should not happen, but replace it in the interim */ |
2312 | + ASSERT(obj_surface->assocs[i]->surface == assoc->surface); |
2313 | + obj_surface->assocs[i] = assoc; |
2314 | + return 0; |
2315 | + } |
2316 | + } |
2317 | + } |
2318 | + |
2319 | + /* Check that we have not reached the maximum subpictures capacity yet */ |
2320 | + if (obj_surface->assocs_count >= VDPAU_MAX_SUBPICTURES) |
2321 | + return -1; |
2322 | + |
2323 | + /* Append this subpicture association */ |
2324 | + SubpictureAssociationP *assocs; |
2325 | + assocs = realloc_buffer( |
2326 | + &obj_surface->assocs, |
2327 | + &obj_surface->assocs_count_max, |
2328 | + 1 + obj_surface->assocs_count, |
2329 | + sizeof(obj_surface->assocs[0]) |
2330 | + ); |
2331 | + if (!assocs) |
2332 | + return -1; |
2333 | + |
2334 | + assocs[obj_surface->assocs_count++] = assoc; |
2335 | + return 0; |
2336 | +} |
2337 | + |
2338 | +// Remove subpicture association from surface |
2339 | +// NOTE: the subpicture owns the SubpictureAssociation object |
2340 | +int surface_remove_association( |
2341 | + object_surface_p obj_surface, |
2342 | + SubpictureAssociationP assoc |
2343 | +) |
2344 | +{ |
2345 | + if (!obj_surface->assocs || obj_surface->assocs_count == 0) |
2346 | + return -1; |
2347 | + |
2348 | + unsigned int i; |
2349 | + const unsigned int last = obj_surface->assocs_count - 1; |
2350 | + for (i = 0; i <= last; i++) { |
2351 | + if (obj_surface->assocs[i] == assoc) { |
2352 | + /* Swap with the last subpicture */ |
2353 | + obj_surface->assocs[i] = obj_surface->assocs[last]; |
2354 | + obj_surface->assocs[last] = NULL; |
2355 | + obj_surface->assocs_count--; |
2356 | + return 0; |
2357 | + } |
2358 | + } |
2359 | + return -1; |
2360 | +} |
2361 | + |
2362 | +// vaDestroySurfaces |
2363 | +VAStatus |
2364 | +vdpau_DestroySurfaces( |
2365 | + VADriverContextP ctx, |
2366 | + VASurfaceID *surface_list, |
2367 | + int num_surfaces |
2368 | +) |
2369 | +{ |
2370 | + VDPAU_DRIVER_DATA_INIT; |
2371 | + |
2372 | + int i, j, n; |
2373 | + for (i = num_surfaces - 1; i >= 0; i--) { |
2374 | + object_surface_p obj_surface = VDPAU_SURFACE(surface_list[i]); |
2375 | + ASSERT(obj_surface); |
2376 | + if (!obj_surface) |
2377 | + continue; |
2378 | + |
2379 | + if (obj_surface->vdp_surface != VDP_INVALID_HANDLE) { |
2380 | + vdpau_video_surface_destroy(driver_data, obj_surface->vdp_surface); |
2381 | + obj_surface->vdp_surface = VDP_INVALID_HANDLE; |
2382 | + } |
2383 | + |
2384 | + for (j = 0; j < obj_surface->output_surfaces_count; j++) { |
2385 | + output_surface_unref(driver_data, obj_surface->output_surfaces[j]); |
2386 | + obj_surface->output_surfaces[j] = NULL; |
2387 | + } |
2388 | + free(obj_surface->output_surfaces); |
2389 | + obj_surface->output_surfaces_count = 0; |
2390 | + obj_surface->output_surfaces_count_max = 0; |
2391 | + |
2392 | + if (obj_surface->video_mixer) { |
2393 | + video_mixer_unref(driver_data, obj_surface->video_mixer); |
2394 | + obj_surface->video_mixer = NULL; |
2395 | + } |
2396 | + |
2397 | + if (obj_surface->assocs) { |
2398 | + object_subpicture_p obj_subpicture; |
2399 | + VAStatus status; |
2400 | + const unsigned int n_assocs = obj_surface->assocs_count; |
2401 | + |
2402 | + for (j = 0, n = 0; j < n_assocs; j++) { |
2403 | + SubpictureAssociationP const assoc = obj_surface->assocs[0]; |
2404 | + ASSERT(assoc); |
2405 | + if (!assoc) |
2406 | + continue; |
2407 | + obj_subpicture = VDPAU_SUBPICTURE(assoc->subpicture); |
2408 | + ASSERT(obj_subpicture); |
2409 | + if (!obj_subpicture) |
2410 | + continue; |
2411 | + status = subpicture_deassociate_1(obj_subpicture, obj_surface); |
2412 | + if (status == VA_STATUS_SUCCESS) |
2413 | + ++n; |
2414 | + } |
2415 | + if (n != n_assocs) |
2416 | + vdpau_error_message("vaDestroySurfaces(): surface 0x%08x still " |
2417 | + "has %d subpictures associated to it\n", |
2418 | + obj_surface->base.id, n_assocs - n); |
2419 | + free(obj_surface->assocs); |
2420 | + obj_surface->assocs = NULL; |
2421 | + } |
2422 | + obj_surface->assocs_count = 0; |
2423 | + obj_surface->assocs_count_max = 0; |
2424 | + |
2425 | + object_heap_free(&driver_data->surface_heap, (object_base_p)obj_surface); |
2426 | + } |
2427 | + return VA_STATUS_SUCCESS; |
2428 | +} |
2429 | + |
2430 | +// vaCreateSurfaces |
2431 | +VAStatus |
2432 | +vdpau_CreateSurfaces( |
2433 | + VADriverContextP ctx, |
2434 | + int width, |
2435 | + int height, |
2436 | + int format, |
2437 | + int num_surfaces, |
2438 | + VASurfaceID *surfaces |
2439 | +) |
2440 | +{ |
2441 | + VDPAU_DRIVER_DATA_INIT; |
2442 | + |
2443 | + VAStatus va_status = VA_STATUS_SUCCESS; |
2444 | + VdpVideoSurface vdp_surface = VDP_INVALID_HANDLE; |
2445 | + VdpChromaType vdp_chroma_type = get_VdpChromaType(format); |
2446 | + VdpStatus vdp_status; |
2447 | + int i; |
2448 | + |
2449 | + /* We only support one format */ |
2450 | + if (format != VA_RT_FORMAT_YUV420) |
2451 | + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; |
2452 | + |
2453 | + for (i = 0; i < num_surfaces; i++) { |
2454 | + vdp_status = vdpau_video_surface_create( |
2455 | + driver_data, |
2456 | + driver_data->vdp_device, |
2457 | + vdp_chroma_type, |
2458 | + width, height, |
2459 | + &vdp_surface |
2460 | + ); |
2461 | + if (!VDPAU_CHECK_STATUS(vdp_status, "VdpVideoSurfaceCreate()")) { |
2462 | + va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; |
2463 | + break; |
2464 | + } |
2465 | + |
2466 | + int va_surface = object_heap_allocate(&driver_data->surface_heap); |
2467 | + object_surface_p obj_surface = VDPAU_SURFACE(va_surface); |
2468 | + if (!obj_surface) { |
2469 | + va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; |
2470 | + break; |
2471 | + } |
2472 | + obj_surface->va_context = VA_INVALID_ID; |
2473 | + obj_surface->va_surface_status = VASurfaceReady; |
2474 | + obj_surface->vdp_surface = vdp_surface; |
2475 | + obj_surface->width = width; |
2476 | + obj_surface->height = height; |
2477 | + obj_surface->assocs = NULL; |
2478 | + obj_surface->assocs_count = 0; |
2479 | + obj_surface->assocs_count_max = 0; |
2480 | + obj_surface->vdp_chroma_type = vdp_chroma_type; |
2481 | + obj_surface->output_surfaces = NULL; |
2482 | + obj_surface->output_surfaces_count = 0; |
2483 | + obj_surface->output_surfaces_count_max = 0; |
2484 | + obj_surface->video_mixer = NULL; |
2485 | + surfaces[i] = va_surface; |
2486 | + vdp_surface = VDP_INVALID_HANDLE; |
2487 | + |
2488 | + object_mixer_p obj_mixer; |
2489 | + obj_mixer = video_mixer_create_cached(driver_data, obj_surface); |
2490 | + if (!obj_mixer) { |
2491 | + va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; |
2492 | + break; |
2493 | + } |
2494 | + obj_surface->video_mixer = obj_mixer; |
2495 | + } |
2496 | + |
2497 | + /* Error recovery */ |
2498 | + if (va_status != VA_STATUS_SUCCESS) { |
2499 | + if (vdp_surface != VDP_INVALID_HANDLE) |
2500 | + vdpau_video_surface_destroy(driver_data, vdp_surface); |
2501 | + vdpau_DestroySurfaces(ctx, surfaces, i); |
2502 | + } |
2503 | + return va_status; |
2504 | +} |
2505 | + |
2506 | +// vaDestroyContext |
2507 | +VAStatus vdpau_DestroyContext(VADriverContextP ctx, VAContextID context) |
2508 | +{ |
2509 | + VDPAU_DRIVER_DATA_INIT; |
2510 | + int i; |
2511 | + |
2512 | + object_context_p obj_context = VDPAU_CONTEXT(context); |
2513 | + if (!obj_context) |
2514 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
2515 | + |
2516 | + if (obj_context->gen_slice_data) { |
2517 | + free(obj_context->gen_slice_data); |
2518 | + obj_context->gen_slice_data = NULL; |
2519 | + obj_context->gen_slice_data_size = 0; |
2520 | + obj_context->gen_slice_data_size_max = 0; |
2521 | + } |
2522 | + |
2523 | + if (obj_context->vdp_bitstream_buffers) { |
2524 | + free(obj_context->vdp_bitstream_buffers); |
2525 | + obj_context->vdp_bitstream_buffers = NULL; |
2526 | + obj_context->vdp_bitstream_buffers_count = 0; |
2527 | + obj_context->vdp_bitstream_buffers_count_max = 0; |
2528 | + } |
2529 | + |
2530 | + if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) { |
2531 | + vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder); |
2532 | + obj_context->vdp_decoder = VDP_INVALID_HANDLE; |
2533 | + } |
2534 | + |
2535 | + if (obj_context->dead_buffers) { |
2536 | + free(obj_context->dead_buffers); |
2537 | + obj_context->dead_buffers = NULL; |
2538 | + } |
2539 | + |
2540 | + if (obj_context->render_targets) { |
2541 | + for (i = 0; i < obj_context->num_render_targets; i++) { |
2542 | + object_surface_p obj_surface; |
2543 | + obj_surface = VDPAU_SURFACE(obj_context->render_targets[i]); |
2544 | + if (obj_surface) |
2545 | + obj_surface->va_context = VA_INVALID_ID; |
2546 | + } |
2547 | + free(obj_context->render_targets); |
2548 | + obj_context->render_targets = NULL; |
2549 | + } |
2550 | + |
2551 | + obj_context->context_id = VA_INVALID_ID; |
2552 | + obj_context->config_id = VA_INVALID_ID; |
2553 | + obj_context->current_render_target = VA_INVALID_SURFACE; |
2554 | + obj_context->picture_width = 0; |
2555 | + obj_context->picture_height = 0; |
2556 | + obj_context->num_render_targets = 0; |
2557 | + obj_context->flags = 0; |
2558 | + obj_context->dead_buffers_count = 0; |
2559 | + obj_context->dead_buffers_count_max = 0; |
2560 | + |
2561 | + object_heap_free(&driver_data->context_heap, (object_base_p)obj_context); |
2562 | + return VA_STATUS_SUCCESS; |
2563 | +} |
2564 | + |
2565 | +// vaCreateContext |
2566 | +VAStatus |
2567 | +vdpau_CreateContext( |
2568 | + VADriverContextP ctx, |
2569 | + VAConfigID config_id, |
2570 | + int picture_width, |
2571 | + int picture_height, |
2572 | + int flag, |
2573 | + VASurfaceID *render_targets, |
2574 | + int num_render_targets, |
2575 | + VAContextID *context |
2576 | +) |
2577 | +{ |
2578 | + VDPAU_DRIVER_DATA_INIT; |
2579 | + |
2580 | + if (context) |
2581 | + *context = VA_INVALID_ID; |
2582 | + |
2583 | + object_config_p obj_config; |
2584 | + if ((obj_config = VDPAU_CONFIG(config_id)) == NULL) |
2585 | + return VA_STATUS_ERROR_INVALID_CONFIG; |
2586 | + |
2587 | + /* XXX: validate flag */ |
2588 | + |
2589 | + VdpDecoderProfile vdp_profile; |
2590 | + uint32_t max_width, max_height; |
2591 | + int i; |
2592 | + vdp_profile = get_VdpDecoderProfile(obj_config->profile); |
2593 | + if (!get_max_surface_size(driver_data, vdp_profile, &max_width, &max_height)) |
2594 | + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; |
2595 | + if (picture_width > max_width || picture_height > max_height) |
2596 | + return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; |
2597 | + |
2598 | + VAContextID context_id = object_heap_allocate(&driver_data->context_heap); |
2599 | + if (context_id == VA_INVALID_ID) |
2600 | + return VA_STATUS_ERROR_ALLOCATION_FAILED; |
2601 | + |
2602 | + object_context_p obj_context = VDPAU_CONTEXT(context_id); |
2603 | + if (!obj_context) |
2604 | + return VA_STATUS_ERROR_ALLOCATION_FAILED; |
2605 | + if (context) |
2606 | + *context = context_id; |
2607 | + |
2608 | + obj_context->context_id = context_id; |
2609 | + obj_context->config_id = config_id; |
2610 | + obj_context->current_render_target = VA_INVALID_SURFACE; |
2611 | + obj_context->picture_width = picture_width; |
2612 | + obj_context->picture_height = picture_height; |
2613 | + obj_context->num_render_targets = num_render_targets; |
2614 | + obj_context->flags = flag; |
2615 | + obj_context->max_ref_frames = -1; |
2616 | + obj_context->render_targets = (VASurfaceID *) |
2617 | + calloc(num_render_targets, sizeof(VASurfaceID)); |
2618 | + obj_context->dead_buffers = NULL; |
2619 | + obj_context->dead_buffers_count = 0; |
2620 | + obj_context->dead_buffers_count_max = 0; |
2621 | + obj_context->vdp_codec = get_VdpCodec(vdp_profile); |
2622 | + obj_context->vdp_profile = vdp_profile; |
2623 | + obj_context->vdp_decoder = VDP_INVALID_HANDLE; |
2624 | + obj_context->gen_slice_data = NULL; |
2625 | + obj_context->gen_slice_data_size = 0; |
2626 | + obj_context->gen_slice_data_size_max = 0; |
2627 | + obj_context->vdp_bitstream_buffers = NULL; |
2628 | + obj_context->vdp_bitstream_buffers_count = 0; |
2629 | + obj_context->vdp_bitstream_buffers_count_max = 0; |
2630 | + |
2631 | + if (!obj_context->render_targets) { |
2632 | + vdpau_DestroyContext(ctx, context_id); |
2633 | + return VA_STATUS_ERROR_ALLOCATION_FAILED; |
2634 | + } |
2635 | + |
2636 | + for (i = 0; i < num_render_targets; i++) { |
2637 | + object_surface_t *obj_surface; |
2638 | + if ((obj_surface = VDPAU_SURFACE(render_targets[i])) == NULL) { |
2639 | + vdpau_DestroyContext(ctx, context_id); |
2640 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
2641 | + } |
2642 | + obj_context->render_targets[i] = render_targets[i]; |
2643 | + /* XXX: assume we can only associate a surface to a single context */ |
2644 | + ASSERT(obj_surface->va_context == VA_INVALID_ID); |
2645 | + obj_surface->va_context = context_id; |
2646 | + } |
2647 | + return VA_STATUS_SUCCESS; |
2648 | +} |
2649 | + |
2650 | +// Query surface status |
2651 | +VAStatus |
2652 | +query_surface_status( |
2653 | + vdpau_driver_data_t *driver_data, |
2654 | + object_surface_p obj_surface, |
2655 | + VASurfaceStatus *status |
2656 | +) |
2657 | +{ |
2658 | + VAStatus va_status = VA_STATUS_SUCCESS; |
2659 | + |
2660 | + if (obj_surface->va_surface_status == VASurfaceDisplaying) { |
2661 | + unsigned int i, num_output_surfaces_displaying = 0; |
2662 | + for (i = 0; i < obj_surface->output_surfaces_count; i++) { |
2663 | + object_output_p obj_output = obj_surface->output_surfaces[i]; |
2664 | + if (!obj_output) |
2665 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
2666 | + |
2667 | + VdpOutputSurface vdp_output_surface; |
2668 | + vdp_output_surface = obj_output->vdp_output_surfaces[obj_output->displayed_output_surface]; |
2669 | + if (vdp_output_surface == VDP_INVALID_HANDLE) |
2670 | + continue; |
2671 | + |
2672 | + VdpPresentationQueueStatus vdp_queue_status; |
2673 | + VdpTime vdp_dummy_time; |
2674 | + VdpStatus vdp_status; |
2675 | + vdp_status = vdpau_presentation_queue_query_surface_status( |
2676 | + driver_data, |
2677 | + obj_output->vdp_flip_queue, |
2678 | + vdp_output_surface, |
2679 | + &vdp_queue_status, |
2680 | + &vdp_dummy_time |
2681 | + ); |
2682 | + va_status = vdpau_get_VAStatus(vdp_status); |
2683 | + |
2684 | + if (vdp_queue_status != VDP_PRESENTATION_QUEUE_STATUS_VISIBLE) |
2685 | + ++num_output_surfaces_displaying; |
2686 | + } |
2687 | + |
2688 | + if (num_output_surfaces_displaying == 0) |
2689 | + obj_surface->va_surface_status = VASurfaceReady; |
2690 | + } |
2691 | + |
2692 | + if (status) |
2693 | + *status = obj_surface->va_surface_status; |
2694 | + |
2695 | + return va_status; |
2696 | +} |
2697 | + |
2698 | +// vaQuerySurfaceStatus |
2699 | +VAStatus |
2700 | +vdpau_QuerySurfaceStatus( |
2701 | + VADriverContextP ctx, |
2702 | + VASurfaceID render_target, |
2703 | + VASurfaceStatus *status |
2704 | +) |
2705 | +{ |
2706 | + VDPAU_DRIVER_DATA_INIT; |
2707 | + |
2708 | + object_surface_p obj_surface = VDPAU_SURFACE(render_target); |
2709 | + if (!obj_surface) |
2710 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
2711 | + |
2712 | + return query_surface_status(driver_data, obj_surface, status); |
2713 | +} |
2714 | + |
2715 | +// Wait for the surface to complete pending operations |
2716 | +VAStatus |
2717 | +sync_surface( |
2718 | + vdpau_driver_data_t *driver_data, |
2719 | + object_surface_p obj_surface |
2720 | +) |
2721 | +{ |
2722 | + /* VDPAU only supports status interface for in-progress display */ |
2723 | + /* XXX: polling is bad but there currently is no alternative */ |
2724 | + for (;;) { |
2725 | + VASurfaceStatus va_surface_status; |
2726 | + VAStatus va_status; |
2727 | + |
2728 | + va_status = query_surface_status( |
2729 | + driver_data, |
2730 | + obj_surface, |
2731 | + &va_surface_status |
2732 | + ); |
2733 | + if (va_status != VA_STATUS_SUCCESS) |
2734 | + return va_status; |
2735 | + |
2736 | + if (va_surface_status != VASurfaceDisplaying) |
2737 | + break; |
2738 | + delay_usec(VDPAU_SYNC_DELAY); |
2739 | + } |
2740 | + return VA_STATUS_SUCCESS; |
2741 | +} |
2742 | + |
2743 | +// vaSyncSurface |
2744 | +VAStatus |
2745 | +vdpau_SyncSurface2( |
2746 | + VADriverContextP ctx, |
2747 | + VASurfaceID render_target |
2748 | +) |
2749 | +{ |
2750 | + VDPAU_DRIVER_DATA_INIT; |
2751 | + |
2752 | + object_surface_p obj_surface = VDPAU_SURFACE(render_target); |
2753 | + if (!obj_surface) |
2754 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
2755 | + |
2756 | + /* Assume that this shouldn't be called before vaEndPicture() */ |
2757 | + object_context_p obj_context = VDPAU_CONTEXT(obj_surface->va_context); |
2758 | + if (obj_context) { |
2759 | + ASSERT(obj_context->current_render_target != obj_surface->base.id); |
2760 | + if (obj_context->current_render_target == obj_surface->base.id) |
2761 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
2762 | + } |
2763 | + |
2764 | + return sync_surface(driver_data, obj_surface); |
2765 | +} |
2766 | + |
2767 | +VAStatus |
2768 | +vdpau_SyncSurface3( |
2769 | + VADriverContextP ctx, |
2770 | + VAContextID context, |
2771 | + VASurfaceID render_target |
2772 | +) |
2773 | +{ |
2774 | + VDPAU_DRIVER_DATA_INIT; |
2775 | + |
2776 | + object_surface_p obj_surface = VDPAU_SURFACE(render_target); |
2777 | + if (!obj_surface) |
2778 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
2779 | + |
2780 | + /* Assume that this shouldn't be called before vaEndPicture() */ |
2781 | + object_context_p obj_context = VDPAU_CONTEXT(context); |
2782 | + if (obj_context) { |
2783 | + ASSERT(obj_context->current_render_target != obj_surface->base.id); |
2784 | + if (obj_context->current_render_target == obj_surface->base.id) |
2785 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
2786 | + } |
2787 | + return sync_surface(driver_data, obj_surface); |
2788 | +} |
2789 | + |
2790 | +// Ensure VA Display Attributes are initialized |
2791 | +static int ensure_display_attributes(vdpau_driver_data_t *driver_data) |
2792 | +{ |
2793 | + VADisplayAttribute *attr; |
2794 | + |
2795 | + if (driver_data->va_display_attrs_count > 0) |
2796 | + return 0; |
2797 | + |
2798 | + memset(driver_data->va_display_attrs_mtime, 0, sizeof(driver_data->va_display_attrs_mtime)); |
2799 | + |
2800 | + attr = &driver_data->va_display_attrs[0]; |
2801 | + |
2802 | + attr->type = VADisplayAttribDirectSurface; |
2803 | + attr->value = 0; /* VdpVideoSurface is copied into VdpOutputSurface */ |
2804 | + attr->min_value = attr->value; |
2805 | + attr->max_value = attr->value; |
2806 | + attr->flags = VA_DISPLAY_ATTRIB_GETTABLE; |
2807 | + attr++; |
2808 | + |
2809 | + attr->type = VADisplayAttribBrightness; |
2810 | + attr->value = 0; |
2811 | + attr->min_value = -100; |
2812 | + attr->max_value = 100; |
2813 | + attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; |
2814 | + attr++; |
2815 | + |
2816 | + attr->type = VADisplayAttribContrast; |
2817 | + attr->value = 0; |
2818 | + attr->min_value = -100; |
2819 | + attr->max_value = 100; |
2820 | + attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; |
2821 | + attr++; |
2822 | + |
2823 | + attr->type = VADisplayAttribHue; |
2824 | + attr->value = 0; |
2825 | + attr->min_value = -100; |
2826 | + attr->max_value = 100; |
2827 | + attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; |
2828 | + attr++; |
2829 | + |
2830 | + attr->type = VADisplayAttribSaturation; |
2831 | + attr->value = 0; |
2832 | + attr->min_value = -100; |
2833 | + attr->max_value = 100; |
2834 | + attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; |
2835 | + attr++; |
2836 | + |
2837 | + attr->type = VADisplayAttribBackgroundColor; |
2838 | + attr->value = 0; |
2839 | + attr->min_value = 0; |
2840 | + attr->max_value = 0xffffff; |
2841 | + attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; |
2842 | + attr++; |
2843 | + |
2844 | + driver_data->va_display_attrs_count = attr - driver_data->va_display_attrs; |
2845 | + ASSERT(driver_data->va_display_attrs_count <= VDPAU_MAX_DISPLAY_ATTRIBUTES); |
2846 | + return 0; |
2847 | +} |
2848 | + |
2849 | +// Look up for the specified VA display attribute |
2850 | +static VADisplayAttribute * |
2851 | +get_display_attribute( |
2852 | + vdpau_driver_data_t *driver_data, |
2853 | + VADisplayAttribType type |
2854 | +) |
2855 | +{ |
2856 | + if (ensure_display_attributes(driver_data) < 0) |
2857 | + return NULL; |
2858 | + |
2859 | + unsigned int i; |
2860 | + for (i = 0; i < driver_data->va_display_attrs_count; i++) { |
2861 | + if (driver_data->va_display_attrs[i].type == type) |
2862 | + return &driver_data->va_display_attrs[i]; |
2863 | + } |
2864 | + return NULL; |
2865 | +} |
2866 | + |
2867 | +// vaQueryDisplayAttributes |
2868 | +VAStatus |
2869 | +vdpau_QueryDisplayAttributes( |
2870 | + VADriverContextP ctx, |
2871 | + VADisplayAttribute *attr_list, |
2872 | + int *num_attributes |
2873 | +) |
2874 | +{ |
2875 | + VDPAU_DRIVER_DATA_INIT; |
2876 | + |
2877 | + if (ensure_display_attributes(driver_data) < 0) |
2878 | + return VA_STATUS_ERROR_OPERATION_FAILED; |
2879 | + |
2880 | + if (attr_list) |
2881 | + memcpy(attr_list, driver_data->va_display_attrs, |
2882 | + driver_data->va_display_attrs_count * sizeof(attr_list[0])); |
2883 | + |
2884 | + if (num_attributes) |
2885 | + *num_attributes = driver_data->va_display_attrs_count; |
2886 | + |
2887 | + return VA_STATUS_SUCCESS; |
2888 | +} |
2889 | + |
2890 | +// vaGetDisplayAttributes |
2891 | +VAStatus |
2892 | +vdpau_GetDisplayAttributes( |
2893 | + VADriverContextP ctx, |
2894 | + VADisplayAttribute *attr_list, |
2895 | + int num_attributes |
2896 | +) |
2897 | +{ |
2898 | + VDPAU_DRIVER_DATA_INIT; |
2899 | + |
2900 | + unsigned int i; |
2901 | + for (i = 0; i < num_attributes; i++) { |
2902 | + VADisplayAttribute * const dst_attr = &attr_list[i]; |
2903 | + VADisplayAttribute *src_attr; |
2904 | + |
2905 | + src_attr = get_display_attribute(driver_data, dst_attr->type); |
2906 | + if (src_attr && (src_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) != 0) { |
2907 | + dst_attr->min_value = src_attr->min_value; |
2908 | + dst_attr->max_value = src_attr->max_value; |
2909 | + dst_attr->value = src_attr->value; |
2910 | + } |
2911 | + else |
2912 | + dst_attr->flags &= ~VA_DISPLAY_ATTRIB_GETTABLE; |
2913 | + } |
2914 | + return VA_STATUS_SUCCESS; |
2915 | +} |
2916 | + |
2917 | +// vaSetDisplayAttributes |
2918 | +VAStatus |
2919 | +vdpau_SetDisplayAttributes( |
2920 | + VADriverContextP ctx, |
2921 | + VADisplayAttribute *attr_list, |
2922 | + int num_attributes |
2923 | +) |
2924 | +{ |
2925 | + VDPAU_DRIVER_DATA_INIT; |
2926 | + |
2927 | + unsigned int i; |
2928 | + for (i = 0; i < num_attributes; i++) { |
2929 | + VADisplayAttribute * const src_attr = &attr_list[i]; |
2930 | + VADisplayAttribute *dst_attr; |
2931 | + |
2932 | + dst_attr = get_display_attribute(driver_data, src_attr->type); |
2933 | + if (!dst_attr) |
2934 | + return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; |
2935 | + |
2936 | + if ((dst_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) != 0) { |
2937 | + dst_attr->value = src_attr->value; |
2938 | + |
2939 | + static uint64_t mtime; |
2940 | + const int display_attr_index = dst_attr - driver_data->va_display_attrs; |
2941 | + ASSERT(display_attr_index < VDPAU_MAX_DISPLAY_ATTRIBUTES); |
2942 | + driver_data->va_display_attrs_mtime[display_attr_index] = ++mtime; |
2943 | + } |
2944 | + } |
2945 | + return VA_STATUS_SUCCESS; |
2946 | +} |
2947 | + |
2948 | +// vaDbgCopySurfaceToBuffer (not a PUBLIC interface) |
2949 | +VAStatus |
2950 | +vdpau_DbgCopySurfaceToBuffer( |
2951 | + VADriverContextP ctx, |
2952 | + VASurfaceID surface, |
2953 | + void **buffer, |
2954 | + unsigned int *stride |
2955 | +) |
2956 | +{ |
2957 | + /* TODO */ |
2958 | + return VA_STATUS_ERROR_UNKNOWN; |
2959 | +} |
2960 | + |
2961 | +#if VA_CHECK_VERSION(0,30,0) |
2962 | +// vaCreateSurfaceFromCIFrame |
2963 | +VAStatus |
2964 | +vdpau_CreateSurfaceFromCIFrame( |
2965 | + VADriverContextP ctx, |
2966 | + unsigned long frame_id, |
2967 | + VASurfaceID *surface |
2968 | +) |
2969 | +{ |
2970 | + /* TODO */ |
2971 | + return VA_STATUS_ERROR_UNKNOWN; |
2972 | +} |
2973 | + |
2974 | +// vaCreateSurfaceFromV4L2Buf |
2975 | +VAStatus |
2976 | +vdpau_CreateSurfaceFromV4L2Buf( |
2977 | + VADriverContextP ctx, |
2978 | + int v4l2_fd, |
2979 | + struct v4l2_format *v4l2_fmt, |
2980 | + struct v4l2_buffer *v4l2_buf, |
2981 | + VASurfaceID *surface |
2982 | +) |
2983 | +{ |
2984 | + /* TODO */ |
2985 | + return VA_STATUS_ERROR_UNKNOWN; |
2986 | +} |
2987 | + |
2988 | +// vaCopySurfaceToBuffer |
2989 | +VAStatus |
2990 | +vdpau_CopySurfaceToBuffer( |
2991 | + VADriverContextP ctx, |
2992 | + VASurfaceID surface, |
2993 | + unsigned int *fourcc, |
2994 | + unsigned int *luma_stride, |
2995 | + unsigned int *chroma_u_stride, |
2996 | + unsigned int *chroma_v_stride, |
2997 | + unsigned int *luma_offset, |
2998 | + unsigned int *chroma_u_offset, |
2999 | + unsigned int *chroma_v_offset, |
3000 | + void **buffer |
3001 | +) |
3002 | +{ |
3003 | + /* TODO */ |
3004 | + return VA_STATUS_ERROR_UNKNOWN; |
3005 | +} |
3006 | +#endif |
3007 | + |
3008 | +#if VA_CHECK_VERSION(0,31,1) |
3009 | +// vaLockSurface |
3010 | +VAStatus |
3011 | +vdpau_LockSurface( |
3012 | + VADriverContextP ctx, |
3013 | + VASurfaceID surface, |
3014 | + unsigned int *fourcc, |
3015 | + unsigned int *luma_stride, |
3016 | + unsigned int *chroma_u_stride, |
3017 | + unsigned int *chroma_v_stride, |
3018 | + unsigned int *luma_offset, |
3019 | + unsigned int *chroma_u_offset, |
3020 | + unsigned int *chroma_v_offset, |
3021 | + unsigned int *buffer_name, |
3022 | + void **buffer |
3023 | +) |
3024 | +{ |
3025 | + if (fourcc) *fourcc = VA_FOURCC('N','V','1','2'); |
3026 | + if (luma_stride) *luma_stride = 0; |
3027 | + if (chroma_u_stride) *chroma_u_stride = 0; |
3028 | + if (chroma_v_stride) *chroma_v_stride = 0; |
3029 | + if (luma_offset) *luma_offset = 0; |
3030 | + if (chroma_u_offset) *chroma_u_offset = 0; |
3031 | + if (chroma_v_offset) *chroma_v_offset = 0; |
3032 | + if (buffer_name) *buffer_name = 0; |
3033 | + if (buffer) *buffer = NULL; |
3034 | + return VA_STATUS_SUCCESS; |
3035 | +} |
3036 | + |
3037 | +// vaUnlockSurface |
3038 | +VAStatus |
3039 | +vdpau_UnlockSurface( |
3040 | + VADriverContextP ctx, |
3041 | + VASurfaceID surface |
3042 | +) |
3043 | +{ |
3044 | + return VA_STATUS_SUCCESS; |
3045 | +} |
3046 | +#endif |
3047 | |
3048 | === added directory '.pc/03_mark_destroyed_buffers_as_deleted.patch' |
3049 | === added directory '.pc/03_mark_destroyed_buffers_as_deleted.patch/src' |
3050 | === added file '.pc/03_mark_destroyed_buffers_as_deleted.patch/src/vdpau_decode.c' |
3051 | --- .pc/03_mark_destroyed_buffers_as_deleted.patch/src/vdpau_decode.c 1970-01-01 00:00:00 +0000 |
3052 | +++ .pc/03_mark_destroyed_buffers_as_deleted.patch/src/vdpau_decode.c 2014-05-06 21:30:45 +0000 |
3053 | @@ -0,0 +1,1264 @@ |
3054 | +/* |
3055 | + * vdpau_decode.c - VDPAU backend for VA-API (decoder) |
3056 | + * |
3057 | + * vdpau-video (C) 2009-2011 Splitted-Desktop Systems |
3058 | + * |
3059 | + * This program is free software; you can redistribute it and/or modify |
3060 | + * it under the terms of the GNU General Public License as published by |
3061 | + * the Free Software Foundation; either version 2 of the License, or |
3062 | + * (at your option) any later version. |
3063 | + * |
3064 | + * This program is distributed in the hope that it will be useful, |
3065 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3066 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3067 | + * GNU General Public License for more details. |
3068 | + * |
3069 | + * You should have received a copy of the GNU General Public License |
3070 | + * along with this program; if not, write to the Free Software |
3071 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
3072 | + */ |
3073 | + |
3074 | +#include "sysdeps.h" |
3075 | +#include "vdpau_decode.h" |
3076 | +#include "vdpau_driver.h" |
3077 | +#include "vdpau_buffer.h" |
3078 | +#include "vdpau_video.h" |
3079 | +#include "vdpau_dump.h" |
3080 | +#include "utils.h" |
3081 | +#include "put_bits.h" |
3082 | + |
3083 | +#define DEBUG 1 |
3084 | +#include "debug.h" |
3085 | + |
3086 | + |
3087 | +// Translates VdpDecoderProfile to VdpCodec |
3088 | +VdpCodec get_VdpCodec(VdpDecoderProfile profile) |
3089 | +{ |
3090 | + switch (profile) { |
3091 | + case VDP_DECODER_PROFILE_MPEG1: |
3092 | + return VDP_CODEC_MPEG1; |
3093 | + case VDP_DECODER_PROFILE_MPEG2_SIMPLE: |
3094 | + case VDP_DECODER_PROFILE_MPEG2_MAIN: |
3095 | + return VDP_CODEC_MPEG2; |
3096 | +#if USE_VDPAU_MPEG4 |
3097 | + case VDP_DECODER_PROFILE_MPEG4_PART2_SP: |
3098 | + case VDP_DECODER_PROFILE_MPEG4_PART2_ASP: |
3099 | + case VDP_DECODER_PROFILE_DIVX4_QMOBILE: |
3100 | + case VDP_DECODER_PROFILE_DIVX4_MOBILE: |
3101 | + case VDP_DECODER_PROFILE_DIVX4_HOME_THEATER: |
3102 | + case VDP_DECODER_PROFILE_DIVX4_HD_1080P: |
3103 | + case VDP_DECODER_PROFILE_DIVX5_QMOBILE: |
3104 | + case VDP_DECODER_PROFILE_DIVX5_MOBILE: |
3105 | + case VDP_DECODER_PROFILE_DIVX5_HOME_THEATER: |
3106 | + case VDP_DECODER_PROFILE_DIVX5_HD_1080P: |
3107 | + return VDP_CODEC_MPEG4; |
3108 | +#endif |
3109 | + case VDP_DECODER_PROFILE_H264_BASELINE: |
3110 | + case VDP_DECODER_PROFILE_H264_MAIN: |
3111 | + case VDP_DECODER_PROFILE_H264_HIGH: |
3112 | + return VDP_CODEC_H264; |
3113 | + case VDP_DECODER_PROFILE_VC1_SIMPLE: |
3114 | + case VDP_DECODER_PROFILE_VC1_MAIN: |
3115 | + case VDP_DECODER_PROFILE_VC1_ADVANCED: |
3116 | + return VDP_CODEC_VC1; |
3117 | + } |
3118 | + return 0; |
3119 | +} |
3120 | + |
3121 | +// Translates VAProfile to VdpDecoderProfile |
3122 | +VdpDecoderProfile get_VdpDecoderProfile(VAProfile profile) |
3123 | +{ |
3124 | + switch (profile) { |
3125 | + case VAProfileMPEG2Simple: return VDP_DECODER_PROFILE_MPEG2_SIMPLE; |
3126 | + case VAProfileMPEG2Main: return VDP_DECODER_PROFILE_MPEG2_MAIN; |
3127 | +#if USE_VDPAU_MPEG4 |
3128 | + case VAProfileMPEG4Simple: return VDP_DECODER_PROFILE_MPEG4_PART2_SP; |
3129 | + case VAProfileMPEG4AdvancedSimple: return VDP_DECODER_PROFILE_MPEG4_PART2_ASP; |
3130 | +#endif |
3131 | + case VAProfileH264Baseline: return VDP_DECODER_PROFILE_H264_BASELINE; |
3132 | + case VAProfileH264Main: return VDP_DECODER_PROFILE_H264_MAIN; |
3133 | + case VAProfileH264High: return VDP_DECODER_PROFILE_H264_HIGH; |
3134 | + case VAProfileVC1Simple: return VDP_DECODER_PROFILE_VC1_SIMPLE; |
3135 | + case VAProfileVC1Main: return VDP_DECODER_PROFILE_VC1_MAIN; |
3136 | + case VAProfileVC1Advanced: return VDP_DECODER_PROFILE_VC1_ADVANCED; |
3137 | + default: break; |
3138 | + } |
3139 | + return (VdpDecoderProfile)-1; |
3140 | +} |
3141 | + |
3142 | +// Checks whether the VDPAU implementation supports the specified profile |
3143 | +static inline VdpBool |
3144 | +is_supported_profile( |
3145 | + vdpau_driver_data_t *driver_data, |
3146 | + VdpDecoderProfile profile |
3147 | +) |
3148 | +{ |
3149 | + VdpBool is_supported = VDP_FALSE; |
3150 | + VdpStatus vdp_status; |
3151 | + uint32_t max_level, max_references, max_width, max_height; |
3152 | + |
3153 | + if (profile == (VdpDecoderProfile)-1) |
3154 | + return VDP_FALSE; |
3155 | + |
3156 | + vdp_status = vdpau_decoder_query_capabilities( |
3157 | + driver_data, |
3158 | + driver_data->vdp_device, |
3159 | + profile, |
3160 | + &is_supported, |
3161 | + &max_level, |
3162 | + &max_references, |
3163 | + &max_width, |
3164 | + &max_height |
3165 | + ); |
3166 | + return (VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderQueryCapabilities()") && |
3167 | + is_supported); |
3168 | +} |
3169 | + |
3170 | +// Checks decoder for profile/entrypoint is available |
3171 | +VAStatus |
3172 | +check_decoder( |
3173 | + vdpau_driver_data_t *driver_data, |
3174 | + VAProfile profile, |
3175 | + VAEntrypoint entrypoint |
3176 | +) |
3177 | +{ |
3178 | + if (!is_supported_profile(driver_data, get_VdpDecoderProfile(profile))) |
3179 | + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; |
3180 | + |
3181 | + /* VDPAU only supports VLD */ |
3182 | + if (entrypoint != VAEntrypointVLD) |
3183 | + return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; |
3184 | + |
3185 | + return VA_STATUS_SUCCESS; |
3186 | +} |
3187 | + |
3188 | +// Computes value for VdpDecoderCreate()::max_references parameter |
3189 | +static int |
3190 | +get_max_ref_frames( |
3191 | + VdpDecoderProfile profile, |
3192 | + unsigned int width, |
3193 | + unsigned int height |
3194 | +) |
3195 | +{ |
3196 | + int max_ref_frames = 2; |
3197 | + |
3198 | + switch (profile) { |
3199 | + case VDP_DECODER_PROFILE_H264_MAIN: |
3200 | + case VDP_DECODER_PROFILE_H264_HIGH: |
3201 | + { |
3202 | + /* level 4.1 limits */ |
3203 | + unsigned int aligned_width = (width + 15) & -16; |
3204 | + unsigned int aligned_height = (height + 15) & -16; |
3205 | + unsigned int surface_size = (aligned_width * aligned_height * 3) / 2; |
3206 | + if ((max_ref_frames = (12 * 1024 * 1024) / surface_size) > 16) |
3207 | + max_ref_frames = 16; |
3208 | + break; |
3209 | + } |
3210 | + } |
3211 | + return max_ref_frames; |
3212 | +} |
3213 | + |
3214 | +// Returns the maximum number of reference frames of a decode session |
3215 | +static inline int get_num_ref_frames(object_context_p obj_context) |
3216 | +{ |
3217 | + if (obj_context->vdp_codec == VDP_CODEC_H264) |
3218 | + return obj_context->vdp_picture_info.h264.num_ref_frames; |
3219 | + return 2; |
3220 | +} |
3221 | + |
3222 | +// Ensure VDPAU decoder is created for the specified number of reference frames |
3223 | +static VdpStatus |
3224 | +ensure_decoder_with_max_refs( |
3225 | + vdpau_driver_data_t *driver_data, |
3226 | + object_context_p obj_context, |
3227 | + int max_ref_frames |
3228 | +) |
3229 | +{ |
3230 | + VdpStatus vdp_status; |
3231 | + |
3232 | + if (max_ref_frames < 0) |
3233 | + max_ref_frames = |
3234 | + get_max_ref_frames(obj_context->vdp_profile, |
3235 | + obj_context->picture_width, |
3236 | + obj_context->picture_height); |
3237 | + |
3238 | + if (obj_context->vdp_decoder == VDP_INVALID_HANDLE || |
3239 | + obj_context->max_ref_frames < max_ref_frames) { |
3240 | + obj_context->max_ref_frames = max_ref_frames; |
3241 | + |
3242 | + if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) { |
3243 | + vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder); |
3244 | + obj_context->vdp_decoder = VDP_INVALID_HANDLE; |
3245 | + } |
3246 | + |
3247 | + vdp_status = vdpau_decoder_create( |
3248 | + driver_data, |
3249 | + driver_data->vdp_device, |
3250 | + obj_context->vdp_profile, |
3251 | + obj_context->picture_width, |
3252 | + obj_context->picture_height, |
3253 | + max_ref_frames, |
3254 | + &obj_context->vdp_decoder |
3255 | + ); |
3256 | + if (!VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderCreate()")) |
3257 | + return vdp_status; |
3258 | + } |
3259 | + return VDP_STATUS_OK; |
3260 | +} |
3261 | + |
3262 | +// Lazy allocate (generated) slice data buffer. Buffer lives until vaDestroyContext() |
3263 | +static uint8_t * |
3264 | +alloc_gen_slice_data(object_context_p obj_context, unsigned int size) |
3265 | +{ |
3266 | + uint8_t *gen_slice_data = obj_context->gen_slice_data; |
3267 | + |
3268 | + if (obj_context->gen_slice_data_size + size > obj_context->gen_slice_data_size_max) { |
3269 | + obj_context->gen_slice_data_size_max += size; |
3270 | + gen_slice_data = realloc(obj_context->gen_slice_data, |
3271 | + obj_context->gen_slice_data_size_max); |
3272 | + if (!gen_slice_data) |
3273 | + return NULL; |
3274 | + obj_context->gen_slice_data = gen_slice_data; |
3275 | + } |
3276 | + gen_slice_data += obj_context->gen_slice_data_size; |
3277 | + obj_context->gen_slice_data_size += size; |
3278 | + return gen_slice_data; |
3279 | +} |
3280 | + |
3281 | +// Lazy allocate VdpBitstreamBuffer. Buffer lives until vaDestroyContext() |
3282 | +static VdpBitstreamBuffer * |
3283 | +alloc_VdpBitstreamBuffer(object_context_p obj_context) |
3284 | +{ |
3285 | + VdpBitstreamBuffer *vdp_bitstream_buffers; |
3286 | + |
3287 | + vdp_bitstream_buffers = realloc_buffer( |
3288 | + &obj_context->vdp_bitstream_buffers, |
3289 | + &obj_context->vdp_bitstream_buffers_count_max, |
3290 | + 1 + obj_context->vdp_bitstream_buffers_count, |
3291 | + sizeof(*obj_context->vdp_bitstream_buffers) |
3292 | + ); |
3293 | + if (!vdp_bitstream_buffers) |
3294 | + return NULL; |
3295 | + |
3296 | + return &vdp_bitstream_buffers[obj_context->vdp_bitstream_buffers_count++]; |
3297 | +} |
3298 | + |
3299 | +// Append VASliceDataBuffer hunk into VDPAU buffer |
3300 | +static int |
3301 | +append_VdpBitstreamBuffer( |
3302 | + object_context_p obj_context, |
3303 | + const uint8_t *buffer, |
3304 | + uint32_t buffer_size |
3305 | +) |
3306 | +{ |
3307 | + VdpBitstreamBuffer *bitstream_buffer; |
3308 | + |
3309 | + bitstream_buffer = alloc_VdpBitstreamBuffer(obj_context); |
3310 | + if (!bitstream_buffer) |
3311 | + return -1; |
3312 | + |
3313 | + bitstream_buffer->struct_version = VDP_BITSTREAM_BUFFER_VERSION; |
3314 | + bitstream_buffer->bitstream = buffer; |
3315 | + bitstream_buffer->bitstream_bytes = buffer_size; |
3316 | + return 0; |
3317 | +} |
3318 | + |
3319 | +// Initialize VdpReferenceFrameH264 to default values |
3320 | +static void init_VdpReferenceFrameH264(VdpReferenceFrameH264 *rf) |
3321 | +{ |
3322 | + rf->surface = VDP_INVALID_HANDLE; |
3323 | + rf->is_long_term = VDP_FALSE; |
3324 | + rf->top_is_reference = VDP_FALSE; |
3325 | + rf->bottom_is_reference = VDP_FALSE; |
3326 | + rf->field_order_cnt[0] = 0; |
3327 | + rf->field_order_cnt[1] = 0; |
3328 | + rf->frame_idx = 0; |
3329 | +} |
3330 | + |
3331 | +static const uint8_t ff_identity[64] = { |
3332 | + 0, 1, 2, 3, 4, 5, 6, 7, |
3333 | + 8, 9, 10, 11, 12, 13, 14, 15, |
3334 | + 16, 17, 18, 19, 20, 21, 22, 23, |
3335 | + 24, 25, 26, 27, 28, 29, 30, 31, |
3336 | + 32, 33, 34, 35, 36, 37, 38, 39, |
3337 | + 40, 41, 42, 43, 44, 45, 46, 47, |
3338 | + 48, 49, 50, 51, 52, 53, 54, 55, |
3339 | + 56, 57, 58, 59, 60, 61, 62, 63 |
3340 | +}; |
3341 | + |
3342 | +static const uint8_t ff_zigzag_direct[64] = { |
3343 | + 0, 1, 8, 16, 9, 2, 3, 10, |
3344 | + 17, 24, 32, 25, 18, 11, 4, 5, |
3345 | + 12, 19, 26, 33, 40, 48, 41, 34, |
3346 | + 27, 20, 13, 6, 7, 14, 21, 28, |
3347 | + 35, 42, 49, 56, 57, 50, 43, 36, |
3348 | + 29, 22, 15, 23, 30, 37, 44, 51, |
3349 | + 58, 59, 52, 45, 38, 31, 39, 46, |
3350 | + 53, 60, 61, 54, 47, 55, 62, 63 |
3351 | +}; |
3352 | + |
3353 | +static const uint8_t ff_mpeg1_default_intra_matrix[64] = { |
3354 | + 8, 16, 19, 22, 26, 27, 29, 34, |
3355 | + 16, 16, 22, 24, 27, 29, 34, 37, |
3356 | + 19, 22, 26, 27, 29, 34, 34, 38, |
3357 | + 22, 22, 26, 27, 29, 34, 37, 40, |
3358 | + 22, 26, 27, 29, 32, 35, 40, 48, |
3359 | + 26, 27, 29, 32, 35, 40, 48, 58, |
3360 | + 26, 27, 29, 34, 38, 46, 56, 69, |
3361 | + 27, 29, 35, 38, 46, 56, 69, 83 |
3362 | +}; |
3363 | + |
3364 | +static const uint8_t ff_mpeg1_default_non_intra_matrix[64] = { |
3365 | + 16, 16, 16, 16, 16, 16, 16, 16, |
3366 | + 16, 16, 16, 16, 16, 16, 16, 16, |
3367 | + 16, 16, 16, 16, 16, 16, 16, 16, |
3368 | + 16, 16, 16, 16, 16, 16, 16, 16, |
3369 | + 16, 16, 16, 16, 16, 16, 16, 16, |
3370 | + 16, 16, 16, 16, 16, 16, 16, 16, |
3371 | + 16, 16, 16, 16, 16, 16, 16, 16, |
3372 | + 16, 16, 16, 16, 16, 16, 16, 16 |
3373 | +}; |
3374 | + |
3375 | +static const uint8_t ff_mpeg4_default_intra_matrix[64] = { |
3376 | + 8, 17, 18, 19, 21, 23, 25, 27, |
3377 | + 17, 18, 19, 21, 23, 25, 27, 28, |
3378 | + 20, 21, 22, 23, 24, 26, 28, 30, |
3379 | + 21, 22, 23, 24, 26, 28, 30, 32, |
3380 | + 22, 23, 24, 26, 28, 30, 32, 35, |
3381 | + 23, 24, 26, 28, 30, 32, 35, 38, |
3382 | + 25, 26, 28, 30, 32, 35, 38, 41, |
3383 | + 27, 28, 30, 32, 35, 38, 41, 45, |
3384 | +}; |
3385 | + |
3386 | +static const uint8_t ff_mpeg4_default_non_intra_matrix[64] = { |
3387 | + 16, 17, 18, 19, 20, 21, 22, 23, |
3388 | + 17, 18, 19, 20, 21, 22, 23, 24, |
3389 | + 18, 19, 20, 21, 22, 23, 24, 25, |
3390 | + 19, 20, 21, 22, 23, 24, 26, 27, |
3391 | + 20, 21, 22, 23, 25, 26, 27, 28, |
3392 | + 21, 22, 23, 24, 26, 27, 28, 30, |
3393 | + 22, 23, 24, 26, 27, 28, 30, 31, |
3394 | + 23, 24, 25, 27, 28, 30, 31, 33, |
3395 | +}; |
3396 | + |
3397 | +// Compute integer log2 |
3398 | +static inline int ilog2(uint32_t v) |
3399 | +{ |
3400 | + /* From <http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog> */ |
3401 | + uint32_t r, shift; |
3402 | + r = (v > 0xffff) << 4; v >>= r; |
3403 | + shift = (v > 0xff ) << 3; v >>= shift; r |= shift; |
3404 | + shift = (v > 0xf ) << 2; v >>= shift; r |= shift; |
3405 | + shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; |
3406 | + return r | (v >> 1); |
3407 | +} |
3408 | + |
3409 | +// Translate VASurfaceID |
3410 | +static int |
3411 | +translate_VASurfaceID( |
3412 | + vdpau_driver_data_t *driver_data, |
3413 | + VASurfaceID va_surface, |
3414 | + VdpVideoSurface *vdp_surface |
3415 | +) |
3416 | +{ |
3417 | + object_surface_p obj_surface; |
3418 | + |
3419 | + if (va_surface == VA_INVALID_SURFACE) { |
3420 | + *vdp_surface = VDP_INVALID_HANDLE; |
3421 | + return 1; |
3422 | + } |
3423 | + |
3424 | + obj_surface = VDPAU_SURFACE(va_surface); |
3425 | + if (!obj_surface) |
3426 | + return 0; |
3427 | + |
3428 | + *vdp_surface = obj_surface->vdp_surface; |
3429 | + return 1; |
3430 | +} |
3431 | + |
3432 | +// Translate VAPictureH264 |
3433 | +static int |
3434 | +translate_VAPictureH264( |
3435 | + vdpau_driver_data_t *driver_data, |
3436 | + const VAPictureH264 *va_pic, |
3437 | + VdpReferenceFrameH264 *rf |
3438 | +) |
3439 | +{ |
3440 | + // Handle invalid surfaces specifically |
3441 | + if (va_pic->picture_id == VA_INVALID_SURFACE) { |
3442 | + init_VdpReferenceFrameH264(rf); |
3443 | + return 1; |
3444 | + } |
3445 | + |
3446 | + if (!translate_VASurfaceID(driver_data, va_pic->picture_id, &rf->surface)) |
3447 | + return 0; |
3448 | + rf->is_long_term = (va_pic->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE) != 0; |
3449 | + if ((va_pic->flags & (VA_PICTURE_H264_TOP_FIELD|VA_PICTURE_H264_BOTTOM_FIELD)) == 0) { |
3450 | + rf->top_is_reference = VDP_TRUE; |
3451 | + rf->bottom_is_reference = VDP_TRUE; |
3452 | + } |
3453 | + else { |
3454 | + rf->top_is_reference = (va_pic->flags & VA_PICTURE_H264_TOP_FIELD) != 0; |
3455 | + rf->bottom_is_reference = (va_pic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0; |
3456 | + } |
3457 | + rf->field_order_cnt[0] = va_pic->TopFieldOrderCnt; |
3458 | + rf->field_order_cnt[1] = va_pic->BottomFieldOrderCnt; |
3459 | + rf->frame_idx = va_pic->frame_idx; |
3460 | + return 1; |
3461 | +} |
3462 | + |
3463 | +// Translate no buffer |
3464 | +static int |
3465 | +translate_nothing( |
3466 | + vdpau_driver_data_t *driver_data, |
3467 | + object_context_p obj_context, |
3468 | + object_buffer_p obj_buffer |
3469 | +) |
3470 | +{ |
3471 | + return 1; |
3472 | +} |
3473 | + |
3474 | +// Translate VASliceDataBuffer |
3475 | +static int |
3476 | +translate_VASliceDataBuffer( |
3477 | + vdpau_driver_data_t *driver_data, |
3478 | + object_context_p obj_context, |
3479 | + object_buffer_p obj_buffer |
3480 | +) |
3481 | +{ |
3482 | + if (obj_context->vdp_codec == VDP_CODEC_H264) { |
3483 | + /* Check we have the start code */ |
3484 | + /* XXX: check for other codecs too? */ |
3485 | + /* XXX: this assumes we get SliceParams before SliceData */ |
3486 | + static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; |
3487 | + VASliceParameterBufferH264 * const slice_params = obj_context->last_slice_params; |
3488 | + unsigned int i; |
3489 | + for (i = 0; i < obj_context->last_slice_params_count; i++) { |
3490 | + VASliceParameterBufferH264 * const slice_param = &slice_params[i]; |
3491 | + uint8_t *buf = (uint8_t *)obj_buffer->buffer_data + slice_param->slice_data_offset; |
3492 | + if (memcmp(buf, start_code_prefix, sizeof(start_code_prefix)) != 0) { |
3493 | + if (append_VdpBitstreamBuffer(obj_context, |
3494 | + start_code_prefix, |
3495 | + sizeof(start_code_prefix)) < 0) |
3496 | + return 0; |
3497 | + } |
3498 | + if (append_VdpBitstreamBuffer(obj_context, |
3499 | + buf, |
3500 | + slice_param->slice_data_size) < 0) |
3501 | + return 0; |
3502 | + } |
3503 | + return 1; |
3504 | + } |
3505 | + |
3506 | +#if USE_VDPAU_MPEG4 |
3507 | + if (obj_context->vdp_codec == VDP_CODEC_MPEG4 && |
3508 | + obj_context->vdp_bitstream_buffers_count == 0) { |
3509 | + PutBitContext pb; |
3510 | + uint8_t slice_header_buffer[32]; |
3511 | + uint8_t *slice_header; |
3512 | + int slice_header_size; |
3513 | + const uint8_t *slice_data = obj_buffer->buffer_data; |
3514 | + uint32_t slice_data_size = obj_buffer->buffer_size; |
3515 | + VAPictureParameterBufferMPEG4 * const pic_param = obj_context->last_pic_param; |
3516 | + VASliceParameterBufferMPEG4 * const slice_param = obj_context->last_slice_params; |
3517 | + |
3518 | + int time_incr = 1 + ilog2(pic_param->vop_time_increment_resolution - 1); |
3519 | + if (time_incr < 1) |
3520 | + time_incr = 1; |
3521 | + |
3522 | + static const uint16_t VOP_STARTCODE = 0x01b6; |
3523 | + enum { |
3524 | + VOP_I_TYPE = 0, |
3525 | + VOP_P_TYPE, |
3526 | + VOP_B_TYPE, |
3527 | + VOP_S_TYPE |
3528 | + }; |
3529 | + |
3530 | + /* XXX: this is a hack to compute the length of |
3531 | + modulo_time_base "1" sequence. We probably should be |
3532 | + reconstructing through an extra VOP field in VA-API? */ |
3533 | + int nbits = (32 + /* VOP start code */ |
3534 | + 2 + /* vop_coding_type */ |
3535 | + 1 + /* modulo_time_base "0" */ |
3536 | + 1 + /* marker_bit */ |
3537 | + time_incr + /* vop_time_increment */ |
3538 | + 1 + /* marker_bit */ |
3539 | + 1 + /* vop_coded */ |
3540 | + (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE ? 1 : 0) + |
3541 | + 3 + /* intra_dc_vlc_thr */ |
3542 | + (pic_param->vol_fields.bits.interlaced ? 2 : 0) + |
3543 | + 5 + /* vop_quant */ |
3544 | + (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE ? 3 : 0) + |
3545 | + (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE ? 3 : 0)); |
3546 | + if ((nbits = slice_param->macroblock_offset - (nbits % 8)) < 0) |
3547 | + nbits += 8; |
3548 | + |
3549 | + /* Reconstruct the VOP header */ |
3550 | + init_put_bits(&pb, slice_header_buffer, sizeof(slice_header_buffer)); |
3551 | + put_bits(&pb, 16, 0); /* vop header */ |
3552 | + put_bits(&pb, 16, VOP_STARTCODE); /* vop header */ |
3553 | + put_bits(&pb, 2, pic_param->vop_fields.bits.vop_coding_type); |
3554 | + while (nbits-- > 0) |
3555 | + put_bits(&pb, 1, 1); /* modulo_time_base "1" */ |
3556 | + put_bits(&pb, 1, 0); /* modulo_time_base "0" */ |
3557 | + put_bits(&pb, 1, 1); /* marker */ |
3558 | + put_bits(&pb, time_incr, 0); /* time increment */ |
3559 | + put_bits(&pb, 1, 1); /* marker */ |
3560 | + put_bits(&pb, 1, 1); /* vop coded */ |
3561 | + if (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE) |
3562 | + put_bits(&pb, 1, pic_param->vop_fields.bits.vop_rounding_type); |
3563 | + put_bits(&pb, 3, pic_param->vop_fields.bits.intra_dc_vlc_thr); |
3564 | + if (pic_param->vol_fields.bits.interlaced) { |
3565 | + put_bits(&pb, 1, pic_param->vop_fields.bits.top_field_first); |
3566 | + put_bits(&pb, 1, pic_param->vop_fields.bits.alternate_vertical_scan_flag); |
3567 | + } |
3568 | + put_bits(&pb, 5, slice_param->quant_scale); |
3569 | + if (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE) |
3570 | + put_bits(&pb, 3, pic_param->vop_fcode_forward); |
3571 | + if (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE) |
3572 | + put_bits(&pb, 3, pic_param->vop_fcode_backward); |
3573 | + |
3574 | + /* Merge in bits from the first byte of the slice */ |
3575 | + ASSERT((put_bits_count(&pb) % 8) == slice_param->macroblock_offset); |
3576 | + if ((put_bits_count(&pb) % 8) != slice_param->macroblock_offset) |
3577 | + return 0; |
3578 | + const int r = 8 - (put_bits_count(&pb) % 8); |
3579 | + if (r > 0) |
3580 | + put_bits(&pb, r, slice_data[0] & ((1U << r) - 1)); |
3581 | + flush_put_bits(&pb); |
3582 | + |
3583 | + ASSERT((put_bits_count(&pb) % 8) == 0); |
3584 | + slice_header_size = put_bits_count(&pb) / 8; |
3585 | + ASSERT(slice_header_size <= sizeof(slice_header_buffer)); |
3586 | + slice_header = alloc_gen_slice_data(obj_context, slice_header_size); |
3587 | + if (!slice_header) |
3588 | + return 0; |
3589 | + memcpy(slice_header, slice_header_buffer, slice_header_size); |
3590 | + if (append_VdpBitstreamBuffer(obj_context, slice_header, slice_header_size) < 0) |
3591 | + return 0; |
3592 | + if (append_VdpBitstreamBuffer(obj_context, slice_data + 1, slice_data_size - 1) < 0) |
3593 | + return 0; |
3594 | + return 1; |
3595 | + } |
3596 | +#endif |
3597 | + |
3598 | + if (append_VdpBitstreamBuffer(obj_context, |
3599 | + obj_buffer->buffer_data, |
3600 | + obj_buffer->buffer_size) < 0) |
3601 | + return 0; |
3602 | + return 1; |
3603 | +} |
3604 | + |
3605 | +// Translate VAPictureParameterBufferMPEG2 |
3606 | +static int |
3607 | +translate_VAPictureParameterBufferMPEG2( |
3608 | + vdpau_driver_data_t *driver_data, |
3609 | + object_context_p obj_context, |
3610 | + object_buffer_p obj_buffer |
3611 | +) |
3612 | +{ |
3613 | + VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; |
3614 | + VAPictureParameterBufferMPEG2 * const pic_param = obj_buffer->buffer_data; |
3615 | + |
3616 | + if (!translate_VASurfaceID(driver_data, |
3617 | + pic_param->forward_reference_picture, |
3618 | + &pic_info->forward_reference)) |
3619 | + return 0; |
3620 | + |
3621 | + if (!translate_VASurfaceID(driver_data, |
3622 | + pic_param->backward_reference_picture, |
3623 | + &pic_info->backward_reference)) |
3624 | + return 0; |
3625 | + |
3626 | + pic_info->picture_structure = pic_param->picture_coding_extension.bits.picture_structure; |
3627 | + pic_info->picture_coding_type = pic_param->picture_coding_type; |
3628 | + pic_info->intra_dc_precision = pic_param->picture_coding_extension.bits.intra_dc_precision; |
3629 | + pic_info->frame_pred_frame_dct = pic_param->picture_coding_extension.bits.frame_pred_frame_dct; |
3630 | + pic_info->concealment_motion_vectors = pic_param->picture_coding_extension.bits.concealment_motion_vectors; |
3631 | + pic_info->intra_vlc_format = pic_param->picture_coding_extension.bits.intra_vlc_format; |
3632 | + pic_info->alternate_scan = pic_param->picture_coding_extension.bits.alternate_scan; |
3633 | + pic_info->q_scale_type = pic_param->picture_coding_extension.bits.q_scale_type; |
3634 | + pic_info->top_field_first = pic_param->picture_coding_extension.bits.top_field_first; |
3635 | + pic_info->full_pel_forward_vector = 0; |
3636 | + pic_info->full_pel_backward_vector = 0; |
3637 | + pic_info->f_code[0][0] = (pic_param->f_code >> 12) & 0xf; |
3638 | + pic_info->f_code[0][1] = (pic_param->f_code >> 8) & 0xf; |
3639 | + pic_info->f_code[1][0] = (pic_param->f_code >> 4) & 0xf; |
3640 | + pic_info->f_code[1][1] = pic_param->f_code & 0xf; |
3641 | + return 1; |
3642 | +} |
3643 | + |
3644 | +// Translate VAIQMatrixBufferMPEG2 |
3645 | +static int |
3646 | +translate_VAIQMatrixBufferMPEG2( |
3647 | + vdpau_driver_data_t *driver_data, |
3648 | + object_context_p obj_context, |
3649 | + object_buffer_p obj_buffer |
3650 | +) |
3651 | +{ |
3652 | + VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; |
3653 | + VAIQMatrixBufferMPEG2 * const iq_matrix = obj_buffer->buffer_data; |
3654 | + const uint8_t *intra_matrix; |
3655 | + const uint8_t *intra_matrix_lookup; |
3656 | + const uint8_t *inter_matrix; |
3657 | + const uint8_t *inter_matrix_lookup; |
3658 | + int i; |
3659 | + |
3660 | + if (iq_matrix->load_intra_quantiser_matrix) { |
3661 | + intra_matrix = iq_matrix->intra_quantiser_matrix; |
3662 | + intra_matrix_lookup = ff_zigzag_direct; |
3663 | + } |
3664 | + else { |
3665 | + intra_matrix = ff_mpeg1_default_intra_matrix; |
3666 | + intra_matrix_lookup = ff_identity; |
3667 | + } |
3668 | + |
3669 | + if (iq_matrix->load_non_intra_quantiser_matrix) { |
3670 | + inter_matrix = iq_matrix->non_intra_quantiser_matrix; |
3671 | + inter_matrix_lookup = ff_zigzag_direct; |
3672 | + } |
3673 | + else { |
3674 | + inter_matrix = ff_mpeg1_default_non_intra_matrix; |
3675 | + inter_matrix_lookup = ff_identity; |
3676 | + } |
3677 | + |
3678 | + for (i = 0; i < 64; i++) { |
3679 | + pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] = |
3680 | + intra_matrix[i]; |
3681 | + pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] = |
3682 | + inter_matrix[i]; |
3683 | + } |
3684 | + return 1; |
3685 | +} |
3686 | + |
3687 | +// Translate VASliceParameterBufferMPEG2 |
3688 | +static int |
3689 | +translate_VASliceParameterBufferMPEG2( |
3690 | + vdpau_driver_data_t *driver_data, |
3691 | + object_context_p obj_context, |
3692 | + object_buffer_p obj_buffer |
3693 | + ) |
3694 | +{ |
3695 | + VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; |
3696 | + |
3697 | + pic_info->slice_count += obj_buffer->num_elements; |
3698 | + obj_context->last_slice_params = obj_buffer->buffer_data; |
3699 | + obj_context->last_slice_params_count = obj_buffer->num_elements; |
3700 | + return 1; |
3701 | +} |
3702 | + |
3703 | +#if USE_VDPAU_MPEG4 |
3704 | +// Translate VAPictureParameterBufferMPEG4 |
3705 | +static int |
3706 | +translate_VAPictureParameterBufferMPEG4( |
3707 | + vdpau_driver_data_p driver_data, |
3708 | + object_context_p obj_context, |
3709 | + object_buffer_p obj_buffer |
3710 | +) |
3711 | +{ |
3712 | + VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4; |
3713 | + VAPictureParameterBufferMPEG4 * const pic_param = obj_buffer->buffer_data; |
3714 | + |
3715 | + /* XXX: we don't support short-video-header formats */ |
3716 | + if (pic_param->vol_fields.bits.short_video_header) |
3717 | + return 0; |
3718 | + |
3719 | + if (!translate_VASurfaceID(driver_data, |
3720 | + pic_param->forward_reference_picture, |
3721 | + &pic_info->forward_reference)) |
3722 | + return 0; |
3723 | + |
3724 | + if (!translate_VASurfaceID(driver_data, |
3725 | + pic_param->backward_reference_picture, |
3726 | + &pic_info->backward_reference)) |
3727 | + return 0; |
3728 | + |
3729 | + if (pic_param->vol_fields.bits.interlaced) { |
3730 | + vdpau_information_message("unsupported MPEG-4 video with interlaced " |
3731 | + "content, please report this video\n"); |
3732 | + pic_info->trd[0] = 2*pic_param->TRD; /* XXX: + d(0) */ |
3733 | + pic_info->trb[0] = 2*pic_param->TRB; /* XXX: + d(0) */ |
3734 | + pic_info->trd[1] = 2*pic_param->TRD; /* XXX: + d(1) */ |
3735 | + pic_info->trb[1] = 2*pic_param->TRB; /* XXX: + d(1) */ |
3736 | + } |
3737 | + else { |
3738 | + pic_info->trd[0] = pic_param->TRD; |
3739 | + pic_info->trb[0] = pic_param->TRB; |
3740 | + pic_info->trd[1] = 0; |
3741 | + pic_info->trb[1] = 0; |
3742 | + } |
3743 | + |
3744 | + pic_info->vop_time_increment_resolution = pic_param->vop_time_increment_resolution; |
3745 | + pic_info->vop_coding_type = pic_param->vop_fields.bits.vop_coding_type; |
3746 | + pic_info->vop_fcode_forward = pic_param->vop_fcode_forward; |
3747 | + pic_info->vop_fcode_backward = pic_param->vop_fcode_backward; |
3748 | + pic_info->resync_marker_disable = pic_param->vol_fields.bits.resync_marker_disable; |
3749 | + pic_info->interlaced = pic_param->vol_fields.bits.interlaced; |
3750 | + pic_info->quant_type = pic_param->vol_fields.bits.quant_type; |
3751 | + pic_info->quarter_sample = pic_param->vol_fields.bits.quarter_sample; |
3752 | + pic_info->short_video_header = pic_param->vol_fields.bits.short_video_header; |
3753 | + pic_info->rounding_control = pic_param->vop_fields.bits.vop_rounding_type; |
3754 | + pic_info->alternate_vertical_scan_flag = pic_param->vop_fields.bits.alternate_vertical_scan_flag; |
3755 | + pic_info->top_field_first = pic_param->vop_fields.bits.top_field_first; |
3756 | + |
3757 | + obj_context->last_pic_param = obj_buffer->buffer_data; |
3758 | + return 1; |
3759 | +} |
3760 | + |
3761 | +// Translate VAIQMatrixBufferMPEG4 |
3762 | +static int |
3763 | +translate_VAIQMatrixBufferMPEG4( |
3764 | + vdpau_driver_data_p driver_data, |
3765 | + object_context_p obj_context, |
3766 | + object_buffer_p obj_buffer |
3767 | +) |
3768 | +{ |
3769 | + VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4; |
3770 | + VAIQMatrixBufferMPEG4 * const iq_matrix = obj_buffer->buffer_data; |
3771 | + const uint8_t *intra_matrix; |
3772 | + const uint8_t *intra_matrix_lookup; |
3773 | + const uint8_t *inter_matrix; |
3774 | + const uint8_t *inter_matrix_lookup; |
3775 | + int i; |
3776 | + |
3777 | + if (iq_matrix->load_intra_quant_mat) { |
3778 | + intra_matrix = iq_matrix->intra_quant_mat; |
3779 | + intra_matrix_lookup = ff_zigzag_direct; |
3780 | + } |
3781 | + else { |
3782 | + intra_matrix = ff_mpeg4_default_intra_matrix; |
3783 | + intra_matrix_lookup = ff_identity; |
3784 | + } |
3785 | + |
3786 | + if (iq_matrix->load_non_intra_quant_mat) { |
3787 | + inter_matrix = iq_matrix->non_intra_quant_mat; |
3788 | + inter_matrix_lookup = ff_zigzag_direct; |
3789 | + } |
3790 | + else { |
3791 | + inter_matrix = ff_mpeg4_default_non_intra_matrix; |
3792 | + inter_matrix_lookup = ff_identity; |
3793 | + } |
3794 | + |
3795 | + for (i = 0; i < 64; i++) { |
3796 | + pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] = |
3797 | + intra_matrix[i]; |
3798 | + pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] = |
3799 | + inter_matrix[i]; |
3800 | + } |
3801 | + return 1; |
3802 | +} |
3803 | + |
3804 | +// Translate VASliceParameterBufferMPEG4 |
3805 | +static int |
3806 | +translate_VASliceParameterBufferMPEG4( |
3807 | + vdpau_driver_data_p driver_data, |
3808 | + object_context_p obj_context, |
3809 | + object_buffer_p obj_buffer |
3810 | + ) |
3811 | +{ |
3812 | + obj_context->last_slice_params = obj_buffer->buffer_data; |
3813 | + obj_context->last_slice_params_count = obj_buffer->num_elements; |
3814 | + return 1; |
3815 | +} |
3816 | +#endif |
3817 | + |
3818 | +// Translate VAPictureParameterBufferH264 |
3819 | +static int |
3820 | +translate_VAPictureParameterBufferH264( |
3821 | + vdpau_driver_data_t *driver_data, |
3822 | + object_context_p obj_context, |
3823 | + object_buffer_p obj_buffer |
3824 | +) |
3825 | +{ |
3826 | + VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; |
3827 | + VAPictureParameterBufferH264 * const pic_param = obj_buffer->buffer_data; |
3828 | + VAPictureH264 * const CurrPic = &pic_param->CurrPic; |
3829 | + unsigned int i; |
3830 | + |
3831 | + pic_info->field_order_cnt[0] = CurrPic->TopFieldOrderCnt; |
3832 | + pic_info->field_order_cnt[1] = CurrPic->BottomFieldOrderCnt; |
3833 | + pic_info->is_reference = pic_param->pic_fields.bits.reference_pic_flag; |
3834 | + |
3835 | + pic_info->frame_num = pic_param->frame_num; |
3836 | + pic_info->field_pic_flag = pic_param->pic_fields.bits.field_pic_flag; |
3837 | + pic_info->bottom_field_flag = pic_param->pic_fields.bits.field_pic_flag && (CurrPic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0; |
3838 | + pic_info->num_ref_frames = pic_param->num_ref_frames; |
3839 | + pic_info->mb_adaptive_frame_field_flag = pic_param->seq_fields.bits.mb_adaptive_frame_field_flag && !pic_info->field_pic_flag; |
3840 | + pic_info->constrained_intra_pred_flag = pic_param->pic_fields.bits.constrained_intra_pred_flag; |
3841 | + pic_info->weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag; |
3842 | + pic_info->weighted_bipred_idc = pic_param->pic_fields.bits.weighted_bipred_idc; |
3843 | + pic_info->frame_mbs_only_flag = pic_param->seq_fields.bits.frame_mbs_only_flag; |
3844 | + pic_info->transform_8x8_mode_flag = pic_param->pic_fields.bits.transform_8x8_mode_flag; |
3845 | + pic_info->chroma_qp_index_offset = pic_param->chroma_qp_index_offset; |
3846 | + pic_info->second_chroma_qp_index_offset = pic_param->second_chroma_qp_index_offset; |
3847 | + pic_info->pic_init_qp_minus26 = pic_param->pic_init_qp_minus26; |
3848 | + pic_info->log2_max_frame_num_minus4 = pic_param->seq_fields.bits.log2_max_frame_num_minus4; |
3849 | + pic_info->pic_order_cnt_type = pic_param->seq_fields.bits.pic_order_cnt_type; |
3850 | + pic_info->log2_max_pic_order_cnt_lsb_minus4 = pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4; |
3851 | + pic_info->delta_pic_order_always_zero_flag = pic_param->seq_fields.bits.delta_pic_order_always_zero_flag; |
3852 | + pic_info->direct_8x8_inference_flag = pic_param->seq_fields.bits.direct_8x8_inference_flag; |
3853 | + pic_info->entropy_coding_mode_flag = pic_param->pic_fields.bits.entropy_coding_mode_flag; |
3854 | + pic_info->pic_order_present_flag = pic_param->pic_fields.bits.pic_order_present_flag; |
3855 | + pic_info->deblocking_filter_control_present_flag = pic_param->pic_fields.bits.deblocking_filter_control_present_flag; |
3856 | + pic_info->redundant_pic_cnt_present_flag = pic_param->pic_fields.bits.redundant_pic_cnt_present_flag; |
3857 | + |
3858 | + for (i = 0; i < 16; i++) { |
3859 | + if (!translate_VAPictureH264(driver_data, |
3860 | + &pic_param->ReferenceFrames[i], |
3861 | + &pic_info->referenceFrames[i])) |
3862 | + return 0; |
3863 | + } |
3864 | + return 1; |
3865 | +} |
3866 | + |
3867 | +// Translate VAIQMatrixBufferH264 |
3868 | +static int |
3869 | +translate_VAIQMatrixBufferH264( |
3870 | + vdpau_driver_data_t *driver_data, |
3871 | + object_context_p obj_context, |
3872 | + object_buffer_p obj_buffer |
3873 | +) |
3874 | +{ |
3875 | + VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; |
3876 | + VAIQMatrixBufferH264 * const iq_matrix = obj_buffer->buffer_data; |
3877 | + int i, j; |
3878 | + |
3879 | + if (sizeof(pic_info->scaling_lists_4x4) == sizeof(iq_matrix->ScalingList4x4)) |
3880 | + memcpy(pic_info->scaling_lists_4x4, iq_matrix->ScalingList4x4, |
3881 | + sizeof(pic_info->scaling_lists_4x4)); |
3882 | + else { |
3883 | + for (j = 0; j < 6; j++) { |
3884 | + for (i = 0; i < 16; i++) |
3885 | + pic_info->scaling_lists_4x4[j][i] = iq_matrix->ScalingList4x4[j][i]; |
3886 | + } |
3887 | + } |
3888 | + |
3889 | + if (sizeof(pic_info->scaling_lists_8x8) == sizeof(iq_matrix->ScalingList8x8)) |
3890 | + memcpy(pic_info->scaling_lists_8x8, iq_matrix->ScalingList8x8, |
3891 | + sizeof(pic_info->scaling_lists_8x8)); |
3892 | + else { |
3893 | + for (j = 0; j < 2; j++) { |
3894 | + for (i = 0; i < 64; i++) |
3895 | + pic_info->scaling_lists_8x8[j][i] = iq_matrix->ScalingList8x8[j][i]; |
3896 | + } |
3897 | + } |
3898 | + return 1; |
3899 | +} |
3900 | + |
3901 | +// Translate VASliceParameterBufferH264 |
3902 | +static int |
3903 | +translate_VASliceParameterBufferH264( |
3904 | + vdpau_driver_data_t *driver_data, |
3905 | + object_context_p obj_context, |
3906 | + object_buffer_p obj_buffer |
3907 | +) |
3908 | +{ |
3909 | + VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; |
3910 | + VASliceParameterBufferH264 * const slice_params = obj_buffer->buffer_data; |
3911 | + VASliceParameterBufferH264 * const slice_param = &slice_params[obj_buffer->num_elements - 1]; |
3912 | + |
3913 | + pic_info->slice_count += obj_buffer->num_elements; |
3914 | + pic_info->num_ref_idx_l0_active_minus1 = slice_param->num_ref_idx_l0_active_minus1; |
3915 | + pic_info->num_ref_idx_l1_active_minus1 = slice_param->num_ref_idx_l1_active_minus1; |
3916 | + obj_context->last_slice_params = obj_buffer->buffer_data; |
3917 | + obj_context->last_slice_params_count = obj_buffer->num_elements; |
3918 | + return 1; |
3919 | +} |
3920 | + |
3921 | +// Translate VAPictureParameterBufferVC1 |
3922 | +static int |
3923 | +translate_VAPictureParameterBufferVC1( |
3924 | + vdpau_driver_data_t *driver_data, |
3925 | + object_context_p obj_context, |
3926 | + object_buffer_p obj_buffer |
3927 | +) |
3928 | +{ |
3929 | + VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1; |
3930 | + VAPictureParameterBufferVC1 * const pic_param = obj_buffer->buffer_data; |
3931 | + int picture_type, major_version, minor_version; |
3932 | + |
3933 | + if (!translate_VASurfaceID(driver_data, |
3934 | + pic_param->forward_reference_picture, |
3935 | + &pic_info->forward_reference)) |
3936 | + return 0; |
3937 | + |
3938 | + if (!translate_VASurfaceID(driver_data, |
3939 | + pic_param->backward_reference_picture, |
3940 | + &pic_info->backward_reference)) |
3941 | + return 0; |
3942 | + |
3943 | + switch (pic_param->picture_fields.bits.picture_type) { |
3944 | + case 0: picture_type = 0; break; /* I */ |
3945 | + case 1: picture_type = 1; break; /* P */ |
3946 | + case 2: picture_type = 3; break; /* B */ |
3947 | + case 3: picture_type = 4; break; /* BI */ |
3948 | + case 4: picture_type = 1; break; /* P "skipped" */ |
3949 | + default: return 0; |
3950 | + } |
3951 | + |
3952 | + pic_info->picture_type = picture_type; |
3953 | + pic_info->frame_coding_mode = pic_param->picture_fields.bits.frame_coding_mode; |
3954 | + pic_info->postprocflag = pic_param->post_processing != 0; |
3955 | + pic_info->pulldown = pic_param->sequence_fields.bits.pulldown; |
3956 | + pic_info->interlace = pic_param->sequence_fields.bits.interlace; |
3957 | + pic_info->tfcntrflag = pic_param->sequence_fields.bits.tfcntrflag; |
3958 | + pic_info->finterpflag = pic_param->sequence_fields.bits.finterpflag; |
3959 | + pic_info->psf = pic_param->sequence_fields.bits.psf; |
3960 | + pic_info->dquant = pic_param->pic_quantizer_fields.bits.dquant; |
3961 | + pic_info->panscan_flag = pic_param->entrypoint_fields.bits.panscan_flag; |
3962 | + pic_info->refdist_flag = pic_param->reference_fields.bits.reference_distance_flag; |
3963 | + pic_info->quantizer = pic_param->pic_quantizer_fields.bits.quantizer; |
3964 | + pic_info->extended_mv = pic_param->mv_fields.bits.extended_mv_flag; |
3965 | + pic_info->extended_dmv = pic_param->mv_fields.bits.extended_dmv_flag; |
3966 | + pic_info->overlap = pic_param->sequence_fields.bits.overlap; |
3967 | + pic_info->vstransform = pic_param->transform_fields.bits.variable_sized_transform_flag; |
3968 | + pic_info->loopfilter = pic_param->entrypoint_fields.bits.loopfilter; |
3969 | + pic_info->fastuvmc = pic_param->fast_uvmc_flag; |
3970 | + pic_info->range_mapy_flag = pic_param->range_mapping_fields.bits.luma_flag; |
3971 | + pic_info->range_mapy = pic_param->range_mapping_fields.bits.luma; |
3972 | + pic_info->range_mapuv_flag = pic_param->range_mapping_fields.bits.chroma_flag; |
3973 | + pic_info->range_mapuv = pic_param->range_mapping_fields.bits.chroma; |
3974 | + pic_info->multires = pic_param->sequence_fields.bits.multires; |
3975 | + pic_info->syncmarker = pic_param->sequence_fields.bits.syncmarker; |
3976 | + pic_info->rangered = pic_param->sequence_fields.bits.rangered; |
3977 | + if (!vdpau_is_nvidia(driver_data, &major_version, &minor_version) || |
3978 | + (major_version > 180 || minor_version >= 35)) |
3979 | + pic_info->rangered |= pic_param->range_reduction_frame << 1; |
3980 | + pic_info->maxbframes = pic_param->sequence_fields.bits.max_b_frames; |
3981 | + pic_info->deblockEnable = pic_param->post_processing != 0; /* XXX: this is NVIDIA's vdpau.c semantics (postprocflag & 1) */ |
3982 | + pic_info->pquant = pic_param->pic_quantizer_fields.bits.pic_quantizer_scale; |
3983 | + return 1; |
3984 | +} |
3985 | + |
3986 | +// Translate VASliceParameterBufferVC1 |
3987 | +static int |
3988 | +translate_VASliceParameterBufferVC1( |
3989 | + vdpau_driver_data_t *driver_data, |
3990 | + object_context_p obj_context, |
3991 | + object_buffer_p obj_buffer |
3992 | +) |
3993 | +{ |
3994 | + VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1; |
3995 | + |
3996 | + pic_info->slice_count += obj_buffer->num_elements; |
3997 | + obj_context->last_slice_params = obj_buffer->buffer_data; |
3998 | + obj_context->last_slice_params_count = obj_buffer->num_elements; |
3999 | + return 1; |
4000 | +} |
4001 | + |
4002 | +// Translate VA buffer |
4003 | +typedef int |
4004 | +(*translate_buffer_func_t)(vdpau_driver_data_t *driver_data, |
4005 | + object_context_p obj_context, |
4006 | + object_buffer_p obj_buffer); |
4007 | + |
4008 | +typedef struct translate_buffer_info translate_buffer_info_t; |
4009 | +struct translate_buffer_info { |
4010 | + VdpCodec codec; |
4011 | + VABufferType type; |
4012 | + translate_buffer_func_t func; |
4013 | +}; |
4014 | + |
4015 | +static int |
4016 | +translate_buffer( |
4017 | + vdpau_driver_data_t *driver_data, |
4018 | + object_context_p obj_context, |
4019 | + object_buffer_p obj_buffer |
4020 | +) |
4021 | +{ |
4022 | + static const translate_buffer_info_t translate_info[] = { |
4023 | +#define _(CODEC, TYPE) \ |
4024 | + { VDP_CODEC_##CODEC, VA##TYPE##BufferType, \ |
4025 | + translate_VA##TYPE##Buffer##CODEC } |
4026 | + _(MPEG2, PictureParameter), |
4027 | + _(MPEG2, IQMatrix), |
4028 | + _(MPEG2, SliceParameter), |
4029 | +#if USE_VDPAU_MPEG4 |
4030 | + _(MPEG4, PictureParameter), |
4031 | + _(MPEG4, IQMatrix), |
4032 | + _(MPEG4, SliceParameter), |
4033 | +#endif |
4034 | + _(H264, PictureParameter), |
4035 | + _(H264, IQMatrix), |
4036 | + _(H264, SliceParameter), |
4037 | + _(VC1, PictureParameter), |
4038 | + _(VC1, SliceParameter), |
4039 | +#undef _ |
4040 | + { VDP_CODEC_VC1, VABitPlaneBufferType, translate_nothing }, |
4041 | + { 0, VASliceDataBufferType, translate_VASliceDataBuffer }, |
4042 | + { 0, 0, NULL } |
4043 | + }; |
4044 | + const translate_buffer_info_t *tbip; |
4045 | + for (tbip = translate_info; tbip->func != NULL; tbip++) { |
4046 | + if (tbip->codec && tbip->codec != obj_context->vdp_codec) |
4047 | + continue; |
4048 | + if (tbip->type != obj_buffer->type) |
4049 | + continue; |
4050 | + return tbip->func(driver_data, obj_context, obj_buffer); |
4051 | + } |
4052 | + D(bug("ERROR: no translate function found for %s%s\n", |
4053 | + string_of_VABufferType(obj_buffer->type), |
4054 | + obj_context->vdp_codec ? string_of_VdpCodec(obj_context->vdp_codec) : NULL)); |
4055 | + return 0; |
4056 | +} |
4057 | + |
4058 | +// vaQueryConfigProfiles |
4059 | +VAStatus |
4060 | +vdpau_QueryConfigProfiles( |
4061 | + VADriverContextP ctx, |
4062 | + VAProfile *profile_list, |
4063 | + int *num_profiles |
4064 | +) |
4065 | +{ |
4066 | + VDPAU_DRIVER_DATA_INIT; |
4067 | + |
4068 | + static const VAProfile va_profiles[] = { |
4069 | + VAProfileMPEG2Simple, |
4070 | + VAProfileMPEG2Main, |
4071 | + VAProfileMPEG4Simple, |
4072 | + VAProfileMPEG4AdvancedSimple, |
4073 | + VAProfileMPEG4Main, |
4074 | + VAProfileH264Baseline, |
4075 | + VAProfileH264Main, |
4076 | + VAProfileH264High, |
4077 | + VAProfileVC1Simple, |
4078 | + VAProfileVC1Main, |
4079 | + VAProfileVC1Advanced |
4080 | + }; |
4081 | + |
4082 | + int i, n = 0; |
4083 | + for (i = 0; i < ARRAY_ELEMS(va_profiles); i++) { |
4084 | + VAProfile profile = va_profiles[i]; |
4085 | + VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile); |
4086 | + if (is_supported_profile(driver_data, vdp_profile)) |
4087 | + profile_list[n++] = profile; |
4088 | + } |
4089 | + |
4090 | + /* If the assert fails then VDPAU_MAX_PROFILES needs to be bigger */ |
4091 | + ASSERT(n <= VDPAU_MAX_PROFILES); |
4092 | + if (num_profiles) |
4093 | + *num_profiles = n; |
4094 | + |
4095 | + return VA_STATUS_SUCCESS; |
4096 | +} |
4097 | + |
4098 | +// vaQueryConfigEntrypoints |
4099 | +VAStatus |
4100 | +vdpau_QueryConfigEntrypoints( |
4101 | + VADriverContextP ctx, |
4102 | + VAProfile profile, |
4103 | + VAEntrypoint *entrypoint_list, |
4104 | + int *num_entrypoints |
4105 | +) |
4106 | +{ |
4107 | + VDPAU_DRIVER_DATA_INIT; |
4108 | + |
4109 | + VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile); |
4110 | + if (!is_supported_profile(driver_data, vdp_profile)) |
4111 | + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; |
4112 | + |
4113 | + VAEntrypoint entrypoint; |
4114 | + switch (profile) { |
4115 | + case VAProfileMPEG2Simple: |
4116 | + case VAProfileMPEG2Main: |
4117 | + entrypoint = VAEntrypointVLD; |
4118 | + break; |
4119 | + case VAProfileMPEG4Simple: |
4120 | + case VAProfileMPEG4AdvancedSimple: |
4121 | + case VAProfileMPEG4Main: |
4122 | + entrypoint = VAEntrypointVLD; |
4123 | + break; |
4124 | + case VAProfileH264Baseline: |
4125 | + case VAProfileH264Main: |
4126 | + case VAProfileH264High: |
4127 | + entrypoint = VAEntrypointVLD; |
4128 | + break; |
4129 | + case VAProfileVC1Simple: |
4130 | + case VAProfileVC1Main: |
4131 | + case VAProfileVC1Advanced: |
4132 | + entrypoint = VAEntrypointVLD; |
4133 | + break; |
4134 | + default: |
4135 | + entrypoint = 0; |
4136 | + break; |
4137 | + } |
4138 | + |
4139 | + if (entrypoint_list) |
4140 | + *entrypoint_list = entrypoint; |
4141 | + |
4142 | + if (num_entrypoints) |
4143 | + *num_entrypoints = entrypoint != 0; |
4144 | + |
4145 | + return VA_STATUS_SUCCESS; |
4146 | +} |
4147 | + |
4148 | +// vaBeginPicture |
4149 | +VAStatus |
4150 | +vdpau_BeginPicture( |
4151 | + VADriverContextP ctx, |
4152 | + VAContextID context, |
4153 | + VASurfaceID render_target |
4154 | +) |
4155 | +{ |
4156 | + VDPAU_DRIVER_DATA_INIT; |
4157 | + |
4158 | + object_context_p obj_context = VDPAU_CONTEXT(context); |
4159 | + if (!obj_context) |
4160 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
4161 | + |
4162 | + object_surface_p obj_surface = VDPAU_SURFACE(render_target); |
4163 | + if (!obj_surface) |
4164 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
4165 | + |
4166 | + obj_surface->va_surface_status = VASurfaceRendering; |
4167 | + obj_context->last_pic_param = NULL; |
4168 | + obj_context->last_slice_params = NULL; |
4169 | + obj_context->last_slice_params_count = 0; |
4170 | + obj_context->current_render_target = obj_surface->base.id; |
4171 | + obj_context->gen_slice_data_size = 0; |
4172 | + obj_context->vdp_bitstream_buffers_count = 0; |
4173 | + |
4174 | + switch (obj_context->vdp_codec) { |
4175 | + case VDP_CODEC_MPEG1: |
4176 | + case VDP_CODEC_MPEG2: |
4177 | + obj_context->vdp_picture_info.mpeg2.slice_count = 0; |
4178 | + break; |
4179 | + case VDP_CODEC_MPEG4: |
4180 | + break; |
4181 | + case VDP_CODEC_H264: |
4182 | + obj_context->vdp_picture_info.h264.slice_count = 0; |
4183 | + break; |
4184 | + case VDP_CODEC_VC1: |
4185 | + obj_context->vdp_picture_info.vc1.slice_count = 0; |
4186 | + break; |
4187 | + default: |
4188 | + return VA_STATUS_ERROR_UNKNOWN; |
4189 | + } |
4190 | + |
4191 | + destroy_dead_va_buffers(driver_data, obj_context); |
4192 | + return VA_STATUS_SUCCESS; |
4193 | +} |
4194 | + |
4195 | +// vaRenderPicture |
4196 | +VAStatus |
4197 | +vdpau_RenderPicture( |
4198 | + VADriverContextP ctx, |
4199 | + VAContextID context, |
4200 | + VABufferID *buffers, |
4201 | + int num_buffers |
4202 | +) |
4203 | +{ |
4204 | + VDPAU_DRIVER_DATA_INIT; |
4205 | + int i; |
4206 | + |
4207 | + object_context_p obj_context = VDPAU_CONTEXT(context); |
4208 | + if (!obj_context) |
4209 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
4210 | + |
4211 | + object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target); |
4212 | + if (!obj_surface) |
4213 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
4214 | + |
4215 | + /* Verify that we got valid buffer references */ |
4216 | + for (i = 0; i < num_buffers; i++) { |
4217 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]); |
4218 | + if (!obj_buffer) |
4219 | + return VA_STATUS_ERROR_INVALID_BUFFER; |
4220 | + } |
4221 | + |
4222 | + /* Translate buffers */ |
4223 | + for (i = 0; i < num_buffers; i++) { |
4224 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]); |
4225 | + if (!translate_buffer(driver_data, obj_context, obj_buffer)) |
4226 | + return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; |
4227 | + /* Release any buffer that is not VASliceDataBuffer */ |
4228 | + /* VASliceParameterBuffer is also needed to check for start_codes */ |
4229 | + switch (obj_buffer->type) { |
4230 | + case VASliceParameterBufferType: |
4231 | + case VASliceDataBufferType: |
4232 | + schedule_destroy_va_buffer(driver_data, obj_buffer); |
4233 | + break; |
4234 | + case VAPictureParameterBufferType: |
4235 | + /* Preserve VAPictureParameterBufferMPEG4 */ |
4236 | + if (obj_context->vdp_codec == VDP_CODEC_MPEG4) { |
4237 | + schedule_destroy_va_buffer(driver_data, obj_buffer); |
4238 | + break; |
4239 | + } |
4240 | + /* fall-through */ |
4241 | + default: |
4242 | + destroy_va_buffer(driver_data, obj_buffer); |
4243 | + break; |
4244 | + } |
4245 | + } |
4246 | + |
4247 | + return VA_STATUS_SUCCESS; |
4248 | +} |
4249 | + |
4250 | +// vaEndPicture |
4251 | +VAStatus |
4252 | +vdpau_EndPicture( |
4253 | + VADriverContextP ctx, |
4254 | + VAContextID context |
4255 | +) |
4256 | +{ |
4257 | + VDPAU_DRIVER_DATA_INIT; |
4258 | + unsigned int i; |
4259 | + |
4260 | + object_context_p obj_context = VDPAU_CONTEXT(context); |
4261 | + if (!obj_context) |
4262 | + return VA_STATUS_ERROR_INVALID_CONTEXT; |
4263 | + |
4264 | + object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target); |
4265 | + if (!obj_surface) |
4266 | + return VA_STATUS_ERROR_INVALID_SURFACE; |
4267 | + |
4268 | + if (trace_enabled()) { |
4269 | + switch (obj_context->vdp_codec) { |
4270 | + case VDP_CODEC_MPEG1: |
4271 | + case VDP_CODEC_MPEG2: |
4272 | + dump_VdpPictureInfoMPEG1Or2(&obj_context->vdp_picture_info.mpeg2); |
4273 | + break; |
4274 | +#if HAVE_VDPAU_MPEG4 |
4275 | + case VDP_CODEC_MPEG4: |
4276 | + dump_VdpPictureInfoMPEG4Part2(&obj_context->vdp_picture_info.mpeg4); |
4277 | + break; |
4278 | +#endif |
4279 | + case VDP_CODEC_H264: |
4280 | + dump_VdpPictureInfoH264(&obj_context->vdp_picture_info.h264); |
4281 | + break; |
4282 | + case VDP_CODEC_VC1: |
4283 | + dump_VdpPictureInfoVC1(&obj_context->vdp_picture_info.vc1); |
4284 | + break; |
4285 | + default: |
4286 | + break; |
4287 | + } |
4288 | + for (i = 0; i < obj_context->vdp_bitstream_buffers_count; i++) |
4289 | + dump_VdpBitstreamBuffer(&obj_context->vdp_bitstream_buffers[i]); |
4290 | + } |
4291 | + |
4292 | + VAStatus va_status; |
4293 | + VdpStatus vdp_status; |
4294 | + vdp_status = ensure_decoder_with_max_refs( |
4295 | + driver_data, |
4296 | + obj_context, |
4297 | + get_num_ref_frames(obj_context) |
4298 | + ); |
4299 | + if (vdp_status == VDP_STATUS_OK) |
4300 | + vdp_status = vdpau_decoder_render( |
4301 | + driver_data, |
4302 | + obj_context->vdp_decoder, |
4303 | + obj_surface->vdp_surface, |
4304 | + (VdpPictureInfo)&obj_context->vdp_picture_info, |
4305 | + obj_context->vdp_bitstream_buffers_count, |
4306 | + obj_context->vdp_bitstream_buffers |
4307 | + ); |
4308 | + va_status = vdpau_get_VAStatus(vdp_status); |
4309 | + |
4310 | + /* XXX: assume we are done with rendering right away */ |
4311 | + obj_context->current_render_target = VA_INVALID_SURFACE; |
4312 | + |
4313 | + /* Release pending buffers */ |
4314 | + destroy_dead_va_buffers(driver_data, obj_context); |
4315 | + |
4316 | + return va_status; |
4317 | +} |
4318 | |
4319 | === modified file '.pc/applied-patches' |
4320 | --- .pc/applied-patches 2013-04-13 09:39:54 +0000 |
4321 | +++ .pc/applied-patches 2014-05-06 21:30:45 +0000 |
4322 | @@ -1,2 +1,5 @@ |
4323 | autoreconf.patch |
4324 | GL_VER_1_3.patch |
4325 | +01_dont_clear_va_buffer_too_early.patch |
4326 | +02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch |
4327 | +03_mark_destroyed_buffers_as_deleted.patch |
4328 | |
4329 | === modified file 'debian/changelog' |
4330 | --- debian/changelog 2013-04-13 09:39:54 +0000 |
4331 | +++ debian/changelog 2014-05-06 21:30:45 +0000 |
4332 | @@ -1,3 +1,10 @@ |
4333 | +vdpau-video (0.7.3-2ubuntu2) UNRELEASED; urgency=medium |
4334 | + |
4335 | + * Added patch-set from upstream to fix crash when using |
4336 | + gstreamer-vaapi (LP: #1222790) |
4337 | + |
4338 | + -- Marco Trevisan (Treviño) <marco@ubuntu.com> Tue, 06 May 2014 23:15:53 +0200 |
4339 | + |
4340 | vdpau-video (0.7.3-2ubuntu1) raring; urgency=low |
4341 | |
4342 | * Added patch from Gentoo bug #438180 (backported from upstream |
4343 | |
4344 | === added file 'debian/patches/01_dont_clear_va_buffer_too_early.patch' |
4345 | --- debian/patches/01_dont_clear_va_buffer_too_early.patch 1970-01-01 00:00:00 +0000 |
4346 | +++ debian/patches/01_dont_clear_va_buffer_too_early.patch 2014-05-06 21:30:45 +0000 |
4347 | @@ -0,0 +1,56 @@ |
4348 | +Description: Don't clear VA buffers too early. |
4349 | + vaRenderPicture() is supposed to destroy a VA buffer implicitly. However, |
4350 | + some buffers need to be kept until vaEndPicture() is reached. Besides, if |
4351 | + user calls vaDestroyBuffer() in between, we still have to keep the buffer |
4352 | + live for vaEndPicture(). |
4353 | + |
4354 | +Origin: upstream, http://cgit.freedesktop.org/vaapi/vdpau-driver/commit/?id=d26b5b3 |
4355 | +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1222790 |
4356 | +Forwarded: yes |
4357 | +Applied-Upstream: 0.7.4 |
4358 | +Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com> |
4359 | + |
4360 | +--- |
4361 | +diff --git a/src/vdpau_buffer.c b/src/vdpau_buffer.c |
4362 | +index f1171f3..540713f 100644 |
4363 | +--- a/src/vdpau_buffer.c |
4364 | ++++ b/src/vdpau_buffer.c |
4365 | +@@ -57,6 +57,7 @@ create_va_buffer( |
4366 | + obj_buffer->buffer_size = size * num_elements; |
4367 | + obj_buffer->buffer_data = malloc(obj_buffer->buffer_size); |
4368 | + obj_buffer->mtime = 0; |
4369 | ++ obj_buffer->delayed_destroy = 0; |
4370 | + |
4371 | + if (!obj_buffer->buffer_data) { |
4372 | + destroy_va_buffer(driver_data, obj_buffer); |
4373 | +@@ -103,6 +104,7 @@ schedule_destroy_va_buffer( |
4374 | + ASSERT(obj_context->dead_buffers); |
4375 | + obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id; |
4376 | + obj_context->dead_buffers_count++; |
4377 | ++ obj_buffer->delayed_destroy = 1; |
4378 | + } |
4379 | + |
4380 | + // vaCreateBuffer |
4381 | +@@ -162,7 +164,7 @@ vdpau_DestroyBuffer( |
4382 | + |
4383 | + object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id); |
4384 | + |
4385 | +- if (obj_buffer) |
4386 | ++ if (obj_buffer && !obj_buffer->delayed_destroy) |
4387 | + destroy_va_buffer(driver_data, obj_buffer); |
4388 | + |
4389 | + return VA_STATUS_SUCCESS; |
4390 | +diff --git a/src/vdpau_buffer.h b/src/vdpau_buffer.h |
4391 | +index 7790f54..0168df9 100644 |
4392 | +--- a/src/vdpau_buffer.h |
4393 | ++++ b/src/vdpau_buffer.h |
4394 | +@@ -33,6 +33,7 @@ struct object_buffer { |
4395 | + unsigned int max_num_elements; |
4396 | + unsigned int num_elements; |
4397 | + uint64_t mtime; |
4398 | ++ unsigned int delayed_destroy : 1; |
4399 | + }; |
4400 | + |
4401 | + // Create VA buffer object |
4402 | +-- |
4403 | +cgit v0.9.0.2-2-gbebe |
4404 | |
4405 | === added file 'debian/patches/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch' |
4406 | --- debian/patches/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch 1970-01-01 00:00:00 +0000 |
4407 | +++ debian/patches/02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch 2014-05-06 21:30:45 +0000 |
4408 | @@ -0,0 +1,111 @@ |
4409 | +Description: Purge VA buffers on context destroy or new picture decdode sequence. |
4410 | +Origin: upstream, http://cgit.freedesktop.org/vaapi/vdpau-driver/commit/?id=2630695 |
4411 | +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1222790 |
4412 | +Forwarded: yes |
4413 | +Applied-Upstream: 0.7.4 |
4414 | +Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com> |
4415 | + |
4416 | +--- |
4417 | +diff --git a/src/vdpau_buffer.c b/src/vdpau_buffer.c |
4418 | +index 540713f..8766046 100644 |
4419 | +--- a/src/vdpau_buffer.c |
4420 | ++++ b/src/vdpau_buffer.c |
4421 | +@@ -28,6 +28,27 @@ |
4422 | + #define DEBUG 1 |
4423 | + #include "debug.h" |
4424 | + |
4425 | ++// Destroy dead VA buffers |
4426 | ++void |
4427 | ++destroy_dead_va_buffers( |
4428 | ++ vdpau_driver_data_t *driver_data, |
4429 | ++ object_context_p obj_context |
4430 | ++) |
4431 | ++{ |
4432 | ++ object_buffer_p obj_buffer; |
4433 | ++ unsigned int i; |
4434 | ++ |
4435 | ++ if (obj_context->dead_buffers_count < 1) |
4436 | ++ return; |
4437 | ++ |
4438 | ++ ASSERT(obj_context->dead_buffers); |
4439 | ++ for (i = 0; i < obj_context->dead_buffers_count; i++) { |
4440 | ++ obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]); |
4441 | ++ ASSERT(obj_buffer); |
4442 | ++ destroy_va_buffer(driver_data, obj_buffer); |
4443 | ++ } |
4444 | ++ obj_context->dead_buffers_count = 0; |
4445 | ++} |
4446 | + |
4447 | + // Create VA buffer object |
4448 | + object_buffer_p |
4449 | +diff --git a/src/vdpau_buffer.h b/src/vdpau_buffer.h |
4450 | +index 0168df9..42672aa 100644 |
4451 | +--- a/src/vdpau_buffer.h |
4452 | ++++ b/src/vdpau_buffer.h |
4453 | +@@ -36,6 +36,13 @@ struct object_buffer { |
4454 | + unsigned int delayed_destroy : 1; |
4455 | + }; |
4456 | + |
4457 | ++// Destroy dead VA buffers |
4458 | ++void |
4459 | ++destroy_dead_va_buffers( |
4460 | ++ vdpau_driver_data_t *driver_data, |
4461 | ++ object_context_p obj_context |
4462 | ++) attribute_hidden; |
4463 | ++ |
4464 | + // Create VA buffer object |
4465 | + object_buffer_p |
4466 | + create_va_buffer( |
4467 | +diff --git a/src/vdpau_decode.c b/src/vdpau_decode.c |
4468 | +index 08dfbf0..dee3993 100644 |
4469 | +--- a/src/vdpau_decode.c |
4470 | ++++ b/src/vdpau_decode.c |
4471 | +@@ -1134,6 +1134,8 @@ vdpau_BeginPicture( |
4472 | + default: |
4473 | + return VA_STATUS_ERROR_UNKNOWN; |
4474 | + } |
4475 | ++ |
4476 | ++ destroy_dead_va_buffers(driver_data, obj_context); |
4477 | + return VA_STATUS_SUCCESS; |
4478 | + } |
4479 | + |
4480 | +@@ -1256,16 +1258,7 @@ vdpau_EndPicture( |
4481 | + obj_context->current_render_target = VA_INVALID_SURFACE; |
4482 | + |
4483 | + /* Release pending buffers */ |
4484 | +- if (obj_context->dead_buffers_count > 0) { |
4485 | +- ASSERT(obj_context->dead_buffers); |
4486 | +- int i; |
4487 | +- for (i = 0; i < obj_context->dead_buffers_count; i++) { |
4488 | +- object_buffer_p obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]); |
4489 | +- ASSERT(obj_buffer); |
4490 | +- destroy_va_buffer(driver_data, obj_buffer); |
4491 | +- } |
4492 | +- obj_context->dead_buffers_count = 0; |
4493 | +- } |
4494 | ++ destroy_dead_va_buffers(driver_data, obj_context); |
4495 | + |
4496 | + return va_status; |
4497 | + } |
4498 | +diff --git a/src/vdpau_video.c b/src/vdpau_video.c |
4499 | +index 3821879..05d1f5e 100644 |
4500 | +--- a/src/vdpau_video.c |
4501 | ++++ b/src/vdpau_video.c |
4502 | +@@ -24,6 +24,7 @@ |
4503 | + #include "vdpau_decode.h" |
4504 | + #include "vdpau_subpic.h" |
4505 | + #include "vdpau_mixer.h" |
4506 | ++#include "vdpau_buffer.h" |
4507 | + #include "utils.h" |
4508 | + |
4509 | + #define DEBUG 1 |
4510 | +@@ -481,6 +482,7 @@ VAStatus vdpau_DestroyContext(VADriverContextP ctx, VAContextID context) |
4511 | + obj_context->vdp_decoder = VDP_INVALID_HANDLE; |
4512 | + } |
4513 | + |
4514 | ++ destroy_dead_va_buffers(driver_data, obj_context); |
4515 | + if (obj_context->dead_buffers) { |
4516 | + free(obj_context->dead_buffers); |
4517 | + obj_context->dead_buffers = NULL; |
4518 | +-- |
4519 | +cgit v0.9.0.2-2-gbebe |
4520 | |
4521 | === added file 'debian/patches/03_mark_destroyed_buffers_as_deleted.patch' |
4522 | --- debian/patches/03_mark_destroyed_buffers_as_deleted.patch 1970-01-01 00:00:00 +0000 |
4523 | +++ debian/patches/03_mark_destroyed_buffers_as_deleted.patch 2014-05-06 21:30:45 +0000 |
4524 | @@ -0,0 +1,28 @@ |
4525 | +Description: decode: mark destroyed buffers as deleted |
4526 | + In multi-threaded scenarios destroying a buffer via destroy_va_buffer() |
4527 | + will allow other threads to claim the freed buffer object. If the |
4528 | + calling code does not know whether the buffer object was freed it may |
4529 | + attempt to vaDestroyBuffer, essentially destroying a buffer object which |
4530 | + is in use by another thread. |
4531 | + |
4532 | +Origin: upstream, http://cgit.freedesktop.org/vaapi/vdpau-driver/commit/?id=e4fd3b |
4533 | +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1222790 |
4534 | +Forwarded: yes |
4535 | +Applied-Upstream: 0.7.4 |
4536 | +Author: Philip Lorenz <philip@bithub.de> |
4537 | + |
4538 | +--- |
4539 | +diff --git a/src/vdpau_decode.c b/src/vdpau_decode.c |
4540 | +index b9f1419..22d9cd9 100644 |
4541 | +--- a/src/vdpau_decode.c |
4542 | ++++ b/src/vdpau_decode.c |
4543 | +@@ -1229,6 +1229,7 @@ vdpau_RenderPicture( |
4544 | + destroy_va_buffer(driver_data, obj_buffer); |
4545 | + break; |
4546 | + } |
4547 | ++ buffers[i] = VA_INVALID_BUFFER; |
4548 | + } |
4549 | + |
4550 | + return VA_STATUS_SUCCESS; |
4551 | +-- |
4552 | +cgit v0.9.0.2-2-gbebe |
4553 | |
4554 | === modified file 'debian/patches/series' |
4555 | --- debian/patches/series 2013-04-13 09:39:54 +0000 |
4556 | +++ debian/patches/series 2014-05-06 21:30:45 +0000 |
4557 | @@ -1,2 +1,5 @@ |
4558 | autoreconf.patch |
4559 | GL_VER_1_3.patch |
4560 | +01_dont_clear_va_buffer_too_early.patch |
4561 | +02_purge_va_buffers_on_context_destroy_or_new_picture_decode_seq.patch |
4562 | +03_mark_destroyed_buffers_as_deleted.patch |
4563 | |
4564 | === modified file 'src/vdpau_buffer.c' |
4565 | --- src/vdpau_buffer.c 2011-09-22 11:35:45 +0000 |
4566 | +++ src/vdpau_buffer.c 2014-05-06 21:30:45 +0000 |
4567 | @@ -28,6 +28,27 @@ |
4568 | #define DEBUG 1 |
4569 | #include "debug.h" |
4570 | |
4571 | +// Destroy dead VA buffers |
4572 | +void |
4573 | +destroy_dead_va_buffers( |
4574 | + vdpau_driver_data_t *driver_data, |
4575 | + object_context_p obj_context |
4576 | +) |
4577 | +{ |
4578 | + object_buffer_p obj_buffer; |
4579 | + unsigned int i; |
4580 | + |
4581 | + if (obj_context->dead_buffers_count < 1) |
4582 | + return; |
4583 | + |
4584 | + ASSERT(obj_context->dead_buffers); |
4585 | + for (i = 0; i < obj_context->dead_buffers_count; i++) { |
4586 | + obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]); |
4587 | + ASSERT(obj_buffer); |
4588 | + destroy_va_buffer(driver_data, obj_buffer); |
4589 | + } |
4590 | + obj_context->dead_buffers_count = 0; |
4591 | +} |
4592 | |
4593 | // Create VA buffer object |
4594 | object_buffer_p |
4595 | @@ -57,6 +78,7 @@ |
4596 | obj_buffer->buffer_size = size * num_elements; |
4597 | obj_buffer->buffer_data = malloc(obj_buffer->buffer_size); |
4598 | obj_buffer->mtime = 0; |
4599 | + obj_buffer->delayed_destroy = 0; |
4600 | |
4601 | if (!obj_buffer->buffer_data) { |
4602 | destroy_va_buffer(driver_data, obj_buffer); |
4603 | @@ -103,6 +125,7 @@ |
4604 | ASSERT(obj_context->dead_buffers); |
4605 | obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id; |
4606 | obj_context->dead_buffers_count++; |
4607 | + obj_buffer->delayed_destroy = 1; |
4608 | } |
4609 | |
4610 | // vaCreateBuffer |
4611 | @@ -162,7 +185,7 @@ |
4612 | |
4613 | object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id); |
4614 | |
4615 | - if (obj_buffer) |
4616 | + if (obj_buffer && !obj_buffer->delayed_destroy) |
4617 | destroy_va_buffer(driver_data, obj_buffer); |
4618 | |
4619 | return VA_STATUS_SUCCESS; |
4620 | |
4621 | === modified file 'src/vdpau_buffer.h' |
4622 | --- src/vdpau_buffer.h 2011-09-22 11:35:45 +0000 |
4623 | +++ src/vdpau_buffer.h 2014-05-06 21:30:45 +0000 |
4624 | @@ -33,8 +33,16 @@ |
4625 | unsigned int max_num_elements; |
4626 | unsigned int num_elements; |
4627 | uint64_t mtime; |
4628 | + unsigned int delayed_destroy : 1; |
4629 | }; |
4630 | |
4631 | +// Destroy dead VA buffers |
4632 | +void |
4633 | +destroy_dead_va_buffers( |
4634 | + vdpau_driver_data_t *driver_data, |
4635 | + object_context_p obj_context |
4636 | +) attribute_hidden; |
4637 | + |
4638 | // Create VA buffer object |
4639 | object_buffer_p |
4640 | create_va_buffer( |
4641 | |
4642 | === modified file 'src/vdpau_decode.c' |
4643 | --- src/vdpau_decode.c 2011-09-22 11:35:45 +0000 |
4644 | +++ src/vdpau_decode.c 2014-05-06 21:30:45 +0000 |
4645 | @@ -1134,6 +1134,8 @@ |
4646 | default: |
4647 | return VA_STATUS_ERROR_UNKNOWN; |
4648 | } |
4649 | + |
4650 | + destroy_dead_va_buffers(driver_data, obj_context); |
4651 | return VA_STATUS_SUCCESS; |
4652 | } |
4653 | |
4654 | @@ -1187,6 +1189,7 @@ |
4655 | destroy_va_buffer(driver_data, obj_buffer); |
4656 | break; |
4657 | } |
4658 | + buffers[i] = VA_INVALID_BUFFER; |
4659 | } |
4660 | |
4661 | return VA_STATUS_SUCCESS; |
4662 | @@ -1256,16 +1259,7 @@ |
4663 | obj_context->current_render_target = VA_INVALID_SURFACE; |
4664 | |
4665 | /* Release pending buffers */ |
4666 | - if (obj_context->dead_buffers_count > 0) { |
4667 | - ASSERT(obj_context->dead_buffers); |
4668 | - int i; |
4669 | - for (i = 0; i < obj_context->dead_buffers_count; i++) { |
4670 | - object_buffer_p obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]); |
4671 | - ASSERT(obj_buffer); |
4672 | - destroy_va_buffer(driver_data, obj_buffer); |
4673 | - } |
4674 | - obj_context->dead_buffers_count = 0; |
4675 | - } |
4676 | + destroy_dead_va_buffers(driver_data, obj_context); |
4677 | |
4678 | return va_status; |
4679 | } |
4680 | |
4681 | === modified file 'src/vdpau_video.c' |
4682 | --- src/vdpau_video.c 2011-09-22 11:35:45 +0000 |
4683 | +++ src/vdpau_video.c 2014-05-06 21:30:45 +0000 |
4684 | @@ -24,6 +24,7 @@ |
4685 | #include "vdpau_decode.h" |
4686 | #include "vdpau_subpic.h" |
4687 | #include "vdpau_mixer.h" |
4688 | +#include "vdpau_buffer.h" |
4689 | #include "utils.h" |
4690 | |
4691 | #define DEBUG 1 |
4692 | @@ -481,6 +482,7 @@ |
4693 | obj_context->vdp_decoder = VDP_INVALID_HANDLE; |
4694 | } |
4695 | |
4696 | + destroy_dead_va_buffers(driver_data, obj_context); |
4697 | if (obj_context->dead_buffers) { |
4698 | free(obj_context->dead_buffers); |
4699 | obj_context->dead_buffers = NULL; |
Uploaded, thanks!