1 /*
2 * Video Decode and Presentation API for UNIX (VDPAU) is used for
3 * HW decode acceleration for MPEG-1/2, MPEG-4 ASP, H.264 and VC-1.
4 *
5 * Copyright (c) 2008 NVIDIA
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
30
31 #undef NDEBUG
32 #include <assert.h>
33
36
37 /**
38 * @addtogroup VDPAU_Decoding
39 *
40 * @{
41 */
42
44 {
45 switch (status) {
46 case VDP_STATUS_OK:
47 return 0;
48 case VDP_STATUS_NO_IMPLEMENTATION:
50 case VDP_STATUS_DISPLAY_PREEMPTED:
52 case VDP_STATUS_INVALID_HANDLE:
54 case VDP_STATUS_INVALID_POINTER:
56 case VDP_STATUS_RESOURCES:
58 case VDP_STATUS_HANDLE_DEVICE_MISMATCH:
60 case VDP_STATUS_ERROR:
62 default:
64 }
65 }
66
68 {
70 }
71
73
77 {
78 VdpChromaType t;
79 uint32_t w = avctx->coded_width;
80 uint32_t h = avctx->coded_height;
81
82 /* See <vdpau/vdpau.h> for per-type alignment constraints. */
83 switch (avctx->sw_pix_fmt) {
86 t = VDP_CHROMA_TYPE_420;
87 w = (w + 1) & ~1;
88 h = (h + 3) & ~3;
89 break;
92 t = VDP_CHROMA_TYPE_422;
93 w = (w + 1) & ~1;
94 h = (h + 1) & ~1;
95 break;
98 t = VDP_CHROMA_TYPE_444;
99 h = (h + 1) & ~1;
100 break;
101 default:
103 }
104
105 if (type)
106 *type = t;
107 if (width)
108 *width = w;
109 if (height)
110 *height = h;
111 return 0;
112 }
113
116 {
119 VdpVideoSurfaceQueryCapabilities *surface_query_caps;
120 VdpDecoderQueryCapabilities *decoder_query_caps;
123 VdpStatus status;
124 VdpBool supported;
125 uint32_t max_level, max_mb, max_width, max_height;
129
130 vdctx->width = UINT32_MAX;
131 vdctx->height = UINT32_MAX;
132
133 if (!hwctx) {
134 vdctx->
device = VDP_INVALID_HANDLE;
135 av_log(avctx,
AV_LOG_WARNING,
"hwaccel_context has not been setup by the user application, cannot initialize\n");
136 return 0;
137 }
138
139 if (hwctx->context.decoder != VDP_INVALID_HANDLE) {
140 vdctx->
decoder = hwctx->context.decoder;
141 vdctx->render = hwctx->context.render;
142 vdctx->
device = VDP_INVALID_HANDLE;
143 return 0; /* Decoder created by user */
144 }
145 hwctx->reset = 0;
146
147 vdctx->
device = hwctx->device;
149
151 level = 0;
152 else if (level < 0)
154
157
159 type != VDP_CHROMA_TYPE_420)
161
163 VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES,
164 &func);
165 if (status != VDP_STATUS_OK)
167 else
168 surface_query_caps =
func;
169
170 status = surface_query_caps(vdctx->
device, type, &supported,
171 &max_width, &max_height);
172 if (status != VDP_STATUS_OK)
174 if (supported != VDP_TRUE ||
175 max_width < width || max_height < height)
177
179 VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES,
180 &func);
181 if (status != VDP_STATUS_OK)
183 else
184 decoder_query_caps =
func;
185
186 status = decoder_query_caps(vdctx->
device, profile, &supported, &max_level,
187 &max_mb, &max_width, &max_height);
188 #ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE
189 if (status != VDP_STATUS_OK && profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE) {
190 /* Run-time backward compatibility for libvdpau 0.8 and earlier */
191 profile = VDP_DECODER_PROFILE_H264_MAIN;
192 status = decoder_query_caps(vdctx->
device, profile, &supported,
193 &max_level, &max_mb,
194 &max_width, &max_height);
195 }
196 #endif
197 if (status != VDP_STATUS_OK)
199
200 if (supported != VDP_TRUE || max_level < level ||
201 max_width < width || max_height < height)
203
205 &func);
206 if (status != VDP_STATUS_OK)
208 else
210
212 &func);
213 if (status != VDP_STATUS_OK)
215 else
216 vdctx->render =
func;
217
220 if (status == VDP_STATUS_OK) {
223 }
224
226 }
227
229 {
233 VdpStatus status;
234
235 if (vdctx->
device == VDP_INVALID_HANDLE)
236 return 0; /* Decoder created and destroyed by user */
237 if (vdctx->width == UINT32_MAX && vdctx->height == UINT32_MAX)
238 return 0;
239
241 VDP_FUNC_ID_DECODER_DESTROY, &func);
242 if (status != VDP_STATUS_OK)
244 else
246
249 }
250
252 {
255
256 if (vdctx->
device == VDP_INVALID_HANDLE)
257 return 0; /* Decoder created by user */
260 return 0;
261
264 }
265
269 {
270 pic_ctx->bitstream_buffers_allocated = 0;
271 pic_ctx->bitstream_buffers_used = 0;
272 pic_ctx->bitstream_buffers =
NULL;
273 return 0;
274 }
275
277 struct vdpau_picture_context *pic_ctx)
278 {
282 VdpStatus status;
284
286 if (val < 0)
288
289 #if FF_API_BUFS_VDPAU
292 memcpy(&hwctx->
info, &pic_ctx->info,
sizeof(hwctx->
info));
297 #endif
298
300 status = hwctx->
render2(avctx, frame, (
void *)&pic_ctx->info,
301 pic_ctx->bitstream_buffers_used, pic_ctx->bitstream_buffers);
302 } else
303 status = vdctx->render(vdctx->
decoder, surf, (
void *)&pic_ctx->info,
304 pic_ctx->bitstream_buffers_used,
305 pic_ctx->bitstream_buffers);
306
307 av_freep(&pic_ctx->bitstream_buffers);
308
309 #if FF_API_BUFS_VDPAU
315 #endif
316
318 }
319
320 #if CONFIG_H263_VDPAU_HWACCEL || CONFIG_MPEG1_VDPAU_HWACCEL || \
321 CONFIG_MPEG2_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL || \
322 CONFIG_VC1_VDPAU_HWACCEL || CONFIG_WMV3_VDPAU_HWACCEL
324 {
329
331 if (val < 0)
333
335 return 0;
336 }
337 #endif
338
341 {
342 VdpBitstreamBuffer *
buffers = pic_ctx->bitstream_buffers;
343
344 buffers =
av_fast_realloc(buffers, &pic_ctx->bitstream_buffers_allocated,
345 (pic_ctx->bitstream_buffers_used + 1) * sizeof(*buffers));
346 if (!buffers)
348
349 pic_ctx->bitstream_buffers =
buffers;
350 buffers += pic_ctx->bitstream_buffers_used++;
351
352 buffers->struct_version = VDP_BITSTREAM_BUFFER_VERSION;
353 buffers->bitstream =
buf;
354 buffers->bitstream_bytes =
size;
355 return 0;
356 }
357
358 /* Obsolete non-hwaccel VDPAU support below... */
359
361 {
363 VdpReferenceFrameH264 *rf, *rf2;
365 int i, list, pic_frame_idx;
366
368 assert(render);
369
370 rf = &render->
info.
h264.referenceFrames[0];
371 #define H264_RF_COUNT FF_ARRAY_ELEMS(render->info.h264.referenceFrames)
372
373 for (list = 0; list < 2; ++list) {
376
377 for (i = 0; i < ls; ++i) {
378 pic = lp[i];
380 continue;
382
384 assert(render_ref);
385
386 rf2 = &render->
info.
h264.referenceFrames[0];
387 while (rf2 != rf) {
388 if (
389 (rf2->surface == render_ref->
surface)
390 && (rf2->is_long_term == pic->
long_ref)
391 && (rf2->frame_idx == pic_frame_idx)
392 )
393 break;
394 ++rf2;
395 }
396 if (rf2 != rf) {
399 continue;
400 }
401
403 continue;
404
405 rf->surface = render_ref->
surface;
409 rf->field_order_cnt[0] = pic->
field_poc[0];
410 rf->field_order_cnt[1] = pic->
field_poc[1];
411 rf->frame_idx = pic_frame_idx;
412
413 ++rf;
414 }
415 }
416
418 rf->surface = VDP_INVALID_HANDLE;
419 rf->is_long_term = 0;
420 rf->top_is_reference = 0;
421 rf->bottom_is_reference = 0;
422 rf->field_order_cnt[0] = 0;
423 rf->field_order_cnt[1] = 0;
424 rf->frame_idx = 0;
425 }
426 }
427
429 {
431 assert(render);
432
437 );
438
443 }
444
445 #if CONFIG_H264_VDPAU_DECODER
447 {
449 int i;
450
452 assert(render);
453
454 for (i = 0; i < 2; ++i) {
456 if (foc == INT_MAX)
457 foc = 0;
458 render->
info.
h264.field_order_cnt[i] = foc;
459 }
460
462 }
463
465 {
467
469 assert(render);
470
472 if (render->
info.
h264.slice_count < 1)
473 return;
474
502
505 }
506 #endif /* CONFIG_H264_VDPAU_DECODER */
507
508 #if CONFIG_MPEG_VDPAU_DECODER || CONFIG_MPEG1_VDPAU_DECODER
510 int buf_size, int slice_count)
511 {
513 int i;
514
516
518 assert(render);
519
520 /* fill VdpPictureInfoMPEG1Or2 struct */
530 render->
info.
mpeg.full_pel_forward_vector = s->
full_pel[0];
// MPEG-1 only. Set 0 for MPEG-2
531 render->
info.
mpeg.full_pel_backward_vector = s->
full_pel[1];
// MPEG-1 only. Set 0 for MPEG-2
532 render->
info.
mpeg.f_code[0][0] = s->
mpeg_f_code[0][0];
// For MPEG-1 fill both horiz. & vert.
536 for (i = 0; i < 64; ++i) {
539 }
540
541 render->
info.
mpeg.forward_reference = VDP_INVALID_HANDLE;
542 render->
info.
mpeg.backward_reference = VDP_INVALID_HANDLE;
543
547 assert(next);
549 // no return here, going to set forward prediction
552 if (!last)
// FIXME: Does this test make sense?
553 last = render; // predict second field from the first
555 }
556
558
559 render->
info.
mpeg.slice_count = slice_count;
560
561 if (slice_count)
564 }
565 #endif /* CONFIG_MPEG_VDPAU_DECODER || CONFIG_MPEG1_VDPAU_DECODER */
566
567 #if CONFIG_VC1_VDPAU_DECODER
569 int buf_size)
570 {
573
575 assert(render);
576
577 /* fill LvPictureInfoVC1 struct */
578 render->
info.
vc1.frame_coding_mode = v->
fcm ? v->
fcm + 1 : 0;
599 /* Specific to simple/main profile only */
604
607
608 render->
info.
vc1.forward_reference = VDP_INVALID_HANDLE;
609 render->
info.
vc1.backward_reference = VDP_INVALID_HANDLE;
610
612 render->
info.
vc1.picture_type = 4;
613 else
615
619 assert(next);
621 // no break here, going to set forward prediction
624 if (!last)
// FIXME: Does this test make sense?
625 last = render; // predict second field from the first
627 }
628
630
631 render->
info.
vc1.slice_count = 1;
632
635 }
636 #endif /* (CONFIG_VC1_VDPAU_DECODER */
637
638 #if CONFIG_MPEG4_VDPAU_DECODER
640 int buf_size)
641 {
644 int i;
645
647
649 assert(render);
650
651 /* fill VdpPictureInfoMPEG4Part2 struct */
668 for (i = 0; i < 64; ++i) {
671 }
672 render->
info.
mpeg4.forward_reference = VDP_INVALID_HANDLE;
673 render->
info.
mpeg4.backward_reference = VDP_INVALID_HANDLE;
674
678 assert(next);
681 // no break here, going to set forward prediction
684 assert(last);
686 }
687
689
692 }
693 #endif /* CONFIG_MPEG4_VDPAU_DECODER */
694
696 {
697 #define PROFILE(prof) \
698 do { \
699 *profile = VDP_DECODER_PROFILE_##prof; \
700 return 0; \
701 } while (0)
702
709 default:
return AVERROR(EINVAL);
710 }
716 default:
return AVERROR(EINVAL);
717 }
724 #ifdef VDP_DECODER_PROFILE_H264_EXTENDED
726 #endif
727 default:
return AVERROR(EINVAL);
728 }
735 default:
return AVERROR(EINVAL);
736 }
737 }
739 #undef PROFILE
740 }
741
743 {
745 }
746
748 VdpGetProcAddress *get_proc,
unsigned flags)
749 {
750 VDPAUHWContext *hwctx;
751
754
757
759
760 memset(hwctx, 0, sizeof(*hwctx));
761 hwctx->context.decoder = VDP_INVALID_HANDLE;
762 hwctx->device = device;
763 hwctx->get_proc_address = get_proc;
764 hwctx->flags =
flags;
765 hwctx->reset = 1;
766 return 0;
767 }
768
769 /* @}*/