Commit | Line | Data |
---|---|---|
369122dd NC |
1 | /* |
2 | * Video Decode and Presentation API for UNIX (VDPAU) is used for | |
3 | * HW decode acceleration for MPEG-1/2, H.264 and VC-1. | |
4 | * | |
406792e7 | 5 | * Copyright (c) 2008 NVIDIA |
369122dd NC |
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 | ||
24 | #include <limits.h> | |
25 | #include "avcodec.h" | |
26 | #include "h264.h" | |
c5b42f4a | 27 | #include "vc1.h" |
369122dd NC |
28 | |
29 | #undef NDEBUG | |
30 | #include <assert.h> | |
31 | ||
fd949a63 | 32 | #include "vdpau.h" |
369122dd NC |
33 | #include "vdpau_internal.h" |
34 | ||
35 | /** | |
36 | * \addtogroup VDPAU_Decoding | |
37 | * | |
38 | * @{ | |
39 | */ | |
40 | ||
17170313 | 41 | void ff_vdpau_h264_set_reference_frames(MpegEncContext *s) |
369122dd | 42 | { |
17170313 | 43 | H264Context *h = s->avctx->priv_data; |
06aae123 RD |
44 | struct vdpau_render_state *render, *render_ref; |
45 | VdpReferenceFrameH264 *rf, *rf2; | |
46 | Picture *pic; | |
369122dd NC |
47 | int i, list, pic_frame_idx; |
48 | ||
06aae123 | 49 | render = (struct vdpau_render_state *)s->current_picture_ptr->data[0]; |
369122dd NC |
50 | assert(render); |
51 | ||
52 | rf = &render->info.h264.referenceFrames[0]; | |
53 | #define H264_RF_COUNT FF_ARRAY_ELEMS(render->info.h264.referenceFrames) | |
54 | ||
55 | for (list = 0; list < 2; ++list) { | |
56 | Picture **lp = list ? h->long_ref : h->short_ref; | |
57 | int ls = list ? h->long_ref_count : h->short_ref_count; | |
58 | ||
59 | for (i = 0; i < ls; ++i) { | |
60 | pic = lp[i]; | |
61 | if (!pic || !pic->reference) | |
62 | continue; | |
63 | pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; | |
64 | ||
06aae123 | 65 | render_ref = (struct vdpau_render_state *)pic->data[0]; |
369122dd NC |
66 | assert(render_ref); |
67 | ||
68 | rf2 = &render->info.h264.referenceFrames[0]; | |
69 | while (rf2 != rf) { | |
70 | if ( | |
71 | (rf2->surface == render_ref->surface) | |
72 | && (rf2->is_long_term == pic->long_ref) | |
73 | && (rf2->frame_idx == pic_frame_idx) | |
74 | ) | |
75 | break; | |
76 | ++rf2; | |
77 | } | |
78 | if (rf2 != rf) { | |
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; | |
81 | continue; | |
82 | } | |
83 | ||
84 | if (rf >= &render->info.h264.referenceFrames[H264_RF_COUNT]) | |
85 | continue; | |
86 | ||
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; | |
94 | ||
95 | ++rf; | |
96 | } | |
97 | } | |
98 | ||
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; | |
106 | rf->frame_idx = 0; | |
107 | } | |
108 | } | |
109 | ||
c639fc72 CEH |
110 | void ff_vdpau_add_data_chunk(MpegEncContext *s, |
111 | const uint8_t *buf, int buf_size) | |
369122dd | 112 | { |
06aae123 | 113 | struct vdpau_render_state *render; |
369122dd | 114 | |
06aae123 | 115 | render = (struct vdpau_render_state *)s->current_picture_ptr->data[0]; |
369122dd NC |
116 | assert(render); |
117 | ||
6cc01c24 CEH |
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) | |
369122dd NC |
122 | ); |
123 | ||
6cc01c24 CEH |
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++; | |
369122dd NC |
128 | } |
129 | ||
17170313 | 130 | void ff_vdpau_h264_picture_complete(MpegEncContext *s) |
369122dd | 131 | { |
17170313 | 132 | H264Context *h = s->avctx->priv_data; |
06aae123 | 133 | struct vdpau_render_state *render; |
d46b2d68 | 134 | int i; |
369122dd | 135 | |
06aae123 | 136 | render = (struct vdpau_render_state *)s->current_picture_ptr->data[0]; |
369122dd NC |
137 | assert(render); |
138 | ||
139 | render->info.h264.slice_count = h->slice_num; | |
140 | if (render->info.h264.slice_count < 1) | |
141 | return; | |
142 | ||
d46b2d68 | 143 | for (i = 0; i < 2; ++i) { |
369122dd NC |
144 | int foc = s->current_picture_ptr->field_poc[i]; |
145 | if (foc == INT_MAX) | |
146 | foc = 0; | |
147 | render->info.h264.field_order_cnt[i] = foc; | |
148 | } | |
149 | ||
150 | render->info.h264.is_reference = s->current_picture_ptr->reference ? VDP_TRUE : VDP_FALSE; | |
151 | render->info.h264.frame_num = h->frame_num; | |
152 | render->info.h264.field_pic_flag = s->picture_structure != PICT_FRAME; | |
153 | render->info.h264.bottom_field_flag = s->picture_structure == PICT_BOTTOM_FIELD; | |
154 | render->info.h264.num_ref_frames = h->sps.ref_frame_count; | |
ef7ae94b | 155 | render->info.h264.mb_adaptive_frame_field_flag = h->sps.mb_aff && !render->info.h264.field_pic_flag; |
369122dd NC |
156 | render->info.h264.constrained_intra_pred_flag = h->pps.constrained_intra_pred; |
157 | render->info.h264.weighted_pred_flag = h->pps.weighted_pred; | |
158 | render->info.h264.weighted_bipred_idc = h->pps.weighted_bipred_idc; | |
159 | render->info.h264.frame_mbs_only_flag = h->sps.frame_mbs_only_flag; | |
160 | render->info.h264.transform_8x8_mode_flag = h->pps.transform_8x8_mode; | |
161 | render->info.h264.chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; | |
162 | render->info.h264.second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; | |
163 | render->info.h264.pic_init_qp_minus26 = h->pps.init_qp - 26; | |
164 | render->info.h264.num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; | |
165 | render->info.h264.num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; | |
166 | render->info.h264.log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; | |
167 | render->info.h264.pic_order_cnt_type = h->sps.poc_type; | |
168 | render->info.h264.log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; | |
169 | render->info.h264.delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; | |
170 | render->info.h264.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; | |
171 | render->info.h264.entropy_coding_mode_flag = h->pps.cabac; | |
172 | render->info.h264.pic_order_present_flag = h->pps.pic_order_present; | |
173 | render->info.h264.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; | |
174 | render->info.h264.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; | |
175 | memcpy(render->info.h264.scaling_lists_4x4, h->pps.scaling_matrix4, sizeof(render->info.h264.scaling_lists_4x4)); | |
176 | memcpy(render->info.h264.scaling_lists_8x8, h->pps.scaling_matrix8, sizeof(render->info.h264.scaling_lists_8x8)); | |
177 | ||
178 | ff_draw_horiz_band(s, 0, s->avctx->height); | |
6cc01c24 | 179 | render->bitstream_buffers_used = 0; |
369122dd NC |
180 | } |
181 | ||
d37edddc NC |
182 | void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf, |
183 | int buf_size, int slice_count) | |
184 | { | |
06aae123 | 185 | struct vdpau_render_state *render, *last, *next; |
d37edddc NC |
186 | int i; |
187 | ||
9bbf1a5c RD |
188 | if (!s->current_picture_ptr) return; |
189 | ||
06aae123 | 190 | render = (struct vdpau_render_state *)s->current_picture_ptr->data[0]; |
d37edddc NC |
191 | assert(render); |
192 | ||
193 | /* fill VdpPictureInfoMPEG1Or2 struct */ | |
194 | render->info.mpeg.picture_structure = s->picture_structure; | |
195 | render->info.mpeg.picture_coding_type = s->pict_type; | |
196 | render->info.mpeg.intra_dc_precision = s->intra_dc_precision; | |
197 | render->info.mpeg.frame_pred_frame_dct = s->frame_pred_frame_dct; | |
198 | render->info.mpeg.concealment_motion_vectors = s->concealment_motion_vectors; | |
199 | render->info.mpeg.intra_vlc_format = s->intra_vlc_format; | |
200 | render->info.mpeg.alternate_scan = s->alternate_scan; | |
201 | render->info.mpeg.q_scale_type = s->q_scale_type; | |
202 | render->info.mpeg.top_field_first = s->top_field_first; | |
203 | render->info.mpeg.full_pel_forward_vector = s->full_pel[0]; // MPEG-1 only. Set 0 for MPEG-2 | |
204 | render->info.mpeg.full_pel_backward_vector = s->full_pel[1]; // MPEG-1 only. Set 0 for MPEG-2 | |
205 | render->info.mpeg.f_code[0][0] = s->mpeg_f_code[0][0]; // For MPEG-1 fill both horiz. & vert. | |
206 | render->info.mpeg.f_code[0][1] = s->mpeg_f_code[0][1]; | |
207 | render->info.mpeg.f_code[1][0] = s->mpeg_f_code[1][0]; | |
208 | render->info.mpeg.f_code[1][1] = s->mpeg_f_code[1][1]; | |
209 | for (i = 0; i < 64; ++i) { | |
210 | render->info.mpeg.intra_quantizer_matrix[i] = s->intra_matrix[i]; | |
211 | render->info.mpeg.non_intra_quantizer_matrix[i] = s->inter_matrix[i]; | |
212 | } | |
213 | ||
214 | render->info.mpeg.forward_reference = VDP_INVALID_HANDLE; | |
215 | render->info.mpeg.backward_reference = VDP_INVALID_HANDLE; | |
216 | ||
217 | switch(s->pict_type){ | |
218 | case FF_B_TYPE: | |
06aae123 | 219 | next = (struct vdpau_render_state *)s->next_picture.data[0]; |
d37edddc NC |
220 | assert(next); |
221 | render->info.mpeg.backward_reference = next->surface; | |
222 | // no return here, going to set forward prediction | |
223 | case FF_P_TYPE: | |
06aae123 | 224 | last = (struct vdpau_render_state *)s->last_picture.data[0]; |
d37edddc NC |
225 | if (!last) // FIXME: Does this test make sense? |
226 | last = render; // predict second field from the first | |
227 | render->info.mpeg.forward_reference = last->surface; | |
228 | } | |
229 | ||
230 | ff_vdpau_add_data_chunk(s, buf, buf_size); | |
231 | ||
232 | render->info.mpeg.slice_count = slice_count; | |
233 | ||
234 | if (slice_count) | |
235 | ff_draw_horiz_band(s, 0, s->avctx->height); | |
236 | render->bitstream_buffers_used = 0; | |
237 | } | |
238 | ||
c5b42f4a NC |
239 | void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf, |
240 | int buf_size) | |
241 | { | |
242 | VC1Context *v = s->avctx->priv_data; | |
06aae123 | 243 | struct vdpau_render_state *render, *last, *next; |
c5b42f4a | 244 | |
06aae123 | 245 | render = (struct vdpau_render_state *)s->current_picture.data[0]; |
c5b42f4a NC |
246 | assert(render); |
247 | ||
248 | /* fill LvPictureInfoVC1 struct */ | |
249 | render->info.vc1.frame_coding_mode = v->fcm; | |
250 | render->info.vc1.postprocflag = v->postprocflag; | |
251 | render->info.vc1.pulldown = v->broadcast; | |
252 | render->info.vc1.interlace = v->interlace; | |
253 | render->info.vc1.tfcntrflag = v->tfcntrflag; | |
254 | render->info.vc1.finterpflag = v->finterpflag; | |
255 | render->info.vc1.psf = v->psf; | |
256 | render->info.vc1.dquant = v->dquant; | |
257 | render->info.vc1.panscan_flag = v->panscanflag; | |
258 | render->info.vc1.refdist_flag = v->refdist_flag; | |
259 | render->info.vc1.quantizer = v->quantizer_mode; | |
260 | render->info.vc1.extended_mv = v->extended_mv; | |
261 | render->info.vc1.extended_dmv = v->extended_dmv; | |
262 | render->info.vc1.overlap = v->overlap; | |
263 | render->info.vc1.vstransform = v->vstransform; | |
264 | render->info.vc1.loopfilter = v->s.loop_filter; | |
265 | render->info.vc1.fastuvmc = v->fastuvmc; | |
266 | render->info.vc1.range_mapy_flag = v->range_mapy_flag; | |
267 | render->info.vc1.range_mapy = v->range_mapy; | |
268 | render->info.vc1.range_mapuv_flag = v->range_mapuv_flag; | |
269 | render->info.vc1.range_mapuv = v->range_mapuv; | |
270 | /* Specific to simple/main profile only */ | |
271 | render->info.vc1.multires = v->multires; | |
272 | render->info.vc1.syncmarker = v->s.resync_marker; | |
273 | render->info.vc1.rangered = v->rangered; | |
274 | render->info.vc1.maxbframes = v->s.max_b_frames; | |
275 | ||
276 | render->info.vc1.deblockEnable = v->postprocflag & 1; | |
277 | render->info.vc1.pquant = v->pq; | |
278 | ||
279 | render->info.vc1.forward_reference = VDP_INVALID_HANDLE; | |
280 | render->info.vc1.backward_reference = VDP_INVALID_HANDLE; | |
281 | ||
282 | if (v->bi_type) | |
283 | render->info.vc1.picture_type = 4; | |
284 | else | |
285 | render->info.vc1.picture_type = s->pict_type - 1 + s->pict_type / 3; | |
286 | ||
287 | switch(s->pict_type){ | |
288 | case FF_B_TYPE: | |
06aae123 | 289 | next = (struct vdpau_render_state *)s->next_picture.data[0]; |
c5b42f4a NC |
290 | assert(next); |
291 | render->info.vc1.backward_reference = next->surface; | |
292 | // no break here, going to set forward prediction | |
293 | case FF_P_TYPE: | |
06aae123 | 294 | last = (struct vdpau_render_state *)s->last_picture.data[0]; |
c5b42f4a NC |
295 | if (!last) // FIXME: Does this test make sense? |
296 | last = render; // predict second field from the first | |
297 | render->info.vc1.forward_reference = last->surface; | |
298 | } | |
299 | ||
300 | ff_vdpau_add_data_chunk(s, buf, buf_size); | |
301 | ||
302 | render->info.vc1.slice_count = 1; | |
303 | ||
304 | ff_draw_horiz_band(s, 0, s->avctx->height); | |
305 | render->bitstream_buffers_used = 0; | |
306 | } | |
307 | ||
369122dd | 308 | /* @}*/ |