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 "vdpau_private.h"
29 #include "mpeg2_bitstream_parser.h"
30 #include <util/u_memory.h>
31 #include <util/u_math.h>
32 #include <pipe/p_video_context.h>
33 #include <util/u_debug.h>
36 vlVdpDecoderCreate(VdpDevice device
,
37 VdpDecoderProfile profile
,
38 uint32_t width
, uint32_t height
,
39 uint32_t max_references
,
42 enum pipe_video_profile p_profile
= PIPE_VIDEO_PROFILE_UNKNOWN
;
43 VdpStatus ret
= VDP_STATUS_OK
;
44 vlVdpDecoder
*vldecoder
= NULL
;
46 debug_printf("[VDPAU] Creating decoder\n");
49 return VDP_STATUS_INVALID_POINTER
;
51 if (!(width
&& height
))
52 return VDP_STATUS_INVALID_VALUE
;
54 vlVdpDevice
*dev
= vlGetDataHTAB(device
);
56 ret
= VDP_STATUS_INVALID_HANDLE
;
60 vldecoder
= CALLOC(1,sizeof(vlVdpDecoder
));
62 ret
= VDP_STATUS_RESOURCES
;
66 p_profile
= ProfileToPipe(profile
);
67 if (p_profile
== PIPE_VIDEO_PROFILE_UNKNOWN
) {
68 ret
= VDP_STATUS_INVALID_DECODER_PROFILE
;
72 // TODO: Define max_references. Used mainly for H264
74 vldecoder
->profile
= p_profile
;
75 vldecoder
->height
= height
;
76 vldecoder
->width
= width
;
77 vldecoder
->device
= dev
;
78 vldecoder
->vctx
= NULL
;
80 *decoder
= vlAddDataHTAB(vldecoder
);
82 ret
= VDP_STATUS_ERROR
;
85 debug_printf("[VDPAU] Decoder created succesfully\n");
99 vlVdpDecoderDestroy(VdpDecoder decoder
)
101 debug_printf("[VDPAU] Destroying decoder\n");
102 vlVdpDecoder
*vldecoder
;
104 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
106 return VDP_STATUS_INVALID_HANDLE
;
109 if (vldecoder
->vctx
) {
110 if (vldecoder
->vctx
->vscreen
)
111 vl_screen_destroy(vldecoder
->vctx
->vscreen
);
115 vl_video_destroy(vldecoder
->vctx
);
119 return VDP_STATUS_OK
;
123 vlVdpCreateSurfaceTarget(vlVdpDecoder
*vldecoder
, vlVdpSurface
*vlsurf
)
125 struct pipe_surface surf_template
;
126 struct pipe_resource tmplt
;
127 struct pipe_resource
*surf_tex
;
128 struct pipe_video_context
*vctx
;
130 debug_printf("[VDPAU] Creating surface\n");
132 if(!(vldecoder
&& vlsurf
))
133 return VDP_STATUS_INVALID_POINTER
;
135 vctx
= vldecoder
->vctx
->vpipe
;
137 memset(&tmplt
, 0, sizeof(struct pipe_resource
));
138 tmplt
.target
= PIPE_TEXTURE_2D
;
139 tmplt
.format
= vctx
->get_param(vctx
,PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT
);
140 tmplt
.last_level
= 0;
142 if (vctx
->is_format_supported(vctx
, tmplt
.format
,
143 PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
,
144 PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
)) {
145 tmplt
.width0
= vlsurf
->width
;
146 tmplt
.height0
= vlsurf
->height
;
148 assert(vctx
->is_format_supported(vctx
, tmplt
.format
,
149 PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
,
150 PIPE_TEXTURE_GEOM_NON_SQUARE
));
151 tmplt
.width0
= util_next_power_of_two(vlsurf
->width
);
152 tmplt
.height0
= util_next_power_of_two(vlsurf
->height
);
156 tmplt
.usage
= PIPE_USAGE_DEFAULT
;
157 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
160 surf_tex
= vctx
->screen
->resource_create(vctx
->screen
, &tmplt
);
162 memset(&surf_template
, 0, sizeof(surf_template
));
163 surf_template
.format
= surf_tex
->format
;
164 surf_template
.usage
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
165 vlsurf
->psurface
= vctx
->create_surface(vctx
->screen
, surf_tex
, &surf_template
);
167 pipe_resource_reference(&surf_tex
, NULL
);
169 if (!vlsurf
->psurface
)
170 return VDP_STATUS_RESOURCES
;
171 debug_printf("[VDPAU] Done creating surface\n");
173 return VDP_STATUS_OK
;
177 vlVdpDecoderRenderMpeg2(vlVdpDecoder
*vldecoder
,
178 vlVdpSurface
*vlsurf
,
179 VdpPictureInfoMPEG1Or2
*picture_info
,
180 uint32_t bitstream_buffer_count
,
181 VdpBitstreamBuffer
const *bitstream_buffers
)
183 struct pipe_video_context
*vpipe
;
184 vlVdpSurface
*t_vdp_surf
;
185 vlVdpSurface
*p_vdp_surf
;
186 vlVdpSurface
*f_vdp_surf
;
187 struct pipe_surface
*t_surf
;
188 struct pipe_surface
*p_surf
;
189 struct pipe_surface
*f_surf
;
190 uint32_t num_macroblocks
;
191 struct pipe_mpeg12_macroblock
*pipe_macroblocks
;
194 debug_printf("[VDPAU] Decoding MPEG2\n");
198 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
199 if (picture_info
->backward_reference
== VDP_INVALID_HANDLE
)
202 p_vdp_surf
= (vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
);
204 return VDP_STATUS_INVALID_HANDLE
;
207 if (picture_info
->forward_reference
== VDP_INVALID_HANDLE
)
210 f_vdp_surf
= (vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
);
212 return VDP_STATUS_INVALID_HANDLE
;
215 if (f_vdp_surf
== VDP_INVALID_HANDLE
) f_vdp_surf
= NULL
;
217 ret
= vlVdpCreateSurfaceTarget(vldecoder
,t_vdp_surf
);
219 vpipe
= vldecoder
->vctx
->vpipe
;
221 if (vlVdpMPEG2BitstreamToMacroblock(vpipe
->screen
, bitstream_buffers
, bitstream_buffer_count
,
222 &num_macroblocks
, &pipe_macroblocks
))
224 debug_printf("[VDPAU] Error in frame-header. Skipping.\n");
230 vpipe
->set_decode_target(vpipe
,t_surf
);
231 vpipe
->decode_macroblocks(vpipe
, p_surf
, f_surf
, num_macroblocks
,
232 (struct pipe_macroblock
*)pipe_macroblocks
, NULL
);
239 vlVdpDecoderRender(VdpDecoder decoder
,
240 VdpVideoSurface target
,
241 VdpPictureInfo
const *picture_info
,
242 uint32_t bitstream_buffer_count
,
243 VdpBitstreamBuffer
const *bitstream_buffers
)
245 vlVdpDecoder
*vldecoder
;
246 vlVdpSurface
*vlsurf
;
247 struct vl_screen
*vscreen
;
250 debug_printf("[VDPAU] Decoding\n");
252 if (!(picture_info
&& bitstream_buffers
))
253 return VDP_STATUS_INVALID_POINTER
;
255 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
257 return VDP_STATUS_INVALID_HANDLE
;
259 vlsurf
= (vlVdpSurface
*)vlGetDataHTAB(target
);
261 return VDP_STATUS_INVALID_HANDLE
;
263 if (vlsurf
->device
!= vldecoder
->device
)
264 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
266 /* Test doesn't make sence */
267 /*if (vlsurf->chroma_format != vldecoder->chroma_format)
268 return VDP_STATUS_INVALID_CHROMA_TYPE;*/
270 vscreen
= vl_screen_create(vldecoder
->device
->display
, vldecoder
->device
->screen
);
272 return VDP_STATUS_RESOURCES
;
274 vldecoder
->vctx
= vl_video_create(vscreen
, vldecoder
->profile
, vlsurf
->chroma_format
, vldecoder
->width
, vldecoder
->height
);
275 if (!vldecoder
->vctx
)
276 return VDP_STATUS_RESOURCES
;
278 // TODO: Right now only mpeg2 is supported.
279 switch (vldecoder
->vctx
->vpipe
->profile
) {
280 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE
:
281 case PIPE_VIDEO_PROFILE_MPEG2_MAIN
:
282 ret
= vlVdpDecoderRenderMpeg2(vldecoder
,vlsurf
,(VdpPictureInfoMPEG1Or2
*)picture_info
,
283 bitstream_buffer_count
,bitstream_buffers
);
286 return VDP_STATUS_INVALID_DECODER_PROFILE
;
294 vlVdpGenerateCSCMatrix(VdpProcamp
*procamp
,
295 VdpColorStandard standard
,
296 VdpCSCMatrix
*csc_matrix
)
298 debug_printf("[VDPAU] Generating CSCMatrix\n");
299 if (!(csc_matrix
&& procamp
))
300 return VDP_STATUS_INVALID_POINTER
;
302 return VDP_STATUS_OK
;