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 "vl/vl_vlc.h"
35 #include "vdpau_private.h"
38 * Create a VdpDecoder.
41 vlVdpDecoderCreate(VdpDevice device
,
42 VdpDecoderProfile profile
,
43 uint32_t width
, uint32_t height
,
44 uint32_t max_references
,
47 enum pipe_video_profile p_profile
;
48 struct pipe_context
*pipe
;
49 struct pipe_screen
*screen
;
51 vlVdpDecoder
*vldecoder
;
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
;
71 screen
= dev
->vscreen
->pscreen
;
73 pipe_mutex_lock(dev
->mutex
);
75 supported
= screen
->get_video_param
79 PIPE_VIDEO_CAP_SUPPORTED
82 pipe_mutex_unlock(dev
->mutex
);
83 return VDP_STATUS_INVALID_DECODER_PROFILE
;
86 vldecoder
= CALLOC(1,sizeof(vlVdpDecoder
));
88 pipe_mutex_unlock(dev
->mutex
);
89 return VDP_STATUS_RESOURCES
;
92 vldecoder
->device
= dev
;
94 vldecoder
->decoder
= pipe
->create_video_decoder
97 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
98 PIPE_VIDEO_CHROMA_FORMAT_420
,
99 width
, height
, max_references
,
103 if (!vldecoder
->decoder
) {
104 ret
= VDP_STATUS_ERROR
;
108 *decoder
= vlAddDataHTAB(vldecoder
);
110 ret
= VDP_STATUS_ERROR
;
113 pipe_mutex_unlock(dev
->mutex
);
115 return VDP_STATUS_OK
;
118 vldecoder
->decoder
->destroy(vldecoder
->decoder
);
121 pipe_mutex_unlock(dev
->mutex
);
127 * Destroy a VdpDecoder.
130 vlVdpDecoderDestroy(VdpDecoder decoder
)
132 vlVdpDecoder
*vldecoder
;
134 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
136 return VDP_STATUS_INVALID_HANDLE
;
138 pipe_mutex_lock(vldecoder
->device
->mutex
);
139 vldecoder
->decoder
->destroy(vldecoder
->decoder
);
140 pipe_mutex_unlock(vldecoder
->device
->mutex
);
142 vlRemoveDataHTAB(decoder
);
145 return VDP_STATUS_OK
;
149 * Retrieve the parameters used to create a VdpBitmapSurface.
152 vlVdpDecoderGetParameters(VdpDecoder decoder
,
153 VdpDecoderProfile
*profile
,
157 vlVdpDecoder
*vldecoder
;
159 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
161 return VDP_STATUS_INVALID_HANDLE
;
163 *profile
= PipeToProfile(vldecoder
->decoder
->profile
);
164 *width
= vldecoder
->decoder
->width
;
165 *height
= vldecoder
->decoder
->height
;
167 return VDP_STATUS_OK
;
171 vlVdpGetReferenceFrame(VdpVideoSurface handle
, struct pipe_video_buffer
**ref_frame
)
173 vlVdpSurface
*surface
;
175 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
176 if (handle
== VDP_INVALID_HANDLE
) {
178 return VDP_STATUS_OK
;
181 surface
= vlGetDataHTAB(handle
);
183 return VDP_STATUS_INVALID_HANDLE
;
185 *ref_frame
= surface
->video_buffer
;
187 return VDP_STATUS_INVALID_HANDLE
;
189 return VDP_STATUS_OK
;
193 * Decode a mpeg 1/2 video.
196 vlVdpDecoderRenderMpeg12(struct pipe_mpeg12_picture_desc
*picture
,
197 VdpPictureInfoMPEG1Or2
*picture_info
)
201 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding MPEG12\n");
203 r
= vlVdpGetReferenceFrame(picture_info
->forward_reference
, &picture
->ref
[0]);
204 if (r
!= VDP_STATUS_OK
)
207 r
= vlVdpGetReferenceFrame(picture_info
->backward_reference
, &picture
->ref
[1]);
208 if (r
!= VDP_STATUS_OK
)
211 picture
->picture_coding_type
= picture_info
->picture_coding_type
;
212 picture
->picture_structure
= picture_info
->picture_structure
;
213 picture
->frame_pred_frame_dct
= picture_info
->frame_pred_frame_dct
;
214 picture
->q_scale_type
= picture_info
->q_scale_type
;
215 picture
->alternate_scan
= picture_info
->alternate_scan
;
216 picture
->intra_vlc_format
= picture_info
->intra_vlc_format
;
217 picture
->concealment_motion_vectors
= picture_info
->concealment_motion_vectors
;
218 picture
->intra_dc_precision
= picture_info
->intra_dc_precision
;
219 picture
->f_code
[0][0] = picture_info
->f_code
[0][0] - 1;
220 picture
->f_code
[0][1] = picture_info
->f_code
[0][1] - 1;
221 picture
->f_code
[1][0] = picture_info
->f_code
[1][0] - 1;
222 picture
->f_code
[1][1] = picture_info
->f_code
[1][1] - 1;
223 picture
->num_slices
= picture_info
->slice_count
;
224 picture
->top_field_first
= picture_info
->top_field_first
;
225 picture
->full_pel_forward_vector
= picture_info
->full_pel_forward_vector
;
226 picture
->full_pel_backward_vector
= picture_info
->full_pel_backward_vector
;
227 picture
->intra_matrix
= picture_info
->intra_quantizer_matrix
;
228 picture
->non_intra_matrix
= picture_info
->non_intra_quantizer_matrix
;
230 return VDP_STATUS_OK
;
234 * Decode a mpeg 4 video.
237 vlVdpDecoderRenderMpeg4(struct pipe_mpeg4_picture_desc
*picture
,
238 VdpPictureInfoMPEG4Part2
*picture_info
)
243 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding MPEG4\n");
245 r
= vlVdpGetReferenceFrame(picture_info
->forward_reference
, &picture
->ref
[0]);
246 if (r
!= VDP_STATUS_OK
)
249 r
= vlVdpGetReferenceFrame(picture_info
->backward_reference
, &picture
->ref
[1]);
250 if (r
!= VDP_STATUS_OK
)
253 for (i
= 0; i
< 2; ++i
) {
254 picture
->trd
[i
] = picture_info
->trd
[i
];
255 picture
->trb
[i
] = picture_info
->trb
[i
];
257 picture
->vop_time_increment_resolution
= picture_info
->vop_time_increment_resolution
;
258 picture
->vop_coding_type
= picture_info
->vop_coding_type
;
259 picture
->vop_fcode_forward
= picture_info
->vop_fcode_forward
;
260 picture
->vop_fcode_backward
= picture_info
->vop_fcode_backward
;
261 picture
->resync_marker_disable
= picture_info
->resync_marker_disable
;
262 picture
->interlaced
= picture_info
->interlaced
;
263 picture
->quant_type
= picture_info
->quant_type
;
264 picture
->quarter_sample
= picture_info
->quarter_sample
;
265 picture
->short_video_header
= picture_info
->short_video_header
;
266 picture
->rounding_control
= picture_info
->rounding_control
;
267 picture
->alternate_vertical_scan_flag
= picture_info
->alternate_vertical_scan_flag
;
268 picture
->top_field_first
= picture_info
->top_field_first
;
269 picture
->intra_matrix
= picture_info
->intra_quantizer_matrix
;
270 picture
->non_intra_matrix
= picture_info
->non_intra_quantizer_matrix
;
272 return VDP_STATUS_OK
;
276 vlVdpDecoderRenderVC1(struct pipe_vc1_picture_desc
*picture
,
277 VdpPictureInfoVC1
*picture_info
)
281 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding VC-1\n");
283 r
= vlVdpGetReferenceFrame(picture_info
->forward_reference
, &picture
->ref
[0]);
284 if (r
!= VDP_STATUS_OK
)
287 r
= vlVdpGetReferenceFrame(picture_info
->backward_reference
, &picture
->ref
[1]);
288 if (r
!= VDP_STATUS_OK
)
291 picture
->slice_count
= picture_info
->slice_count
;
292 picture
->picture_type
= picture_info
->picture_type
;
293 picture
->frame_coding_mode
= picture_info
->frame_coding_mode
;
294 picture
->postprocflag
= picture_info
->postprocflag
;
295 picture
->pulldown
= picture_info
->pulldown
;
296 picture
->interlace
= picture_info
->interlace
;
297 picture
->tfcntrflag
= picture_info
->tfcntrflag
;
298 picture
->finterpflag
= picture_info
->finterpflag
;
299 picture
->psf
= picture_info
->psf
;
300 picture
->dquant
= picture_info
->dquant
;
301 picture
->panscan_flag
= picture_info
->panscan_flag
;
302 picture
->refdist_flag
= picture_info
->refdist_flag
;
303 picture
->quantizer
= picture_info
->quantizer
;
304 picture
->extended_mv
= picture_info
->extended_mv
;
305 picture
->extended_dmv
= picture_info
->extended_dmv
;
306 picture
->overlap
= picture_info
->overlap
;
307 picture
->vstransform
= picture_info
->vstransform
;
308 picture
->loopfilter
= picture_info
->loopfilter
;
309 picture
->fastuvmc
= picture_info
->fastuvmc
;
310 picture
->range_mapy_flag
= picture_info
->range_mapy_flag
;
311 picture
->range_mapy
= picture_info
->range_mapy
;
312 picture
->range_mapuv_flag
= picture_info
->range_mapuv_flag
;
313 picture
->range_mapuv
= picture_info
->range_mapuv
;
314 picture
->multires
= picture_info
->multires
;
315 picture
->syncmarker
= picture_info
->syncmarker
;
316 picture
->rangered
= picture_info
->rangered
;
317 picture
->maxbframes
= picture_info
->maxbframes
;
318 picture
->deblockEnable
= picture_info
->deblockEnable
;
319 picture
->pquant
= picture_info
->pquant
;
321 return VDP_STATUS_OK
;
325 vlVdpDecoderRenderH264(struct pipe_h264_picture_desc
*picture
,
326 VdpPictureInfoH264
*picture_info
)
330 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding H264\n");
332 picture
->slice_count
= picture_info
->slice_count
;
333 picture
->field_order_cnt
[0] = picture_info
->field_order_cnt
[0];
334 picture
->field_order_cnt
[1] = picture_info
->field_order_cnt
[1];
335 picture
->is_reference
= picture_info
->is_reference
;
336 picture
->frame_num
= picture_info
->frame_num
;
337 picture
->field_pic_flag
= picture_info
->field_pic_flag
;
338 picture
->bottom_field_flag
= picture_info
->bottom_field_flag
;
339 picture
->num_ref_frames
= picture_info
->num_ref_frames
;
340 picture
->mb_adaptive_frame_field_flag
= picture_info
->mb_adaptive_frame_field_flag
;
341 picture
->constrained_intra_pred_flag
= picture_info
->constrained_intra_pred_flag
;
342 picture
->weighted_pred_flag
= picture_info
->weighted_pred_flag
;
343 picture
->weighted_bipred_idc
= picture_info
->weighted_bipred_idc
;
344 picture
->frame_mbs_only_flag
= picture_info
->frame_mbs_only_flag
;
345 picture
->transform_8x8_mode_flag
= picture_info
->transform_8x8_mode_flag
;
346 picture
->chroma_qp_index_offset
= picture_info
->chroma_qp_index_offset
;
347 picture
->second_chroma_qp_index_offset
= picture_info
->second_chroma_qp_index_offset
;
348 picture
->pic_init_qp_minus26
= picture_info
->pic_init_qp_minus26
;
349 picture
->num_ref_idx_l0_active_minus1
= picture_info
->num_ref_idx_l0_active_minus1
;
350 picture
->num_ref_idx_l1_active_minus1
= picture_info
->num_ref_idx_l1_active_minus1
;
351 picture
->log2_max_frame_num_minus4
= picture_info
->log2_max_frame_num_minus4
;
352 picture
->pic_order_cnt_type
= picture_info
->pic_order_cnt_type
;
353 picture
->log2_max_pic_order_cnt_lsb_minus4
= picture_info
->log2_max_pic_order_cnt_lsb_minus4
;
354 picture
->delta_pic_order_always_zero_flag
= picture_info
->delta_pic_order_always_zero_flag
;
355 picture
->direct_8x8_inference_flag
= picture_info
->direct_8x8_inference_flag
;
356 picture
->entropy_coding_mode_flag
= picture_info
->entropy_coding_mode_flag
;
357 picture
->pic_order_present_flag
= picture_info
->pic_order_present_flag
;
358 picture
->deblocking_filter_control_present_flag
= picture_info
->deblocking_filter_control_present_flag
;
359 picture
->redundant_pic_cnt_present_flag
= picture_info
->redundant_pic_cnt_present_flag
;
361 memcpy(picture
->scaling_lists_4x4
, picture_info
->scaling_lists_4x4
, 6*16);
362 memcpy(picture
->scaling_lists_8x8
, picture_info
->scaling_lists_8x8
, 2*64);
364 for (i
= 0; i
< 16; ++i
) {
365 VdpStatus ret
= vlVdpGetReferenceFrame
367 picture_info
->referenceFrames
[i
].surface
,
370 if (ret
!= VDP_STATUS_OK
)
373 picture
->is_long_term
[i
] = picture_info
->referenceFrames
[i
].is_long_term
;
374 picture
->top_is_reference
[i
] = picture_info
->referenceFrames
[i
].top_is_reference
;
375 picture
->bottom_is_reference
[i
] = picture_info
->referenceFrames
[i
].bottom_is_reference
;
376 picture
->field_order_cnt_list
[i
][0] = picture_info
->referenceFrames
[i
].field_order_cnt
[0];
377 picture
->field_order_cnt_list
[i
][1] = picture_info
->referenceFrames
[i
].field_order_cnt
[1];
378 picture
->frame_num_list
[i
] = picture_info
->referenceFrames
[i
].frame_idx
;
381 return VDP_STATUS_OK
;
385 vlVdpDecoderFixVC1Startcode(uint32_t *num_buffers
, const void *buffers
[], unsigned sizes
[])
387 static const uint8_t vc1_startcode
[] = { 0x00, 0x00, 0x01, 0x0D };
391 /* search the first 64 bytes for a startcode */
392 vl_vlc_init(&vlc
, *num_buffers
, buffers
, sizes
);
393 for (i
= 0; i
< 64 && vl_vlc_bits_left(&vlc
) >= 32; ++i
) {
394 uint32_t value
= vl_vlc_peekbits(&vlc
, 32);
395 if (value
== 0x0000010D ||
396 value
== 0x0000010C ||
399 vl_vlc_eatbits(&vlc
, 8);
400 vl_vlc_fillbits(&vlc
);
403 /* none found, ok add one manually */
404 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Manually adding VC-1 startcode\n");
405 for (i
= *num_buffers
; i
> 0; --i
) {
406 buffers
[i
] = buffers
[i
- 1];
407 sizes
[i
] = sizes
[i
- 1];
410 buffers
[0] = vc1_startcode
;
415 * Decode a compressed field/frame and render the result into a VdpVideoSurface.
418 vlVdpDecoderRender(VdpDecoder decoder
,
419 VdpVideoSurface target
,
420 VdpPictureInfo
const *picture_info
,
421 uint32_t bitstream_buffer_count
,
422 VdpBitstreamBuffer
const *bitstream_buffers
)
424 const void * buffers
[bitstream_buffer_count
+ 1];
425 unsigned sizes
[bitstream_buffer_count
+ 1];
426 vlVdpDecoder
*vldecoder
;
427 vlVdpSurface
*vlsurf
;
429 struct pipe_screen
*screen
;
430 struct pipe_video_decoder
*dec
;
431 bool buffer_support
[2];
434 struct pipe_picture_desc base
;
435 struct pipe_mpeg12_picture_desc mpeg12
;
436 struct pipe_mpeg4_picture_desc mpeg4
;
437 struct pipe_vc1_picture_desc vc1
;
438 struct pipe_h264_picture_desc h264
;
441 if (!(picture_info
&& bitstream_buffers
))
442 return VDP_STATUS_INVALID_POINTER
;
444 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
446 return VDP_STATUS_INVALID_HANDLE
;
447 dec
= vldecoder
->decoder
;
448 screen
= dec
->context
->screen
;
450 vlsurf
= (vlVdpSurface
*)vlGetDataHTAB(target
);
452 return VDP_STATUS_INVALID_HANDLE
;
454 if (vlsurf
->device
!= vldecoder
->device
)
455 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
457 if (vlsurf
->video_buffer
!= NULL
&& vlsurf
->video_buffer
->chroma_format
!= dec
->chroma_format
)
458 // TODO: Recreate decoder with correct chroma
459 return VDP_STATUS_INVALID_CHROMA_TYPE
;
461 pipe_mutex_lock(vlsurf
->device
->mutex
);
463 buffer_support
[0] = screen
->get_video_param(screen
, dec
->profile
, PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE
);
464 buffer_support
[1] = screen
->get_video_param(screen
, dec
->profile
, PIPE_VIDEO_CAP_SUPPORTS_INTERLACED
);
466 if (vlsurf
->video_buffer
== NULL
||
467 !screen
->is_video_format_supported(screen
, vlsurf
->video_buffer
->buffer_format
, dec
->profile
) ||
468 !buffer_support
[vlsurf
->video_buffer
->interlaced
]) {
470 /* destroy the old one */
471 if (vlsurf
->video_buffer
)
472 vlsurf
->video_buffer
->destroy(vlsurf
->video_buffer
);
474 /* set the buffer format to the prefered one */
475 vlsurf
->templat
.buffer_format
= screen
->get_video_param(screen
, dec
->profile
, PIPE_VIDEO_CAP_PREFERED_FORMAT
);
477 /* also set interlacing to decoders preferences */
478 vlsurf
->templat
.interlaced
= screen
->get_video_param(screen
, dec
->profile
, PIPE_VIDEO_CAP_PREFERS_INTERLACED
);
480 /* and recreate the video buffer */
481 vlsurf
->video_buffer
= dec
->context
->create_video_buffer(dec
->context
, &vlsurf
->templat
);
483 /* still no luck? get me out of here... */
484 if (!vlsurf
->video_buffer
) {
485 pipe_mutex_unlock(vlsurf
->device
->mutex
);
486 return VDP_STATUS_NO_IMPLEMENTATION
;
488 vlVdpVideoSurfaceClear(vlsurf
);
491 for (i
= 0; i
< bitstream_buffer_count
; ++i
) {
492 buffers
[i
] = bitstream_buffers
[i
].bitstream
;
493 sizes
[i
] = bitstream_buffers
[i
].bitstream_bytes
;
496 memset(&desc
, 0, sizeof(desc
));
497 desc
.base
.profile
= dec
->profile
;
498 switch (u_reduce_video_profile(dec
->profile
)) {
499 case PIPE_VIDEO_CODEC_MPEG12
:
500 ret
= vlVdpDecoderRenderMpeg12(&desc
.mpeg12
, (VdpPictureInfoMPEG1Or2
*)picture_info
);
502 case PIPE_VIDEO_CODEC_MPEG4
:
503 ret
= vlVdpDecoderRenderMpeg4(&desc
.mpeg4
, (VdpPictureInfoMPEG4Part2
*)picture_info
);
505 case PIPE_VIDEO_CODEC_VC1
:
506 if (dec
->profile
== PIPE_VIDEO_PROFILE_VC1_ADVANCED
)
507 vlVdpDecoderFixVC1Startcode(&bitstream_buffer_count
, buffers
, sizes
);
508 ret
= vlVdpDecoderRenderVC1(&desc
.vc1
, (VdpPictureInfoVC1
*)picture_info
);
510 case PIPE_VIDEO_CODEC_MPEG4_AVC
:
511 ret
= vlVdpDecoderRenderH264(&desc
.h264
, (VdpPictureInfoH264
*)picture_info
);
514 pipe_mutex_unlock(vlsurf
->device
->mutex
);
515 return VDP_STATUS_INVALID_DECODER_PROFILE
;
518 if (ret
!= VDP_STATUS_OK
) {
519 pipe_mutex_unlock(vlsurf
->device
->mutex
);
523 dec
->begin_frame(dec
, vlsurf
->video_buffer
, &desc
.base
);
524 dec
->decode_bitstream(dec
, vlsurf
->video_buffer
, &desc
.base
, bitstream_buffer_count
, buffers
, sizes
);
525 dec
->end_frame(dec
, vlsurf
->video_buffer
, &desc
.base
);
526 pipe_mutex_unlock(vlsurf
->device
->mutex
);