1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "util/u_memory.h"
29 #include "util/u_math.h"
30 #include "util/u_debug.h"
31 #include "util/u_video.h"
33 #include "vdpau_private.h"
36 * Create a VdpDecoder.
39 vlVdpDecoderCreate(VdpDevice device
,
40 VdpDecoderProfile profile
,
41 uint32_t width
, uint32_t height
,
42 uint32_t max_references
,
45 enum pipe_video_profile p_profile
;
46 struct pipe_context
*pipe
;
47 struct pipe_screen
*screen
;
49 vlVdpDecoder
*vldecoder
;
53 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Creating decoder\n");
56 return VDP_STATUS_INVALID_POINTER
;
59 if (!(width
&& height
))
60 return VDP_STATUS_INVALID_VALUE
;
62 p_profile
= ProfileToPipe(profile
);
63 if (p_profile
== PIPE_VIDEO_PROFILE_UNKNOWN
)
64 return VDP_STATUS_INVALID_DECODER_PROFILE
;
66 dev
= vlGetDataHTAB(device
);
68 return VDP_STATUS_INVALID_HANDLE
;
70 pipe
= dev
->context
->pipe
;
71 screen
= dev
->vscreen
->pscreen
;
72 supported
= screen
->get_video_param
76 PIPE_VIDEO_CAP_SUPPORTED
79 return VDP_STATUS_INVALID_DECODER_PROFILE
;
81 vldecoder
= CALLOC(1,sizeof(vlVdpDecoder
));
83 return VDP_STATUS_RESOURCES
;
85 vldecoder
->device
= dev
;
87 vldecoder
->decoder
= pipe
->create_video_decoder
90 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
91 PIPE_VIDEO_CHROMA_FORMAT_420
,
92 width
, height
, max_references
95 if (!vldecoder
->decoder
) {
96 ret
= VDP_STATUS_ERROR
;
100 *decoder
= vlAddDataHTAB(vldecoder
);
102 ret
= VDP_STATUS_ERROR
;
106 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoder created succesfully\n");
108 return VDP_STATUS_OK
;
111 vldecoder
->decoder
->destroy(vldecoder
->decoder
);
119 * Destroy a VdpDecoder.
122 vlVdpDecoderDestroy(VdpDecoder decoder
)
124 vlVdpDecoder
*vldecoder
;
126 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Destroying decoder\n");
128 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
130 return VDP_STATUS_INVALID_HANDLE
;
132 vldecoder
->decoder
->destroy(vldecoder
->decoder
);
136 return VDP_STATUS_OK
;
140 * Retrieve the parameters used to create a VdpBitmapSurface.
143 vlVdpDecoderGetParameters(VdpDecoder decoder
,
144 VdpDecoderProfile
*profile
,
148 vlVdpDecoder
*vldecoder
;
150 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoder get parameters called\n");
152 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
154 return VDP_STATUS_INVALID_HANDLE
;
156 *profile
= PipeToProfile(vldecoder
->decoder
->profile
);
157 *width
= vldecoder
->decoder
->width
;
158 *height
= vldecoder
->decoder
->height
;
160 return VDP_STATUS_OK
;
164 * Decode a mpeg 1/2 video.
167 vlVdpDecoderRenderMpeg12(struct pipe_mpeg12_picture_desc
*picture
,
168 VdpPictureInfoMPEG1Or2
*picture_info
)
170 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding MPEG12\n");
172 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
173 if (picture_info
->forward_reference
!= VDP_INVALID_HANDLE
) {
174 picture
->ref_forward
= ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
))->video_buffer
;
175 if (!picture
->ref_forward
)
176 return VDP_STATUS_INVALID_HANDLE
;
179 picture
->ref_forward
= NULL
;
181 if (picture_info
->backward_reference
!= VDP_INVALID_HANDLE
) {
182 picture
->ref_backward
= ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
))->video_buffer
;
183 if (!picture
->ref_backward
)
184 return VDP_STATUS_INVALID_HANDLE
;
187 picture
->ref_backward
= NULL
;
189 picture
->picture_coding_type
= picture_info
->picture_coding_type
;
190 picture
->picture_structure
= picture_info
->picture_structure
;
191 picture
->frame_pred_frame_dct
= picture_info
->frame_pred_frame_dct
;
192 picture
->q_scale_type
= picture_info
->q_scale_type
;
193 picture
->alternate_scan
= picture_info
->alternate_scan
;
194 picture
->intra_vlc_format
= picture_info
->intra_vlc_format
;
195 picture
->concealment_motion_vectors
= picture_info
->concealment_motion_vectors
;
196 picture
->intra_dc_precision
= picture_info
->intra_dc_precision
;
197 picture
->f_code
[0][0] = picture_info
->f_code
[0][0] - 1;
198 picture
->f_code
[0][1] = picture_info
->f_code
[0][1] - 1;
199 picture
->f_code
[1][0] = picture_info
->f_code
[1][0] - 1;
200 picture
->f_code
[1][1] = picture_info
->f_code
[1][1] - 1;
201 picture
->num_slices
= picture_info
->slice_count
;
202 picture
->top_field_first
= picture_info
->top_field_first
;
203 picture
->full_pel_forward_vector
= picture_info
->full_pel_forward_vector
;
204 picture
->full_pel_backward_vector
= picture_info
->full_pel_backward_vector
;
205 picture
->intra_matrix
= picture_info
->intra_quantizer_matrix
;
206 picture
->non_intra_matrix
= picture_info
->non_intra_quantizer_matrix
;
207 return VDP_STATUS_OK
;
211 * Decode a mpeg 4 video.
214 vlVdpDecoderRenderMpeg4(struct pipe_mpeg4_picture_desc
*picture
,
215 VdpPictureInfoMPEG4Part2
*picture_info
)
219 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding MPEG4\n");
221 if (picture_info
->forward_reference
!= VDP_INVALID_HANDLE
) {
222 picture
->ref_forward
= ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
))->video_buffer
;
223 if (!picture
->ref_forward
)
224 return VDP_STATUS_INVALID_HANDLE
;
227 picture
->ref_forward
= NULL
;
229 if (picture_info
->backward_reference
!= VDP_INVALID_HANDLE
) {
230 picture
->ref_backward
= ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
))->video_buffer
;
231 if (!picture
->ref_backward
)
232 return VDP_STATUS_INVALID_HANDLE
;
235 picture
->ref_backward
= NULL
;
237 for (i
= 0; i
< 2; ++i
) {
238 picture
->trd
[i
] = picture_info
->trd
[i
];
239 picture
->trb
[i
] = picture_info
->trb
[i
];
241 picture
->vop_time_increment_resolution
= picture_info
->vop_time_increment_resolution
;
242 picture
->vop_coding_type
= picture_info
->vop_coding_type
;
243 picture
->vop_fcode_forward
= picture_info
->vop_fcode_forward
;
244 picture
->vop_fcode_backward
= picture_info
->vop_fcode_backward
;
245 picture
->resync_marker_disable
= picture_info
->resync_marker_disable
;
246 picture
->interlaced
= picture_info
->interlaced
;
247 picture
->quant_type
= picture_info
->quant_type
;
248 picture
->quarter_sample
= picture_info
->quarter_sample
;
249 picture
->short_video_header
= picture_info
->short_video_header
;
250 picture
->rounding_control
= picture_info
->rounding_control
;
251 picture
->alternate_vertical_scan_flag
= picture_info
->alternate_vertical_scan_flag
;
252 picture
->top_field_first
= picture_info
->top_field_first
;
253 picture
->intra_matrix
= picture_info
->intra_quantizer_matrix
;
254 picture
->non_intra_matrix
= picture_info
->non_intra_quantizer_matrix
;
255 return VDP_STATUS_OK
;
259 vlVdpDecoderRenderVC1(struct pipe_vc1_picture_desc
*picture
,
260 VdpPictureInfoVC1
*picture_info
)
262 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding VC-1\n");
264 if (picture_info
->forward_reference
!= VDP_INVALID_HANDLE
) {
265 picture
->ref_forward
= ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
))->video_buffer
;
266 if (!picture
->ref_forward
)
267 return VDP_STATUS_INVALID_HANDLE
;
270 picture
->ref_forward
= NULL
;
272 if (picture_info
->backward_reference
!= VDP_INVALID_HANDLE
) {
273 picture
->ref_backward
= ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
))->video_buffer
;
274 if (!picture
->ref_backward
)
275 return VDP_STATUS_INVALID_HANDLE
;
278 picture
->ref_backward
= NULL
;
280 picture
->slice_count
= picture_info
->slice_count
;
281 picture
->picture_type
= picture_info
->picture_type
;
282 picture
->frame_coding_mode
= picture_info
->frame_coding_mode
;
283 picture
->postprocflag
= picture_info
->postprocflag
;
284 picture
->pulldown
= picture_info
->pulldown
;
285 picture
->interlace
= picture_info
->interlace
;
286 picture
->tfcntrflag
= picture_info
->tfcntrflag
;
287 picture
->finterpflag
= picture_info
->finterpflag
;
288 picture
->psf
= picture_info
->psf
;
289 picture
->dquant
= picture_info
->dquant
;
290 picture
->panscan_flag
= picture_info
->panscan_flag
;
291 picture
->refdist_flag
= picture_info
->refdist_flag
;
292 picture
->quantizer
= picture_info
->quantizer
;
293 picture
->extended_mv
= picture_info
->extended_mv
;
294 picture
->extended_dmv
= picture_info
->extended_dmv
;
295 picture
->overlap
= picture_info
->overlap
;
296 picture
->vstransform
= picture_info
->vstransform
;
297 picture
->loopfilter
= picture_info
->loopfilter
;
298 picture
->fastuvmc
= picture_info
->fastuvmc
;
299 picture
->range_mapy_flag
= picture_info
->range_mapy_flag
;
300 picture
->range_mapy
= picture_info
->range_mapy
;
301 picture
->range_mapuv_flag
= picture_info
->range_mapuv_flag
;
302 picture
->range_mapuv
= picture_info
->range_mapuv
;
303 picture
->multires
= picture_info
->multires
;
304 picture
->syncmarker
= picture_info
->syncmarker
;
305 picture
->rangered
= picture_info
->rangered
;
306 picture
->maxbframes
= picture_info
->maxbframes
;
307 picture
->deblockEnable
= picture_info
->deblockEnable
;
308 picture
->pquant
= picture_info
->pquant
;
309 return VDP_STATUS_OK
;
313 vlVdpDecoderRenderH264(struct pipe_h264_picture_desc
*p
,
314 VdpPictureInfoH264
*vdp
)
317 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding H264\n");
319 p
->slice_count
= vdp
->slice_count
;
320 p
->field_order_cnt
[0] = vdp
->field_order_cnt
[0];
321 p
->field_order_cnt
[1] = vdp
->field_order_cnt
[1];
322 p
->is_reference
= vdp
->is_reference
;
324 p
->frame_num
= vdp
->frame_num
;
325 p
->field_pic_flag
= vdp
->field_pic_flag
;
326 p
->bottom_field_flag
= vdp
->bottom_field_flag
;
327 p
->num_ref_frames
= vdp
->num_ref_frames
;
328 p
->mb_adaptive_frame_field_flag
= vdp
->mb_adaptive_frame_field_flag
;
329 p
->constrained_intra_pred_flag
= vdp
->constrained_intra_pred_flag
;
330 p
->weighted_pred_flag
= vdp
->weighted_pred_flag
;
331 p
->weighted_bipred_idc
= vdp
->weighted_bipred_idc
;
332 p
->frame_mbs_only_flag
= vdp
->frame_mbs_only_flag
;
333 p
->transform_8x8_mode_flag
= vdp
->transform_8x8_mode_flag
;
334 p
->chroma_qp_index_offset
= vdp
->chroma_qp_index_offset
;
335 p
->second_chroma_qp_index_offset
= vdp
->second_chroma_qp_index_offset
;
336 p
->pic_init_qp_minus26
= vdp
->pic_init_qp_minus26
;
337 p
->num_ref_idx_l0_active_minus1
= vdp
->num_ref_idx_l0_active_minus1
;
338 p
->num_ref_idx_l1_active_minus1
= vdp
->num_ref_idx_l1_active_minus1
;
339 p
->log2_max_frame_num_minus4
= vdp
->log2_max_frame_num_minus4
;
340 p
->pic_order_cnt_type
= vdp
->pic_order_cnt_type
;
341 p
->log2_max_pic_order_cnt_lsb_minus4
= vdp
->log2_max_pic_order_cnt_lsb_minus4
;
342 p
->delta_pic_order_always_zero_flag
= vdp
->delta_pic_order_always_zero_flag
;
343 p
->direct_8x8_inference_flag
= vdp
->direct_8x8_inference_flag
;
344 p
->entropy_coding_mode_flag
= vdp
->entropy_coding_mode_flag
;
345 p
->pic_order_present_flag
= vdp
->pic_order_present_flag
;
346 p
->deblocking_filter_control_present_flag
= vdp
->deblocking_filter_control_present_flag
;
347 p
->redundant_pic_cnt_present_flag
= vdp
->redundant_pic_cnt_present_flag
;
349 p
->scaling_lists_4x4
= vdp
->scaling_lists_4x4
[0];
350 p
->scaling_lists_8x8
= vdp
->scaling_lists_8x8
[0];
351 for (i
= 0; i
< 16; ++i
) {
352 struct pipe_h264_reference_frame
*ref
= &p
->refs
[i
];
353 VdpReferenceFrameH264
*vdp_ref
= &vdp
->referenceFrames
[i
];
354 if (vdp_ref
->surface
!= VDP_INVALID_HANDLE
) {
355 vlVdpSurface
*surf
= vlGetDataHTAB(vdp_ref
->surface
);
357 return VDP_STATUS_INVALID_HANDLE
;
358 ref
->surface
= surf
->video_buffer
;
361 ref
->is_long_term
= vdp_ref
->is_long_term
;
362 ref
->top_is_reference
= vdp_ref
->top_is_reference
;
363 ref
->bottom_is_reference
= vdp_ref
->bottom_is_reference
;
364 ref
->field_order_cnt
[0] = vdp_ref
->field_order_cnt
[0];
365 ref
->field_order_cnt
[1] = vdp_ref
->field_order_cnt
[1];
366 ref
->frame_idx
= vdp_ref
->frame_idx
;
368 return VDP_STATUS_OK
;
372 * Decode a compressed field/frame and render the result into a VdpVideoSurface.
375 vlVdpDecoderRender(VdpDecoder decoder
,
376 VdpVideoSurface target
,
377 VdpPictureInfo
const *picture_info
,
378 uint32_t bitstream_buffer_count
,
379 VdpBitstreamBuffer
const *bitstream_buffers
)
381 vlVdpDecoder
*vldecoder
;
382 vlVdpSurface
*vlsurf
;
384 struct pipe_video_decoder
*dec
;
387 struct pipe_picture_desc base
;
388 struct pipe_mpeg12_picture_desc mpeg12
;
389 struct pipe_mpeg4_picture_desc mpeg4
;
390 struct pipe_vc1_picture_desc vc1
;
391 struct pipe_h264_picture_desc h264
;
394 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding\n");
396 if (!(picture_info
&& bitstream_buffers
))
397 return VDP_STATUS_INVALID_POINTER
;
399 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
401 return VDP_STATUS_INVALID_HANDLE
;
402 dec
= vldecoder
->decoder
;
404 vlsurf
= (vlVdpSurface
*)vlGetDataHTAB(target
);
406 return VDP_STATUS_INVALID_HANDLE
;
408 if (vlsurf
->device
!= vldecoder
->device
)
409 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
411 if (vlsurf
->video_buffer
->chroma_format
!= dec
->chroma_format
)
412 // TODO: Recreate decoder with correct chroma
413 return VDP_STATUS_INVALID_CHROMA_TYPE
;
415 memset(&desc
, 0, sizeof(desc
));
416 desc
.base
.profile
= dec
->profile
;
417 switch (u_reduce_video_profile(dec
->profile
)) {
418 case PIPE_VIDEO_CODEC_MPEG12
:
419 ret
= vlVdpDecoderRenderMpeg12(&desc
.mpeg12
, (VdpPictureInfoMPEG1Or2
*)picture_info
);
421 case PIPE_VIDEO_CODEC_MPEG4
:
422 ret
= vlVdpDecoderRenderMpeg4(&desc
.mpeg4
, (VdpPictureInfoMPEG4Part2
*)picture_info
);
424 case PIPE_VIDEO_CODEC_VC1
:
425 ret
= vlVdpDecoderRenderVC1(&desc
.vc1
, (VdpPictureInfoVC1
*)picture_info
);
427 case PIPE_VIDEO_CODEC_MPEG4_AVC
:
428 ret
= vlVdpDecoderRenderH264(&desc
.h264
, (VdpPictureInfoH264
*)picture_info
);
431 return VDP_STATUS_INVALID_DECODER_PROFILE
;
433 if (ret
!= VDP_STATUS_OK
)
436 if (bitstream_buffer_count
) {
437 void const *data
[bitstream_buffer_count
];
438 uint32_t sizes
[bitstream_buffer_count
];
439 uint32_t total_size
= 0;
440 for (i
= 0; i
< bitstream_buffer_count
; ++i
) {
441 data
[i
] = bitstream_buffers
[i
].bitstream
;
442 sizes
[i
] = bitstream_buffers
[i
].bitstream_bytes
;
443 total_size
+= sizes
[i
];
445 dec
->decode_bitstream(dec
, vlsurf
->video_buffer
, &desc
.base
,
446 bitstream_buffer_count
, total_size
,
449 return VDP_STATUS_INVALID_VALUE
;