decode.c revision 12bf452945ae64da69f474298758f9a7c8b94af5
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 unsigned i; 52 bool supported; 53 54 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating decoder\n"); 55 56 if (!decoder) 57 return VDP_STATUS_INVALID_POINTER; 58 *decoder = 0; 59 60 if (!(width && height)) 61 return VDP_STATUS_INVALID_VALUE; 62 63 p_profile = ProfileToPipe(profile); 64 if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) 65 return VDP_STATUS_INVALID_DECODER_PROFILE; 66 67 dev = vlGetDataHTAB(device); 68 if (!dev) 69 return VDP_STATUS_INVALID_HANDLE; 70 71 pipe = dev->context->pipe; 72 screen = dev->vscreen->pscreen; 73 supported = screen->get_video_param 74 ( 75 screen, 76 p_profile, 77 PIPE_VIDEO_CAP_SUPPORTED 78 ); 79 if (!supported) 80 return VDP_STATUS_INVALID_DECODER_PROFILE; 81 82 vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); 83 if (!vldecoder) 84 return VDP_STATUS_RESOURCES; 85 86 vldecoder->device = dev; 87 88 vldecoder->decoder = pipe->create_video_decoder 89 ( 90 pipe, p_profile, 91 PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 92 PIPE_VIDEO_CHROMA_FORMAT_420, 93 width, height, max_references 94 ); 95 96 if (!vldecoder->decoder) { 97 ret = VDP_STATUS_ERROR; 98 goto error_decoder; 99 } 100 101 vldecoder->num_buffers = pipe->screen->get_video_param 102 ( 103 pipe->screen, p_profile, 104 PIPE_VIDEO_CAP_NUM_BUFFERS_DESIRED 105 ); 106 vldecoder->cur_buffer = 0; 107 108 vldecoder->buffers = CALLOC(vldecoder->num_buffers, sizeof(void*)); 109 if (!vldecoder->buffers) 110 goto error_alloc_buffers; 111 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; 117 } 118 } 119 120 *decoder = vlAddDataHTAB(vldecoder); 121 if (*decoder == 0) { 122 ret = VDP_STATUS_ERROR; 123 goto error_handle; 124 } 125 126 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoder created succesfully\n"); 127 128 return VDP_STATUS_OK; 129 130error_handle: 131error_create_buffers: 132 133 for (i = 0; i < vldecoder->num_buffers; ++i) 134 if (vldecoder->buffers[i]) 135 vldecoder->decoder->destroy_buffer(vldecoder->decoder, vldecoder->buffers[i]); 136 137 FREE(vldecoder->buffers); 138 139error_alloc_buffers: 140 141 vldecoder->decoder->destroy(vldecoder->decoder); 142 143error_decoder: 144 FREE(vldecoder); 145 return ret; 146} 147 148/** 149 * Destroy a VdpDecoder. 150 */ 151VdpStatus 152vlVdpDecoderDestroy(VdpDecoder decoder) 153{ 154 vlVdpDecoder *vldecoder; 155 unsigned i; 156 157 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying decoder\n"); 158 159 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 160 if (!vldecoder) 161 return VDP_STATUS_INVALID_HANDLE; 162 163 for (i = 0; i < vldecoder->num_buffers; ++i) 164 if (vldecoder->buffers[i]) 165 vldecoder->decoder->destroy_buffer(vldecoder->decoder, vldecoder->buffers[i]); 166 167 FREE(vldecoder->buffers); 168 169 vldecoder->decoder->destroy(vldecoder->decoder); 170 171 FREE(vldecoder); 172 173 return VDP_STATUS_OK; 174} 175 176/** 177 * Retrieve the parameters used to create a VdpBitmapSurface. 178 */ 179VdpStatus 180vlVdpDecoderGetParameters(VdpDecoder decoder, 181 VdpDecoderProfile *profile, 182 uint32_t *width, 183 uint32_t *height) 184{ 185 vlVdpDecoder *vldecoder; 186 187 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoder get parameters called\n"); 188 189 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 190 if (!vldecoder) 191 return VDP_STATUS_INVALID_HANDLE; 192 193 *profile = PipeToProfile(vldecoder->decoder->profile); 194 *width = vldecoder->decoder->width; 195 *height = vldecoder->decoder->height; 196 197 return VDP_STATUS_OK; 198} 199 200/** 201 * Decode a mpeg 1/2 video. 202 */ 203static VdpStatus 204vlVdpDecoderRenderMpeg12(struct pipe_video_decoder *decoder, 205 VdpPictureInfoMPEG1Or2 *picture_info) 206{ 207 struct pipe_mpeg12_picture_desc picture; 208 struct pipe_mpeg12_quant_matrix quant; 209 struct pipe_video_buffer *ref_frames[2]; 210 unsigned i; 211 212 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG12\n"); 213 214 i = 0; 215 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; 219 if (!ref_frames[i]) 220 return VDP_STATUS_INVALID_HANDLE; 221 ++i; 222 } 223 224 if (picture_info->backward_reference != VDP_INVALID_HANDLE) { 225 ref_frames[i] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; 226 if (!ref_frames[i]) 227 return VDP_STATUS_INVALID_HANDLE; 228 ++i; 229 } 230 231 decoder->set_reference_frames(decoder, ref_frames, i); 232 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 249 decoder->set_picture_parameters(decoder, &picture.base); 250 251 memset(&quant, 0, sizeof(quant)); 252 quant.base.codec = PIPE_VIDEO_CODEC_MPEG12; 253 quant.intra_matrix = picture_info->intra_quantizer_matrix; 254 quant.non_intra_matrix = picture_info->non_intra_quantizer_matrix; 255 256 decoder->set_quant_matrix(decoder, &quant.base); 257 return VDP_STATUS_OK; 258} 259 260/** 261 * Decode a mpeg 1/2 video. 262 */ 263static VdpStatus 264vlVdpDecoderRenderMpeg4(struct pipe_video_decoder *decoder, 265 VdpPictureInfoMPEG4Part2 *picture_info) 266{ 267 struct pipe_mpeg4_picture_desc picture; 268 struct pipe_mpeg4_quant_matrix quant; 269 struct pipe_video_buffer *ref_frames[2] = {}; 270 unsigned i; 271 272 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG4\n"); 273 274 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ 275 if (picture_info->forward_reference != VDP_INVALID_HANDLE) { 276 ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer; 277 if (!ref_frames[0]) 278 return VDP_STATUS_INVALID_HANDLE; 279 } 280 281 if (picture_info->backward_reference != VDP_INVALID_HANDLE) { 282 ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; 283 if (!ref_frames[1]) 284 return VDP_STATUS_INVALID_HANDLE; 285 } 286 decoder->set_reference_frames(decoder, ref_frames, 2); 287 288 memset(&picture, 0, sizeof(picture)); 289 picture.base.profile = decoder->profile; 290 for (i = 0; i < 2; ++i) { 291 picture.trd[i] = picture_info->trd[i]; 292 picture.trb[i] = picture_info->trb[i]; 293 } 294 picture.vop_time_increment_resolution = picture_info->vop_time_increment_resolution; 295 picture.vop_coding_type = picture_info->vop_coding_type; 296 picture.vop_fcode_forward = picture_info->vop_fcode_forward; 297 picture.vop_fcode_backward = picture_info->vop_fcode_backward; 298 picture.resync_marker_disable = picture_info->resync_marker_disable; 299 picture.interlaced = picture_info->interlaced; 300 picture.quant_type = picture_info->quant_type; 301 picture.quarter_sample = picture_info->quarter_sample; 302 picture.short_video_header = picture_info->short_video_header; 303 picture.rounding_control = picture_info->rounding_control; 304 picture.alternate_vertical_scan_flag = picture_info->alternate_vertical_scan_flag; 305 picture.top_field_first = picture_info->top_field_first; 306 decoder->set_picture_parameters(decoder, &picture.base); 307 308 memset(&quant, 0, sizeof(quant)); 309 quant.base.codec = PIPE_VIDEO_CODEC_MPEG4; 310 quant.intra_matrix = picture_info->intra_quantizer_matrix; 311 quant.non_intra_matrix = picture_info->non_intra_quantizer_matrix; 312 decoder->set_quant_matrix(decoder, &quant.base); 313 return VDP_STATUS_OK; 314} 315 316/** 317 * Decode a compressed field/frame and render the result into a VdpVideoSurface. 318 */ 319VdpStatus 320vlVdpDecoderRender(VdpDecoder decoder, 321 VdpVideoSurface target, 322 VdpPictureInfo const *picture_info, 323 uint32_t bitstream_buffer_count, 324 VdpBitstreamBuffer const *bitstream_buffers) 325{ 326 vlVdpDecoder *vldecoder; 327 vlVdpSurface *vlsurf; 328 VdpStatus ret; 329 struct pipe_video_decoder *dec; 330 unsigned i; 331 332 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding\n"); 333 334 if (!(picture_info && bitstream_buffers)) 335 return VDP_STATUS_INVALID_POINTER; 336 337 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 338 if (!vldecoder) 339 return VDP_STATUS_INVALID_HANDLE; 340 dec = vldecoder->decoder; 341 342 vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); 343 if (!vlsurf) 344 return VDP_STATUS_INVALID_HANDLE; 345 346 if (vlsurf->device != vldecoder->device) 347 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 348 349 if (vlsurf->video_buffer->chroma_format != dec->chroma_format) 350 // TODO: Recreate decoder with correct chroma 351 return VDP_STATUS_INVALID_CHROMA_TYPE; 352 353 ++vldecoder->cur_buffer; 354 vldecoder->cur_buffer %= vldecoder->num_buffers; 355 356 dec->set_decode_buffer(dec, vldecoder->buffers[vldecoder->cur_buffer]); 357 dec->set_decode_target(dec, vlsurf->video_buffer); 358 359 switch (u_reduce_video_profile(dec->profile)) { 360 case PIPE_VIDEO_CODEC_MPEG12: 361 ret = vlVdpDecoderRenderMpeg12(dec, (VdpPictureInfoMPEG1Or2 *)picture_info); 362 break; 363 case PIPE_VIDEO_CODEC_MPEG4: 364 ret = vlVdpDecoderRenderMpeg4(dec, (VdpPictureInfoMPEG4Part2 *)picture_info); 365 break; 366 367 default: 368 return VDP_STATUS_INVALID_DECODER_PROFILE; 369 } 370 if (ret != VDP_STATUS_OK) 371 return ret; 372 373 dec->begin_frame(dec); 374 for (i = 0; i < bitstream_buffer_count; ++i) 375 dec->decode_bitstream(dec, bitstream_buffers[i].bitstream_bytes, 376 bitstream_buffers[i].bitstream); 377 dec->end_frame(dec); 378 return ret; 379} 380