decode.c revision 2471acfc4c051d480861265011fa5e77fad02887
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_video_buffer *ref_frames[2]; 150 151 debug_printf("[VDPAU] Decoding MPEG2\n"); 152 153 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ 154 if (picture_info->backward_reference == VDP_INVALID_HANDLE) 155 ref_frames[0] = NULL; 156 else { 157 ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; 158 if (!ref_frames[0]) 159 return VDP_STATUS_INVALID_HANDLE; 160 } 161 162 if (picture_info->forward_reference == VDP_INVALID_HANDLE) 163 ref_frames[1] = NULL; 164 else { 165 ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer; 166 if (!ref_frames[1]) 167 return VDP_STATUS_INVALID_HANDLE; 168 } 169 170 //if (vlVdpMPEG2BitstreamToMacroblock(vpipe->screen, bitstream_buffers, bitstream_buffer_count, 171 // &num_macroblocks, &pipe_macroblocks)) 172 //{ 173 // debug_printf("[VDPAU] Error in frame-header. Skipping.\n"); 174 // 175 // ret = VDP_STATUS_OK; 176 // goto skip_frame; 177 //} 178 179 // TODO 180 //vpipe->set_decode_target(vpipe,t_surf); 181 //vpipe->decode_macroblocks(vpipe, p_surf, f_surf, num_macroblocks, 182 // (struct pipe_macroblock *)pipe_macroblocks, NULL); 183 184 return VDP_STATUS_OK; 185} 186 187VdpStatus 188vlVdpDecoderRender(VdpDecoder decoder, 189 VdpVideoSurface target, 190 VdpPictureInfo const *picture_info, 191 uint32_t bitstream_buffer_count, 192 VdpBitstreamBuffer const *bitstream_buffers) 193{ 194 vlVdpDecoder *vldecoder; 195 vlVdpSurface *vlsurf; 196 197 debug_printf("[VDPAU] Decoding\n"); 198 199 if (!(picture_info && bitstream_buffers)) 200 return VDP_STATUS_INVALID_POINTER; 201 202 vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); 203 if (!vldecoder) 204 return VDP_STATUS_INVALID_HANDLE; 205 206 vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); 207 if (!vlsurf) 208 return VDP_STATUS_INVALID_HANDLE; 209 210 if (vlsurf->device != vldecoder->device) 211 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 212 213 if (vlsurf->video_buffer->chroma_format != vldecoder->decoder->chroma_format) 214 // TODO: Recreate decoder with correct chroma 215 return VDP_STATUS_INVALID_CHROMA_TYPE; 216 217 // TODO: Right now only mpeg2 is supported. 218 switch (vldecoder->decoder->profile) { 219 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: 220 case PIPE_VIDEO_PROFILE_MPEG2_MAIN: 221 return vlVdpDecoderRenderMpeg2(vldecoder->decoder, vldecoder->buffer, 222 vlsurf, (VdpPictureInfoMPEG1Or2 *)picture_info, 223 bitstream_buffer_count,bitstream_buffers); 224 break; 225 226 default: 227 return VDP_STATUS_INVALID_DECODER_PROFILE; 228 } 229} 230