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