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

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merge reported by: Martin Pitt
Merged at revision: not available
Proposed branch: lp:~3v1n0/ubuntu/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
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

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

Uploaded, thanks!

review: Approve
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://lists.freedesktop.org/archives/libva/2013-May/001669.html
[2] http://lists.freedesktop.org/archives/libva/2013-June/001762.html

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;

Subscribers

People subscribed via source and target branches