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.
5 * Copyright (c) 2008 NVIDIA
7 * This file is part of FFmpeg.
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.
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.
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
31 #include "vdpau_compat.h"
32 #include "vdpau_internal.h"
34 // XXX: at the time of adding this ifdefery, av_assert* wasn't use outside.
35 // When dropping it, make sure other av_assert* were not added since then.
37 #include "libavutil/avassert.h"
46 * @addtogroup VDPAU_Decoding
51 static int vdpau_error(VdpStatus status)
56 case VDP_STATUS_NO_IMPLEMENTATION:
57 return AVERROR(ENOSYS);
58 case VDP_STATUS_DISPLAY_PREEMPTED:
60 case VDP_STATUS_INVALID_HANDLE:
61 return AVERROR(EBADF);
62 case VDP_STATUS_INVALID_POINTER:
63 return AVERROR(EFAULT);
64 case VDP_STATUS_RESOURCES:
65 return AVERROR(ENOBUFS);
66 case VDP_STATUS_HANDLE_DEVICE_MISMATCH:
67 return AVERROR(EXDEV);
68 case VDP_STATUS_ERROR:
71 return AVERROR(EINVAL);
75 AVVDPAUContext *av_alloc_vdpaucontext(void)
77 return av_vdpau_alloc_context();
80 MAKE_ACCESSORS(AVVDPAUContext, vdpau_hwaccel, AVVDPAU_Render2, render2)
82 int av_vdpau_get_surface_parameters(AVCodecContext *avctx,
84 uint32_t *width, uint32_t *height)
87 uint32_t w = avctx->coded_width;
88 uint32_t h = avctx->coded_height;
90 /* See <vdpau/vdpau.h> for per-type alignment constraints. */
91 switch (avctx->sw_pix_fmt) {
92 case AV_PIX_FMT_YUV420P:
93 case AV_PIX_FMT_YUVJ420P:
94 t = VDP_CHROMA_TYPE_420;
98 case AV_PIX_FMT_YUV422P:
99 case AV_PIX_FMT_YUVJ422P:
100 t = VDP_CHROMA_TYPE_422;
104 case AV_PIX_FMT_YUV444P:
105 case AV_PIX_FMT_YUVJ444P:
106 t = VDP_CHROMA_TYPE_444;
110 return AVERROR(ENOSYS);
122 int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
125 VDPAUHWContext *hwctx = avctx->hwaccel_context;
126 VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
127 VdpVideoSurfaceQueryCapabilities *surface_query_caps;
128 VdpDecoderQueryCapabilities *decoder_query_caps;
129 VdpDecoderCreate *create;
133 uint32_t max_level, max_mb, max_width, max_height;
138 vdctx->width = UINT32_MAX;
139 vdctx->height = UINT32_MAX;
142 vdctx->device = VDP_INVALID_HANDLE;
143 av_log(avctx, AV_LOG_WARNING, "hwaccel_context has not been setup by the user application, cannot initialize\n");
147 if (hwctx->context.decoder != VDP_INVALID_HANDLE) {
148 vdctx->decoder = hwctx->context.decoder;
149 vdctx->render = hwctx->context.render;
150 vdctx->device = VDP_INVALID_HANDLE;
151 return 0; /* Decoder created by user */
155 vdctx->device = hwctx->device;
156 vdctx->get_proc_address = hwctx->get_proc_address;
158 if (hwctx->flags & AV_HWACCEL_FLAG_IGNORE_LEVEL)
161 return AVERROR(ENOTSUP);
163 if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height))
164 return AVERROR(ENOSYS);
166 if (!(hwctx->flags & AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH) &&
167 type != VDP_CHROMA_TYPE_420)
168 return AVERROR(ENOSYS);
170 status = vdctx->get_proc_address(vdctx->device,
171 VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES,
173 if (status != VDP_STATUS_OK)
174 return vdpau_error(status);
176 surface_query_caps = func;
178 status = surface_query_caps(vdctx->device, type, &supported,
179 &max_width, &max_height);
180 if (status != VDP_STATUS_OK)
181 return vdpau_error(status);
182 if (supported != VDP_TRUE ||
183 max_width < width || max_height < height)
184 return AVERROR(ENOTSUP);
186 status = vdctx->get_proc_address(vdctx->device,
187 VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES,
189 if (status != VDP_STATUS_OK)
190 return vdpau_error(status);
192 decoder_query_caps = func;
194 status = decoder_query_caps(vdctx->device, profile, &supported, &max_level,
195 &max_mb, &max_width, &max_height);
196 #ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE
197 if ((status != VDP_STATUS_OK || supported != VDP_TRUE) && profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE) {
198 profile = VDP_DECODER_PROFILE_H264_MAIN;
199 status = decoder_query_caps(vdctx->device, profile, &supported,
201 &max_width, &max_height);
204 if (status != VDP_STATUS_OK)
205 return vdpau_error(status);
207 if (supported != VDP_TRUE || max_level < level ||
208 max_width < width || max_height < height)
209 return AVERROR(ENOTSUP);
211 status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_CREATE,
213 if (status != VDP_STATUS_OK)
214 return vdpau_error(status);
218 status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_RENDER,
220 if (status != VDP_STATUS_OK)
221 return vdpau_error(status);
223 vdctx->render = func;
225 status = create(vdctx->device, profile, width, height, avctx->refs,
227 if (status == VDP_STATUS_OK) {
228 vdctx->width = avctx->coded_width;
229 vdctx->height = avctx->coded_height;
232 return vdpau_error(status);
235 int ff_vdpau_common_uninit(AVCodecContext *avctx)
237 VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
238 VdpDecoderDestroy *destroy;
242 if (vdctx->device == VDP_INVALID_HANDLE)
243 return 0; /* Decoder created and destroyed by user */
244 if (vdctx->width == UINT32_MAX && vdctx->height == UINT32_MAX)
247 status = vdctx->get_proc_address(vdctx->device,
248 VDP_FUNC_ID_DECODER_DESTROY, &func);
249 if (status != VDP_STATUS_OK)
250 return vdpau_error(status);
254 status = destroy(vdctx->decoder);
255 return vdpau_error(status);
258 static int ff_vdpau_common_reinit(AVCodecContext *avctx)
260 VDPAUHWContext *hwctx = avctx->hwaccel_context;
261 VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
263 if (vdctx->device == VDP_INVALID_HANDLE)
264 return 0; /* Decoder created by user */
265 if (avctx->coded_width == vdctx->width &&
266 avctx->coded_height == vdctx->height && !hwctx->reset)
269 avctx->hwaccel->uninit(avctx);
270 return avctx->hwaccel->init(avctx);
273 int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx,
274 av_unused const uint8_t *buffer,
275 av_unused uint32_t size)
277 pic_ctx->bitstream_buffers_allocated = 0;
278 pic_ctx->bitstream_buffers_used = 0;
279 pic_ctx->bitstream_buffers = NULL;
283 int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
284 struct vdpau_picture_context *pic_ctx)
286 VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
287 AVVDPAUContext *hwctx = avctx->hwaccel_context;
288 VdpVideoSurface surf = ff_vdpau_get_surface_id(frame);
292 val = ff_vdpau_common_reinit(avctx);
296 #if FF_API_BUFS_VDPAU
297 FF_DISABLE_DEPRECATION_WARNINGS
298 av_assert0(sizeof(hwctx->info) <= sizeof(pic_ctx->info));
299 memcpy(&hwctx->info, &pic_ctx->info, sizeof(hwctx->info));
300 hwctx->bitstream_buffers = pic_ctx->bitstream_buffers;
301 hwctx->bitstream_buffers_used = pic_ctx->bitstream_buffers_used;
302 hwctx->bitstream_buffers_allocated = pic_ctx->bitstream_buffers_allocated;
303 FF_ENABLE_DEPRECATION_WARNINGS
306 if (!hwctx->render && hwctx->render2) {
307 status = hwctx->render2(avctx, frame, (void *)&pic_ctx->info,
308 pic_ctx->bitstream_buffers_used, pic_ctx->bitstream_buffers);
310 status = vdctx->render(vdctx->decoder, surf, (void *)&pic_ctx->info,
311 pic_ctx->bitstream_buffers_used,
312 pic_ctx->bitstream_buffers);
314 av_freep(&pic_ctx->bitstream_buffers);
316 #if FF_API_BUFS_VDPAU
317 FF_DISABLE_DEPRECATION_WARNINGS
318 hwctx->bitstream_buffers = NULL;
319 hwctx->bitstream_buffers_used = 0;
320 hwctx->bitstream_buffers_allocated = 0;
321 FF_ENABLE_DEPRECATION_WARNINGS
324 return vdpau_error(status);
327 #if CONFIG_MPEG1_VDPAU_HWACCEL || \
328 CONFIG_MPEG2_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL || \
329 CONFIG_VC1_VDPAU_HWACCEL || CONFIG_WMV3_VDPAU_HWACCEL
330 int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx)
332 MpegEncContext *s = avctx->priv_data;
333 Picture *pic = s->current_picture_ptr;
334 struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
337 val = ff_vdpau_common_end_frame(avctx, pic->f, pic_ctx);
341 ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
346 int ff_vdpau_add_buffer(struct vdpau_picture_context *pic_ctx,
347 const uint8_t *buf, uint32_t size)
349 VdpBitstreamBuffer *buffers = pic_ctx->bitstream_buffers;
351 buffers = av_fast_realloc(buffers, &pic_ctx->bitstream_buffers_allocated,
352 (pic_ctx->bitstream_buffers_used + 1) * sizeof(*buffers));
354 return AVERROR(ENOMEM);
356 pic_ctx->bitstream_buffers = buffers;
357 buffers += pic_ctx->bitstream_buffers_used++;
359 buffers->struct_version = VDP_BITSTREAM_BUFFER_VERSION;
360 buffers->bitstream = buf;
361 buffers->bitstream_bytes = size;
365 /* Obsolete non-hwaccel VDPAU support below... */
368 void ff_vdpau_add_data_chunk(uint8_t *data, const uint8_t *buf, int buf_size)
370 struct vdpau_render_state *render = (struct vdpau_render_state*)data;
373 render->bitstream_buffers= av_fast_realloc(
374 render->bitstream_buffers,
375 &render->bitstream_buffers_allocated,
376 sizeof(*render->bitstream_buffers)*(render->bitstream_buffers_used + 1)
379 render->bitstream_buffers[render->bitstream_buffers_used].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
380 render->bitstream_buffers[render->bitstream_buffers_used].bitstream = buf;
381 render->bitstream_buffers[render->bitstream_buffers_used].bitstream_bytes = buf_size;
382 render->bitstream_buffers_used++;
385 #if CONFIG_H264_VDPAU_DECODER
386 void ff_vdpau_h264_set_reference_frames(H264Context *h)
388 struct vdpau_render_state *render, *render_ref;
389 VdpReferenceFrameH264 *rf, *rf2;
391 int i, list, pic_frame_idx;
393 render = (struct vdpau_render_state *)h->cur_pic_ptr->f->data[0];
396 rf = &render->info.h264.referenceFrames[0];
397 #define H264_RF_COUNT FF_ARRAY_ELEMS(render->info.h264.referenceFrames)
399 for (list = 0; list < 2; ++list) {
400 H264Picture **lp = list ? h->long_ref : h->short_ref;
401 int ls = list ? 16 : h->short_ref_count;
403 for (i = 0; i < ls; ++i) {
405 if (!pic || !pic->reference)
407 pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num;
409 render_ref = (struct vdpau_render_state *)pic->f->data[0];
412 rf2 = &render->info.h264.referenceFrames[0];
415 (rf2->surface == render_ref->surface)
416 && (rf2->is_long_term == pic->long_ref)
417 && (rf2->frame_idx == pic_frame_idx)
423 rf2->top_is_reference |= (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE;
424 rf2->bottom_is_reference |= (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE;
428 if (rf >= &render->info.h264.referenceFrames[H264_RF_COUNT])
431 rf->surface = render_ref->surface;
432 rf->is_long_term = pic->long_ref;
433 rf->top_is_reference = (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE;
434 rf->bottom_is_reference = (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE;
435 rf->field_order_cnt[0] = pic->field_poc[0];
436 rf->field_order_cnt[1] = pic->field_poc[1];
437 rf->frame_idx = pic_frame_idx;
443 for (; rf < &render->info.h264.referenceFrames[H264_RF_COUNT]; ++rf) {
444 rf->surface = VDP_INVALID_HANDLE;
445 rf->is_long_term = 0;
446 rf->top_is_reference = 0;
447 rf->bottom_is_reference = 0;
448 rf->field_order_cnt[0] = 0;
449 rf->field_order_cnt[1] = 0;
454 void ff_vdpau_h264_picture_start(H264Context *h)
456 struct vdpau_render_state *render;
459 render = (struct vdpau_render_state *)h->cur_pic_ptr->f->data[0];
462 for (i = 0; i < 2; ++i) {
463 int foc = h->cur_pic_ptr->field_poc[i];
466 render->info.h264.field_order_cnt[i] = foc;
469 render->info.h264.frame_num = h->poc.frame_num;
472 void ff_vdpau_h264_picture_complete(H264Context *h)
474 struct vdpau_render_state *render;
476 render = (struct vdpau_render_state *)h->cur_pic_ptr->f->data[0];
479 render->info.h264.slice_count = h->current_slice;
480 if (render->info.h264.slice_count < 1)
483 render->info.h264.is_reference = (h->cur_pic_ptr->reference & 3) ? VDP_TRUE : VDP_FALSE;
484 render->info.h264.field_pic_flag = h->picture_structure != PICT_FRAME;
485 render->info.h264.bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD;
486 render->info.h264.num_ref_frames = h->ps.sps->ref_frame_count;
487 render->info.h264.mb_adaptive_frame_field_flag = h->ps.sps->mb_aff && !render->info.h264.field_pic_flag;
488 render->info.h264.constrained_intra_pred_flag = h->ps.pps->constrained_intra_pred;
489 render->info.h264.weighted_pred_flag = h->ps.pps->weighted_pred;
490 render->info.h264.weighted_bipred_idc = h->ps.pps->weighted_bipred_idc;
491 render->info.h264.frame_mbs_only_flag = h->ps.sps->frame_mbs_only_flag;
492 render->info.h264.transform_8x8_mode_flag = h->ps.pps->transform_8x8_mode;
493 render->info.h264.chroma_qp_index_offset = h->ps.pps->chroma_qp_index_offset[0];
494 render->info.h264.second_chroma_qp_index_offset = h->ps.pps->chroma_qp_index_offset[1];
495 render->info.h264.pic_init_qp_minus26 = h->ps.pps->init_qp - 26;
496 render->info.h264.num_ref_idx_l0_active_minus1 = h->ps.pps->ref_count[0] - 1;
497 render->info.h264.num_ref_idx_l1_active_minus1 = h->ps.pps->ref_count[1] - 1;
498 render->info.h264.log2_max_frame_num_minus4 = h->ps.sps->log2_max_frame_num - 4;
499 render->info.h264.pic_order_cnt_type = h->ps.sps->poc_type;
500 render->info.h264.log2_max_pic_order_cnt_lsb_minus4 = h->ps.sps->poc_type ? 0 : h->ps.sps->log2_max_poc_lsb - 4;
501 render->info.h264.delta_pic_order_always_zero_flag = h->ps.sps->delta_pic_order_always_zero_flag;
502 render->info.h264.direct_8x8_inference_flag = h->ps.sps->direct_8x8_inference_flag;
503 render->info.h264.entropy_coding_mode_flag = h->ps.pps->cabac;
504 render->info.h264.pic_order_present_flag = h->ps.pps->pic_order_present;
505 render->info.h264.deblocking_filter_control_present_flag = h->ps.pps->deblocking_filter_parameters_present;
506 render->info.h264.redundant_pic_cnt_present_flag = h->ps.pps->redundant_pic_cnt_present;
507 memcpy(render->info.h264.scaling_lists_4x4, h->ps.pps->scaling_matrix4, sizeof(render->info.h264.scaling_lists_4x4));
508 memcpy(render->info.h264.scaling_lists_8x8[0], h->ps.pps->scaling_matrix8[0], sizeof(render->info.h264.scaling_lists_8x8[0]));
509 memcpy(render->info.h264.scaling_lists_8x8[1], h->ps.pps->scaling_matrix8[3], sizeof(render->info.h264.scaling_lists_8x8[0]));
511 ff_h264_draw_horiz_band(h, &h->slice_ctx[0], 0, h->avctx->height);
512 render->bitstream_buffers_used = 0;
514 #endif /* CONFIG_H264_VDPAU_DECODER */
516 #if CONFIG_MPEG_VDPAU_DECODER || CONFIG_MPEG1_VDPAU_DECODER
517 void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
518 int buf_size, int slice_count)
520 struct vdpau_render_state *render, *last, *next;
523 if (!s->current_picture_ptr) return;
525 render = (struct vdpau_render_state *)s->current_picture_ptr->f->data[0];
528 /* fill VdpPictureInfoMPEG1Or2 struct */
529 render->info.mpeg.picture_structure = s->picture_structure;
530 render->info.mpeg.picture_coding_type = s->pict_type;
531 render->info.mpeg.intra_dc_precision = s->intra_dc_precision;
532 render->info.mpeg.frame_pred_frame_dct = s->frame_pred_frame_dct;
533 render->info.mpeg.concealment_motion_vectors = s->concealment_motion_vectors;
534 render->info.mpeg.intra_vlc_format = s->intra_vlc_format;
535 render->info.mpeg.alternate_scan = s->alternate_scan;
536 render->info.mpeg.q_scale_type = s->q_scale_type;
537 render->info.mpeg.top_field_first = s->top_field_first;
538 render->info.mpeg.full_pel_forward_vector = s->full_pel[0]; // MPEG-1 only. Set 0 for MPEG-2
539 render->info.mpeg.full_pel_backward_vector = s->full_pel[1]; // MPEG-1 only. Set 0 for MPEG-2
540 render->info.mpeg.f_code[0][0] = s->mpeg_f_code[0][0]; // For MPEG-1 fill both horiz. & vert.
541 render->info.mpeg.f_code[0][1] = s->mpeg_f_code[0][1];
542 render->info.mpeg.f_code[1][0] = s->mpeg_f_code[1][0];
543 render->info.mpeg.f_code[1][1] = s->mpeg_f_code[1][1];
544 for (i = 0; i < 64; ++i) {
545 render->info.mpeg.intra_quantizer_matrix[i] = s->intra_matrix[i];
546 render->info.mpeg.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
549 render->info.mpeg.forward_reference = VDP_INVALID_HANDLE;
550 render->info.mpeg.backward_reference = VDP_INVALID_HANDLE;
552 switch(s->pict_type){
553 case AV_PICTURE_TYPE_B:
554 next = (struct vdpau_render_state *)s->next_picture.f->data[0];
556 render->info.mpeg.backward_reference = next->surface;
557 // no return here, going to set forward prediction
558 case AV_PICTURE_TYPE_P:
559 last = (struct vdpau_render_state *)s->last_picture.f->data[0];
560 if (!last) // FIXME: Does this test make sense?
561 last = render; // predict second field from the first
562 render->info.mpeg.forward_reference = last->surface;
565 ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size);
567 render->info.mpeg.slice_count = slice_count;
570 ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
571 render->bitstream_buffers_used = 0;
573 #endif /* CONFIG_MPEG_VDPAU_DECODER || CONFIG_MPEG1_VDPAU_DECODER */
575 #if CONFIG_VC1_VDPAU_DECODER
576 void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf,
579 VC1Context *v = s->avctx->priv_data;
580 struct vdpau_render_state *render, *last, *next;
582 render = (struct vdpau_render_state *)s->current_picture.f->data[0];
585 /* fill LvPictureInfoVC1 struct */
586 render->info.vc1.frame_coding_mode = v->fcm ? v->fcm + 1 : 0;
587 render->info.vc1.postprocflag = v->postprocflag;
588 render->info.vc1.pulldown = v->broadcast;
589 render->info.vc1.interlace = v->interlace;
590 render->info.vc1.tfcntrflag = v->tfcntrflag;
591 render->info.vc1.finterpflag = v->finterpflag;
592 render->info.vc1.psf = v->psf;
593 render->info.vc1.dquant = v->dquant;
594 render->info.vc1.panscan_flag = v->panscanflag;
595 render->info.vc1.refdist_flag = v->refdist_flag;
596 render->info.vc1.quantizer = v->quantizer_mode;
597 render->info.vc1.extended_mv = v->extended_mv;
598 render->info.vc1.extended_dmv = v->extended_dmv;
599 render->info.vc1.overlap = v->overlap;
600 render->info.vc1.vstransform = v->vstransform;
601 render->info.vc1.loopfilter = v->s.loop_filter;
602 render->info.vc1.fastuvmc = v->fastuvmc;
603 render->info.vc1.range_mapy_flag = v->range_mapy_flag;
604 render->info.vc1.range_mapy = v->range_mapy;
605 render->info.vc1.range_mapuv_flag = v->range_mapuv_flag;
606 render->info.vc1.range_mapuv = v->range_mapuv;
607 /* Specific to simple/main profile only */
608 render->info.vc1.multires = v->multires;
609 render->info.vc1.syncmarker = v->resync_marker;
610 render->info.vc1.rangered = v->rangered | (v->rangeredfrm << 1);
611 render->info.vc1.maxbframes = v->s.max_b_frames;
613 render->info.vc1.deblockEnable = v->postprocflag & 1;
614 render->info.vc1.pquant = v->pq;
616 render->info.vc1.forward_reference = VDP_INVALID_HANDLE;
617 render->info.vc1.backward_reference = VDP_INVALID_HANDLE;
620 render->info.vc1.picture_type = 4;
622 render->info.vc1.picture_type = s->pict_type - 1 + s->pict_type / 3;
624 switch(s->pict_type){
625 case AV_PICTURE_TYPE_B:
626 next = (struct vdpau_render_state *)s->next_picture.f->data[0];
628 render->info.vc1.backward_reference = next->surface;
629 // no break here, going to set forward prediction
630 case AV_PICTURE_TYPE_P:
631 last = (struct vdpau_render_state *)s->last_picture.f->data[0];
632 if (!last) // FIXME: Does this test make sense?
633 last = render; // predict second field from the first
634 render->info.vc1.forward_reference = last->surface;
637 ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size);
639 render->info.vc1.slice_count = 1;
641 ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
642 render->bitstream_buffers_used = 0;
644 #endif /* (CONFIG_VC1_VDPAU_DECODER */
646 #if CONFIG_MPEG4_VDPAU_DECODER
647 void ff_vdpau_mpeg4_decode_picture(Mpeg4DecContext *ctx, const uint8_t *buf,
650 MpegEncContext *s = &ctx->m;
651 struct vdpau_render_state *render, *last, *next;
654 if (!s->current_picture_ptr) return;
656 render = (struct vdpau_render_state *)s->current_picture_ptr->f->data[0];
659 /* fill VdpPictureInfoMPEG4Part2 struct */
660 render->info.mpeg4.trd[0] = s->pp_time;
661 render->info.mpeg4.trb[0] = s->pb_time;
662 render->info.mpeg4.trd[1] = s->pp_field_time >> 1;
663 render->info.mpeg4.trb[1] = s->pb_field_time >> 1;
664 render->info.mpeg4.vop_time_increment_resolution = s->avctx->time_base.den;
665 render->info.mpeg4.vop_coding_type = 0;
666 render->info.mpeg4.vop_fcode_forward = s->f_code;
667 render->info.mpeg4.vop_fcode_backward = s->b_code;
668 render->info.mpeg4.resync_marker_disable = !ctx->resync_marker;
669 render->info.mpeg4.interlaced = !s->progressive_sequence;
670 render->info.mpeg4.quant_type = s->mpeg_quant;
671 render->info.mpeg4.quarter_sample = s->quarter_sample;
672 render->info.mpeg4.short_video_header = s->avctx->codec->id == AV_CODEC_ID_H263;
673 render->info.mpeg4.rounding_control = s->no_rounding;
674 render->info.mpeg4.alternate_vertical_scan_flag = s->alternate_scan;
675 render->info.mpeg4.top_field_first = s->top_field_first;
676 for (i = 0; i < 64; ++i) {
677 render->info.mpeg4.intra_quantizer_matrix[i] = s->intra_matrix[i];
678 render->info.mpeg4.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
680 render->info.mpeg4.forward_reference = VDP_INVALID_HANDLE;
681 render->info.mpeg4.backward_reference = VDP_INVALID_HANDLE;
683 switch (s->pict_type) {
684 case AV_PICTURE_TYPE_B:
685 next = (struct vdpau_render_state *)s->next_picture.f->data[0];
687 render->info.mpeg4.backward_reference = next->surface;
688 render->info.mpeg4.vop_coding_type = 2;
689 // no break here, going to set forward prediction
690 case AV_PICTURE_TYPE_P:
691 last = (struct vdpau_render_state *)s->last_picture.f->data[0];
693 render->info.mpeg4.forward_reference = last->surface;
696 ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size);
698 ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
699 render->bitstream_buffers_used = 0;
701 #endif /* CONFIG_MPEG4_VDPAU_DECODER */
702 #endif /* FF_API_VDPAU */
704 #if FF_API_VDPAU_PROFILE
705 int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile)
707 #define PROFILE(prof) \
709 *profile = VDP_DECODER_PROFILE_##prof; \
713 switch (avctx->codec_id) {
714 case AV_CODEC_ID_MPEG1VIDEO: PROFILE(MPEG1);
715 case AV_CODEC_ID_MPEG2VIDEO:
716 switch (avctx->profile) {
717 case FF_PROFILE_MPEG2_MAIN: PROFILE(MPEG2_MAIN);
718 case FF_PROFILE_MPEG2_SIMPLE: PROFILE(MPEG2_SIMPLE);
719 default: return AVERROR(EINVAL);
721 case AV_CODEC_ID_H263: PROFILE(MPEG4_PART2_ASP);
722 case AV_CODEC_ID_MPEG4:
723 switch (avctx->profile) {
724 case FF_PROFILE_MPEG4_SIMPLE: PROFILE(MPEG4_PART2_SP);
725 case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: PROFILE(MPEG4_PART2_ASP);
726 default: return AVERROR(EINVAL);
728 case AV_CODEC_ID_H264:
729 switch (avctx->profile & ~FF_PROFILE_H264_INTRA) {
730 case FF_PROFILE_H264_BASELINE: PROFILE(H264_BASELINE);
731 case FF_PROFILE_H264_CONSTRAINED_BASELINE:
732 case FF_PROFILE_H264_MAIN: PROFILE(H264_MAIN);
733 case FF_PROFILE_H264_HIGH: PROFILE(H264_HIGH);
734 #ifdef VDP_DECODER_PROFILE_H264_EXTENDED
735 case FF_PROFILE_H264_EXTENDED: PROFILE(H264_EXTENDED);
737 default: return AVERROR(EINVAL);
739 case AV_CODEC_ID_WMV3:
740 case AV_CODEC_ID_VC1:
741 switch (avctx->profile) {
742 case FF_PROFILE_VC1_SIMPLE: PROFILE(VC1_SIMPLE);
743 case FF_PROFILE_VC1_MAIN: PROFILE(VC1_MAIN);
744 case FF_PROFILE_VC1_ADVANCED: PROFILE(VC1_ADVANCED);
745 default: return AVERROR(EINVAL);
748 return AVERROR(EINVAL);
751 #endif /* FF_API_VDPAU_PROFILE */
753 AVVDPAUContext *av_vdpau_alloc_context(void)
755 return av_mallocz(sizeof(AVVDPAUContext));
758 int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,
759 VdpGetProcAddress *get_proc, unsigned flags)
761 VDPAUHWContext *hwctx;
763 if (flags & ~(AV_HWACCEL_FLAG_IGNORE_LEVEL|AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH))
764 return AVERROR(EINVAL);
766 if (av_reallocp(&avctx->hwaccel_context, sizeof(*hwctx)))
767 return AVERROR(ENOMEM);
769 hwctx = avctx->hwaccel_context;
771 memset(hwctx, 0, sizeof(*hwctx));
772 hwctx->context.decoder = VDP_INVALID_HANDLE;
773 hwctx->device = device;
774 hwctx->get_proc_address = get_proc;
775 hwctx->flags = flags;