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 <util/u_memory.h>
30 #include <util/u_math.h>
31 #include <pipe/p_video_context.h>
32 #include <util/u_debug.h>
35 vlVdpDecoderCreate ( VdpDevice device
,
36 VdpDecoderProfile profile
,
37 uint32_t width
, uint32_t height
,
38 uint32_t max_references
,
42 struct vl_screen
*vscreen
;
43 enum pipe_video_profile p_profile
;
45 vlVdpDecoder
*vldecoder
;
47 debug_printf("[VDPAU] Creating decoder\n");
50 return VDP_STATUS_INVALID_POINTER
;
52 if (!(width
&& height
))
53 return VDP_STATUS_INVALID_VALUE
;
55 vlVdpDevice
*dev
= vlGetDataHTAB(device
);
57 ret
= VDP_STATUS_INVALID_HANDLE
;
61 vldecoder
= CALLOC(1,sizeof(vlVdpDecoder
));
63 ret
= VDP_STATUS_RESOURCES
;
67 p_profile
= ProfileToPipe(profile
);
68 if (p_profile
== PIPE_VIDEO_PROFILE_UNKNOWN
) {
69 ret
= VDP_STATUS_INVALID_DECODER_PROFILE
;
73 // TODO: Define max_references. Used mainly for H264
75 vldecoder
->profile
= p_profile
;
76 vldecoder
->device
= dev
;
78 *decoder
= vlAddDataHTAB(vldecoder
);
80 ret
= VDP_STATUS_ERROR
;
83 debug_printf("[VDPAU] Decoder created succesfully\n");
97 vlVdpDecoderDestroy (VdpDecoder decoder
100 vlVdpDecoder
*vldecoder
;
102 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
104 return VDP_STATUS_INVALID_HANDLE
;
107 if (vldecoder
->vctx
->vscreen
)
108 vl_screen_destroy(vldecoder
->vctx
->vscreen
);
111 vl_video_destroy(vldecoder
->vctx
);
115 return VDP_STATUS_OK
;
119 vlVdpCreateSurfaceTarget (vlVdpDecoder
*vldecoder
,
123 struct pipe_resource tmplt
;
124 struct pipe_resource
*surf_tex
;
125 struct pipe_video_context
*vpipe
;
127 if(!(vldecoder
&& vlsurf
))
128 return VDP_STATUS_INVALID_POINTER
;
130 vpipe
= vldecoder
->vctx
;
132 memset(&tmplt
, 0, sizeof(struct pipe_resource
));
133 tmplt
.target
= PIPE_TEXTURE_2D
;
134 tmplt
.format
= vlsurf
->format
;
135 tmplt
.last_level
= 0;
136 if (vpipe
->is_format_supported(vpipe
, tmplt
.format
,
137 PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
,
138 PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
)) {
139 tmplt
.width0
= vlsurf
->width
;
140 tmplt
.height0
= vlsurf
->height
;
143 assert(vpipe
->is_format_supported(vpipe
, tmplt
.format
,
144 PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
,
145 PIPE_TEXTURE_GEOM_NON_SQUARE
));
146 tmplt
.width0
= util_next_power_of_two(vlsurf
->width
);
147 tmplt
.height0
= util_next_power_of_two(vlsurf
->height
);
150 tmplt
.usage
= PIPE_USAGE_DEFAULT
;
151 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
154 surf_tex
= vpipe
->screen
->resource_create(vpipe
->screen
, &tmplt
);
156 vlsurf
->psurface
= vpipe
->screen
->get_tex_surface(vpipe
->screen
, surf_tex
, 0, 0, 0,
157 PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
);
159 pipe_resource_reference(&surf_tex
, NULL
);
161 if (!vlsurf
->psurface
)
162 return VDP_STATUS_RESOURCES
;
165 return VDP_STATUS_OK
;
169 vlVdpBitstreamToMacroblocks(struct pipe_screen
*screen
,
170 VdpBitstreamBuffer
const *bitstream_buffers
,
171 unsigned int num_macroblocks
,
172 struct pipe_mpeg12_macroblock
*pipe_macroblocks
)
174 debug_printf("NAF!\n");
178 vlVdpDecoderRenderMpeg2 (vlVdpDecoder
*vldecoder
,
179 vlVdpSurface
*vlsurf
,
180 VdpPictureInfoMPEG1Or2
*picture_info
,
181 uint32_t bitstream_buffer_count
,
182 VdpBitstreamBuffer
const *bitstream_buffers
185 struct pipe_video_context
*vpipe
;
186 vlVdpSurface
*t_vdp_surf
;
187 vlVdpSurface
*p_vdp_surf
;
188 vlVdpSurface
*f_vdp_surf
;
189 struct pipe_surface
*t_surf
;
190 struct pipe_surface
*p_surf
;
191 struct pipe_surface
*f_surf
;
192 uint32_t num_macroblocks
;
196 vpipe
= vldecoder
->vctx
->vpipe
;
199 /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
200 if (picture_info
->backward_reference
== VDP_INVALID_HANDLE
)
203 p_vdp_surf
= (vlVdpSurface
*)vlGetDataHTAB(picture_info
->backward_reference
);
205 return VDP_STATUS_INVALID_HANDLE
;
208 if (picture_info
->forward_reference
== VDP_INVALID_HANDLE
)
211 f_vdp_surf
= (vlVdpSurface
*)vlGetDataHTAB(picture_info
->forward_reference
);
213 return VDP_STATUS_INVALID_HANDLE
;
217 if (f_vdp_surf
== VDP_INVALID_HANDLE
) f_vdp_surf
= NULL
;
219 ret
= vlVdpCreateSurfaceTarget(vldecoder
,t_vdp_surf
);
221 num_macroblocks
= bitstream_buffer_count
;
222 struct pipe_mpeg12_macroblock pipe_macroblocks
[num_macroblocks
];
224 vlVdpBitstreamToMacroblocks(vpipe
->screen
, bitstream_buffers
,
225 num_macroblocks
, pipe_macroblocks
);
227 vpipe
->set_decode_target(vpipe
,t_surf
);
228 vpipe
->decode_macroblocks(vpipe
, p_surf
, f_surf
, num_macroblocks
, &pipe_macroblocks
->base
, NULL
);
233 vlVdpDecoderRender (VdpDecoder decoder
,
234 VdpVideoSurface target
,
235 VdpPictureInfo
const *picture_info
,
236 uint32_t bitstream_buffer_count
,
237 VdpBitstreamBuffer
const *bitstream_buffers
240 vlVdpDecoder
*vldecoder
;
241 vlVdpSurface
*vlsurf
;
242 struct vl_screen
*vscreen
;
244 debug_printf("[VDPAU] Decoding\n");
246 if (!(picture_info
&& bitstream_buffers
))
247 return VDP_STATUS_INVALID_POINTER
;
250 vldecoder
= (vlVdpDecoder
*)vlGetDataHTAB(decoder
);
252 return VDP_STATUS_INVALID_HANDLE
;
254 vlsurf
= (vlVdpSurface
*)vlGetDataHTAB(target
);
256 return VDP_STATUS_INVALID_HANDLE
;
258 if (vlsurf
->device
!= vldecoder
->device
)
259 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
261 if (vlsurf
->chroma_format
!= vldecoder
->chroma_format
)
262 return VDP_STATUS_INVALID_CHROMA_TYPE
;
264 vscreen
= vl_screen_create(vldecoder
->device
->display
, vldecoder
->device
->screen
);
266 return VDP_STATUS_RESOURCES
;
268 vldecoder
->vctx
= vl_video_create(vscreen
, vldecoder
->profile
, vlsurf
->format
, vlsurf
->width
, vlsurf
->height
);
269 if (!vldecoder
->vctx
)
270 return VDP_STATUS_RESOURCES
;
272 vldecoder
->vctx
->vscreen
= vscreen
;
274 // TODO: Right now only mpeg2 is supported.
275 switch (vldecoder
->vctx
->vpipe
->profile
) {
276 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE
:
277 case PIPE_VIDEO_PROFILE_MPEG2_MAIN
:
278 ret
= vlVdpDecoderRenderMpeg2(vldecoder
,vlsurf
,(VdpPictureInfoMPEG1Or2
*)picture_info
,
279 bitstream_buffer_count
,bitstream_buffers
);
282 return VDP_STATUS_INVALID_DECODER_PROFILE
;