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
33 #include "vdpau_internal.h"
36 * \addtogroup VDPAU_Decoding
41 void ff_vdpau_h264_set_reference_frames(MpegEncContext
*s
)
43 H264Context
*h
= s
->avctx
->priv_data
;
44 struct vdpau_render_state
*render
, *render_ref
;
45 VdpReferenceFrameH264
*rf
, *rf2
;
47 int i
, list
, pic_frame_idx
;
49 render
= (struct vdpau_render_state
*)s
->current_picture_ptr
->data
[0];
52 rf
= &render
->info
.h264
.referenceFrames
[0];
53 #define H264_RF_COUNT FF_ARRAY_ELEMS(render->info.h264.referenceFrames)
55 for (list
= 0; list
< 2; ++list
) {
56 Picture
**lp
= list
? h
->long_ref
: h
->short_ref
;
57 int ls
= list
? 16 : h
->short_ref_count
;
59 for (i
= 0; i
< ls
; ++i
) {
61 if (!pic
|| !pic
->reference
)
63 pic_frame_idx
= pic
->long_ref
? pic
->pic_id
: pic
->frame_num
;
65 render_ref
= (struct vdpau_render_state
*)pic
->data
[0];
68 rf2
= &render
->info
.h264
.referenceFrames
[0];
71 (rf2
->surface
== render_ref
->surface
)
72 && (rf2
->is_long_term
== pic
->long_ref
)
73 && (rf2
->frame_idx
== pic_frame_idx
)
79 rf2
->top_is_reference
|= (pic
->reference
& PICT_TOP_FIELD
) ? VDP_TRUE
: VDP_FALSE
;
80 rf2
->bottom_is_reference
|= (pic
->reference
& PICT_BOTTOM_FIELD
) ? VDP_TRUE
: VDP_FALSE
;
84 if (rf
>= &render
->info
.h264
.referenceFrames
[H264_RF_COUNT
])
87 rf
->surface
= render_ref
->surface
;
88 rf
->is_long_term
= pic
->long_ref
;
89 rf
->top_is_reference
= (pic
->reference
& PICT_TOP_FIELD
) ? VDP_TRUE
: VDP_FALSE
;
90 rf
->bottom_is_reference
= (pic
->reference
& PICT_BOTTOM_FIELD
) ? VDP_TRUE
: VDP_FALSE
;
91 rf
->field_order_cnt
[0] = pic
->field_poc
[0];
92 rf
->field_order_cnt
[1] = pic
->field_poc
[1];
93 rf
->frame_idx
= pic_frame_idx
;
99 for (; rf
< &render
->info
.h264
.referenceFrames
[H264_RF_COUNT
]; ++rf
) {
100 rf
->surface
= VDP_INVALID_HANDLE
;
101 rf
->is_long_term
= 0;
102 rf
->top_is_reference
= 0;
103 rf
->bottom_is_reference
= 0;
104 rf
->field_order_cnt
[0] = 0;
105 rf
->field_order_cnt
[1] = 0;
110 void ff_vdpau_add_data_chunk(MpegEncContext
*s
,
111 const uint8_t *buf
, int buf_size
)
113 struct vdpau_render_state
*render
;
115 render
= (struct vdpau_render_state
*)s
->current_picture_ptr
->data
[0];
118 render
->bitstream_buffers
= av_fast_realloc(
119 render
->bitstream_buffers
,
120 &render
->bitstream_buffers_allocated
,
121 sizeof(*render
->bitstream_buffers
)*(render
->bitstream_buffers_used
+ 1)
124 render
->bitstream_buffers
[render
->bitstream_buffers_used
].struct_version
= VDP_BITSTREAM_BUFFER_VERSION
;
125 render
->bitstream_buffers
[render
->bitstream_buffers_used
].bitstream
= buf
;
126 render
->bitstream_buffers
[render
->bitstream_buffers_used
].bitstream_bytes
= buf_size
;
127 render
->bitstream_buffers_used
++;
130 void ff_vdpau_h264_picture_start(MpegEncContext
*s
)
132 H264Context
*h
= s
->avctx
->priv_data
;
133 struct vdpau_render_state
*render
;
136 render
= (struct vdpau_render_state
*)s
->current_picture_ptr
->data
[0];
139 for (i
= 0; i
< 2; ++i
) {
140 int foc
= s
->current_picture_ptr
->field_poc
[i
];
143 render
->info
.h264
.field_order_cnt
[i
] = foc
;
146 render
->info
.h264
.frame_num
= h
->frame_num
;
149 void ff_vdpau_h264_picture_complete(MpegEncContext
*s
)
151 H264Context
*h
= s
->avctx
->priv_data
;
152 struct vdpau_render_state
*render
;
154 render
= (struct vdpau_render_state
*)s
->current_picture_ptr
->data
[0];
157 render
->info
.h264
.slice_count
= h
->slice_num
;
158 if (render
->info
.h264
.slice_count
< 1)
161 render
->info
.h264
.is_reference
= (s
->current_picture_ptr
->reference
& 3) ? VDP_TRUE
: VDP_FALSE
;
162 render
->info
.h264
.field_pic_flag
= s
->picture_structure
!= PICT_FRAME
;
163 render
->info
.h264
.bottom_field_flag
= s
->picture_structure
== PICT_BOTTOM_FIELD
;
164 render
->info
.h264
.num_ref_frames
= h
->sps
.ref_frame_count
;
165 render
->info
.h264
.mb_adaptive_frame_field_flag
= h
->sps
.mb_aff
&& !render
->info
.h264
.field_pic_flag
;
166 render
->info
.h264
.constrained_intra_pred_flag
= h
->pps
.constrained_intra_pred
;
167 render
->info
.h264
.weighted_pred_flag
= h
->pps
.weighted_pred
;
168 render
->info
.h264
.weighted_bipred_idc
= h
->pps
.weighted_bipred_idc
;
169 render
->info
.h264
.frame_mbs_only_flag
= h
->sps
.frame_mbs_only_flag
;
170 render
->info
.h264
.transform_8x8_mode_flag
= h
->pps
.transform_8x8_mode
;
171 render
->info
.h264
.chroma_qp_index_offset
= h
->pps
.chroma_qp_index_offset
[0];
172 render
->info
.h264
.second_chroma_qp_index_offset
= h
->pps
.chroma_qp_index_offset
[1];
173 render
->info
.h264
.pic_init_qp_minus26
= h
->pps
.init_qp
- 26;
174 render
->info
.h264
.num_ref_idx_l0_active_minus1
= h
->pps
.ref_count
[0] - 1;
175 render
->info
.h264
.num_ref_idx_l1_active_minus1
= h
->pps
.ref_count
[1] - 1;
176 render
->info
.h264
.log2_max_frame_num_minus4
= h
->sps
.log2_max_frame_num
- 4;
177 render
->info
.h264
.pic_order_cnt_type
= h
->sps
.poc_type
;
178 render
->info
.h264
.log2_max_pic_order_cnt_lsb_minus4
= h
->sps
.poc_type
? 0 : h
->sps
.log2_max_poc_lsb
- 4;
179 render
->info
.h264
.delta_pic_order_always_zero_flag
= h
->sps
.delta_pic_order_always_zero_flag
;
180 render
->info
.h264
.direct_8x8_inference_flag
= h
->sps
.direct_8x8_inference_flag
;
181 render
->info
.h264
.entropy_coding_mode_flag
= h
->pps
.cabac
;
182 render
->info
.h264
.pic_order_present_flag
= h
->pps
.pic_order_present
;
183 render
->info
.h264
.deblocking_filter_control_present_flag
= h
->pps
.deblocking_filter_parameters_present
;
184 render
->info
.h264
.redundant_pic_cnt_present_flag
= h
->pps
.redundant_pic_cnt_present
;
185 memcpy(render
->info
.h264
.scaling_lists_4x4
, h
->pps
.scaling_matrix4
, sizeof(render
->info
.h264
.scaling_lists_4x4
));
186 memcpy(render
->info
.h264
.scaling_lists_8x8
, h
->pps
.scaling_matrix8
, sizeof(render
->info
.h264
.scaling_lists_8x8
));
188 ff_draw_horiz_band(s
, 0, s
->avctx
->height
);
189 render
->bitstream_buffers_used
= 0;
192 void ff_vdpau_mpeg_picture_complete(MpegEncContext
*s
, const uint8_t *buf
,
193 int buf_size
, int slice_count
)
195 struct vdpau_render_state
*render
, *last
, *next
;
198 if (!s
->current_picture_ptr
) return;
200 render
= (struct vdpau_render_state
*)s
->current_picture_ptr
->data
[0];
203 /* fill VdpPictureInfoMPEG1Or2 struct */
204 render
->info
.mpeg
.picture_structure
= s
->picture_structure
;
205 render
->info
.mpeg
.picture_coding_type
= s
->pict_type
;
206 render
->info
.mpeg
.intra_dc_precision
= s
->intra_dc_precision
;
207 render
->info
.mpeg
.frame_pred_frame_dct
= s
->frame_pred_frame_dct
;
208 render
->info
.mpeg
.concealment_motion_vectors
= s
->concealment_motion_vectors
;
209 render
->info
.mpeg
.intra_vlc_format
= s
->intra_vlc_format
;
210 render
->info
.mpeg
.alternate_scan
= s
->alternate_scan
;
211 render
->info
.mpeg
.q_scale_type
= s
->q_scale_type
;
212 render
->info
.mpeg
.top_field_first
= s
->top_field_first
;
213 render
->info
.mpeg
.full_pel_forward_vector
= s
->full_pel
[0]; // MPEG-1 only. Set 0 for MPEG-2
214 render
->info
.mpeg
.full_pel_backward_vector
= s
->full_pel
[1]; // MPEG-1 only. Set 0 for MPEG-2
215 render
->info
.mpeg
.f_code
[0][0] = s
->mpeg_f_code
[0][0]; // For MPEG-1 fill both horiz. & vert.
216 render
->info
.mpeg
.f_code
[0][1] = s
->mpeg_f_code
[0][1];
217 render
->info
.mpeg
.f_code
[1][0] = s
->mpeg_f_code
[1][0];
218 render
->info
.mpeg
.f_code
[1][1] = s
->mpeg_f_code
[1][1];
219 for (i
= 0; i
< 64; ++i
) {
220 render
->info
.mpeg
.intra_quantizer_matrix
[i
] = s
->intra_matrix
[i
];
221 render
->info
.mpeg
.non_intra_quantizer_matrix
[i
] = s
->inter_matrix
[i
];
224 render
->info
.mpeg
.forward_reference
= VDP_INVALID_HANDLE
;
225 render
->info
.mpeg
.backward_reference
= VDP_INVALID_HANDLE
;
227 switch(s
->pict_type
){
229 next
= (struct vdpau_render_state
*)s
->next_picture
.data
[0];
231 render
->info
.mpeg
.backward_reference
= next
->surface
;
232 // no return here, going to set forward prediction
234 last
= (struct vdpau_render_state
*)s
->last_picture
.data
[0];
235 if (!last
) // FIXME: Does this test make sense?
236 last
= render
; // predict second field from the first
237 render
->info
.mpeg
.forward_reference
= last
->surface
;
240 ff_vdpau_add_data_chunk(s
, buf
, buf_size
);
242 render
->info
.mpeg
.slice_count
= slice_count
;
245 ff_draw_horiz_band(s
, 0, s
->avctx
->height
);
246 render
->bitstream_buffers_used
= 0;
249 void ff_vdpau_vc1_decode_picture(MpegEncContext
*s
, const uint8_t *buf
,
252 VC1Context
*v
= s
->avctx
->priv_data
;
253 struct vdpau_render_state
*render
, *last
, *next
;
255 render
= (struct vdpau_render_state
*)s
->current_picture
.data
[0];
258 /* fill LvPictureInfoVC1 struct */
259 render
->info
.vc1
.frame_coding_mode
= v
->fcm
;
260 render
->info
.vc1
.postprocflag
= v
->postprocflag
;
261 render
->info
.vc1
.pulldown
= v
->broadcast
;
262 render
->info
.vc1
.interlace
= v
->interlace
;
263 render
->info
.vc1
.tfcntrflag
= v
->tfcntrflag
;
264 render
->info
.vc1
.finterpflag
= v
->finterpflag
;
265 render
->info
.vc1
.psf
= v
->psf
;
266 render
->info
.vc1
.dquant
= v
->dquant
;
267 render
->info
.vc1
.panscan_flag
= v
->panscanflag
;
268 render
->info
.vc1
.refdist_flag
= v
->refdist_flag
;
269 render
->info
.vc1
.quantizer
= v
->quantizer_mode
;
270 render
->info
.vc1
.extended_mv
= v
->extended_mv
;
271 render
->info
.vc1
.extended_dmv
= v
->extended_dmv
;
272 render
->info
.vc1
.overlap
= v
->overlap
;
273 render
->info
.vc1
.vstransform
= v
->vstransform
;
274 render
->info
.vc1
.loopfilter
= v
->s
.loop_filter
;
275 render
->info
.vc1
.fastuvmc
= v
->fastuvmc
;
276 render
->info
.vc1
.range_mapy_flag
= v
->range_mapy_flag
;
277 render
->info
.vc1
.range_mapy
= v
->range_mapy
;
278 render
->info
.vc1
.range_mapuv_flag
= v
->range_mapuv_flag
;
279 render
->info
.vc1
.range_mapuv
= v
->range_mapuv
;
280 /* Specific to simple/main profile only */
281 render
->info
.vc1
.multires
= v
->multires
;
282 render
->info
.vc1
.syncmarker
= v
->s
.resync_marker
;
283 render
->info
.vc1
.rangered
= v
->rangered
| (v
->rangeredfrm
<< 1);
284 render
->info
.vc1
.maxbframes
= v
->s
.max_b_frames
;
286 render
->info
.vc1
.deblockEnable
= v
->postprocflag
& 1;
287 render
->info
.vc1
.pquant
= v
->pq
;
289 render
->info
.vc1
.forward_reference
= VDP_INVALID_HANDLE
;
290 render
->info
.vc1
.backward_reference
= VDP_INVALID_HANDLE
;
293 render
->info
.vc1
.picture_type
= 4;
295 render
->info
.vc1
.picture_type
= s
->pict_type
- 1 + s
->pict_type
/ 3;
297 switch(s
->pict_type
){
299 next
= (struct vdpau_render_state
*)s
->next_picture
.data
[0];
301 render
->info
.vc1
.backward_reference
= next
->surface
;
302 // no break here, going to set forward prediction
304 last
= (struct vdpau_render_state
*)s
->last_picture
.data
[0];
305 if (!last
) // FIXME: Does this test make sense?
306 last
= render
; // predict second field from the first
307 render
->info
.vc1
.forward_reference
= last
->surface
;
310 ff_vdpau_add_data_chunk(s
, buf
, buf_size
);
312 render
->info
.vc1
.slice_count
= 1;
314 ff_draw_horiz_band(s
, 0, s
->avctx
->height
);
315 render
->bitstream_buffers_used
= 0;
318 void ff_vdpau_mpeg4_decode_picture(MpegEncContext
*s
, const uint8_t *buf
,
321 struct vdpau_render_state
*render
, *last
, *next
;
324 if (!s
->current_picture_ptr
) return;
326 render
= (struct vdpau_render_state
*)s
->current_picture_ptr
->data
[0];
329 /* fill VdpPictureInfoMPEG4Part2 struct */
330 render
->info
.mpeg4
.trd
[0] = s
->pp_time
;
331 render
->info
.mpeg4
.trb
[0] = s
->pb_time
;
332 render
->info
.mpeg4
.trd
[1] = s
->pp_field_time
>> 1;
333 render
->info
.mpeg4
.trb
[1] = s
->pb_field_time
>> 1;
334 render
->info
.mpeg4
.vop_time_increment_resolution
= s
->avctx
->time_base
.den
;
335 render
->info
.mpeg4
.vop_coding_type
= 0;
336 render
->info
.mpeg4
.vop_fcode_forward
= s
->f_code
;
337 render
->info
.mpeg4
.vop_fcode_backward
= s
->b_code
;
338 render
->info
.mpeg4
.resync_marker_disable
= !s
->resync_marker
;
339 render
->info
.mpeg4
.interlaced
= !s
->progressive_sequence
;
340 render
->info
.mpeg4
.quant_type
= s
->mpeg_quant
;
341 render
->info
.mpeg4
.quarter_sample
= s
->quarter_sample
;
342 render
->info
.mpeg4
.short_video_header
= s
->avctx
->codec
->id
== CODEC_ID_H263
;
343 render
->info
.mpeg4
.rounding_control
= s
->no_rounding
;
344 render
->info
.mpeg4
.alternate_vertical_scan_flag
= s
->alternate_scan
;
345 render
->info
.mpeg4
.top_field_first
= s
->top_field_first
;
346 for (i
= 0; i
< 64; ++i
) {
347 render
->info
.mpeg4
.intra_quantizer_matrix
[i
] = s
->intra_matrix
[i
];
348 render
->info
.mpeg4
.non_intra_quantizer_matrix
[i
] = s
->inter_matrix
[i
];
350 render
->info
.mpeg4
.forward_reference
= VDP_INVALID_HANDLE
;
351 render
->info
.mpeg4
.backward_reference
= VDP_INVALID_HANDLE
;
353 switch (s
->pict_type
) {
355 next
= (struct vdpau_render_state
*)s
->next_picture
.data
[0];
357 render
->info
.mpeg4
.backward_reference
= next
->surface
;
358 render
->info
.mpeg4
.vop_coding_type
= 2;
359 // no break here, going to set forward prediction
361 last
= (struct vdpau_render_state
*)s
->last_picture
.data
[0];
363 render
->info
.mpeg4
.forward_reference
= last
->surface
;
366 ff_vdpau_add_data_chunk(s
, buf
, buf_size
);
368 ff_draw_horiz_band(s
, 0, s
->avctx
->height
);
369 render
->bitstream_buffers_used
= 0;