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