decode.c revision 8c2bfa34a0d70ab08de44e3b091b3a097abbad97
1/************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Sørensen. 4 * All Rights Reserved. 5 * 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: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 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. 25 * 26 **************************************************************************/ 27 28#include "util/u_memory.h" 29#include "util/u_math.h" 30#include "util/u_debug.h" 31#include "util/u_video.h" 32 33#include "vdpau_private.h" 34 35/** 36 * Create a VdpDecoder. 37 */ 38VdpStatus 39vlVdpDecoderCreate(VdpDevice device, 40 VdpDecoderProfile profile, 41 uint32_t width, uint32_t height, 42 uint32_t max_references, 43 VdpDecoder *decoder) 44{ 45 enum pipe_video_profile p_profile; 46 struct pipe_context *pipe; 47 struct pipe_screen *screen; 48 vlVdpDevice *dev; 49 vlVdpDecoder *vldecoder; 50 VdpStatus ret; 51 bool supported; 52 53 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating decoder\n"); 54 55 if (!decoder) 56 return VDP_STATUS_INVALID_POINTER; 57 *decoder = 0; 58 59 if (!(width && height)) 60 return VDP_STATUS_INVALID_VALUE; 61 62 p_profile = ProfileToPipe(profile); 63 if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) 64 return VDP_STATUS_INVALID_DECODER_PROFILE; 65 66 dev = vlGetDataHTAB(device); 67 if (!dev) 68 return VDP_STATUS_INVALID_HANDLE; 69 70 pipe = dev->context->pipe; 71 screen = dev->vscreen->pscreen; 72 supported = screen->get_video_param 73 ( 74 screen, 75 p_profile, 76 PIPE_VIDEO_CAP_SUPPORTED 77 ); 78 if (!supported) 79 return VDP_STATUS_INVALID_DECODER_PROFILE; 80 81 vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); 82 if (!vldecoder) 83 return VDP_STATUS_RESOURCES; 84 85 vldecoder->device = dev; 86 87 vldecoder->decoder = pipe->create_video_decoder 88 ( 89 pipe, p_profile, 90 PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 91 PIPE_VIDEO_CHROMA_FORMAT_420, 92 width, height, max_references, 93 false 94 ); 95 96 if (!vldecoder->decoder) { 97 ret = VDP_STATUS_ERROR; 98 goto error_decoder; 99 } 100 101 *decoder = vlAddDataHTAB(vldecoder); 102 if (*decoder == 0) { 103 ret = VDP_STATUS_ERROR; 104 goto error_handle; 105 } 106 107 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoder created succesfully\n"); 108 109 return VDP_STATUS_OK; 110 111error_handle: 112 113 vldecoder->decoder->destroy(vldecoder->decoder); 114 115error_decoder: 116 FREE(vldecoder); 117 return ret; 118} 119 120/** 121 * Destroy a VdpDecoder. 122 */ 123VdpStatus 124vlVdpDecoderDestroy(VdpDecoder decoder) 125{ 126 vlVdpDecoder *vldecoder; 127 128 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying decoder\n"); 129 130 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 131 if (!vldecoder) 132 return VDP_STATUS_INVALID_HANDLE; 133 134 vldecoder->decoder->destroy(vldecoder->decoder); 135 136 FREE(vldecoder); 137 138 return VDP_STATUS_OK; 139} 140 141/** 142 * Retrieve the parameters used to create a VdpBitmapSurface. 143 */ 144VdpStatus 145vlVdpDecoderGetParameters(VdpDecoder decoder, 146 VdpDecoderProfile *profile, 147 uint32_t *width, 148 uint32_t *height) 149{ 150 vlVdpDecoder *vldecoder; 151 152 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoder get parameters called\n"); 153 154 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 155 if (!vldecoder) 156 return VDP_STATUS_INVALID_HANDLE; 157 158 *profile = PipeToProfile(vldecoder->decoder->profile); 159 *width = vldecoder->decoder->width; 160 *height = vldecoder->decoder->height; 161 162 return VDP_STATUS_OK; 163} 164 165/** 166 * Decode a mpeg 1/2 video. 167 */ 168static VdpStatus 169vlVdpDecoderRenderMpeg12(struct pipe_video_decoder *decoder, 170 VdpPictureInfoMPEG1Or2 *picture_info) 171{ 172 struct pipe_mpeg12_picture_desc picture; 173 struct pipe_mpeg12_quant_matrix quant; 174 struct pipe_video_buffer *ref_frames[2]; 175 unsigned i; 176 177 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG12\n"); 178 179 i = 0; 180 181 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ 182 if (picture_info->forward_reference != VDP_INVALID_HANDLE) { 183 ref_frames[i] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer; 184 if (!ref_frames[i]) 185 return VDP_STATUS_INVALID_HANDLE; 186 ++i; 187 } 188 189 if (picture_info->backward_reference != VDP_INVALID_HANDLE) { 190 ref_frames[i] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; 191 if (!ref_frames[i]) 192 return VDP_STATUS_INVALID_HANDLE; 193 ++i; 194 } 195 196 decoder->set_reference_frames(decoder, ref_frames, i); 197 198 memset(&picture, 0, sizeof(picture)); 199 picture.base.profile = decoder->profile; 200 picture.picture_coding_type = picture_info->picture_coding_type; 201 picture.picture_structure = picture_info->picture_structure; 202 picture.frame_pred_frame_dct = picture_info->frame_pred_frame_dct; 203 picture.q_scale_type = picture_info->q_scale_type; 204 picture.alternate_scan = picture_info->alternate_scan; 205 picture.intra_vlc_format = picture_info->intra_vlc_format; 206 picture.concealment_motion_vectors = picture_info->concealment_motion_vectors; 207 picture.intra_dc_precision = picture_info->intra_dc_precision; 208 picture.f_code[0][0] = picture_info->f_code[0][0] - 1; 209 picture.f_code[0][1] = picture_info->f_code[0][1] - 1; 210 picture.f_code[1][0] = picture_info->f_code[1][0] - 1; 211 picture.f_code[1][1] = picture_info->f_code[1][1] - 1; 212 picture.num_slices = picture_info->slice_count; 213 picture.top_field_first = picture_info->top_field_first; 214 picture.full_pel_forward_vector = picture_info->full_pel_forward_vector; 215 picture.full_pel_backward_vector = picture_info->full_pel_backward_vector; 216 217 decoder->set_picture_parameters(decoder, &picture.base); 218 219 memset(&quant, 0, sizeof(quant)); 220 quant.base.codec = PIPE_VIDEO_CODEC_MPEG12; 221 quant.intra_matrix = picture_info->intra_quantizer_matrix; 222 quant.non_intra_matrix = picture_info->non_intra_quantizer_matrix; 223 224 decoder->set_quant_matrix(decoder, &quant.base); 225 return VDP_STATUS_OK; 226} 227 228/** 229 * Decode a mpeg 4 video. 230 */ 231static VdpStatus 232vlVdpDecoderRenderMpeg4(struct pipe_video_decoder *decoder, 233 VdpPictureInfoMPEG4Part2 *picture_info) 234{ 235 struct pipe_mpeg4_picture_desc picture; 236 struct pipe_mpeg4_quant_matrix quant; 237 struct pipe_video_buffer *ref_frames[2] = {}; 238 unsigned i; 239 240 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG4\n"); 241 242 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ 243 if (picture_info->forward_reference != VDP_INVALID_HANDLE) { 244 ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer; 245 if (!ref_frames[0]) 246 return VDP_STATUS_INVALID_HANDLE; 247 } 248 249 if (picture_info->backward_reference != VDP_INVALID_HANDLE) { 250 ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; 251 if (!ref_frames[1]) 252 return VDP_STATUS_INVALID_HANDLE; 253 } 254 decoder->set_reference_frames(decoder, ref_frames, 2); 255 256 memset(&picture, 0, sizeof(picture)); 257 picture.base.profile = decoder->profile; 258 for (i = 0; i < 2; ++i) { 259 picture.trd[i] = picture_info->trd[i]; 260 picture.trb[i] = picture_info->trb[i]; 261 } 262 picture.vop_time_increment_resolution = picture_info->vop_time_increment_resolution; 263 picture.vop_coding_type = picture_info->vop_coding_type; 264 picture.vop_fcode_forward = picture_info->vop_fcode_forward; 265 picture.vop_fcode_backward = picture_info->vop_fcode_backward; 266 picture.resync_marker_disable = picture_info->resync_marker_disable; 267 picture.interlaced = picture_info->interlaced; 268 picture.quant_type = picture_info->quant_type; 269 picture.quarter_sample = picture_info->quarter_sample; 270 picture.short_video_header = picture_info->short_video_header; 271 picture.rounding_control = picture_info->rounding_control; 272 picture.alternate_vertical_scan_flag = picture_info->alternate_vertical_scan_flag; 273 picture.top_field_first = picture_info->top_field_first; 274 decoder->set_picture_parameters(decoder, &picture.base); 275 276 memset(&quant, 0, sizeof(quant)); 277 quant.base.codec = PIPE_VIDEO_CODEC_MPEG4; 278 quant.intra_matrix = picture_info->intra_quantizer_matrix; 279 quant.non_intra_matrix = picture_info->non_intra_quantizer_matrix; 280 decoder->set_quant_matrix(decoder, &quant.base); 281 return VDP_STATUS_OK; 282} 283 284static VdpStatus 285vlVdpDecoderRenderVC1(struct pipe_video_decoder *decoder, 286 VdpPictureInfoVC1 *picture_info) 287{ 288 struct pipe_vc1_picture_desc picture; 289 struct pipe_video_buffer *ref_frames[2] = {}; 290 291 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding VC-1\n"); 292 293 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ 294 if (picture_info->forward_reference != VDP_INVALID_HANDLE) { 295 ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer; 296 if (!ref_frames[0]) 297 return VDP_STATUS_INVALID_HANDLE; 298 } 299 300 if (picture_info->backward_reference != VDP_INVALID_HANDLE) { 301 ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; 302 if (!ref_frames[1]) 303 return VDP_STATUS_INVALID_HANDLE; 304 } 305 decoder->set_reference_frames(decoder, ref_frames, 2); 306 307 memset(&picture, 0, sizeof(picture)); 308 picture.base.profile = decoder->profile; 309 picture.slice_count = picture_info->slice_count; 310 picture.picture_type = picture_info->picture_type; 311 picture.frame_coding_mode = picture_info->frame_coding_mode; 312 picture.postprocflag = picture_info->postprocflag; 313 picture.pulldown = picture_info->pulldown; 314 picture.interlace = picture_info->interlace; 315 picture.tfcntrflag = picture_info->tfcntrflag; 316 picture.finterpflag = picture_info->finterpflag; 317 picture.psf = picture_info->psf; 318 picture.dquant = picture_info->dquant; 319 picture.panscan_flag = picture_info->panscan_flag; 320 picture.refdist_flag = picture_info->refdist_flag; 321 picture.quantizer = picture_info->quantizer; 322 picture.extended_mv = picture_info->extended_mv; 323 picture.extended_dmv = picture_info->extended_dmv; 324 picture.overlap = picture_info->overlap; 325 picture.vstransform = picture_info->vstransform; 326 picture.loopfilter = picture_info->loopfilter; 327 picture.fastuvmc = picture_info->fastuvmc; 328 picture.range_mapy_flag = picture_info->range_mapy_flag; 329 picture.range_mapy = picture_info->range_mapy; 330 picture.range_mapuv_flag = picture_info->range_mapuv_flag; 331 picture.range_mapuv = picture_info->range_mapuv; 332 picture.multires = picture_info->multires; 333 picture.syncmarker = picture_info->syncmarker; 334 picture.rangered = picture_info->rangered; 335 picture.maxbframes = picture_info->maxbframes; 336 picture.deblockEnable = picture_info->deblockEnable; 337 picture.pquant = picture_info->pquant; 338 decoder->set_picture_parameters(decoder, &picture.base); 339 return VDP_STATUS_OK; 340} 341 342/** 343 * Decode a compressed field/frame and render the result into a VdpVideoSurface. 344 */ 345VdpStatus 346vlVdpDecoderRender(VdpDecoder decoder, 347 VdpVideoSurface target, 348 VdpPictureInfo const *picture_info, 349 uint32_t bitstream_buffer_count, 350 VdpBitstreamBuffer const *bitstream_buffers) 351{ 352 const void * buffers[bitstream_buffer_count]; 353 unsigned sizes[bitstream_buffer_count]; 354 vlVdpDecoder *vldecoder; 355 vlVdpSurface *vlsurf; 356 VdpStatus ret; 357 struct pipe_video_decoder *dec; 358 unsigned i; 359 360 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding\n"); 361 362 if (!(picture_info && bitstream_buffers)) 363 return VDP_STATUS_INVALID_POINTER; 364 365 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 366 if (!vldecoder) 367 return VDP_STATUS_INVALID_HANDLE; 368 dec = vldecoder->decoder; 369 370 vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); 371 if (!vlsurf) 372 return VDP_STATUS_INVALID_HANDLE; 373 374 if (vlsurf->device != vldecoder->device) 375 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 376 377 if (vlsurf->video_buffer->chroma_format != dec->chroma_format) 378 // TODO: Recreate decoder with correct chroma 379 return VDP_STATUS_INVALID_CHROMA_TYPE; 380 381 dec->set_decode_target(dec, vlsurf->video_buffer); 382 383 switch (u_reduce_video_profile(dec->profile)) { 384 case PIPE_VIDEO_CODEC_MPEG12: 385 ret = vlVdpDecoderRenderMpeg12(dec, (VdpPictureInfoMPEG1Or2 *)picture_info); 386 break; 387 case PIPE_VIDEO_CODEC_MPEG4: 388 ret = vlVdpDecoderRenderMpeg4(dec, (VdpPictureInfoMPEG4Part2 *)picture_info); 389 break; 390 case PIPE_VIDEO_CODEC_VC1: 391 ret = vlVdpDecoderRenderVC1(dec, (VdpPictureInfoVC1 *)picture_info); 392 break; 393 default: 394 return VDP_STATUS_INVALID_DECODER_PROFILE; 395 } 396 if (ret != VDP_STATUS_OK) 397 return ret; 398 399 dec->begin_frame(dec); 400 for (i = 0; i < bitstream_buffer_count; ++i) { 401 buffers[i] = bitstream_buffers[i].bitstream; 402 sizes[i] = bitstream_buffers[i].bitstream_bytes; 403 } 404 dec->decode_bitstream(dec, bitstream_buffer_count, buffers, sizes); 405 dec->end_frame(dec); 406 return ret; 407} 408