~ubuntu-branches/ubuntu/precise/gst-plugins-bad0.10/precise-proposed

« back to all changes in this revision

Viewing changes to sys/vdpau/gstvdpvideoyuv.c

Tags: upstream-0.10.17.2
Import upstream version 0.10.17.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * GStreamer
3
 
 * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
4
 
 *
5
 
 * This library is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU Library General Public
7
 
 * License as published by the Free Software Foundation; either
8
 
 * version 2 of the License, or (at your option) any later version.
9
 
 *
10
 
 * This library is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 
 * Library General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU Library General Public
16
 
 * License along with this library; if not, write to the
17
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
 
 * Boston, MA 02111-1307, USA.
19
 
 */
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
#include "config.h"
23
 
#endif
24
 
 
25
 
#include <gst/gst.h>
26
 
#include <gst/video/video.h>
27
 
 
28
 
#include "gstvdpvideobuffer.h"
29
 
#include "gstvdputils.h"
30
 
#include "gstvdpvideoyuv.h"
31
 
 
32
 
GST_DEBUG_CATEGORY_STATIC (gst_vdp_video_yuv_debug);
33
 
#define GST_CAT_DEFAULT gst_vdp_video_yuv_debug
34
 
 
35
 
/* Filter signals and args */
36
 
enum
37
 
{
38
 
  /* FILL ME */
39
 
  LAST_SIGNAL
40
 
};
41
 
 
42
 
enum
43
 
{
44
 
  PROP_0,
45
 
  PROP_DISPLAY
46
 
};
47
 
 
48
 
static GstStaticPadTemplate sink_template =
49
 
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SINK_NAME,
50
 
    GST_PAD_SINK,
51
 
    GST_PAD_ALWAYS,
52
 
    GST_STATIC_CAPS (GST_VDP_VIDEO_CAPS));
53
 
 
54
 
static GstStaticPadTemplate src_template =
55
 
    GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME,
56
 
    GST_PAD_SRC,
57
 
    GST_PAD_ALWAYS,
58
 
    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";"
59
 
        GST_VIDEO_CAPS_YUV ("YV12") ";" GST_VIDEO_CAPS_YUV ("NV12") ";"
60
 
        GST_VIDEO_CAPS_YUV ("UYVY") ";" GST_VIDEO_CAPS_YUV ("YUY2")));
61
 
 
62
 
#define DEBUG_INIT(bla) \
63
 
    GST_DEBUG_CATEGORY_INIT (gst_vdp_video_yuv_debug, "vdpauvideoyuv", 0, "VDPAU VdpSurface to YUV");
64
 
 
65
 
GST_BOILERPLATE_FULL (GstVdpVideoYUV, gst_vdp_video_yuv, GstBaseTransform,
66
 
    GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
67
 
 
68
 
GstFlowReturn
69
 
gst_vdp_video_yuv_transform (GstBaseTransform * trans, GstBuffer * inbuf,
70
 
    GstBuffer * outbuf)
71
 
{
72
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans);
73
 
  GstVdpDevice *device;
74
 
  VdpVideoSurface surface;
75
 
 
76
 
  device = GST_VDP_VIDEO_BUFFER (inbuf)->device;
77
 
  surface = GST_VDP_VIDEO_BUFFER (inbuf)->surface;
78
 
 
79
 
  switch (video_yuv->format) {
80
 
    case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
81
 
    {
82
 
      VdpStatus status;
83
 
      guint8 *data[3];
84
 
      guint32 stride[3];
85
 
 
86
 
      data[0] = GST_BUFFER_DATA (outbuf) +
87
 
          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
88
 
          0, video_yuv->width, video_yuv->height);
89
 
      data[1] = GST_BUFFER_DATA (outbuf) +
90
 
          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
91
 
          2, video_yuv->width, video_yuv->height);
92
 
      data[2] = GST_BUFFER_DATA (outbuf) +
93
 
          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12,
94
 
          1, video_yuv->width, video_yuv->height);
95
 
 
96
 
      stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12,
97
 
          0, video_yuv->width);
98
 
      stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12,
99
 
          2, video_yuv->width);
100
 
      stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12,
101
 
          1, video_yuv->width);
102
 
 
103
 
      GST_LOG_OBJECT (video_yuv, "Entering vdp_video_surface_get_bits_ycbcr");
104
 
      status =
105
 
          device->vdp_video_surface_get_bits_ycbcr (surface,
106
 
          VDP_YCBCR_FORMAT_YV12, (void *) data, stride);
107
 
      GST_LOG_OBJECT (video_yuv,
108
 
          "Got status %d from vdp_video_surface_get_bits_ycbcr", status);
109
 
      if (G_UNLIKELY (status != VDP_STATUS_OK)) {
110
 
        GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ,
111
 
            ("Couldn't get data from vdpau"),
112
 
            ("Error returned from vdpau was: %s",
113
 
                device->vdp_get_error_string (status)));
114
 
        return GST_FLOW_ERROR;
115
 
      }
116
 
      break;
117
 
    }
118
 
    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
119
 
    {
120
 
      VdpStatus status;
121
 
      guint8 *data[3];
122
 
      guint32 stride[3];
123
 
 
124
 
      data[0] = GST_BUFFER_DATA (outbuf) +
125
 
          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
126
 
          0, video_yuv->width, video_yuv->height);
127
 
      data[1] = GST_BUFFER_DATA (outbuf) +
128
 
          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
129
 
          2, video_yuv->width, video_yuv->height);
130
 
      data[2] = GST_BUFFER_DATA (outbuf) +
131
 
          gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420,
132
 
          1, video_yuv->width, video_yuv->height);
133
 
 
134
 
      stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420,
135
 
          0, video_yuv->width);
136
 
      stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420,
137
 
          2, video_yuv->width);
138
 
      stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420,
139
 
          1, video_yuv->width);
140
 
 
141
 
      GST_LOG_OBJECT (video_yuv, "Entering vdp_video_surface_get_bits_ycbcr");
142
 
      status =
143
 
          device->vdp_video_surface_get_bits_ycbcr (surface,
144
 
          VDP_YCBCR_FORMAT_YV12, (void *) data, stride);
145
 
      GST_LOG_OBJECT (video_yuv,
146
 
          "Got status %d from vdp_video_surface_get_bits_ycbcr", status);
147
 
      if (G_UNLIKELY (status != VDP_STATUS_OK)) {
148
 
        GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ,
149
 
            ("Couldn't get data from vdpau"),
150
 
            ("Error returned from vdpau was: %s",
151
 
                device->vdp_get_error_string (status)));
152
 
        return GST_FLOW_ERROR;
153
 
      }
154
 
      break;
155
 
    }
156
 
    case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
157
 
    {
158
 
      VdpStatus status;
159
 
      guint8 *data[2];
160
 
      guint32 stride[2];
161
 
 
162
 
      data[0] = GST_BUFFER_DATA (outbuf);
163
 
      data[1] = GST_BUFFER_DATA (outbuf) + video_yuv->width * video_yuv->height;
164
 
 
165
 
      stride[0] = video_yuv->width;
166
 
      stride[1] = video_yuv->width;
167
 
 
168
 
      GST_LOG_OBJECT (video_yuv, "Entering vdp_video_surface_get_bits_ycbcr");
169
 
      status =
170
 
          device->vdp_video_surface_get_bits_ycbcr (surface,
171
 
          VDP_YCBCR_FORMAT_NV12, (void *) data, stride);
172
 
      GST_LOG_OBJECT (video_yuv,
173
 
          "Got status %d from vdp_video_surface_get_bits_ycbcr", status);
174
 
      if (G_UNLIKELY (status != VDP_STATUS_OK)) {
175
 
        GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ,
176
 
            ("Couldn't get data from vdpau"),
177
 
            ("Error returned from vdpau was: %s",
178
 
                device->vdp_get_error_string (status)));
179
 
        return GST_FLOW_ERROR;
180
 
      }
181
 
      break;
182
 
    }
183
 
    case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
184
 
    {
185
 
      VdpStatus status;
186
 
      guint8 *data[1];
187
 
      guint32 stride[1];
188
 
 
189
 
      data[0] = GST_BUFFER_DATA (outbuf);
190
 
 
191
 
      stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_UYVY,
192
 
          0, video_yuv->width);
193
 
 
194
 
      GST_LOG_OBJECT (video_yuv, "Entering vdp_video_surface_get_bits_ycbcr");
195
 
      status =
196
 
          device->vdp_video_surface_get_bits_ycbcr (surface,
197
 
          VDP_YCBCR_FORMAT_UYVY, (void *) data, stride);
198
 
      GST_LOG_OBJECT (video_yuv,
199
 
          "Got status %d from vdp_video_surface_get_bits_ycbcr", status);
200
 
      if (G_UNLIKELY (status != VDP_STATUS_OK)) {
201
 
        GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ,
202
 
            ("Couldn't get data from vdpau"),
203
 
            ("Error returned from vdpau was: %s",
204
 
                device->vdp_get_error_string (status)));
205
 
        return GST_FLOW_ERROR;
206
 
      }
207
 
      break;
208
 
    }
209
 
    case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
210
 
    {
211
 
      VdpStatus status;
212
 
      guint8 *data[1];
213
 
      guint32 stride[1];
214
 
 
215
 
      data[0] = GST_BUFFER_DATA (outbuf);
216
 
 
217
 
      stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YUY2,
218
 
          0, video_yuv->width);
219
 
 
220
 
      GST_LOG_OBJECT (video_yuv, "Entering vdp_video_surface_get_bits_ycbcr");
221
 
      status =
222
 
          device->vdp_video_surface_get_bits_ycbcr (surface,
223
 
          VDP_YCBCR_FORMAT_YUYV, (void *) data, stride);
224
 
      GST_LOG_OBJECT (video_yuv,
225
 
          "Got status %d from vdp_video_surface_get_bits_ycbcr", status);
226
 
      if (G_UNLIKELY (status != VDP_STATUS_OK)) {
227
 
        GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ,
228
 
            ("Couldn't get data from vdpau"),
229
 
            ("Error returned from vdpau was: %s",
230
 
                device->vdp_get_error_string (status)));
231
 
        return GST_FLOW_ERROR;
232
 
      }
233
 
      break;
234
 
    }
235
 
    default:
236
 
      break;
237
 
  }
238
 
 
239
 
  gst_buffer_copy_metadata (outbuf, inbuf,
240
 
      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
241
 
 
242
 
  GST_LOG_OBJECT (video_yuv, "Pushing buffer with ts %" GST_TIME_FORMAT,
243
 
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
244
 
 
245
 
  return GST_FLOW_OK;
246
 
}
247
 
 
248
 
gboolean
249
 
gst_vdp_video_transform_size (GstBaseTransform * trans,
250
 
    GstPadDirection direction, GstCaps * caps, guint size,
251
 
    GstCaps * othercaps, guint * othersize)
252
 
{
253
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans);
254
 
 
255
 
  if (direction == GST_PAD_SINK) {
256
 
    switch (video_yuv->format) {
257
 
      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
258
 
      {
259
 
        *othersize =
260
 
            gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width,
261
 
            video_yuv->height);
262
 
        break;
263
 
      }
264
 
      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
265
 
      {
266
 
        *othersize =
267
 
            gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width,
268
 
            video_yuv->height);
269
 
        break;
270
 
      }
271
 
      case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
272
 
      {
273
 
        *othersize =
274
 
            video_yuv->width * video_yuv->height +
275
 
            video_yuv->width * video_yuv->height / 2;
276
 
        break;
277
 
      }
278
 
      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
279
 
      {
280
 
        *othersize =
281
 
            gst_video_format_get_size (GST_VIDEO_FORMAT_UYVY, video_yuv->width,
282
 
            video_yuv->height);
283
 
        break;
284
 
      }
285
 
      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
286
 
      {
287
 
        *othersize =
288
 
            gst_video_format_get_size (GST_VIDEO_FORMAT_YUY2, video_yuv->width,
289
 
            video_yuv->height);
290
 
        break;
291
 
      }
292
 
      default:
293
 
        return FALSE;
294
 
    }
295
 
  } else
296
 
    *othersize = size;
297
 
 
298
 
  return TRUE;
299
 
}
300
 
 
301
 
gboolean
302
 
gst_vdp_video_yuv_set_caps (GstBaseTransform * trans, GstCaps * incaps,
303
 
    GstCaps * outcaps)
304
 
{
305
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans);
306
 
  GstStructure *structure;
307
 
 
308
 
  structure = gst_caps_get_structure (incaps, 0);
309
 
 
310
 
  if (!gst_structure_get_int (structure, "width", &video_yuv->width))
311
 
    return FALSE;
312
 
  if (!gst_structure_get_int (structure, "height", &video_yuv->height))
313
 
    return FALSE;
314
 
 
315
 
  structure = gst_caps_get_structure (outcaps, 0);
316
 
  if (!gst_structure_get_fourcc (structure, "format", &video_yuv->format))
317
 
    return FALSE;
318
 
 
319
 
  return TRUE;
320
 
}
321
 
 
322
 
GstCaps *
323
 
gst_vdp_video_yuv_transform_caps (GstBaseTransform * trans,
324
 
    GstPadDirection direction, GstCaps * caps)
325
 
{
326
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans);
327
 
  GstCaps *result = NULL;
328
 
 
329
 
  if (direction == GST_PAD_SINK)
330
 
    result = gst_vdp_video_to_yuv_caps (caps, video_yuv->device);
331
 
 
332
 
  else if (direction == GST_PAD_SRC)
333
 
    result = gst_vdp_yuv_to_video_caps (caps, video_yuv->device);
334
 
 
335
 
  GST_LOG ("transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, result);
336
 
 
337
 
  return result;
338
 
}
339
 
 
340
 
static gboolean
341
 
gst_vdp_video_yuv_start (GstBaseTransform * trans)
342
 
{
343
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans);
344
 
 
345
 
  video_yuv->device = gst_vdp_get_device (video_yuv->display);
346
 
  if (!video_yuv->device)
347
 
    return FALSE;
348
 
 
349
 
  return TRUE;
350
 
}
351
 
 
352
 
static gboolean
353
 
gst_vdp_video_yuv_stop (GstBaseTransform * trans)
354
 
{
355
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans);
356
 
 
357
 
  g_object_unref (video_yuv->device);
358
 
 
359
 
  return TRUE;
360
 
}
361
 
 
362
 
static GstFlowReturn
363
 
gst_vdp_video_yuv_buffer_alloc (GstPad * pad, guint64 offset,
364
 
    guint size, GstCaps * caps, GstBuffer ** buf)
365
 
{
366
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (gst_pad_get_parent (pad));
367
 
  GstFlowReturn ret = GST_FLOW_ERROR;
368
 
  GstStructure *structure;
369
 
  gint width, height;
370
 
  gint chroma_type;
371
 
 
372
 
  structure = gst_caps_get_structure (caps, 0);
373
 
  if (!structure)
374
 
    goto error;
375
 
 
376
 
  if (!gst_structure_get_int (structure, "width", &width))
377
 
    goto error;
378
 
  if (!gst_structure_get_int (structure, "height", &height))
379
 
    goto error;
380
 
 
381
 
  if (!gst_structure_get_int (structure, "chroma-type", &chroma_type))
382
 
    goto error;
383
 
 
384
 
  *buf = GST_BUFFER (gst_vdp_video_buffer_new (video_yuv->device,
385
 
          chroma_type, width, height));
386
 
 
387
 
  if (*buf == NULL)
388
 
    goto error;
389
 
 
390
 
  GST_BUFFER_SIZE (*buf) = size;
391
 
  GST_BUFFER_OFFSET (*buf) = offset;
392
 
 
393
 
  gst_buffer_set_caps (*buf, caps);
394
 
 
395
 
  ret = GST_FLOW_OK;
396
 
 
397
 
error:
398
 
  gst_object_unref (video_yuv);
399
 
  return ret;
400
 
}
401
 
 
402
 
/* GObject vmethod implementations */
403
 
 
404
 
static void
405
 
gst_vdp_video_yuv_base_init (gpointer klass)
406
 
{
407
 
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
408
 
 
409
 
  gst_element_class_set_details_simple (element_class,
410
 
      "VdpauVideoYUV",
411
 
      "Filter/Converter/Decoder/Video",
412
 
      "VDPAU video surface to YUV",
413
 
      "Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>");
414
 
 
415
 
  gst_element_class_add_pad_template (element_class,
416
 
      gst_static_pad_template_get (&sink_template));
417
 
  gst_element_class_add_pad_template (element_class,
418
 
      gst_static_pad_template_get (&src_template));
419
 
}
420
 
 
421
 
static void
422
 
gst_vdp_video_yuv_finalize (GObject * object)
423
 
{
424
 
  GstVdpVideoYUV *video_yuv = (GstVdpVideoYUV *) object;
425
 
 
426
 
  g_free (video_yuv->display);
427
 
}
428
 
 
429
 
static void
430
 
gst_vdp_video_yuv_set_property (GObject * object, guint prop_id,
431
 
    const GValue * value, GParamSpec * pspec)
432
 
{
433
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (object);
434
 
 
435
 
  switch (prop_id) {
436
 
    case PROP_DISPLAY:
437
 
      g_free (video_yuv->display);
438
 
      video_yuv->display = g_value_dup_string (value);
439
 
      break;
440
 
    default:
441
 
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
442
 
      break;
443
 
  }
444
 
}
445
 
 
446
 
static void
447
 
gst_vdp_video_yuv_get_property (GObject * object, guint prop_id,
448
 
    GValue * value, GParamSpec * pspec)
449
 
{
450
 
  GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (object);
451
 
 
452
 
  switch (prop_id) {
453
 
    case PROP_DISPLAY:
454
 
      g_value_set_string (value, video_yuv->display);
455
 
      break;
456
 
    default:
457
 
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
458
 
      break;
459
 
  }
460
 
}
461
 
 
462
 
static void
463
 
gst_vdp_video_yuv_class_init (GstVdpVideoYUVClass * klass)
464
 
{
465
 
  GObjectClass *gobject_class;
466
 
  GstBaseTransformClass *trans_class;
467
 
 
468
 
  gobject_class = (GObjectClass *) klass;
469
 
  trans_class = (GstBaseTransformClass *) klass;
470
 
 
471
 
  gobject_class->finalize = gst_vdp_video_yuv_finalize;
472
 
  gobject_class->set_property = gst_vdp_video_yuv_set_property;
473
 
  gobject_class->get_property = gst_vdp_video_yuv_get_property;
474
 
 
475
 
  g_object_class_install_property (gobject_class, PROP_DISPLAY,
476
 
      g_param_spec_string ("display", "Display", "X Display name",
477
 
          NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
478
 
 
479
 
  trans_class->start = gst_vdp_video_yuv_start;
480
 
  trans_class->stop = gst_vdp_video_yuv_stop;
481
 
  trans_class->transform_caps = gst_vdp_video_yuv_transform_caps;
482
 
  trans_class->transform_size = gst_vdp_video_transform_size;
483
 
  trans_class->transform = gst_vdp_video_yuv_transform;
484
 
  trans_class->set_caps = gst_vdp_video_yuv_set_caps;
485
 
}
486
 
 
487
 
static void
488
 
gst_vdp_video_yuv_init (GstVdpVideoYUV * video_yuv, GstVdpVideoYUVClass * klass)
489
 
{
490
 
  video_yuv->display = NULL;
491
 
 
492
 
  gst_pad_set_bufferalloc_function (GST_BASE_TRANSFORM_SINK_PAD (video_yuv),
493
 
      gst_vdp_video_yuv_buffer_alloc);
494
 
}