decode.c revision d5b05a869a71147987a1c1d6c84f8df17148f031
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
242vlVdpDecoderRender(VdpDecoder decoder,
243                   VdpVideoSurface target,
244                   VdpPictureInfo const *picture_info,
245                   uint32_t bitstream_buffer_count,
246                   VdpBitstreamBuffer const *bitstream_buffers)
247{
248   return VDP_STATUS_NO_IMPLEMENTATION;
249
250#if 0
251   vlVdpDecoder *vldecoder;
252   vlVdpSurface *vlsurf;
253   struct vl_screen *vscreen;
254   VdpStatus ret;
255
256   debug_printf("[VDPAU] Decoding\n");
257
258   if (!(picture_info && bitstream_buffers))
259      return VDP_STATUS_INVALID_POINTER;
260
261   vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
262   if (!vldecoder)
263      return VDP_STATUS_INVALID_HANDLE;
264
265   vlsurf = (vlVdpSurface *)vlGetDataHTAB(target);
266   if (!vlsurf)
267      return VDP_STATUS_INVALID_HANDLE;
268
269   if (vlsurf->device != vldecoder->device)
270      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
271
272   /* Test doesn't make sence */
273   /*if (vlsurf->chroma_format != vldecoder->chroma_format)
274   return VDP_STATUS_INVALID_CHROMA_TYPE;*/
275
276   vscreen = vl_screen_create(vldecoder->device->display, vldecoder->device->screen);
277   if (!vscreen)
278      return VDP_STATUS_RESOURCES;
279
280   vldecoder->vctx = vl_video_create(vscreen, vldecoder->profile, vlsurf->chroma_format, vldecoder->width, vldecoder->height);
281   if (!vldecoder->vctx)
282      return VDP_STATUS_RESOURCES;
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#endif
298}
299
300VdpStatus
301vlVdpGenerateCSCMatrix(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}
311