decode.c revision 38bd8131776879e9dc90d06848657756a4a13a66
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   return VDP_STATUS_NO_IMPLEMENTATION;
43
44#if 0
45   enum pipe_video_profile p_profile = PIPE_VIDEO_PROFILE_UNKNOWN;
46   VdpStatus ret = VDP_STATUS_OK;
47   vlVdpDecoder *vldecoder = NULL;
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   vlVdpDevice *dev = vlGetDataHTAB(device);
58   if (!dev) {
59      ret = VDP_STATUS_INVALID_HANDLE;
60      goto inv_device;
61   }
62
63   vldecoder = CALLOC(1,sizeof(vlVdpDecoder));
64   if (!vldecoder) {
65      ret = VDP_STATUS_RESOURCES;
66      goto no_decoder;
67   }
68
69   p_profile = ProfileToPipe(profile);
70   if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN)	{
71      ret = VDP_STATUS_INVALID_DECODER_PROFILE;
72      goto inv_profile;
73   }
74
75   // TODO: Define max_references. Used mainly for H264
76
77   vldecoder->profile = p_profile;
78   vldecoder->height = height;
79   vldecoder->width = width;
80   vldecoder->device = dev;
81   vldecoder->vctx = NULL;
82
83   *decoder = vlAddDataHTAB(vldecoder);
84   if (*decoder == 0) {
85      ret = VDP_STATUS_ERROR;
86      goto no_handle;
87   }
88   debug_printf("[VDPAU] Decoder created succesfully\n");
89
90   return VDP_STATUS_OK;
91
92no_handle:
93   FREE(vldecoder);
94   inv_profile:
95no_screen:
96no_decoder:
97inv_device:
98    return ret;
99#endif
100}
101
102VdpStatus
103vlVdpDecoderDestroy(VdpDecoder decoder)
104{
105   return VDP_STATUS_NO_IMPLEMENTATION;
106
107#if 0
108   debug_printf("[VDPAU] Destroying decoder\n");
109   vlVdpDecoder *vldecoder;
110
111   vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
112   if (!vldecoder) {
113      return VDP_STATUS_INVALID_HANDLE;
114   }
115
116   if (vldecoder->vctx) {
117      if (vldecoder->vctx->vscreen)
118         vl_screen_destroy(vldecoder->vctx->vscreen);
119   }
120
121   if (vldecoder->vctx)
122       vl_video_destroy(vldecoder->vctx);
123
124   FREE(vldecoder);
125
126   return VDP_STATUS_OK;
127#endif
128}
129
130#if 0
131VdpStatus
132vlVdpCreateSurfaceTarget(vlVdpDecoder *vldecoder, vlVdpSurface *vlsurf)
133{
134   struct pipe_surface surf_template;
135   struct pipe_resource tmplt;
136   struct pipe_resource *surf_tex;
137   struct pipe_video_context *vctx;
138
139   debug_printf("[VDPAU] Creating surface\n");
140
141   if(!(vldecoder && vlsurf))
142      return VDP_STATUS_INVALID_POINTER;
143
144   vctx = vldecoder->vctx->vpipe;
145
146   if (!vctx->is_format_supported(vctx, tmplt.format, PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET))
147      return VDP_STATUS_RESOURCES;
148
149   memset(&tmplt, 0, sizeof(struct pipe_resource));
150   tmplt.target = PIPE_TEXTURE_2D;
151   // TODO
152   //tmplt.format = vctx->get_param(vctx,PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT);
153   tmplt.last_level = 0;
154   tmplt.width0 = vlsurf->width;
155   tmplt.height0 = vlsurf->height;
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 = vctx->screen->resource_create(vctx->screen, &tmplt);
162
163   memset(&surf_template, 0, sizeof(surf_template));
164   surf_template.format = surf_tex->format;
165   surf_template.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
166   //vlsurf->psurface = vctx->create_surface(vctx->screen, surf_tex, &surf_template);
167
168   pipe_resource_reference(&surf_tex, NULL);
169
170   //if (!vlsurf->psurface)
171   //   return VDP_STATUS_RESOURCES;
172   debug_printf("[VDPAU] Done creating surface\n");
173
174   return VDP_STATUS_OK;
175}
176
177VdpStatus
178vlVdpDecoderRenderMpeg2(vlVdpDecoder *vldecoder,
179                        vlVdpSurface *vlsurf,
180                        VdpPictureInfoMPEG1Or2 *picture_info,
181                        uint32_t bitstream_buffer_count,
182                        VdpBitstreamBuffer const *bitstream_buffers)
183{
184   struct pipe_video_context *vpipe;
185   vlVdpSurface *t_vdp_surf;
186   vlVdpSurface *p_vdp_surf;
187   vlVdpSurface *f_vdp_surf;
188   struct pipe_surface *t_surf;
189   struct pipe_surface *p_surf;
190   struct pipe_surface *f_surf;
191   uint32_t num_macroblocks;
192   struct pipe_mpeg12_macroblock *pipe_macroblocks;
193   VdpStatus ret;
194
195   debug_printf("[VDPAU] Decoding MPEG2\n");
196
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   if (f_vdp_surf ==  VDP_INVALID_HANDLE) f_vdp_surf = NULL;
217
218   ret = vlVdpCreateSurfaceTarget(vldecoder,t_vdp_surf);
219
220   vpipe = vldecoder->vctx->vpipe;
221
222   if (vlVdpMPEG2BitstreamToMacroblock(vpipe->screen, bitstream_buffers, bitstream_buffer_count,
223                                       &num_macroblocks, &pipe_macroblocks))
224   {
225      debug_printf("[VDPAU] Error in frame-header. Skipping.\n");
226
227      ret = VDP_STATUS_OK;
228      goto skip_frame;
229   }
230
231   // TODO
232   //vpipe->set_decode_target(vpipe,t_surf);
233   //vpipe->decode_macroblocks(vpipe, p_surf, f_surf, num_macroblocks,
234   //                          (struct pipe_macroblock *)pipe_macroblocks, NULL);
235
236   skip_frame:
237   return ret;
238}
239#endif
240
241VdpStatus
242vlVdpDecoderGetParameters(VdpDecoder decoder,
243                          VdpDecoderProfile *profile,
244                          uint32_t *width,
245                          uint32_t *height)
246{
247   return VDP_STATUS_NO_IMPLEMENTATION;
248}
249
250VdpStatus
251vlVdpDecoderRender(VdpDecoder decoder,
252                   VdpVideoSurface target,
253                   VdpPictureInfo const *picture_info,
254                   uint32_t bitstream_buffer_count,
255                   VdpBitstreamBuffer const *bitstream_buffers)
256{
257   return VDP_STATUS_NO_IMPLEMENTATION;
258
259#if 0
260   vlVdpDecoder *vldecoder;
261   vlVdpSurface *vlsurf;
262   struct vl_screen *vscreen;
263   VdpStatus ret;
264
265   debug_printf("[VDPAU] Decoding\n");
266
267   if (!(picture_info && bitstream_buffers))
268      return VDP_STATUS_INVALID_POINTER;
269
270   vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
271   if (!vldecoder)
272      return VDP_STATUS_INVALID_HANDLE;
273
274   vlsurf = (vlVdpSurface *)vlGetDataHTAB(target);
275   if (!vlsurf)
276      return VDP_STATUS_INVALID_HANDLE;
277
278   if (vlsurf->device != vldecoder->device)
279      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
280
281   /* Test doesn't make sence */
282   /*if (vlsurf->chroma_format != vldecoder->chroma_format)
283   return VDP_STATUS_INVALID_CHROMA_TYPE;*/
284
285   vscreen = vl_screen_create(vldecoder->device->display, vldecoder->device->screen);
286   if (!vscreen)
287      return VDP_STATUS_RESOURCES;
288
289   vldecoder->vctx = vl_video_create(vscreen, vldecoder->profile, vlsurf->chroma_format, vldecoder->width, vldecoder->height);
290   if (!vldecoder->vctx)
291      return VDP_STATUS_RESOURCES;
292
293   // TODO: Right now only mpeg2 is supported.
294   switch (vldecoder->vctx->vpipe->profile)   {
295   case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
296   case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
297      ret = vlVdpDecoderRenderMpeg2(vldecoder,vlsurf,(VdpPictureInfoMPEG1Or2 *)picture_info,
298                                    bitstream_buffer_count,bitstream_buffers);
299      break;
300   default:
301      return VDP_STATUS_INVALID_DECODER_PROFILE;
302   }
303   assert(0);
304
305   return ret;
306#endif
307}
308
309VdpStatus
310vlVdpGenerateCSCMatrix(VdpProcamp *procamp,
311                       VdpColorStandard standard,
312                       VdpCSCMatrix *csc_matrix)
313{
314   debug_printf("[VDPAU] Generating CSCMatrix\n");
315   if (!(csc_matrix && procamp))
316      return VDP_STATUS_INVALID_POINTER;
317
318   return VDP_STATUS_OK;
319}
320