decode.c revision c888fe027c338f337123de4da2de1ac73b0f7587
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 <pipe/p_video_context.h> 29 30#include <util/u_memory.h> 31#include <util/u_math.h> 32#include <util/u_debug.h> 33 34#include "vdpau_private.h" 35 36VdpStatus 37vlVdpDecoderCreate(VdpDevice device, 38 VdpDecoderProfile profile, 39 uint32_t width, uint32_t height, 40 uint32_t max_references, 41 VdpDecoder *decoder) 42{ 43 enum pipe_video_profile p_profile; 44 struct pipe_video_context *vpipe; 45 vlVdpDevice *dev; 46 vlVdpDecoder *vldecoder; 47 VdpStatus ret; 48 49 debug_printf("[VDPAU] Creating decoder\n"); 50 51 if (!decoder) 52 return VDP_STATUS_INVALID_POINTER; 53 54 if (!(width && height)) 55 return VDP_STATUS_INVALID_VALUE; 56 57 p_profile = ProfileToPipe(profile); 58 if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) 59 return VDP_STATUS_INVALID_DECODER_PROFILE; 60 61 dev = vlGetDataHTAB(device); 62 if (!dev) 63 return VDP_STATUS_INVALID_HANDLE; 64 65 vpipe = dev->context->vpipe; 66 67 vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); 68 if (!vldecoder) 69 return VDP_STATUS_RESOURCES; 70 71 vldecoder->device = dev; 72 73 // TODO: Define max_references. Used mainly for H264 74 vldecoder->decoder = vpipe->create_decoder 75 ( 76 vpipe, p_profile, 77 PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 78 PIPE_VIDEO_CHROMA_FORMAT_420, 79 width, height 80 ); 81 if (!vldecoder->decoder) { 82 ret = VDP_STATUS_ERROR; 83 goto error_decoder; 84 } 85 86 vldecoder->buffer = vldecoder->decoder->create_buffer(vldecoder->decoder); 87 if (!vldecoder->buffer) { 88 ret = VDP_STATUS_ERROR; 89 goto error_buffer; 90 } 91 92 *decoder = vlAddDataHTAB(vldecoder); 93 if (*decoder == 0) { 94 ret = VDP_STATUS_ERROR; 95 goto error_handle; 96 } 97 98 debug_printf("[VDPAU] Decoder created succesfully\n"); 99 100 return VDP_STATUS_OK; 101 102error_handle: 103 vldecoder->buffer->destroy(vldecoder->buffer); 104 105error_buffer: 106 vldecoder->decoder->destroy(vldecoder->decoder); 107 108error_decoder: 109 FREE(vldecoder); 110 return ret; 111} 112 113VdpStatus 114vlVdpDecoderDestroy(VdpDecoder decoder) 115{ 116 vlVdpDecoder *vldecoder; 117 118 debug_printf("[VDPAU] Destroying decoder\n"); 119 120 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 121 if (!vldecoder) 122 return VDP_STATUS_INVALID_HANDLE; 123 124 vldecoder->buffer->destroy(vldecoder->buffer); 125 vldecoder->decoder->destroy(vldecoder->decoder); 126 127 FREE(vldecoder); 128 129 return VDP_STATUS_OK; 130} 131 132VdpStatus 133vlVdpDecoderGetParameters(VdpDecoder decoder, 134 VdpDecoderProfile *profile, 135 uint32_t *width, 136 uint32_t *height) 137{ 138 return VDP_STATUS_OK; 139} 140 141static VdpStatus 142vlVdpDecoderRenderMpeg2(struct pipe_video_decoder *decoder, 143 struct pipe_video_decode_buffer *buffer, 144 struct pipe_video_buffer *target, 145 VdpPictureInfoMPEG1Or2 *picture_info, 146 uint32_t bitstream_buffer_count, 147 VdpBitstreamBuffer const *bitstream_buffers) 148{ 149 struct pipe_mpeg12_picture_desc picture; 150 struct pipe_video_buffer *ref_frames[2]; 151 unsigned num_ycbcr_blocks[3] = { 0, 0, 0 }; 152 unsigned i; 153 154 debug_printf("[VDPAU] Decoding MPEG2\n"); 155 156 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ 157 if (picture_info->forward_reference == VDP_INVALID_HANDLE) 158 ref_frames[0] = NULL; 159 else { 160 ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer; 161 if (!ref_frames[0]) 162 return VDP_STATUS_INVALID_HANDLE; 163 } 164 165 if (picture_info->backward_reference == VDP_INVALID_HANDLE) 166 ref_frames[1] = NULL; 167 else { 168 ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; 169 if (!ref_frames[1]) 170 return VDP_STATUS_INVALID_HANDLE; 171 } 172 173 memset(&picture, 0, sizeof(picture)); 174 picture.picture_coding_type = picture_info->picture_coding_type; 175 picture.picture_structure = picture_info->picture_structure; 176 picture.frame_pred_frame_dct = picture_info->frame_pred_frame_dct; 177 picture.q_scale_type = picture_info->q_scale_type; 178 picture.alternate_scan = picture_info->alternate_scan; 179 picture.intra_dc_precision = picture_info->intra_dc_precision; 180 picture.intra_vlc_format = picture_info->intra_vlc_format; 181 picture.concealment_motion_vectors = picture_info->concealment_motion_vectors; 182 picture.f_code[0][0] = picture_info->f_code[0][0] - 1; 183 picture.f_code[0][1] = picture_info->f_code[0][1] - 1; 184 picture.f_code[1][0] = picture_info->f_code[1][0] - 1; 185 picture.f_code[1][1] = picture_info->f_code[1][1] - 1; 186 187 picture.intra_quantizer_matrix = picture_info->intra_quantizer_matrix; 188 picture.non_intra_quantizer_matrix = picture_info->non_intra_quantizer_matrix; 189 190 buffer->map(buffer); 191 192 for (i = 0; i < bitstream_buffer_count; ++i) 193 buffer->decode_bitstream(buffer, bitstream_buffers[i].bitstream_bytes, 194 bitstream_buffers[i].bitstream, &picture, num_ycbcr_blocks); 195 196 buffer->unmap(buffer); 197 198 decoder->flush_buffer(buffer, num_ycbcr_blocks, ref_frames, target); 199 200 return VDP_STATUS_OK; 201} 202 203VdpStatus 204vlVdpDecoderRender(VdpDecoder decoder, 205 VdpVideoSurface target, 206 VdpPictureInfo const *picture_info, 207 uint32_t bitstream_buffer_count, 208 VdpBitstreamBuffer const *bitstream_buffers) 209{ 210 vlVdpDecoder *vldecoder; 211 vlVdpSurface *vlsurf; 212 213 debug_printf("[VDPAU] Decoding\n"); 214 215 if (!(picture_info && bitstream_buffers)) 216 return VDP_STATUS_INVALID_POINTER; 217 218 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 219 if (!vldecoder) 220 return VDP_STATUS_INVALID_HANDLE; 221 222 vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); 223 if (!vlsurf) 224 return VDP_STATUS_INVALID_HANDLE; 225 226 if (vlsurf->device != vldecoder->device) 227 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 228 229 if (vlsurf->video_buffer->chroma_format != vldecoder->decoder->chroma_format) 230 // TODO: Recreate decoder with correct chroma 231 return VDP_STATUS_INVALID_CHROMA_TYPE; 232 233 // TODO: Right now only mpeg2 is supported. 234 switch (vldecoder->decoder->profile) { 235 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: 236 case PIPE_VIDEO_PROFILE_MPEG2_MAIN: 237 return vlVdpDecoderRenderMpeg2(vldecoder->decoder, vldecoder->buffer, vlsurf->video_buffer, 238 (VdpPictureInfoMPEG1Or2 *)picture_info, 239 bitstream_buffer_count,bitstream_buffers); 240 break; 241 242 default: 243 return VDP_STATUS_INVALID_DECODER_PROFILE; 244 } 245} 246