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
25 #include "libavutil/avassert.h"
35 #include "vdpau_internal.h"
38 * @addtogroup VDPAU_Decoding
43 static int vdpau_error(VdpStatus status
)
48 case VDP_STATUS_NO_IMPLEMENTATION
:
49 return AVERROR(ENOSYS
);
50 case VDP_STATUS_DISPLAY_PREEMPTED
:
52 case VDP_STATUS_INVALID_HANDLE
:
53 return AVERROR(EBADF
);
54 case VDP_STATUS_INVALID_POINTER
:
55 return AVERROR(EFAULT
);
56 case VDP_STATUS_RESOURCES
:
57 return AVERROR(ENOBUFS
);
58 case VDP_STATUS_HANDLE_DEVICE_MISMATCH
:
59 return AVERROR(EXDEV
);
60 case VDP_STATUS_ERROR
:
63 return AVERROR(EINVAL
);
67 AVVDPAUContext
*av_alloc_vdpaucontext(void)
69 return av_vdpau_alloc_context();
72 MAKE_ACCESSORS(AVVDPAUContext
, vdpau_hwaccel
, AVVDPAU_Render2
, render2
)
74 int ff_vdpau_common_init(AVCodecContext
*avctx
, VdpDecoderProfile profile
,
77 VDPAUHWContext
*hwctx
= avctx
->hwaccel_context
;
78 VDPAUContext
*vdctx
= avctx
->internal
->hwaccel_priv_data
;
79 VdpVideoSurfaceQueryCapabilities
*surface_query_caps
;
80 VdpDecoderQueryCapabilities
*decoder_query_caps
;
81 VdpDecoderCreate
*create
;
85 uint32_t max_level
, max_mb
, max_width
, max_height
;
86 /* See vdpau/vdpau.h for alignment constraints. */
87 uint32_t width
= (avctx
->coded_width
+ 1) & ~1;
88 uint32_t height
= (avctx
->coded_height
+ 3) & ~3;
90 vdctx
->width
= UINT32_MAX
;
91 vdctx
->height
= UINT32_MAX
;
94 vdctx
->device
= VDP_INVALID_HANDLE
;
95 av_log(avctx
, AV_LOG_WARNING
, "hwaccel_context has not been setup by the user application, cannot initialize\n");
99 if (hwctx
->context
.decoder
!= VDP_INVALID_HANDLE
) {
100 vdctx
->decoder
= hwctx
->context
.decoder
;
101 vdctx
->render
= hwctx
->context
.render
;
102 vdctx
->device
= VDP_INVALID_HANDLE
;
103 return 0; /* Decoder created by user */
107 vdctx
->device
= hwctx
->device
;
108 vdctx
->get_proc_address
= hwctx
->get_proc_address
;
110 if (hwctx
->flags
& AV_HWACCEL_FLAG_IGNORE_LEVEL
)
113 return AVERROR(ENOTSUP
);
115 status
= vdctx
->get_proc_address(vdctx
->device
,
116 VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES
,
118 if (status
!= VDP_STATUS_OK
)
119 return vdpau_error(status
);
121 surface_query_caps
= func
;
123 status
= surface_query_caps(vdctx
->device
, VDP_CHROMA_TYPE_420
, &supported
,
124 &max_width
, &max_height
);
125 if (status
!= VDP_STATUS_OK
)
126 return vdpau_error(status
);
127 if (supported
!= VDP_TRUE
||
128 max_width
< width
|| max_height
< height
)
129 return AVERROR(ENOTSUP
);
131 status
= vdctx
->get_proc_address(vdctx
->device
,
132 VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES
,
134 if (status
!= VDP_STATUS_OK
)
135 return vdpau_error(status
);
137 decoder_query_caps
= func
;
139 status
= decoder_query_caps(vdctx
->device
, profile
, &supported
, &max_level
,
140 &max_mb
, &max_width
, &max_height
);
141 if (status
!= VDP_STATUS_OK
)
142 return vdpau_error(status
);
144 if (supported
!= VDP_TRUE
|| max_level
< level
||
145 max_width
< width
|| max_height
< height
)
146 return AVERROR(ENOTSUP
);
148 status
= vdctx
->get_proc_address(vdctx
->device
, VDP_FUNC_ID_DECODER_CREATE
,
150 if (status
!= VDP_STATUS_OK
)
151 return vdpau_error(status
);
155 status
= vdctx
->get_proc_address(vdctx
->device
, VDP_FUNC_ID_DECODER_RENDER
,
157 if (status
!= VDP_STATUS_OK
)
158 return vdpau_error(status
);
160 vdctx
->render
= func
;
162 status
= create(vdctx
->device
, profile
, width
, height
, avctx
->refs
,
164 if (status
== VDP_STATUS_OK
) {
165 vdctx
->width
= avctx
->coded_width
;
166 vdctx
->height
= avctx
->coded_height
;
169 return vdpau_error(status
);
172 int ff_vdpau_common_uninit(AVCodecContext
*avctx
)
174 VDPAUContext
*vdctx
= avctx
->internal
->hwaccel_priv_data
;
175 VdpDecoderDestroy
*destroy
;
179 if (vdctx
->device
== VDP_INVALID_HANDLE
)
180 return 0; /* Decoder created and destroyed by user */
181 if (vdctx
->width
== UINT32_MAX
&& vdctx
->height
== UINT32_MAX
)
184 status
= vdctx
->get_proc_address(vdctx
->device
,
185 VDP_FUNC_ID_DECODER_DESTROY
, &func
);
186 if (status
!= VDP_STATUS_OK
)
187 return vdpau_error(status
);
191 status
= destroy(vdctx
->decoder
);
192 return vdpau_error(status
);
195 static int ff_vdpau_common_reinit(AVCodecContext
*avctx
)
197 VDPAUHWContext
*hwctx
= avctx
->hwaccel_context
;
198 VDPAUContext
*vdctx
= avctx
->internal
->hwaccel_priv_data
;
200 if (vdctx
->device
== VDP_INVALID_HANDLE
)
201 return 0; /* Decoder created by user */
202 if (avctx
->coded_width
== vdctx
->width
&&
203 avctx
->coded_height
== vdctx
->height
&& !hwctx
->reset
)
206 avctx
->hwaccel
->uninit(avctx
);
207 return avctx
->hwaccel
->init(avctx
);
210 int ff_vdpau_common_start_frame(struct vdpau_picture_context
*pic_ctx
,
211 av_unused
const uint8_t *buffer
,
212 av_unused
uint32_t size
)
214 pic_ctx
->bitstream_buffers_allocated
= 0;
215 pic_ctx
->bitstream_buffers_used
= 0;
216 pic_ctx
->bitstream_buffers
= NULL
;
220 int ff_vdpau_common_end_frame(AVCodecContext
*avctx
, AVFrame
*frame
,
221 struct vdpau_picture_context
*pic_ctx
)
223 VDPAUContext
*vdctx
= avctx
->internal
->hwaccel_priv_data
;
224 AVVDPAUContext
*hwctx
= avctx
->hwaccel_context
;
225 VdpVideoSurface surf
= ff_vdpau_get_surface_id(frame
);
229 val
= ff_vdpau_common_reinit(avctx
);
233 #if FF_API_BUFS_VDPAU
234 FF_DISABLE_DEPRECATION_WARNINGS
235 hwctx
->info
= pic_ctx
->info
;
236 hwctx
->bitstream_buffers
= pic_ctx
->bitstream_buffers
;
237 hwctx
->bitstream_buffers_used
= pic_ctx
->bitstream_buffers_used
;
238 hwctx
->bitstream_buffers_allocated
= pic_ctx
->bitstream_buffers_allocated
;
239 FF_ENABLE_DEPRECATION_WARNINGS
242 if (!hwctx
->render
&& hwctx
->render2
) {
243 status
= hwctx
->render2(avctx
, frame
, (void *)&pic_ctx
->info
,
244 pic_ctx
->bitstream_buffers_used
, pic_ctx
->bitstream_buffers
);
246 status
= vdctx
->render(vdctx
->decoder
, surf
, (void *)&pic_ctx
->info
,
247 pic_ctx
->bitstream_buffers_used
,
248 pic_ctx
->bitstream_buffers
);
250 av_freep(&pic_ctx
->bitstream_buffers
);
252 #if FF_API_BUFS_VDPAU
253 FF_DISABLE_DEPRECATION_WARNINGS
254 hwctx
->bitstream_buffers
= NULL
;
255 hwctx
->bitstream_buffers_used
= 0;
256 hwctx
->bitstream_buffers_allocated
= 0;
257 FF_ENABLE_DEPRECATION_WARNINGS
260 return vdpau_error(status
);
263 #if CONFIG_H263_VDPAU_HWACCEL || CONFIG_MPEG1_VDPAU_HWACCEL || \
264 CONFIG_MPEG2_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL || \
265 CONFIG_VC1_VDPAU_HWACCEL || CONFIG_WMV3_VDPAU_HWACCEL
266 int ff_vdpau_mpeg_end_frame(AVCodecContext
*avctx
)
268 MpegEncContext
*s
= avctx
->priv_data
;
269 Picture
*pic
= s
->current_picture_ptr
;
270 struct vdpau_picture_context
*pic_ctx
= pic
->hwaccel_picture_private
;
273 val
= ff_vdpau_common_end_frame(avctx
, pic
->f
, pic_ctx
);
277 ff_mpeg_draw_horiz_band(s
, 0, s
->avctx
->height
);
282 int ff_vdpau_add_buffer(struct vdpau_picture_context
*pic_ctx
,
283 const uint8_t *buf
, uint32_t size
)
285 VdpBitstreamBuffer
*buffers
= pic_ctx
->bitstream_buffers
;
287 buffers
= av_fast_realloc(buffers
, &pic_ctx
->bitstream_buffers_allocated
,
288 (pic_ctx
->bitstream_buffers_used
+ 1) * sizeof(*buffers
));
290 return AVERROR(ENOMEM
);
292 pic_ctx
->bitstream_buffers
= buffers
;
293 buffers
+= pic_ctx
->bitstream_buffers_used
++;
295 buffers
->struct_version
= VDP_BITSTREAM_BUFFER_VERSION
;
296 buffers
->bitstream
= buf
;
297 buffers
->bitstream_bytes
= size
;
301 /* Obsolete non-hwaccel VDPAU support below... */
303 void ff_vdpau_h264_set_reference_frames(H264Context
*h
)
305 struct vdpau_render_state
*render
, *render_ref
;
306 VdpReferenceFrameH264
*rf
, *rf2
;
308 int i
, list
, pic_frame_idx
;
310 render
= (struct vdpau_render_state
*)h
->cur_pic_ptr
->f
.data
[0];
313 rf
= &render
->info
.h264
.referenceFrames
[0];
314 #define H264_RF_COUNT FF_ARRAY_ELEMS(render->info.h264.referenceFrames)
316 for (list
= 0; list
< 2; ++list
) {
317 H264Picture
**lp
= list
? h
->long_ref
: h
->short_ref
;
318 int ls
= list
? 16 : h
->short_ref_count
;
320 for (i
= 0; i
< ls
; ++i
) {
322 if (!pic
|| !pic
->reference
)
324 pic_frame_idx
= pic
->long_ref
? pic
->pic_id
: pic
->frame_num
;
326 render_ref
= (struct vdpau_render_state
*)pic
->f
.data
[0];
329 rf2
= &render
->info
.h264
.referenceFrames
[0];
332 (rf2
->surface
== render_ref
->surface
)
333 && (rf2
->is_long_term
== pic
->long_ref
)
334 && (rf2
->frame_idx
== pic_frame_idx
)
340 rf2
->top_is_reference
|= (pic
->reference
& PICT_TOP_FIELD
) ? VDP_TRUE
: VDP_FALSE
;
341 rf2
->bottom_is_reference
|= (pic
->reference
& PICT_BOTTOM_FIELD
) ? VDP_TRUE
: VDP_FALSE
;
345 if (rf
>= &render
->info
.h264
.referenceFrames
[H264_RF_COUNT
])
348 rf
->surface
= render_ref
->surface
;
349 rf
->is_long_term
= pic
->long_ref
;
350 rf
->top_is_reference
= (pic
->reference
& PICT_TOP_FIELD
) ? VDP_TRUE
: VDP_FALSE
;
351 rf
->bottom_is_reference
= (pic
->reference
& PICT_BOTTOM_FIELD
) ? VDP_TRUE
: VDP_FALSE
;
352 rf
->field_order_cnt
[0] = pic
->field_poc
[0];
353 rf
->field_order_cnt
[1] = pic
->field_poc
[1];
354 rf
->frame_idx
= pic_frame_idx
;
360 for (; rf
< &render
->info
.h264
.referenceFrames
[H264_RF_COUNT
]; ++rf
) {
361 rf
->surface
= VDP_INVALID_HANDLE
;
362 rf
->is_long_term
= 0;
363 rf
->top_is_reference
= 0;
364 rf
->bottom_is_reference
= 0;
365 rf
->field_order_cnt
[0] = 0;
366 rf
->field_order_cnt
[1] = 0;
371 void ff_vdpau_add_data_chunk(uint8_t *data
, const uint8_t *buf
, int buf_size
)
373 struct vdpau_render_state
*render
= (struct vdpau_render_state
*)data
;
376 render
->bitstream_buffers
= av_fast_realloc(
377 render
->bitstream_buffers
,
378 &render
->bitstream_buffers_allocated
,
379 sizeof(*render
->bitstream_buffers
)*(render
->bitstream_buffers_used
+ 1)
382 render
->bitstream_buffers
[render
->bitstream_buffers_used
].struct_version
= VDP_BITSTREAM_BUFFER_VERSION
;
383 render
->bitstream_buffers
[render
->bitstream_buffers_used
].bitstream
= buf
;
384 render
->bitstream_buffers
[render
->bitstream_buffers_used
].bitstream_bytes
= buf_size
;
385 render
->bitstream_buffers_used
++;
388 #if CONFIG_H264_VDPAU_DECODER
389 void ff_vdpau_h264_picture_start(H264Context
*h
)
391 struct vdpau_render_state
*render
;
394 render
= (struct vdpau_render_state
*)h
->cur_pic_ptr
->f
.data
[0];
397 for (i
= 0; i
< 2; ++i
) {
398 int foc
= h
->cur_pic_ptr
->field_poc
[i
];
401 render
->info
.h264
.field_order_cnt
[i
] = foc
;
404 render
->info
.h264
.frame_num
= h
->frame_num
;
407 void ff_vdpau_h264_picture_complete(H264Context
*h
)
409 struct vdpau_render_state
*render
;
411 render
= (struct vdpau_render_state
*)h
->cur_pic_ptr
->f
.data
[0];
414 render
->info
.h264
.slice_count
= h
->slice_num
;
415 if (render
->info
.h264
.slice_count
< 1)
418 render
->info
.h264
.is_reference
= (h
->cur_pic_ptr
->reference
& 3) ? VDP_TRUE
: VDP_FALSE
;
419 render
->info
.h264
.field_pic_flag
= h
->picture_structure
!= PICT_FRAME
;
420 render
->info
.h264
.bottom_field_flag
= h
->picture_structure
== PICT_BOTTOM_FIELD
;
421 render
->info
.h264
.num_ref_frames
= h
->sps
.ref_frame_count
;
422 render
->info
.h264
.mb_adaptive_frame_field_flag
= h
->sps
.mb_aff
&& !render
->info
.h264
.field_pic_flag
;
423 render
->info
.h264
.constrained_intra_pred_flag
= h
->pps
.constrained_intra_pred
;
424 render
->info
.h264
.weighted_pred_flag
= h
->pps
.weighted_pred
;
425 render
->info
.h264
.weighted_bipred_idc
= h
->pps
.weighted_bipred_idc
;
426 render
->info
.h264
.frame_mbs_only_flag
= h
->sps
.frame_mbs_only_flag
;
427 render
->info
.h264
.transform_8x8_mode_flag
= h
->pps
.transform_8x8_mode
;
428 render
->info
.h264
.chroma_qp_index_offset
= h
->pps
.chroma_qp_index_offset
[0];
429 render
->info
.h264
.second_chroma_qp_index_offset
= h
->pps
.chroma_qp_index_offset
[1];
430 render
->info
.h264
.pic_init_qp_minus26
= h
->pps
.init_qp
- 26;
431 render
->info
.h264
.num_ref_idx_l0_active_minus1
= h
->pps
.ref_count
[0] - 1;
432 render
->info
.h264
.num_ref_idx_l1_active_minus1
= h
->pps
.ref_count
[1] - 1;
433 render
->info
.h264
.log2_max_frame_num_minus4
= h
->sps
.log2_max_frame_num
- 4;
434 render
->info
.h264
.pic_order_cnt_type
= h
->sps
.poc_type
;
435 render
->info
.h264
.log2_max_pic_order_cnt_lsb_minus4
= h
->sps
.poc_type
? 0 : h
->sps
.log2_max_poc_lsb
- 4;
436 render
->info
.h264
.delta_pic_order_always_zero_flag
= h
->sps
.delta_pic_order_always_zero_flag
;
437 render
->info
.h264
.direct_8x8_inference_flag
= h
->sps
.direct_8x8_inference_flag
;
438 render
->info
.h264
.entropy_coding_mode_flag
= h
->pps
.cabac
;
439 render
->info
.h264
.pic_order_present_flag
= h
->pps
.pic_order_present
;
440 render
->info
.h264
.deblocking_filter_control_present_flag
= h
->pps
.deblocking_filter_parameters_present
;
441 render
->info
.h264
.redundant_pic_cnt_present_flag
= h
->pps
.redundant_pic_cnt_present
;
442 memcpy(render
->info
.h264
.scaling_lists_4x4
, h
->pps
.scaling_matrix4
, sizeof(render
->info
.h264
.scaling_lists_4x4
));
443 memcpy(render
->info
.h264
.scaling_lists_8x8
[0], h
->pps
.scaling_matrix8
[0], sizeof(render
->info
.h264
.scaling_lists_8x8
[0]));
444 memcpy(render
->info
.h264
.scaling_lists_8x8
[1], h
->pps
.scaling_matrix8
[3], sizeof(render
->info
.h264
.scaling_lists_8x8
[0]));
446 ff_h264_draw_horiz_band(h
, 0, h
->avctx
->height
);
447 render
->bitstream_buffers_used
= 0;
449 #endif /* CONFIG_H264_VDPAU_DECODER */
451 #if CONFIG_MPEG_VDPAU_DECODER || CONFIG_MPEG1_VDPAU_DECODER
452 void ff_vdpau_mpeg_picture_complete(MpegEncContext
*s
, const uint8_t *buf
,
453 int buf_size
, int slice_count
)
455 struct vdpau_render_state
*render
, *last
, *next
;
458 if (!s
->current_picture_ptr
) return;
460 render
= (struct vdpau_render_state
*)s
->current_picture_ptr
->f
->data
[0];
463 /* fill VdpPictureInfoMPEG1Or2 struct */
464 render
->info
.mpeg
.picture_structure
= s
->picture_structure
;
465 render
->info
.mpeg
.picture_coding_type
= s
->pict_type
;
466 render
->info
.mpeg
.intra_dc_precision
= s
->intra_dc_precision
;
467 render
->info
.mpeg
.frame_pred_frame_dct
= s
->frame_pred_frame_dct
;
468 render
->info
.mpeg
.concealment_motion_vectors
= s
->concealment_motion_vectors
;
469 render
->info
.mpeg
.intra_vlc_format
= s
->intra_vlc_format
;
470 render
->info
.mpeg
.alternate_scan
= s
->alternate_scan
;
471 render
->info
.mpeg
.q_scale_type
= s
->q_scale_type
;
472 render
->info
.mpeg
.top_field_first
= s
->top_field_first
;
473 render
->info
.mpeg
.full_pel_forward_vector
= s
->full_pel
[0]; // MPEG-1 only. Set 0 for MPEG-2
474 render
->info
.mpeg
.full_pel_backward_vector
= s
->full_pel
[1]; // MPEG-1 only. Set 0 for MPEG-2
475 render
->info
.mpeg
.f_code
[0][0] = s
->mpeg_f_code
[0][0]; // For MPEG-1 fill both horiz. & vert.
476 render
->info
.mpeg
.f_code
[0][1] = s
->mpeg_f_code
[0][1];
477 render
->info
.mpeg
.f_code
[1][0] = s
->mpeg_f_code
[1][0];
478 render
->info
.mpeg
.f_code
[1][1] = s
->mpeg_f_code
[1][1];
479 for (i
= 0; i
< 64; ++i
) {
480 render
->info
.mpeg
.intra_quantizer_matrix
[i
] = s
->intra_matrix
[i
];
481 render
->info
.mpeg
.non_intra_quantizer_matrix
[i
] = s
->inter_matrix
[i
];
484 render
->info
.mpeg
.forward_reference
= VDP_INVALID_HANDLE
;
485 render
->info
.mpeg
.backward_reference
= VDP_INVALID_HANDLE
;
487 switch(s
->pict_type
){
488 case AV_PICTURE_TYPE_B
:
489 next
= (struct vdpau_render_state
*)s
->next_picture
.f
->data
[0];
491 render
->info
.mpeg
.backward_reference
= next
->surface
;
492 // no return here, going to set forward prediction
493 case AV_PICTURE_TYPE_P
:
494 last
= (struct vdpau_render_state
*)s
->last_picture
.f
->data
[0];
495 if (!last
) // FIXME: Does this test make sense?
496 last
= render
; // predict second field from the first
497 render
->info
.mpeg
.forward_reference
= last
->surface
;
500 ff_vdpau_add_data_chunk(s
->current_picture_ptr
->f
->data
[0], buf
, buf_size
);
502 render
->info
.mpeg
.slice_count
= slice_count
;
505 ff_mpeg_draw_horiz_band(s
, 0, s
->avctx
->height
);
506 render
->bitstream_buffers_used
= 0;
508 #endif /* CONFIG_MPEG_VDPAU_DECODER || CONFIG_MPEG1_VDPAU_DECODER */
510 #if CONFIG_VC1_VDPAU_DECODER
511 void ff_vdpau_vc1_decode_picture(MpegEncContext
*s
, const uint8_t *buf
,
514 VC1Context
*v
= s
->avctx
->priv_data
;
515 struct vdpau_render_state
*render
, *last
, *next
;
517 render
= (struct vdpau_render_state
*)s
->current_picture
.f
->data
[0];
520 /* fill LvPictureInfoVC1 struct */
521 render
->info
.vc1
.frame_coding_mode
= v
->fcm
? v
->fcm
+ 1 : 0;
522 render
->info
.vc1
.postprocflag
= v
->postprocflag
;
523 render
->info
.vc1
.pulldown
= v
->broadcast
;
524 render
->info
.vc1
.interlace
= v
->interlace
;
525 render
->info
.vc1
.tfcntrflag
= v
->tfcntrflag
;
526 render
->info
.vc1
.finterpflag
= v
->finterpflag
;
527 render
->info
.vc1
.psf
= v
->psf
;
528 render
->info
.vc1
.dquant
= v
->dquant
;
529 render
->info
.vc1
.panscan_flag
= v
->panscanflag
;
530 render
->info
.vc1
.refdist_flag
= v
->refdist_flag
;
531 render
->info
.vc1
.quantizer
= v
->quantizer_mode
;
532 render
->info
.vc1
.extended_mv
= v
->extended_mv
;
533 render
->info
.vc1
.extended_dmv
= v
->extended_dmv
;
534 render
->info
.vc1
.overlap
= v
->overlap
;
535 render
->info
.vc1
.vstransform
= v
->vstransform
;
536 render
->info
.vc1
.loopfilter
= v
->s
.loop_filter
;
537 render
->info
.vc1
.fastuvmc
= v
->fastuvmc
;
538 render
->info
.vc1
.range_mapy_flag
= v
->range_mapy_flag
;
539 render
->info
.vc1
.range_mapy
= v
->range_mapy
;
540 render
->info
.vc1
.range_mapuv_flag
= v
->range_mapuv_flag
;
541 render
->info
.vc1
.range_mapuv
= v
->range_mapuv
;
542 /* Specific to simple/main profile only */
543 render
->info
.vc1
.multires
= v
->multires
;
544 render
->info
.vc1
.syncmarker
= v
->resync_marker
;
545 render
->info
.vc1
.rangered
= v
->rangered
| (v
->rangeredfrm
<< 1);
546 render
->info
.vc1
.maxbframes
= v
->s
.max_b_frames
;
548 render
->info
.vc1
.deblockEnable
= v
->postprocflag
& 1;
549 render
->info
.vc1
.pquant
= v
->pq
;
551 render
->info
.vc1
.forward_reference
= VDP_INVALID_HANDLE
;
552 render
->info
.vc1
.backward_reference
= VDP_INVALID_HANDLE
;
555 render
->info
.vc1
.picture_type
= 4;
557 render
->info
.vc1
.picture_type
= s
->pict_type
- 1 + s
->pict_type
/ 3;
559 switch(s
->pict_type
){
560 case AV_PICTURE_TYPE_B
:
561 next
= (struct vdpau_render_state
*)s
->next_picture
.f
->data
[0];
563 render
->info
.vc1
.backward_reference
= next
->surface
;
564 // no break here, going to set forward prediction
565 case AV_PICTURE_TYPE_P
:
566 last
= (struct vdpau_render_state
*)s
->last_picture
.f
->data
[0];
567 if (!last
) // FIXME: Does this test make sense?
568 last
= render
; // predict second field from the first
569 render
->info
.vc1
.forward_reference
= last
->surface
;
572 ff_vdpau_add_data_chunk(s
->current_picture_ptr
->f
->data
[0], buf
, buf_size
);
574 render
->info
.vc1
.slice_count
= 1;
576 ff_mpeg_draw_horiz_band(s
, 0, s
->avctx
->height
);
577 render
->bitstream_buffers_used
= 0;
579 #endif /* (CONFIG_VC1_VDPAU_DECODER */
581 #if CONFIG_MPEG4_VDPAU_DECODER
582 void ff_vdpau_mpeg4_decode_picture(Mpeg4DecContext
*ctx
, const uint8_t *buf
,
585 MpegEncContext
*s
= &ctx
->m
;
586 struct vdpau_render_state
*render
, *last
, *next
;
589 if (!s
->current_picture_ptr
) return;
591 render
= (struct vdpau_render_state
*)s
->current_picture_ptr
->f
->data
[0];
594 /* fill VdpPictureInfoMPEG4Part2 struct */
595 render
->info
.mpeg4
.trd
[0] = s
->pp_time
;
596 render
->info
.mpeg4
.trb
[0] = s
->pb_time
;
597 render
->info
.mpeg4
.trd
[1] = s
->pp_field_time
>> 1;
598 render
->info
.mpeg4
.trb
[1] = s
->pb_field_time
>> 1;
599 render
->info
.mpeg4
.vop_time_increment_resolution
= s
->avctx
->time_base
.den
;
600 render
->info
.mpeg4
.vop_coding_type
= 0;
601 render
->info
.mpeg4
.vop_fcode_forward
= s
->f_code
;
602 render
->info
.mpeg4
.vop_fcode_backward
= s
->b_code
;
603 render
->info
.mpeg4
.resync_marker_disable
= !ctx
->resync_marker
;
604 render
->info
.mpeg4
.interlaced
= !s
->progressive_sequence
;
605 render
->info
.mpeg4
.quant_type
= s
->mpeg_quant
;
606 render
->info
.mpeg4
.quarter_sample
= s
->quarter_sample
;
607 render
->info
.mpeg4
.short_video_header
= s
->avctx
->codec
->id
== AV_CODEC_ID_H263
;
608 render
->info
.mpeg4
.rounding_control
= s
->no_rounding
;
609 render
->info
.mpeg4
.alternate_vertical_scan_flag
= s
->alternate_scan
;
610 render
->info
.mpeg4
.top_field_first
= s
->top_field_first
;
611 for (i
= 0; i
< 64; ++i
) {
612 render
->info
.mpeg4
.intra_quantizer_matrix
[i
] = s
->intra_matrix
[i
];
613 render
->info
.mpeg4
.non_intra_quantizer_matrix
[i
] = s
->inter_matrix
[i
];
615 render
->info
.mpeg4
.forward_reference
= VDP_INVALID_HANDLE
;
616 render
->info
.mpeg4
.backward_reference
= VDP_INVALID_HANDLE
;
618 switch (s
->pict_type
) {
619 case AV_PICTURE_TYPE_B
:
620 next
= (struct vdpau_render_state
*)s
->next_picture
.f
->data
[0];
622 render
->info
.mpeg4
.backward_reference
= next
->surface
;
623 render
->info
.mpeg4
.vop_coding_type
= 2;
624 // no break here, going to set forward prediction
625 case AV_PICTURE_TYPE_P
:
626 last
= (struct vdpau_render_state
*)s
->last_picture
.f
->data
[0];
628 render
->info
.mpeg4
.forward_reference
= last
->surface
;
631 ff_vdpau_add_data_chunk(s
->current_picture_ptr
->f
->data
[0], buf
, buf_size
);
633 ff_mpeg_draw_horiz_band(s
, 0, s
->avctx
->height
);
634 render
->bitstream_buffers_used
= 0;
636 #endif /* CONFIG_MPEG4_VDPAU_DECODER */
638 int av_vdpau_get_profile(AVCodecContext
*avctx
, VdpDecoderProfile
*profile
)
640 #define PROFILE(prof) \
646 switch (avctx
->codec_id
) {
647 case AV_CODEC_ID_MPEG1VIDEO
: PROFILE(VDP_DECODER_PROFILE_MPEG1
);
648 case AV_CODEC_ID_MPEG2VIDEO
:
649 switch (avctx
->profile
) {
650 case FF_PROFILE_MPEG2_MAIN
: PROFILE(VDP_DECODER_PROFILE_MPEG2_MAIN
);
651 case FF_PROFILE_MPEG2_SIMPLE
: PROFILE(VDP_DECODER_PROFILE_MPEG2_SIMPLE
);
652 default: return AVERROR(EINVAL
);
654 case AV_CODEC_ID_H263
: PROFILE(VDP_DECODER_PROFILE_MPEG4_PART2_ASP
);
655 case AV_CODEC_ID_MPEG4
:
656 switch (avctx
->profile
) {
657 case FF_PROFILE_MPEG4_SIMPLE
: PROFILE(VDP_DECODER_PROFILE_MPEG4_PART2_SP
);
658 case FF_PROFILE_MPEG4_ADVANCED_SIMPLE
: PROFILE(VDP_DECODER_PROFILE_MPEG4_PART2_ASP
);
659 default: return AVERROR(EINVAL
);
661 case AV_CODEC_ID_H264
:
662 switch (avctx
->profile
& ~FF_PROFILE_H264_INTRA
) {
663 case FF_PROFILE_H264_BASELINE
: PROFILE(VDP_DECODER_PROFILE_H264_BASELINE
);
664 case FF_PROFILE_H264_CONSTRAINED_BASELINE
:
665 case FF_PROFILE_H264_MAIN
: PROFILE(VDP_DECODER_PROFILE_H264_MAIN
);
666 case FF_PROFILE_H264_HIGH
: PROFILE(VDP_DECODER_PROFILE_H264_HIGH
);
667 default: return AVERROR(EINVAL
);
669 case AV_CODEC_ID_WMV3
:
670 case AV_CODEC_ID_VC1
:
671 switch (avctx
->profile
) {
672 case FF_PROFILE_VC1_SIMPLE
: PROFILE(VDP_DECODER_PROFILE_VC1_SIMPLE
);
673 case FF_PROFILE_VC1_MAIN
: PROFILE(VDP_DECODER_PROFILE_VC1_MAIN
);
674 case FF_PROFILE_VC1_ADVANCED
: PROFILE(VDP_DECODER_PROFILE_VC1_ADVANCED
);
675 default: return AVERROR(EINVAL
);
678 return AVERROR(EINVAL
);
681 AVVDPAUContext
*av_vdpau_alloc_context(void)
683 return av_mallocz(sizeof(AVVDPAUContext
));
686 int av_vdpau_bind_context(AVCodecContext
*avctx
, VdpDevice device
,
687 VdpGetProcAddress
*get_proc
, unsigned flags
)
689 VDPAUHWContext
*hwctx
;
691 if (flags
& ~AV_HWACCEL_FLAG_IGNORE_LEVEL
)
692 return AVERROR(EINVAL
);
694 if (av_reallocp(&avctx
->hwaccel_context
, sizeof(*hwctx
)))
695 return AVERROR(ENOMEM
);
697 hwctx
= avctx
->hwaccel_context
;
699 memset(hwctx
, 0, sizeof(*hwctx
));
700 hwctx
->context
.decoder
= VDP_INVALID_HANDLE
;
701 hwctx
->device
= device
;
702 hwctx
->get_proc_address
= get_proc
;
703 hwctx
->flags
= flags
;