decode.c revision 65fe0866aec7b5608419f6d184cb1fa4fe1dc45a
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 "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>
34
35VdpStatus
36vlVdpDecoderCreate ( 	VdpDevice device,
37						VdpDecoderProfile profile,
38						uint32_t width, uint32_t height,
39						uint32_t max_references,
40						VdpDecoder *decoder
41)
42{
43	struct vl_screen *vscreen;
44	enum pipe_video_profile p_profile;
45	VdpStatus ret;
46	vlVdpDecoder *vldecoder;
47
48	debug_printf("[VDPAU] Creating decoder\n");
49
50	if (!decoder)
51		return VDP_STATUS_INVALID_POINTER;
52
53	if (!(width && height))
54		return VDP_STATUS_INVALID_VALUE;
55
56   vlVdpDevice *dev = vlGetDataHTAB(device);
57   if (!dev)  {
58      ret = VDP_STATUS_INVALID_HANDLE;
59      goto inv_device;
60   }
61
62   vldecoder = CALLOC(1,sizeof(vlVdpDecoder));
63   if (!vldecoder)   {
64	   ret = VDP_STATUS_RESOURCES;
65	   goto no_decoder;
66   }
67
68   p_profile = ProfileToPipe(profile);
69   if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN)	{
70	   ret = VDP_STATUS_INVALID_DECODER_PROFILE;
71	   goto inv_profile;
72   }
73
74	// TODO: Define max_references. Used mainly for H264
75
76	vldecoder->profile = p_profile;
77	vldecoder->device = dev;
78
79	*decoder = vlAddDataHTAB(vldecoder);
80	if (*decoder == 0) {
81      ret = VDP_STATUS_ERROR;
82      goto no_handle;
83	}
84	debug_printf("[VDPAU] Decoder created succesfully\n");
85
86	return VDP_STATUS_OK;
87
88	no_handle:
89	FREE(vldecoder);
90	inv_profile:
91	no_screen:
92	no_decoder:
93	inv_device:
94    return ret;
95}
96
97VdpStatus
98vlVdpDecoderDestroy  (VdpDecoder decoder
99)
100{
101	debug_printf("[VDPAU] Destroying decoder\n");
102	vlVdpDecoder *vldecoder;
103
104	vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
105	if (!vldecoder)  {
106      return VDP_STATUS_INVALID_HANDLE;
107	}
108
109	if (vldecoder->vctx)
110	{
111		if (vldecoder->vctx->vscreen)
112			vl_screen_destroy(vldecoder->vctx->vscreen);
113	}
114
115	if (vldecoder->vctx)
116		vl_video_destroy(vldecoder->vctx);
117
118	FREE(vldecoder);
119
120	return VDP_STATUS_OK;
121}
122
123VdpStatus
124vlVdpCreateSurfaceTarget   (vlVdpDecoder *vldecoder,
125							vlVdpSurface *vlsurf
126)
127{
128	struct pipe_resource tmplt;
129	struct pipe_resource *surf_tex;
130	struct pipe_video_context *vpipe;
131
132	debug_printf("[VDPAU] Creating surface\n");
133
134	if(!(vldecoder && vlsurf))
135		return VDP_STATUS_INVALID_POINTER;
136
137	vpipe = vldecoder->vctx;
138
139	memset(&tmplt, 0, sizeof(struct pipe_resource));
140	tmplt.target = PIPE_TEXTURE_2D;
141	tmplt.format = vlsurf->format;
142	tmplt.last_level = 0;
143	if (vpipe->is_format_supported(vpipe, tmplt.format,
144                                  PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
145                                  PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)) {
146      tmplt.width0 = vlsurf->width;
147      tmplt.height0 = vlsurf->height;
148    }
149    else {
150      assert(vpipe->is_format_supported(vpipe, tmplt.format,
151                                       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
152                                       PIPE_TEXTURE_GEOM_NON_SQUARE));
153      tmplt.width0 = util_next_power_of_two(vlsurf->width);
154      tmplt.height0 = util_next_power_of_two(vlsurf->height);
155    }
156	tmplt.depth0 = 1;
157	tmplt.usage = PIPE_USAGE_DEFAULT;
158	tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
159	tmplt.flags = 0;
160
161	surf_tex = vpipe->screen->resource_create(vpipe->screen, &tmplt);
162
163	vlsurf->psurface = vpipe->screen->get_tex_surface(vpipe->screen, surf_tex, 0, 0, 0,
164                                         PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET);
165
166	pipe_resource_reference(&surf_tex, NULL);
167
168	if (!vlsurf->psurface)
169		return VDP_STATUS_RESOURCES;
170
171
172	return VDP_STATUS_OK;
173}
174
175VdpStatus
176vlVdpDecoderRenderMpeg2    (vlVdpDecoder *vldecoder,
177							vlVdpSurface *vlsurf,
178							VdpPictureInfoMPEG1Or2 *picture_info,
179							uint32_t bitstream_buffer_count,
180							VdpBitstreamBuffer const *bitstream_buffers
181							)
182{
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;
192	VdpStatus ret;
193
194	debug_printf("[VDPAU] Decoding MPEG2\n");
195
196	vpipe = vldecoder->vctx->vpipe;
197	t_vdp_surf = vlsurf;
198
199	/* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
200	if (picture_info->backward_reference ==  VDP_INVALID_HANDLE)
201		p_vdp_surf = NULL;
202	else	{
203		p_vdp_surf = (vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference);
204		if (!p_vdp_surf)
205			return VDP_STATUS_INVALID_HANDLE;
206	}
207
208	if (picture_info->forward_reference ==  VDP_INVALID_HANDLE)
209		f_vdp_surf = NULL;
210	else	{
211		f_vdp_surf = (vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference);
212		if (!f_vdp_surf)
213			return VDP_STATUS_INVALID_HANDLE;
214	}
215
216
217	if (f_vdp_surf ==  VDP_INVALID_HANDLE) f_vdp_surf = NULL;
218
219	ret = vlVdpCreateSurfaceTarget(vldecoder,t_vdp_surf);
220
221	if (vlVdpMPEG2BitstreamToMacroblock(vpipe->screen, bitstream_buffers, bitstream_buffer_count,
222                     &num_macroblocks, &pipe_macroblocks))
223					 {
224						 debug_printf("[VDPAU] Error in frame-header. Skipping.\n");
225
226						 ret = VDP_STATUS_OK;
227						 goto skip_frame;
228					 }
229
230	vpipe->set_decode_target(vpipe,t_surf);
231	//vpipe->decode_macroblocks(vpipe, p_surf, f_surf, num_macroblocks, (struct pipe_macroblock *)pipe_macroblocks, NULL);
232
233	skip_frame:
234	return ret;
235}
236
237VdpStatus
238vlVdpDecoderRender (VdpDecoder decoder,
239					VdpVideoSurface target,
240					VdpPictureInfo const *picture_info,
241					uint32_t bitstream_buffer_count,
242					VdpBitstreamBuffer const *bitstream_buffers
243)
244{
245	vlVdpDecoder *vldecoder;
246	vlVdpSurface *vlsurf;
247	struct vl_screen *vscreen;
248	VdpStatus ret;
249	debug_printf("[VDPAU] Decoding\n");
250
251	if (!(picture_info && bitstream_buffers))
252		return VDP_STATUS_INVALID_POINTER;
253
254
255	vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
256	if (!vldecoder)
257		return VDP_STATUS_INVALID_HANDLE;
258
259	vlsurf = (vlVdpSurface *)vlGetDataHTAB(target);
260	if (!vlsurf)
261		return VDP_STATUS_INVALID_HANDLE;
262
263	if (vlsurf->device != vldecoder->device)
264		return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
265
266	if (vlsurf->chroma_format != vldecoder->chroma_format)
267		return VDP_STATUS_INVALID_CHROMA_TYPE;
268
269	vscreen = vl_screen_create(vldecoder->device->display, vldecoder->device->screen);
270	if (!vscreen)
271		return VDP_STATUS_RESOURCES;
272
273	vldecoder->vctx = vl_video_create(vscreen, vldecoder->profile, vlsurf->format, vlsurf->width, vlsurf->height);
274	if (!vldecoder->vctx)
275		return VDP_STATUS_RESOURCES;
276
277	vldecoder->vctx->vscreen = vscreen;
278
279    // TODO: Right now only mpeg2 is supported.
280	switch (vldecoder->vctx->vpipe->profile)   {
281		case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
282		case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
283			ret = vlVdpDecoderRenderMpeg2(vldecoder,vlsurf,(VdpPictureInfoMPEG1Or2 *)picture_info,
284											bitstream_buffer_count,bitstream_buffers);
285			break;
286		default:
287			return VDP_STATUS_INVALID_DECODER_PROFILE;
288	}
289	assert(0);
290
291	return ret;
292}
293
294VdpStatus
295vlVdpGenerateCSCMatrix(
296	VdpProcamp *procamp,
297	VdpColorStandard standard,
298	VdpCSCMatrix *csc_matrix)
299{
300	debug_printf("[VDPAU] Generating CSCMatrix\n");
301	if (!(csc_matrix && procamp))
302		return VDP_STATUS_INVALID_POINTER;
303
304	return VDP_STATUS_OK;
305}