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
;
54 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Creating decoder\n");
57 return VDP_STATUS_INVALID_POINTER
;
60 if (!(width
&& height
))
61 return VDP_STATUS_INVALID_VALUE
;
63 p_profile
= ProfileToPipe(profile
);
64 if (p_profile
== PIPE_VIDEO_PROFILE_UNKNOWN
)
65 return VDP_STATUS_INVALID_DECODER_PROFILE
;
67 dev
= vlGetDataHTAB(device
);
69 return VDP_STATUS_INVALID_HANDLE
;
71 pipe
= dev
->context
->pipe
;
72 screen
= dev
->vscreen
->pscreen
;
73 supported
= screen
->get_video_param
77 PIPE_VIDEO_CAP_SUPPORTED
80 return VDP_STATUS_INVALID_DECODER_PROFILE
;
82 vldecoder
= CALLOC(1,sizeof(vlVdpDecoder
));
84 return VDP_STATUS_RESOURCES
;
86 vldecoder
->device
= dev
;
88 vldecoder
->decoder
= pipe
->create_video_decoder
91 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
92 PIPE_VIDEO_CHROMA_FORMAT_420
,
93 width
, height
, max_references
96 if (!vldecoder
->decoder
) {
97 ret
= VDP_STATUS_ERROR
;
101 vldecoder
->num_buffers
= pipe
->screen
->get_video_param
103 pipe
->screen
, p_profile
,
104 PIPE_VIDEO_CAP_NUM_BUFFERS_DESIRED
106 vldecoder
->cur_buffer
= 0;
108 vldecoder
->buffers
= CALLOC(vldecoder
->num_buffers
, sizeof(void*));
109 if (!vldecoder
->buffers
)
110 goto error_alloc_buffers
;
112 for (i
= 0; i
< vldecoder
->num_buffers
; ++i
) {
113 vldecoder
->buffers
[i
] = vldecoder
->decoder
->create_buffer(vldecoder
->decoder
);
114 if (!vldecoder
->buffers
[i
]) {
115 ret
= VDP_STATUS_ERROR
;
116 goto error_create_buffers
;
120 *decoder
= vlAddDataHTAB(vldecoder
);
122 ret
= VDP_STATUS_ERROR
;
126 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoder created succesfully\n");
128 return VDP_STATUS_OK
;
131 error_create_buffers
:
133 for (i
= 0; i
< vldecoder
->num_buffers
; ++i
)
134 if (vldecoder
->buffers
[i
])
135 vldecoder
->decoder
->destroy_buffer(vldecoder
->decoder
, vldecoder
->buffers
[i
]);
137 FREE(vldecoder
->buffers
);
141 vldecoder
->decoder
->destroy(vldecoder
->decoder
);
149 * Destroy a VdpDecoder.
152 vlVdpDecoderDestroy(VdpDecoder decoder
)
154 vlVdpDecoder
*vldecoder
;
157 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Destroying decoder\n");
159 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
161 return VDP_STATUS_INVALID_HANDLE
;
163 for (i
= 0; i
< vldecoder
->num_buffers
; ++i
)
164 if (vldecoder
->buffers
[i
])
165 vldecoder
->decoder
->destroy_buffer(vldecoder
->decoder
, vldecoder
->buffers
[i
]);
167 FREE(vldecoder
->buffers
);
169 vldecoder
->decoder
->destroy(vldecoder
->decoder
);
173 return VDP_STATUS_OK
;
177 * Retrieve the parameters used to create a VdpBitmapSurface.
180 vlVdpDecoderGetParameters(VdpDecoder decoder
,
181 VdpDecoderProfile
*profile
,
185 vlVdpDecoder
*vldecoder
;
187 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoder get parameters called\n");
189 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
191 return VDP_STATUS_INVALID_HANDLE
;
193 *profile
= PipeToProfile(vldecoder
->decoder
->profile
);
194 *width
= vldecoder
->decoder
->width
;
195 *height
= vldecoder
->decoder
->height
;
197 return VDP_STATUS_OK
;
201 * Decode a mpeg 1/2 video.
204 vlVdpDecoderRenderMpeg12(struct pipe_video_decoder
*decoder
,
205 VdpPictureInfoMPEG1Or2
*picture_info
)
207 struct pipe_mpeg12_picture_desc picture
;
208 struct pipe_mpeg12_quant_matrix quant
;
209 struct pipe_video_buffer
*ref_frames
[2];
212 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding MPEG12\n");
216 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
217 if (picture_info
->forward_reference
!= VDP_INVALID_HANDLE
) {
218 ref_frames
[i
] = ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
))->video_buffer
;
220 return VDP_STATUS_INVALID_HANDLE
;
224 if (picture_info
->backward_reference
!= VDP_INVALID_HANDLE
) {
225 ref_frames
[i
] = ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
))->video_buffer
;
227 return VDP_STATUS_INVALID_HANDLE
;
231 decoder
->set_reference_frames(decoder
, ref_frames
, i
);
233 memset(&picture
, 0, sizeof(picture
));
234 picture
.base
.profile
= decoder
->profile
;
235 picture
.picture_coding_type
= picture_info
->picture_coding_type
;
236 picture
.picture_structure
= picture_info
->picture_structure
;
237 picture
.frame_pred_frame_dct
= picture_info
->frame_pred_frame_dct
;
238 picture
.q_scale_type
= picture_info
->q_scale_type
;
239 picture
.alternate_scan
= picture_info
->alternate_scan
;
240 picture
.intra_vlc_format
= picture_info
->intra_vlc_format
;
241 picture
.concealment_motion_vectors
= picture_info
->concealment_motion_vectors
;
242 picture
.intra_dc_precision
= picture_info
->intra_dc_precision
;
243 picture
.f_code
[0][0] = picture_info
->f_code
[0][0] - 1;
244 picture
.f_code
[0][1] = picture_info
->f_code
[0][1] - 1;
245 picture
.f_code
[1][0] = picture_info
->f_code
[1][0] - 1;
246 picture
.f_code
[1][1] = picture_info
->f_code
[1][1] - 1;
247 picture
.num_slices
= picture_info
->slice_count
;
248 picture
.top_field_first
= picture_info
->top_field_first
;
249 picture
.full_pel_forward_vector
= picture_info
->full_pel_forward_vector
;
250 picture
.full_pel_backward_vector
= picture_info
->full_pel_backward_vector
;
252 decoder
->set_picture_parameters(decoder
, &picture
.base
);
254 memset(&quant
, 0, sizeof(quant
));
255 quant
.base
.codec
= PIPE_VIDEO_CODEC_MPEG12
;
256 quant
.intra_matrix
= picture_info
->intra_quantizer_matrix
;
257 quant
.non_intra_matrix
= picture_info
->non_intra_quantizer_matrix
;
259 decoder
->set_quant_matrix(decoder
, &quant
.base
);
260 return VDP_STATUS_OK
;
264 * Decode a mpeg 4 video.
267 vlVdpDecoderRenderMpeg4(struct pipe_video_decoder
*decoder
,
268 VdpPictureInfoMPEG4Part2
*picture_info
)
270 struct pipe_mpeg4_picture_desc picture
;
271 struct pipe_mpeg4_quant_matrix quant
;
272 struct pipe_video_buffer
*ref_frames
[2] = {};
275 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding MPEG4\n");
277 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
278 if (picture_info
->forward_reference
!= VDP_INVALID_HANDLE
) {
279 ref_frames
[0] = ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
))->video_buffer
;
281 return VDP_STATUS_INVALID_HANDLE
;
284 if (picture_info
->backward_reference
!= VDP_INVALID_HANDLE
) {
285 ref_frames
[1] = ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
))->video_buffer
;
287 return VDP_STATUS_INVALID_HANDLE
;
289 decoder
->set_reference_frames(decoder
, ref_frames
, 2);
291 memset(&picture
, 0, sizeof(picture
));
292 picture
.base
.profile
= decoder
->profile
;
293 for (i
= 0; i
< 2; ++i
) {
294 picture
.trd
[i
] = picture_info
->trd
[i
];
295 picture
.trb
[i
] = picture_info
->trb
[i
];
297 picture
.vop_time_increment_resolution
= picture_info
->vop_time_increment_resolution
;
298 picture
.vop_coding_type
= picture_info
->vop_coding_type
;
299 picture
.vop_fcode_forward
= picture_info
->vop_fcode_forward
;
300 picture
.vop_fcode_backward
= picture_info
->vop_fcode_backward
;
301 picture
.resync_marker_disable
= picture_info
->resync_marker_disable
;
302 picture
.interlaced
= picture_info
->interlaced
;
303 picture
.quant_type
= picture_info
->quant_type
;
304 picture
.quarter_sample
= picture_info
->quarter_sample
;
305 picture
.short_video_header
= picture_info
->short_video_header
;
306 picture
.rounding_control
= picture_info
->rounding_control
;
307 picture
.alternate_vertical_scan_flag
= picture_info
->alternate_vertical_scan_flag
;
308 picture
.top_field_first
= picture_info
->top_field_first
;
309 decoder
->set_picture_parameters(decoder
, &picture
.base
);
311 memset(&quant
, 0, sizeof(quant
));
312 quant
.base
.codec
= PIPE_VIDEO_CODEC_MPEG4
;
313 quant
.intra_matrix
= picture_info
->intra_quantizer_matrix
;
314 quant
.non_intra_matrix
= picture_info
->non_intra_quantizer_matrix
;
315 decoder
->set_quant_matrix(decoder
, &quant
.base
);
316 return VDP_STATUS_OK
;
320 vlVdpDecoderRenderVC1(struct pipe_video_decoder
*decoder
,
321 VdpPictureInfoVC1
*picture_info
)
323 struct pipe_vc1_picture_desc picture
;
324 struct pipe_video_buffer
*ref_frames
[2] = {};
327 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Decoding VC-1\n");
329 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
330 if (picture_info
->forward_reference
!= VDP_INVALID_HANDLE
) {
331 ref_frames
[0] = ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
))->video_buffer
;
333 return VDP_STATUS_INVALID_HANDLE
;
336 if (picture_info
->backward_reference
!= VDP_INVALID_HANDLE
) {
337 ref_frames
[1] = ((vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
))->video_buffer
;
339 return VDP_STATUS_INVALID_HANDLE
;
341 decoder
->set_reference_frames(decoder
, ref_frames
, 2);
343 memset(&picture
, 0, sizeof(picture
));
344 picture
.base
.profile
= decoder
->profile
;
345 picture
.slice_count
= picture_info
->slice_count
;
346 picture
.picture_type
= picture_info
->picture_type
;
347 picture
.frame_coding_mode
= picture_info
->frame_coding_mode
;
348 picture
.postprocflag
= picture_info
->postprocflag
;
349 picture
.pulldown
= picture_info
->pulldown
;
350 picture
.interlace
= picture_info
->interlace
;
351 picture
.tfcntrflag
= picture_info
->tfcntrflag
;
352 picture
.finterpflag
= picture_info
->finterpflag
;
353 picture
.psf
= picture_info
->psf
;
354 picture
.dquant
= picture_info
->dquant
;
355 picture
.panscan_flag
= picture_info
->panscan_flag
;
356 picture
.refdist_flag
= picture_info
->refdist_flag
;
357 picture
.quantizer
= picture_info
->quantizer
;
358 picture
.extended_mv
= picture_info
->extended_mv
;
359 picture
.extended_dmv
= picture_info
->extended_dmv
;
360 picture
.overlap
= picture_info
->overlap
;
361 picture
.vstransform
= picture_info
->vstransform
;
362 picture
.loopfilter
= picture_info
->loopfilter
;
363 picture
.fastuvmc
= picture_info
->fastuvmc
;
364 picture
.range_mapy_flag
= picture_info
->range_mapy_flag
;
365 picture
.range_mapy
= picture_info
->range_mapy
;
366 picture
.range_mapuv_flag
= picture_info
->range_mapuv_flag
;
367 picture
.range_mapuv
= picture_info
->range_mapuv
;
368 picture
.multires
= picture_info
->multires
;
369 picture
.syncmarker
= picture_info
->syncmarker
;
370 picture
.rangered
= picture_info
->rangered
;
371 picture
.maxbframes
= picture_info
->maxbframes
;
372 picture
.deblockEnable
= picture_info
->deblockEnable
;
373 picture
.pquant
= picture_info
->pquant
;
374 decoder
->set_picture_parameters(decoder
, &picture
.base
);
375 return VDP_STATUS_OK
;
379 * Decode a compressed field/frame and render the result into a VdpVideoSurface.
382 vlVdpDecoderRender(VdpDecoder decoder
,
383 VdpVideoSurface target
,
384 VdpPictureInfo
const *picture_info
,
385 uint32_t bitstream_buffer_count
,
386 VdpBitstreamBuffer
const *bitstream_buffers
)
388 vlVdpDecoder
*vldecoder
;
389 vlVdpSurface
*vlsurf
;
391 struct pipe_video_decoder
*dec
;
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 ++vldecoder
->cur_buffer
;
416 vldecoder
->cur_buffer
%= vldecoder
->num_buffers
;
418 dec
->set_decode_buffer(dec
, vldecoder
->buffers
[vldecoder
->cur_buffer
]);
419 dec
->set_decode_target(dec
, vlsurf
->video_buffer
);
421 switch (u_reduce_video_profile(dec
->profile
)) {
422 case PIPE_VIDEO_CODEC_MPEG12
:
423 ret
= vlVdpDecoderRenderMpeg12(dec
, (VdpPictureInfoMPEG1Or2
*)picture_info
);
425 case PIPE_VIDEO_CODEC_MPEG4
:
426 ret
= vlVdpDecoderRenderMpeg4(dec
, (VdpPictureInfoMPEG4Part2
*)picture_info
);
428 case PIPE_VIDEO_CODEC_VC1
:
429 ret
= vlVdpDecoderRenderVC1(dec
, (VdpPictureInfoVC1
*)picture_info
);
432 return VDP_STATUS_INVALID_DECODER_PROFILE
;
434 if (ret
!= VDP_STATUS_OK
)
437 dec
->begin_frame(dec
);
438 for (i
= 0; i
< bitstream_buffer_count
; ++i
)
439 dec
->decode_bitstream(dec
, bitstream_buffers
[i
].bitstream_bytes
,
440 bitstream_buffers
[i
].bitstream
);