mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-04 14:38:48 +00:00
vdpau: add new vdpausink and vdpauvideopostprocess elements
vdpausink is as the name implies a sink which takes vide/x-vdpau-output buffers and outputs it to the screen. vdpauvideopostprocess is an element which takes video/x-vdpau-video buffers and outputs video/x-vdpau-output buffers. The element can also do things like deinterlacing and other postprocessing but this is not implemented yet.
This commit is contained in:
parent
3b2faded12
commit
3e05ddca61
16 changed files with 2685 additions and 164 deletions
|
@ -8,11 +8,14 @@ libgstvdpau_la_SOURCES = \
|
||||||
gstvdpvideobuffer.c \
|
gstvdpvideobuffer.c \
|
||||||
gstvdp.c \
|
gstvdp.c \
|
||||||
gstvdpyuvvideo.c \
|
gstvdpyuvvideo.c \
|
||||||
gstvdputils.c
|
gstvdputils.c \
|
||||||
|
gstvdpvideopostprocess.c \
|
||||||
|
gstvdpoutputbuffer.c \
|
||||||
|
gstvdpsink.c
|
||||||
|
|
||||||
libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS)
|
libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS)
|
||||||
libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \
|
libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \
|
||||||
$(GST_PLUGINS_BASE_LIBS) $(X11_LIBS) -lgstvideo-$(GST_MAJORMINOR) \
|
$(GST_PLUGINS_BASE_LIBS) $(X11_LIBS) -lgstvideo-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \
|
||||||
$(VDPAU_LIBS)
|
$(VDPAU_LIBS)
|
||||||
libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static
|
libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static
|
||||||
|
@ -24,6 +27,9 @@ noinst_HEADERS = \
|
||||||
gstvdpvideoyuv.h \
|
gstvdpvideoyuv.h \
|
||||||
gstvdpvideobuffer.h \
|
gstvdpvideobuffer.h \
|
||||||
gstvdpyuvvideo.h \
|
gstvdpyuvvideo.h \
|
||||||
gstvdputils.h
|
gstvdputils.h \
|
||||||
|
gstvdpvideopostprocess.h \
|
||||||
|
gstvdpoutputbuffer.h \
|
||||||
|
gstvdpsink.c
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include "gstvdpmpegdec.h"
|
#include "gstvdpmpegdec.h"
|
||||||
#include "gstvdpvideoyuv.h"
|
#include "gstvdpvideoyuv.h"
|
||||||
#include "gstvdpyuvvideo.h"
|
#include "gstvdpyuvvideo.h"
|
||||||
|
#include "gstvdpvideopostprocess.h"
|
||||||
|
#include "gstvdpsink.h"
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
vdpau_init (GstPlugin * vdpau_plugin)
|
vdpau_init (GstPlugin * vdpau_plugin)
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdpau/vdpau_x11.h>
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
#include "gstvdpdevice.h"
|
#include "gstvdpdevice.h"
|
||||||
|
@ -100,6 +99,25 @@ gst_vdp_device_constructed (GObject * object)
|
||||||
&device->vdp_decoder_query_capabilities},
|
&device->vdp_decoder_query_capabilities},
|
||||||
{VDP_FUNC_ID_DECODER_GET_PARAMETERS,
|
{VDP_FUNC_ID_DECODER_GET_PARAMETERS,
|
||||||
&device->vdp_decoder_get_parameters},
|
&device->vdp_decoder_get_parameters},
|
||||||
|
{VDP_FUNC_ID_VIDEO_MIXER_CREATE, &device->vdp_video_mixer_create},
|
||||||
|
{VDP_FUNC_ID_VIDEO_MIXER_DESTROY, &device->vdp_video_mixer_destroy},
|
||||||
|
{VDP_FUNC_ID_VIDEO_MIXER_RENDER, &device->vdp_video_mixer_render},
|
||||||
|
{VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, &device->vdp_output_surface_create},
|
||||||
|
{VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY, &device->vdp_output_surface_destroy},
|
||||||
|
{VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES,
|
||||||
|
&device->vdp_output_surface_query_capabilities},
|
||||||
|
{VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,
|
||||||
|
&device->vdp_presentation_queue_target_create_x11},
|
||||||
|
{VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE,
|
||||||
|
&device->vdp_presentation_queue_create},
|
||||||
|
{VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY,
|
||||||
|
&device->vdp_presentation_queue_destroy},
|
||||||
|
{VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY,
|
||||||
|
&device->vdp_presentation_queue_display},
|
||||||
|
{VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE,
|
||||||
|
&device->vdp_presentation_queue_block_until_surface_idle},
|
||||||
|
{VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR,
|
||||||
|
&device->vdp_presentation_queue_set_background_color},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <vdpau/vdpau.h>
|
#include <vdpau/vdpau.h>
|
||||||
|
#include <vdpau/vdpau_x11.h>
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
@ -68,6 +69,21 @@ struct _GstVdpDevice
|
||||||
VdpDecoderRender *vdp_decoder_render;
|
VdpDecoderRender *vdp_decoder_render;
|
||||||
VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities;
|
VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities;
|
||||||
VdpDecoderGetParameters *vdp_decoder_get_parameters;
|
VdpDecoderGetParameters *vdp_decoder_get_parameters;
|
||||||
|
|
||||||
|
VdpVideoMixerCreate *vdp_video_mixer_create;
|
||||||
|
VdpVideoMixerDestroy *vdp_video_mixer_destroy;
|
||||||
|
VdpVideoMixerRender *vdp_video_mixer_render;
|
||||||
|
|
||||||
|
VdpOutputSurfaceCreate *vdp_output_surface_create;
|
||||||
|
VdpOutputSurfaceDestroy *vdp_output_surface_destroy;
|
||||||
|
VdpOutputSurfaceQueryCapabilities *vdp_output_surface_query_capabilities;
|
||||||
|
|
||||||
|
VdpPresentationQueueTargetCreateX11 *vdp_presentation_queue_target_create_x11;
|
||||||
|
VdpPresentationQueueCreate *vdp_presentation_queue_create;
|
||||||
|
VdpPresentationQueueDestroy *vdp_presentation_queue_destroy;
|
||||||
|
VdpPresentationQueueDisplay *vdp_presentation_queue_display;
|
||||||
|
VdpPresentationQueueBlockUntilSurfaceIdle *vdp_presentation_queue_block_until_surface_idle;
|
||||||
|
VdpPresentationQueueSetBackgroundColor *vdp_presentation_queue_set_background_color;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_vdp_device_get_type (void) G_GNUC_CONST;
|
GType gst_vdp_device_get_type (void) G_GNUC_CONST;
|
||||||
|
|
217
sys/vdpau/gstvdpoutputbuffer.c
Normal file
217
sys/vdpau/gstvdpoutputbuffer.c
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gstvdpoutputbuffer.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_vdp_output_buffer_debug);
|
||||||
|
#define GST_CAT_DEFAULT gst_vdp_output_buffer_debug
|
||||||
|
|
||||||
|
#define DEBUG_INIT(bla) \
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_vdp_output_buffer_debug, "vdpauoutputbuffer", 0, "VDPAU output buffer");
|
||||||
|
|
||||||
|
GstVdpOutputBuffer *
|
||||||
|
gst_vdp_output_buffer_new (GstVdpDevice * device, VdpRGBAFormat rgba_format,
|
||||||
|
gint width, gint height)
|
||||||
|
{
|
||||||
|
GstVdpOutputBuffer *buffer;
|
||||||
|
VdpStatus status;
|
||||||
|
VdpOutputSurface surface;
|
||||||
|
|
||||||
|
status =
|
||||||
|
device->vdp_output_surface_create (device->device, rgba_format, width,
|
||||||
|
height, &surface);
|
||||||
|
if (status != VDP_STATUS_OK) {
|
||||||
|
GST_ERROR ("Couldn't create a VdpOutputSurface, error returned was: %s",
|
||||||
|
device->vdp_get_error_string (status));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer =
|
||||||
|
(GstVdpOutputBuffer *) gst_mini_object_new (GST_TYPE_VDP_OUTPUT_BUFFER);
|
||||||
|
|
||||||
|
buffer->device = g_object_ref (device);
|
||||||
|
buffer->surface = surface;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObjectClass *gst_vdp_output_buffer_parent_class;
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_output_buffer_finalize (GstVdpOutputBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstVdpDevice *device;
|
||||||
|
VdpStatus status;
|
||||||
|
|
||||||
|
device = buffer->device;
|
||||||
|
|
||||||
|
status = device->vdp_output_surface_destroy (buffer->surface);
|
||||||
|
if (status != VDP_STATUS_OK)
|
||||||
|
GST_ERROR
|
||||||
|
("Couldn't destroy the buffers VdpOutputSurface, error returned was: %s",
|
||||||
|
device->vdp_get_error_string (status));
|
||||||
|
|
||||||
|
g_object_unref (buffer->device);
|
||||||
|
|
||||||
|
GST_MINI_OBJECT_CLASS (gst_vdp_output_buffer_parent_class)->finalize
|
||||||
|
(GST_MINI_OBJECT (buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_output_buffer_init (GstVdpOutputBuffer * buffer, gpointer g_class)
|
||||||
|
{
|
||||||
|
buffer->device = NULL;
|
||||||
|
buffer->surface = VDP_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_output_buffer_class_init (gpointer g_class, gpointer class_data)
|
||||||
|
{
|
||||||
|
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
||||||
|
|
||||||
|
gst_vdp_output_buffer_parent_class = g_type_class_peek_parent (g_class);
|
||||||
|
|
||||||
|
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
||||||
|
gst_vdp_output_buffer_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_vdp_output_buffer_get_type (void)
|
||||||
|
{
|
||||||
|
static GType _gst_vdp_output_buffer_type;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (_gst_vdp_output_buffer_type == 0)) {
|
||||||
|
static const GTypeInfo info = {
|
||||||
|
sizeof (GstBufferClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
gst_vdp_output_buffer_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstVdpOutputBuffer),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_vdp_output_buffer_init,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
_gst_vdp_output_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
||||||
|
"GstVdpOutputBuffer", &info, 0);
|
||||||
|
|
||||||
|
DEBUG_INIT ();
|
||||||
|
}
|
||||||
|
return _gst_vdp_output_buffer_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
VdpRGBAFormat format;
|
||||||
|
GstStaticCaps caps;
|
||||||
|
} GstVdpOutputBufferFormats;
|
||||||
|
|
||||||
|
GstVdpOutputBufferFormats rgba_formats[] = {
|
||||||
|
{VDP_RGBA_FORMAT_A8,
|
||||||
|
GST_STATIC_CAPS ("video/x-raw-rgb, "
|
||||||
|
"bpp = (int)8, "
|
||||||
|
"depth = (int)0, "
|
||||||
|
"endianness = G_BIG_ENDIAN, "
|
||||||
|
"red_mask = (int)0x00, "
|
||||||
|
"green_mask = (int)0x00, "
|
||||||
|
"blue_mask = (int)0x00, " "alpha_mask = (int)0xff")},
|
||||||
|
{VDP_RGBA_FORMAT_B10G10R10A2,
|
||||||
|
GST_STATIC_CAPS ("video/x-raw-rgb, "
|
||||||
|
"bpp = (int)32, "
|
||||||
|
"depth = (int)30, "
|
||||||
|
"endianness = G_BIG_ENDIAN, "
|
||||||
|
"red_mask = (int)0x000003fc, "
|
||||||
|
"green_mask = (int)0x003ff000, "
|
||||||
|
"blue_mask = (int)0xffc00000, " "alpha_mask = (int)0x00000003")},
|
||||||
|
{VDP_RGBA_FORMAT_B8G8R8A8,
|
||||||
|
GST_STATIC_CAPS ("video/x-raw-rgb, "
|
||||||
|
"bpp = (int)32, "
|
||||||
|
"depth = (int)24, "
|
||||||
|
"endianness = G_BIG_ENDIAN, "
|
||||||
|
"red_mask = (int)0x0000ff00, "
|
||||||
|
"green_mask = (int)0x00ff0000, "
|
||||||
|
"blue_mask = (int)0xff000000, " "alpha_mask = (int)0x000000ff")},
|
||||||
|
{VDP_RGBA_FORMAT_R10G10B10A2,
|
||||||
|
GST_STATIC_CAPS ("video/x-raw-rgb, "
|
||||||
|
"bpp = (int)32, "
|
||||||
|
"depth = (int)30, "
|
||||||
|
"endianness = G_BIG_ENDIAN, "
|
||||||
|
"red_mask = (int)0xffc00000, "
|
||||||
|
"green_mask = (int)0x003ff000, "
|
||||||
|
"blue_mask = (int)0x000003fc, " "alpha_mask = (int)0x00000003")},
|
||||||
|
{VDP_RGBA_FORMAT_R8G8B8A8,
|
||||||
|
GST_STATIC_CAPS ("video/x-raw-rgb, "
|
||||||
|
"bpp = (int)32, "
|
||||||
|
"depth = (int)24, "
|
||||||
|
"endianness = G_BIG_ENDIAN"
|
||||||
|
"red_mask = (int)0xff000000, "
|
||||||
|
"green_mask = (int)0x00ff0000, "
|
||||||
|
"blue_mask = (int)0x0000ff00, " "alpha_mask = (int)0x000000ff")},
|
||||||
|
};
|
||||||
|
|
||||||
|
int n_rgba_formats = G_N_ELEMENTS (rgba_formats);
|
||||||
|
|
||||||
|
GstCaps *
|
||||||
|
gst_vdp_output_buffer_get_allowed_caps (GstVdpDevice * device)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_VDP_DEVICE (device), NULL);
|
||||||
|
|
||||||
|
caps = gst_caps_new_empty ();
|
||||||
|
|
||||||
|
for (i = 0; i < n_rgba_formats; i++) {
|
||||||
|
VdpStatus status;
|
||||||
|
VdpBool is_supported;
|
||||||
|
guint max_w, max_h;
|
||||||
|
|
||||||
|
status = device->vdp_output_surface_query_capabilities (device->device,
|
||||||
|
rgba_formats[i].format, &is_supported, &max_w, &max_h);
|
||||||
|
if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_RGBA_FORMAT) {
|
||||||
|
GST_ERROR_OBJECT (device,
|
||||||
|
"Could not get query VDPAU output surface capabilites, "
|
||||||
|
"Error returned from vdpau was: %s",
|
||||||
|
device->vdp_get_error_string (status));
|
||||||
|
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_supported) {
|
||||||
|
GstCaps *format_caps;
|
||||||
|
|
||||||
|
format_caps = gst_caps_new_simple ("video/x-vdpau-output",
|
||||||
|
"rgba-format", G_TYPE_INT, rgba_formats[i].format,
|
||||||
|
"width", GST_TYPE_INT_RANGE, 1, max_w,
|
||||||
|
"height", GST_TYPE_INT_RANGE, 1, max_h, NULL);
|
||||||
|
gst_caps_append (caps, format_caps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
53
sys/vdpau/gstvdpoutputbuffer.h
Normal file
53
sys/vdpau/gstvdpoutputbuffer.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GST_VDP_OUTPUT_BUFFER_H_
|
||||||
|
#define _GST_VDP_OUTPUT_BUFFER_H_
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "gstvdpdevice.h"
|
||||||
|
|
||||||
|
typedef struct _GstVdpOutputBuffer GstVdpOutputBuffer;
|
||||||
|
|
||||||
|
#define GST_TYPE_VDP_OUTPUT_BUFFER (gst_vdp_output_buffer_get_type())
|
||||||
|
#define GST_IS_VDP_OUTPUT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_OUTPUT_BUFFER))
|
||||||
|
#define GST_VDP_OUTPUT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDP_OUTPUT_BUFFER, GstVdpOutputBuffer))
|
||||||
|
|
||||||
|
struct _GstVdpOutputBuffer {
|
||||||
|
GstBuffer buffer;
|
||||||
|
|
||||||
|
GstVdpDevice *device;
|
||||||
|
VdpOutputSurface surface;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_vdp_output_buffer_get_type (void);
|
||||||
|
|
||||||
|
GstVdpOutputBuffer* gst_vdp_output_buffer_new (GstVdpDevice * device, VdpRGBAFormat rgba_format, gint width, gint height);
|
||||||
|
|
||||||
|
GstCaps *gst_vdp_output_buffer_get_allowed_caps (GstVdpDevice *device);
|
||||||
|
|
||||||
|
#define GST_VDP_OUTPUT_CAPS \
|
||||||
|
"video/x-vdpau-output, " \
|
||||||
|
"rgba-format = (int)[0,4], " \
|
||||||
|
"width = (int)[1,8192], " \
|
||||||
|
"height = (int)[1,8192]"
|
||||||
|
|
||||||
|
#endif
|
1476
sys/vdpau/gstvdpsink.c
Normal file
1476
sys/vdpau/gstvdpsink.c
Normal file
File diff suppressed because it is too large
Load diff
135
sys/vdpau/gstvdpsink.h
Normal file
135
sys/vdpau/gstvdpsink.h
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2005> Julien Moutte <julien@moutte.net>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_VDP_SINK_H__
|
||||||
|
#define __GST_VDP_SINK_H__
|
||||||
|
|
||||||
|
#include <gst/video/gstvideosink.h>
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "gstvdpdevice.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_VDP_SINK \
|
||||||
|
(gst_vdp_sink_get_type())
|
||||||
|
#define GST_VDP_SINK(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_VDP_SINK, VdpSink))
|
||||||
|
#define GST_VDP_SINK_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_VDP_SINK, VdpSinkClass))
|
||||||
|
#define GST_IS_VDP_SINK(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VDP_SINK))
|
||||||
|
#define GST_IS_VDP_SINK_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VDP_SINK))
|
||||||
|
|
||||||
|
typedef struct _GstXContext GstXContext;
|
||||||
|
typedef struct _GstVdpWindow GstVdpWindow;
|
||||||
|
|
||||||
|
typedef struct _VdpSink VdpSink;
|
||||||
|
typedef struct _VdpSinkClass VdpSinkClass;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GstVdpWindow:
|
||||||
|
* @win: the Window ID of this X11 window
|
||||||
|
* @target the VdpPresentationQueueTarget of this window
|
||||||
|
* @queue the VdpPresentationQueue of this window
|
||||||
|
* @width: the width in pixels of Window @win
|
||||||
|
* @height: the height in pixels of Window @win
|
||||||
|
* @internal: used to remember if Window @win was created internally or passed
|
||||||
|
* through the #GstXOverlay interface
|
||||||
|
*
|
||||||
|
* Structure used to store informations about a Window.
|
||||||
|
*/
|
||||||
|
struct _GstVdpWindow {
|
||||||
|
Window win;
|
||||||
|
VdpPresentationQueueTarget target;
|
||||||
|
VdpPresentationQueue queue;
|
||||||
|
gint width, height;
|
||||||
|
gboolean internal;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VdpSink:
|
||||||
|
* @display_name: the name of the Display we want to render to
|
||||||
|
* @device: the GstVdpDevice associated with the display_name
|
||||||
|
* @window: the #GstVdpWindow we are rendering to
|
||||||
|
* @cur_image: a reference to the last #GstBuffer that was put to @window. It
|
||||||
|
* is used when Expose events are received to redraw the latest video frame
|
||||||
|
* @event_thread: a thread listening for events on @window and handling them
|
||||||
|
* @running: used to inform @event_thread if it should run/shutdown
|
||||||
|
* @fps_n: the framerate fraction numerator
|
||||||
|
* @fps_d: the framerate fraction denominator
|
||||||
|
* @x_lock: used to protect X calls as we are not using the XLib in threaded
|
||||||
|
* mode
|
||||||
|
* @flow_lock: used to protect data flow routines from external calls such as
|
||||||
|
* events from @event_thread or methods from the #GstXOverlay interface
|
||||||
|
* @par: used to override calculated pixel aspect ratio from @xcontext
|
||||||
|
* @synchronous: used to store if XSynchronous should be used or not (for
|
||||||
|
* debugging purpose only)
|
||||||
|
* @handle_events: used to know if we should handle select XEvents or not
|
||||||
|
*
|
||||||
|
* The #VdpSink data structure.
|
||||||
|
*/
|
||||||
|
struct _VdpSink {
|
||||||
|
/* Our element stuff */
|
||||||
|
GstVideoSink videosink;
|
||||||
|
|
||||||
|
char *display_name;
|
||||||
|
|
||||||
|
GstVdpDevice *device;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
GstVdpWindow *window;
|
||||||
|
GstBuffer *cur_image;
|
||||||
|
|
||||||
|
GThread *event_thread;
|
||||||
|
gboolean running;
|
||||||
|
|
||||||
|
/* Framerate numerator and denominator */
|
||||||
|
gint fps_n;
|
||||||
|
gint fps_d;
|
||||||
|
|
||||||
|
GMutex *x_lock;
|
||||||
|
GMutex *flow_lock;
|
||||||
|
|
||||||
|
/* object-set pixel aspect ratio */
|
||||||
|
GValue *par;
|
||||||
|
|
||||||
|
gboolean synchronous;
|
||||||
|
gboolean handle_events;
|
||||||
|
gboolean handle_expose;
|
||||||
|
|
||||||
|
/* stream metadata */
|
||||||
|
gchar *media_title;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _VdpSinkClass {
|
||||||
|
GstVideoSinkClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_vdp_sink_get_type(void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_VDP_SINK_H__ */
|
|
@ -18,68 +18,10 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "gstvdpvideobuffer.h"
|
||||||
|
|
||||||
#include "gstvdputils.h"
|
#include "gstvdputils.h"
|
||||||
|
|
||||||
static GstCaps *
|
|
||||||
gst_vdp_get_allowed_yuv_caps (GstVdpDevice * device)
|
|
||||||
{
|
|
||||||
GstCaps *caps;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
caps = gst_caps_new_empty ();
|
|
||||||
for (i = 0; i < N_CHROMA_TYPES; i++) {
|
|
||||||
VdpStatus status;
|
|
||||||
VdpBool is_supported;
|
|
||||||
guint32 max_w, max_h;
|
|
||||||
|
|
||||||
status =
|
|
||||||
device->vdp_video_surface_query_capabilities (device->device,
|
|
||||||
chroma_types[i], &is_supported, &max_w, &max_h);
|
|
||||||
|
|
||||||
if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) {
|
|
||||||
GST_ERROR_OBJECT (device,
|
|
||||||
"Could not get query VDPAU video surface capabilites, "
|
|
||||||
"Error returned from vdpau was: %s",
|
|
||||||
device->vdp_get_error_string (status));
|
|
||||||
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (is_supported) {
|
|
||||||
gint j;
|
|
||||||
|
|
||||||
for (j = 0; j < N_FORMATS; j++) {
|
|
||||||
if (formats[j].chroma_type != chroma_types[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
status =
|
|
||||||
device->vdp_video_surface_query_ycbcr_capabilities (device->device,
|
|
||||||
formats[j].chroma_type, formats[j].format, &is_supported);
|
|
||||||
if (status != VDP_STATUS_OK
|
|
||||||
&& status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) {
|
|
||||||
GST_ERROR_OBJECT (device, "Could not query VDPAU YCbCr capabilites, "
|
|
||||||
"Error returned from vdpau was: %s",
|
|
||||||
device->vdp_get_error_string (status));
|
|
||||||
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_supported) {
|
|
||||||
GstCaps *format_caps;
|
|
||||||
|
|
||||||
format_caps = gst_caps_new_simple ("video/x-raw-yuv",
|
|
||||||
"format", GST_TYPE_FOURCC, formats[j].fourcc,
|
|
||||||
"width", GST_TYPE_INT_RANGE, 1, max_w,
|
|
||||||
"height", GST_TYPE_INT_RANGE, 1, max_h, NULL);
|
|
||||||
gst_caps_append (caps, format_caps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
return caps;
|
|
||||||
}
|
|
||||||
|
|
||||||
GstCaps *
|
GstCaps *
|
||||||
gst_vdp_video_to_yuv_caps (GstCaps * caps, GstVdpDevice * device)
|
gst_vdp_video_to_yuv_caps (GstCaps * caps, GstVdpDevice * device)
|
||||||
{
|
{
|
||||||
|
@ -124,7 +66,7 @@ gst_vdp_video_to_yuv_caps (GstCaps * caps, GstVdpDevice * device)
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
if (device) {
|
if (device) {
|
||||||
allowed_caps = gst_vdp_get_allowed_yuv_caps (device);
|
allowed_caps = gst_vdp_video_buffer_get_allowed_yuv_caps (device);
|
||||||
result = gst_caps_intersect (new_caps, allowed_caps);
|
result = gst_caps_intersect (new_caps, allowed_caps);
|
||||||
|
|
||||||
gst_caps_unref (new_caps);
|
gst_caps_unref (new_caps);
|
||||||
|
@ -135,46 +77,6 @@ gst_vdp_video_to_yuv_caps (GstCaps * caps, GstVdpDevice * device)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
|
||||||
gst_vdp_get_allowed_video_caps (GstVdpDevice * device)
|
|
||||||
{
|
|
||||||
GstCaps *caps;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
caps = gst_caps_new_empty ();
|
|
||||||
for (i = 0; i < N_CHROMA_TYPES; i++) {
|
|
||||||
VdpStatus status;
|
|
||||||
VdpBool is_supported;
|
|
||||||
guint32 max_w, max_h;
|
|
||||||
|
|
||||||
status =
|
|
||||||
device->vdp_video_surface_query_capabilities (device->device,
|
|
||||||
chroma_types[i], &is_supported, &max_w, &max_h);
|
|
||||||
|
|
||||||
if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) {
|
|
||||||
GST_ERROR_OBJECT (device,
|
|
||||||
"Could not get query VDPAU video surface capabilites, "
|
|
||||||
"Error returned from vdpau was: %s",
|
|
||||||
device->vdp_get_error_string (status));
|
|
||||||
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_supported) {
|
|
||||||
GstCaps *format_caps;
|
|
||||||
|
|
||||||
format_caps = gst_caps_new_simple ("video/x-vdpau-video",
|
|
||||||
"chroma-type", G_TYPE_INT, chroma_types[i],
|
|
||||||
"width", GST_TYPE_INT_RANGE, 1, max_w,
|
|
||||||
"height", GST_TYPE_INT_RANGE, 1, max_h, NULL);
|
|
||||||
gst_caps_append (caps, format_caps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
return caps;
|
|
||||||
}
|
|
||||||
|
|
||||||
GstCaps *
|
GstCaps *
|
||||||
gst_vdp_yuv_to_video_caps (GstCaps * caps, GstVdpDevice * device)
|
gst_vdp_yuv_to_video_caps (GstCaps * caps, GstVdpDevice * device)
|
||||||
{
|
{
|
||||||
|
@ -209,7 +111,7 @@ gst_vdp_yuv_to_video_caps (GstCaps * caps, GstVdpDevice * device)
|
||||||
if (device) {
|
if (device) {
|
||||||
GstCaps *allowed_caps;
|
GstCaps *allowed_caps;
|
||||||
|
|
||||||
allowed_caps = gst_vdp_get_allowed_video_caps (device);
|
allowed_caps = gst_vdp_video_buffer_get_allowed_video_caps (device);
|
||||||
result = gst_caps_intersect (new_caps, allowed_caps);
|
result = gst_caps_intersect (new_caps, allowed_caps);
|
||||||
|
|
||||||
gst_caps_unref (new_caps);
|
gst_caps_unref (new_caps);
|
||||||
|
@ -219,3 +121,20 @@ gst_vdp_yuv_to_video_caps (GstCaps * caps, GstVdpDevice * device)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstCaps *
|
||||||
|
gst_vdp_video_to_output_caps (GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstCaps *result;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
result = gst_caps_copy (caps);
|
||||||
|
for (i = 0; i < gst_caps_get_size (result); i++) {
|
||||||
|
GstStructure *structure = gst_caps_get_structure (result, i);
|
||||||
|
|
||||||
|
gst_structure_set_name (structure, "video/x-vdpau-output");
|
||||||
|
gst_structure_remove_field (structure, "chroma-type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -25,58 +25,9 @@
|
||||||
|
|
||||||
#include "gstvdpdevice.h"
|
#include "gstvdpdevice.h"
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
VdpChromaType chroma_type;
|
|
||||||
VdpYCbCrFormat format;
|
|
||||||
guint32 fourcc;
|
|
||||||
} VdpauFormats;
|
|
||||||
|
|
||||||
#define N_CHROMA_TYPES 3
|
|
||||||
#define N_FORMATS 7
|
|
||||||
|
|
||||||
static const VdpChromaType chroma_types[N_CHROMA_TYPES] =
|
|
||||||
{ VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 };
|
|
||||||
|
|
||||||
static const VdpauFormats formats[N_FORMATS] = {
|
|
||||||
{
|
|
||||||
VDP_CHROMA_TYPE_420,
|
|
||||||
VDP_YCBCR_FORMAT_YV12,
|
|
||||||
GST_MAKE_FOURCC ('I', '4', '2', '0')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
VDP_CHROMA_TYPE_420,
|
|
||||||
VDP_YCBCR_FORMAT_YV12,
|
|
||||||
GST_MAKE_FOURCC ('Y', 'V', '1', '2')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
VDP_CHROMA_TYPE_420,
|
|
||||||
VDP_YCBCR_FORMAT_NV12,
|
|
||||||
GST_MAKE_FOURCC ('N', 'V', '1', '2')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
VDP_CHROMA_TYPE_422,
|
|
||||||
VDP_YCBCR_FORMAT_UYVY,
|
|
||||||
GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
VDP_CHROMA_TYPE_444,
|
|
||||||
VDP_YCBCR_FORMAT_V8U8Y8A8,
|
|
||||||
GST_MAKE_FOURCC ('A', 'Y', 'U', 'V')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
VDP_CHROMA_TYPE_444,
|
|
||||||
VDP_YCBCR_FORMAT_Y8U8V8A8,
|
|
||||||
GST_MAKE_FOURCC ('A', 'V', 'U', 'Y')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
VDP_CHROMA_TYPE_422,
|
|
||||||
VDP_YCBCR_FORMAT_YUYV,
|
|
||||||
GST_MAKE_FOURCC ('Y', 'U', 'Y', '2')
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
GstCaps *gst_vdp_video_to_yuv_caps (GstCaps *caps, GstVdpDevice *device);
|
GstCaps *gst_vdp_video_to_yuv_caps (GstCaps *caps, GstVdpDevice *device);
|
||||||
GstCaps *gst_vdp_yuv_to_video_caps (GstCaps *caps, GstVdpDevice *device);
|
GstCaps *gst_vdp_yuv_to_video_caps (GstCaps *caps, GstVdpDevice *device);
|
||||||
|
|
||||||
|
GstCaps *gst_vdp_video_to_output_caps (GstCaps * caps);
|
||||||
|
|
||||||
#endif /* _GST_VDP_UTILS_H_ */
|
#endif /* _GST_VDP_UTILS_H_ */
|
|
@ -136,3 +136,103 @@ gst_vdp_video_buffer_get_type (void)
|
||||||
}
|
}
|
||||||
return _gst_vdp_video_buffer_type;
|
return _gst_vdp_video_buffer_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstCaps *
|
||||||
|
gst_vdp_video_buffer_get_allowed_yuv_caps (GstVdpDevice * device)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
caps = gst_caps_new_empty ();
|
||||||
|
for (i = 0; i < N_CHROMA_TYPES; i++) {
|
||||||
|
VdpStatus status;
|
||||||
|
VdpBool is_supported;
|
||||||
|
guint32 max_w, max_h;
|
||||||
|
|
||||||
|
status =
|
||||||
|
device->vdp_video_surface_query_capabilities (device->device,
|
||||||
|
chroma_types[i], &is_supported, &max_w, &max_h);
|
||||||
|
|
||||||
|
if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) {
|
||||||
|
GST_ERROR_OBJECT (device,
|
||||||
|
"Could not get query VDPAU video surface capabilites, "
|
||||||
|
"Error returned from vdpau was: %s",
|
||||||
|
device->vdp_get_error_string (status));
|
||||||
|
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (is_supported) {
|
||||||
|
gint j;
|
||||||
|
|
||||||
|
for (j = 0; j < N_FORMATS; j++) {
|
||||||
|
if (formats[j].chroma_type != chroma_types[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
status =
|
||||||
|
device->vdp_video_surface_query_ycbcr_capabilities (device->device,
|
||||||
|
formats[j].chroma_type, formats[j].format, &is_supported);
|
||||||
|
if (status != VDP_STATUS_OK
|
||||||
|
&& status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) {
|
||||||
|
GST_ERROR_OBJECT (device, "Could not query VDPAU YCbCr capabilites, "
|
||||||
|
"Error returned from vdpau was: %s",
|
||||||
|
device->vdp_get_error_string (status));
|
||||||
|
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_supported) {
|
||||||
|
GstCaps *format_caps;
|
||||||
|
|
||||||
|
format_caps = gst_caps_new_simple ("video/x-raw-yuv",
|
||||||
|
"format", GST_TYPE_FOURCC, formats[j].fourcc,
|
||||||
|
"width", GST_TYPE_INT_RANGE, 1, max_w,
|
||||||
|
"height", GST_TYPE_INT_RANGE, 1, max_h, NULL);
|
||||||
|
gst_caps_append (caps, format_caps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstCaps *
|
||||||
|
gst_vdp_video_buffer_get_allowed_video_caps (GstVdpDevice * device)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
caps = gst_caps_new_empty ();
|
||||||
|
for (i = 0; i < N_CHROMA_TYPES; i++) {
|
||||||
|
VdpStatus status;
|
||||||
|
VdpBool is_supported;
|
||||||
|
guint32 max_w, max_h;
|
||||||
|
|
||||||
|
status =
|
||||||
|
device->vdp_video_surface_query_capabilities (device->device,
|
||||||
|
chroma_types[i], &is_supported, &max_w, &max_h);
|
||||||
|
|
||||||
|
if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) {
|
||||||
|
GST_ERROR_OBJECT (device,
|
||||||
|
"Could not get query VDPAU video surface capabilites, "
|
||||||
|
"Error returned from vdpau was: %s",
|
||||||
|
device->vdp_get_error_string (status));
|
||||||
|
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_supported) {
|
||||||
|
GstCaps *format_caps;
|
||||||
|
|
||||||
|
format_caps = gst_caps_new_simple ("video/x-vdpau-video",
|
||||||
|
"chroma-type", G_TYPE_INT, chroma_types[i],
|
||||||
|
"width", GST_TYPE_INT_RANGE, 1, max_w,
|
||||||
|
"height", GST_TYPE_INT_RANGE, 1, max_h, NULL);
|
||||||
|
gst_caps_append (caps, format_caps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
|
@ -44,12 +44,65 @@ struct _GstVdpVideoBuffer {
|
||||||
GSList *refs;
|
GSList *refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
VdpChromaType chroma_type;
|
||||||
|
VdpYCbCrFormat format;
|
||||||
|
guint32 fourcc;
|
||||||
|
} GstVdpVideoBufferFormats;
|
||||||
|
|
||||||
|
#define N_CHROMA_TYPES 3
|
||||||
|
#define N_FORMATS 7
|
||||||
|
|
||||||
|
static const VdpChromaType chroma_types[N_CHROMA_TYPES] =
|
||||||
|
{ VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 };
|
||||||
|
|
||||||
|
static const GstVdpVideoBufferFormats formats[N_FORMATS] = {
|
||||||
|
{
|
||||||
|
VDP_CHROMA_TYPE_420,
|
||||||
|
VDP_YCBCR_FORMAT_YV12,
|
||||||
|
GST_MAKE_FOURCC ('I', '4', '2', '0')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
VDP_CHROMA_TYPE_420,
|
||||||
|
VDP_YCBCR_FORMAT_YV12,
|
||||||
|
GST_MAKE_FOURCC ('Y', 'V', '1', '2')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
VDP_CHROMA_TYPE_420,
|
||||||
|
VDP_YCBCR_FORMAT_NV12,
|
||||||
|
GST_MAKE_FOURCC ('N', 'V', '1', '2')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
VDP_CHROMA_TYPE_422,
|
||||||
|
VDP_YCBCR_FORMAT_UYVY,
|
||||||
|
GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
VDP_CHROMA_TYPE_444,
|
||||||
|
VDP_YCBCR_FORMAT_V8U8Y8A8,
|
||||||
|
GST_MAKE_FOURCC ('A', 'Y', 'U', 'V')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
VDP_CHROMA_TYPE_444,
|
||||||
|
VDP_YCBCR_FORMAT_Y8U8V8A8,
|
||||||
|
GST_MAKE_FOURCC ('A', 'V', 'U', 'Y')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
VDP_CHROMA_TYPE_422,
|
||||||
|
VDP_YCBCR_FORMAT_YUYV,
|
||||||
|
GST_MAKE_FOURCC ('Y', 'U', 'Y', '2')
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
GType gst_vdp_video_buffer_get_type (void);
|
GType gst_vdp_video_buffer_get_type (void);
|
||||||
|
|
||||||
GstVdpVideoBuffer* gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, gint width, gint height);
|
GstVdpVideoBuffer* gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, gint width, gint height);
|
||||||
|
|
||||||
void gst_vdp_video_buffer_add_reference (GstVdpVideoBuffer *buffer, GstVdpVideoBuffer *buf);
|
void gst_vdp_video_buffer_add_reference (GstVdpVideoBuffer *buffer, GstVdpVideoBuffer *buf);
|
||||||
|
|
||||||
|
GstCaps *gst_vdp_video_buffer_get_allowed_yuv_caps (GstVdpDevice * device);
|
||||||
|
GstCaps *gst_vdp_video_buffer_get_allowed_video_caps (GstVdpDevice * device);
|
||||||
|
|
||||||
#define GST_VDP_VIDEO_CAPS \
|
#define GST_VDP_VIDEO_CAPS \
|
||||||
"video/x-vdpau-video, " \
|
"video/x-vdpau-video, " \
|
||||||
"chroma-type = (int)[0,2], " \
|
"chroma-type = (int)[0,2], " \
|
||||||
|
|
512
sys/vdpau/gstvdpvideopostprocess.c
Normal file
512
sys/vdpau/gstvdpvideopostprocess.c
Normal file
|
@ -0,0 +1,512 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:element-vdpauvideopostprocess
|
||||||
|
*
|
||||||
|
* FIXME:Describe vdpaumpegdec here.
|
||||||
|
*
|
||||||
|
* <refsect2>
|
||||||
|
* <title>Example launch line</title>
|
||||||
|
* |[
|
||||||
|
* gst-launch -v -m fakesrc ! vdpauvideopostprocess ! fakesink silent=TRUE
|
||||||
|
* ]|
|
||||||
|
* </refsect2>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO:
|
||||||
|
* + add support for postprocessing eg. deinterlace
|
||||||
|
* + mixing videos. (This should perhaps be done in a separate element based on
|
||||||
|
* VdpOutputSurface)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/gstvideosink.h>
|
||||||
|
|
||||||
|
#include "gstvdputils.h"
|
||||||
|
#include "gstvdpvideobuffer.h"
|
||||||
|
#include "gstvdpoutputbuffer.h"
|
||||||
|
|
||||||
|
#include "gstvdpvideopostprocess.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_vdp_vpp_debug);
|
||||||
|
#define GST_CAT_DEFAULT gst_vdp_vpp_debug
|
||||||
|
|
||||||
|
/* Filter signals and args */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* FILL ME */
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_FORCE_ASPECT_RATIO
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the capabilities of the inputs and outputs.
|
||||||
|
*
|
||||||
|
* describe the real formats here.
|
||||||
|
*/
|
||||||
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VDP_VIDEO_CAPS));
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VDP_OUTPUT_CAPS));
|
||||||
|
|
||||||
|
#define DEBUG_INIT(bla) \
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_vdp_vpp_debug, "vdpauvideopostprocess", 0, "VDPAU video surface to output surface");
|
||||||
|
|
||||||
|
GST_BOILERPLATE_FULL (GstVdpVideoPostProcess, gst_vdp_vpp,
|
||||||
|
GstElement, GST_TYPE_ELEMENT, DEBUG_INIT);
|
||||||
|
|
||||||
|
static void gst_vdp_vpp_finalize (GObject * object);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vdp_vpp_set_caps (GstPad * pad, GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstVdpVideoPostProcess *vpp =
|
||||||
|
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
|
||||||
|
GstCaps *output_caps, *allowed_caps, *src_caps;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
output_caps = gst_vdp_video_to_output_caps (caps);
|
||||||
|
allowed_caps = gst_pad_get_allowed_caps (vpp->srcpad);
|
||||||
|
|
||||||
|
src_caps = gst_caps_intersect (output_caps, allowed_caps);
|
||||||
|
gst_caps_truncate (src_caps);
|
||||||
|
GST_DEBUG ("output_caps: %" GST_PTR_FORMAT " allowed_caps: %" GST_PTR_FORMAT
|
||||||
|
" src_caps: %" GST_PTR_FORMAT, output_caps, allowed_caps, src_caps);
|
||||||
|
|
||||||
|
gst_caps_unref (output_caps);
|
||||||
|
gst_caps_unref (allowed_caps);
|
||||||
|
|
||||||
|
res = gst_pad_set_caps (vpp->srcpad, src_caps);
|
||||||
|
|
||||||
|
gst_object_unref (vpp);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_flush (GstVdpVideoPostProcess * vpp)
|
||||||
|
{
|
||||||
|
/* TODO: Write this */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_start (GstVdpVideoPostProcess * vpp)
|
||||||
|
{
|
||||||
|
vpp->mixer = VDP_INVALID_HANDLE;
|
||||||
|
vpp->device = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_stop (GstVdpVideoPostProcess * vpp)
|
||||||
|
{
|
||||||
|
if (vpp->mixer != VDP_INVALID_HANDLE)
|
||||||
|
vpp->device->vdp_video_mixer_destroy (vpp->mixer);
|
||||||
|
if (!vpp->device)
|
||||||
|
g_object_unref (vpp->device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vdp_vpp_alloc_output_buffer (GstVdpVideoPostProcess * vpp, GstCaps * caps,
|
||||||
|
GstVdpOutputBuffer ** outbuf)
|
||||||
|
{
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
|
ret = gst_pad_alloc_buffer_and_set_caps (vpp->srcpad, 0, 0,
|
||||||
|
caps, (GstBuffer **) outbuf);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!vpp->device) {
|
||||||
|
#define VDP_NUM_MIXER_PARAMETER 3
|
||||||
|
#define MAX_NUM_FEATURES 5
|
||||||
|
|
||||||
|
GstStructure *structure;
|
||||||
|
gint chroma_type;
|
||||||
|
gint width, height;
|
||||||
|
|
||||||
|
VdpStatus status;
|
||||||
|
GstVdpDevice *device;
|
||||||
|
|
||||||
|
VdpVideoMixerFeature features[5];
|
||||||
|
guint n_features = 0;
|
||||||
|
VdpVideoMixerParameter parameters[VDP_NUM_MIXER_PARAMETER] = {
|
||||||
|
VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
|
||||||
|
VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
|
||||||
|
VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
|
||||||
|
};
|
||||||
|
const void *parameter_values[VDP_NUM_MIXER_PARAMETER];
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (GST_PAD_CAPS (vpp->sinkpad), 0);
|
||||||
|
if (!gst_structure_get_int (structure, "chroma-type", &chroma_type) ||
|
||||||
|
!gst_structure_get_int (structure, "width", &width) ||
|
||||||
|
!gst_structure_get_int (structure, "height", &height))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
parameter_values[0] = &width;
|
||||||
|
parameter_values[1] = &height;
|
||||||
|
parameter_values[2] = &chroma_type;
|
||||||
|
|
||||||
|
device = vpp->device = g_object_ref ((*outbuf)->device);
|
||||||
|
|
||||||
|
|
||||||
|
status =
|
||||||
|
device->vdp_video_mixer_create (device->device, n_features, features,
|
||||||
|
VDP_NUM_MIXER_PARAMETER, parameters, parameter_values, &vpp->mixer);
|
||||||
|
if (status != VDP_STATUS_OK) {
|
||||||
|
GST_ELEMENT_ERROR (vpp, RESOURCE, READ,
|
||||||
|
("Could not create vdpau video mixer"),
|
||||||
|
("Error returned from vdpau was: %s",
|
||||||
|
device->vdp_get_error_string (status)));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
error:
|
||||||
|
gst_buffer_unref (GST_BUFFER (*outbuf));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vdp_vpp_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstVdpVideoPostProcess *vpp =
|
||||||
|
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
|
||||||
|
GstFlowReturn ret;
|
||||||
|
GstVdpOutputBuffer *outbuf;
|
||||||
|
|
||||||
|
GstStructure *structure;
|
||||||
|
GstVideoRectangle src_r, dest_r;
|
||||||
|
VdpRect rect;
|
||||||
|
|
||||||
|
GstVdpDevice *device;
|
||||||
|
VdpStatus status;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
|
||||||
|
GST_DEBUG_OBJECT (vpp, "Received discont buffer");
|
||||||
|
gst_vdp_vpp_flush (vpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret =
|
||||||
|
gst_vdp_vpp_alloc_output_buffer (vpp, GST_PAD_CAPS (vpp->srcpad),
|
||||||
|
&outbuf);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (GST_BUFFER_CAPS (buffer), 0);
|
||||||
|
if (!gst_structure_get_int (structure, "width", &src_r.w) ||
|
||||||
|
!gst_structure_get_int (structure, "height", &src_r.h))
|
||||||
|
goto invalid_caps;
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (GST_BUFFER_CAPS (outbuf), 0);
|
||||||
|
if (!gst_structure_get_int (structure, "width", &dest_r.w) ||
|
||||||
|
!gst_structure_get_int (structure, "height", &dest_r.h))
|
||||||
|
goto invalid_caps;
|
||||||
|
|
||||||
|
if (vpp->force_aspect_ratio) {
|
||||||
|
GstVideoRectangle res_r;
|
||||||
|
|
||||||
|
gst_video_sink_center_rect (src_r, dest_r, &res_r, TRUE);
|
||||||
|
rect.x0 = res_r.x;
|
||||||
|
rect.x1 = res_r.w + res_r.x;
|
||||||
|
rect.y0 = res_r.y;
|
||||||
|
rect.y1 = res_r.h + res_r.y;
|
||||||
|
} else {
|
||||||
|
rect.x0 = 0;
|
||||||
|
rect.x1 = dest_r.w;
|
||||||
|
rect.y0 = 0;
|
||||||
|
rect.y1 = dest_r.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
device = vpp->device;
|
||||||
|
status = device->vdp_video_mixer_render (vpp->mixer, VDP_INVALID_HANDLE, NULL,
|
||||||
|
VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, 0, NULL,
|
||||||
|
GST_VDP_VIDEO_BUFFER (buffer)->surface, 0, NULL, NULL, outbuf->surface,
|
||||||
|
NULL, &rect, 0, NULL);
|
||||||
|
if (status != VDP_STATUS_OK) {
|
||||||
|
GST_ELEMENT_ERROR (vpp, RESOURCE, READ,
|
||||||
|
("Could not post process frame"),
|
||||||
|
("Error returned from vdpau was: %s",
|
||||||
|
device->vdp_get_error_string (status)));
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_buffer_copy_metadata (GST_BUFFER (outbuf), buffer,
|
||||||
|
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
|
||||||
|
|
||||||
|
ret = gst_pad_push (vpp->srcpad, GST_BUFFER (outbuf));
|
||||||
|
|
||||||
|
done:
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
gst_object_unref (vpp);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
invalid_caps:
|
||||||
|
gst_buffer_unref (GST_BUFFER (outbuf));
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
gst_vdp_vpp_sink_getcaps (GstPad * pad)
|
||||||
|
{
|
||||||
|
GstVdpVideoPostProcess *vpp =
|
||||||
|
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
if (vpp->device)
|
||||||
|
caps = gst_vdp_video_buffer_get_allowed_video_caps (vpp->device);
|
||||||
|
else
|
||||||
|
caps = gst_static_pad_template_get_caps (&sink_template);
|
||||||
|
|
||||||
|
gst_object_unref (vpp);
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vdp_vpp_sink_bufferalloc (GstPad * pad, guint64 offset, guint size,
|
||||||
|
GstCaps * caps, GstBuffer ** buf)
|
||||||
|
{
|
||||||
|
GstVdpVideoPostProcess *vpp =
|
||||||
|
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
|
||||||
|
GstVdpOutputBuffer *outbuf;
|
||||||
|
GstFlowReturn ret = GST_FLOW_ERROR;
|
||||||
|
GstVdpDevice *device = NULL;
|
||||||
|
GstStructure *structure;
|
||||||
|
gint width, height;
|
||||||
|
gint chroma_type;
|
||||||
|
|
||||||
|
if (!vpp->device) {
|
||||||
|
/* if we haven't got a device yet we must alloc a buffer downstream to get it */
|
||||||
|
GstCaps *src_caps = gst_pad_get_allowed_caps (vpp->srcpad);
|
||||||
|
gst_pad_fixate_caps (vpp->srcpad, src_caps);
|
||||||
|
ret = gst_pad_alloc_buffer (vpp->srcpad, 0, 0, src_caps,
|
||||||
|
(GstBuffer **) & outbuf);
|
||||||
|
|
||||||
|
gst_caps_unref (src_caps);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
device = outbuf->device;
|
||||||
|
gst_buffer_unref (GST_BUFFER (outbuf));
|
||||||
|
} else
|
||||||
|
device = vpp->device;
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
|
if (!gst_structure_get_int (structure, "width", &width) ||
|
||||||
|
!gst_structure_get_int (structure, "height", &height) ||
|
||||||
|
!gst_structure_get_int (structure, "chroma-type", &chroma_type))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
*buf = GST_BUFFER (gst_vdp_video_buffer_new (device,
|
||||||
|
chroma_type, width, height));
|
||||||
|
|
||||||
|
if (*buf == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
GST_BUFFER_SIZE (*buf) = size;
|
||||||
|
GST_BUFFER_OFFSET (*buf) = offset;
|
||||||
|
|
||||||
|
gst_buffer_set_caps (*buf, caps);
|
||||||
|
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
gst_object_unref (vpp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vdp_vpp_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstVdpVideoPostProcess *vpp =
|
||||||
|
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_FLUSH_STOP:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (vpp, "flush stop");
|
||||||
|
|
||||||
|
gst_vdp_vpp_flush (vpp);
|
||||||
|
res = gst_pad_push_event (vpp->srcpad, event);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
res = gst_pad_event_default (pad, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_object_unref (vpp);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstStateChangeReturn
|
||||||
|
gst_vdp_vpp_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
{
|
||||||
|
GstVdpVideoPostProcess *vpp;
|
||||||
|
GstStateChangeReturn ret;
|
||||||
|
|
||||||
|
vpp = GST_VDP_VIDEO_POST_PROCESS (element);
|
||||||
|
|
||||||
|
switch (transition) {
|
||||||
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
|
gst_vdp_vpp_start (vpp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||||
|
|
||||||
|
switch (transition) {
|
||||||
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
|
gst_vdp_vpp_stop (vpp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GObject vmethod implementations */
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_get_property (GObject * object, guint property_id, GValue * value,
|
||||||
|
GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstVdpVideoPostProcess *vpp = GST_VDP_VIDEO_POST_PROCESS (object);
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_FORCE_ASPECT_RATIO:
|
||||||
|
g_value_set_boolean (value, vpp->force_aspect_ratio);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GObject vmethod implementations */
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_set_property (GObject * object, guint property_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstVdpVideoPostProcess *vpp = GST_VDP_VIDEO_POST_PROCESS (object);
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_FORCE_ASPECT_RATIO:
|
||||||
|
vpp->force_aspect_ratio = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GType vmethod implementations */
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_base_init (gpointer gclass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (element_class,
|
||||||
|
"VDPAU Mpeg Decoder",
|
||||||
|
"Filter/Converter/Decoder/Video",
|
||||||
|
"Post process GstVdpVideoBuffers and output GstVdpOutputBuffers",
|
||||||
|
"Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&sink_template));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&src_template));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize the vdpaumpegdecoder's class */
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_class_init (GstVdpVideoPostProcessClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
GstElementClass *gstelement_class;
|
||||||
|
|
||||||
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
|
gobject_class->get_property = gst_vdp_vpp_get_property;
|
||||||
|
gobject_class->set_property = gst_vdp_vpp_set_property;
|
||||||
|
gobject_class->finalize = gst_vdp_vpp_finalize;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
|
||||||
|
g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
|
||||||
|
"When enabled, the plugin will only scale up the input surface to the"
|
||||||
|
"maximum size where the aspect ratio can be preserved", FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
gstelement_class->change_state = gst_vdp_vpp_change_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_init (GstVdpVideoPostProcess * vpp,
|
||||||
|
GstVdpVideoPostProcessClass * gclass)
|
||||||
|
{
|
||||||
|
vpp->force_aspect_ratio = FALSE;
|
||||||
|
|
||||||
|
/* SRC PAD */
|
||||||
|
vpp->srcpad = gst_pad_new_from_static_template (&src_template, "src");
|
||||||
|
gst_element_add_pad (GST_ELEMENT (vpp), vpp->srcpad);
|
||||||
|
|
||||||
|
/* SINK PAD */
|
||||||
|
vpp->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
|
||||||
|
gst_element_add_pad (GST_ELEMENT (vpp), vpp->sinkpad);
|
||||||
|
|
||||||
|
gst_pad_set_getcaps_function (vpp->sinkpad, gst_vdp_vpp_sink_getcaps);
|
||||||
|
gst_pad_set_setcaps_function (vpp->sinkpad, gst_vdp_vpp_set_caps);
|
||||||
|
gst_pad_set_chain_function (vpp->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_vdp_vpp_chain));
|
||||||
|
gst_pad_set_event_function (vpp->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_vdp_vpp_sink_event));
|
||||||
|
gst_pad_set_bufferalloc_function (vpp->sinkpad, gst_vdp_vpp_sink_bufferalloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vdp_vpp_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
}
|
60
sys/vdpau/gstvdpvideopostprocess.h
Normal file
60
sys/vdpau/gstvdpvideopostprocess.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_VDP_VIDEO_POST_PROCESS_H__
|
||||||
|
#define __GST_VDP_VIDEO_POST_PROCESS_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "gstvdpdevice.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_VDP_VIDEO_POST_PROCESS (gst_vdp_vpp_get_type())
|
||||||
|
#define GST_VDP_VIDEO_POST_PROCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_VIDEO_POST_PROCESS,GstVdpVideoPostProcess))
|
||||||
|
#define GST_VDP_VIDEO_POST_PROCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_VIDEO_POST_PROCESS,GstVdpVideoPostProcessClass))
|
||||||
|
#define GST_IS_VDP_VIDEO_POST_PROCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_VIDEO_POST_PROCESS))
|
||||||
|
#define GST_IS_VDP_VIDEO_POST_PROCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_VIDEO_POST_PROCESS))
|
||||||
|
|
||||||
|
typedef struct _GstVdpVideoPostProcess GstVdpVideoPostProcess;
|
||||||
|
typedef struct _GstVdpVideoPostProcessClass GstVdpVideoPostProcessClass;
|
||||||
|
|
||||||
|
struct _GstVdpVideoPostProcess
|
||||||
|
{
|
||||||
|
GstElement element;
|
||||||
|
|
||||||
|
GstPad *sinkpad, *srcpad;
|
||||||
|
|
||||||
|
GstVdpDevice *device;
|
||||||
|
VdpVideoMixer mixer;
|
||||||
|
|
||||||
|
gboolean force_aspect_ratio;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstVdpVideoPostProcessClass
|
||||||
|
{
|
||||||
|
GstElementClass element_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_vdp_vpp_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_VDP_VIDEO_POST_PROCESS_H__ */
|
|
@ -236,7 +236,9 @@ gst_vdp_video_yuv_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS);
|
gst_buffer_copy_metadata (outbuf, inbuf,
|
||||||
|
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
|
||||||
|
|
||||||
GST_LOG_OBJECT (video_yuv, "Pushing buffer with ts %" GST_TIME_FORMAT,
|
GST_LOG_OBJECT (video_yuv, "Pushing buffer with ts %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
|
||||||
|
|
||||||
|
@ -322,7 +324,7 @@ gst_vdp_video_yuv_transform_caps (GstBaseTransform * trans,
|
||||||
GstPadDirection direction, GstCaps * caps)
|
GstPadDirection direction, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans);
|
GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (trans);
|
||||||
GstCaps *result;
|
GstCaps *result = NULL;
|
||||||
|
|
||||||
if (direction == GST_PAD_SINK)
|
if (direction == GST_PAD_SINK)
|
||||||
result = gst_vdp_video_to_yuv_caps (caps, video_yuv->device);
|
result = gst_vdp_video_to_yuv_caps (caps, video_yuv->device);
|
||||||
|
@ -406,7 +408,7 @@ gst_vdp_video_yuv_base_init (gpointer klass)
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class,
|
gst_element_class_set_details_simple (element_class,
|
||||||
"VdpauVideoYUV",
|
"VdpauVideoYUV",
|
||||||
"Covideo_yuv/Decoder/Video",
|
"Filter/Converter/Decoder/Video",
|
||||||
"VDPAU video surface to YUV",
|
"VDPAU video surface to YUV",
|
||||||
"Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>");
|
"Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>");
|
||||||
|
|
||||||
|
|
|
@ -233,7 +233,8 @@ gst_vdp_yuv_video_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS);
|
gst_buffer_copy_metadata (outbuf, inbuf,
|
||||||
|
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +263,7 @@ gst_vdp_yuv_video_transform_caps (GstBaseTransform * trans,
|
||||||
GstPadDirection direction, GstCaps * caps)
|
GstPadDirection direction, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstVdpYUVVideo *yuv_video = GST_VDP_YUV_VIDEO (trans);
|
GstVdpYUVVideo *yuv_video = GST_VDP_YUV_VIDEO (trans);
|
||||||
GstCaps *result;
|
GstCaps *result = NULL;
|
||||||
|
|
||||||
if (direction == GST_PAD_SINK) {
|
if (direction == GST_PAD_SINK) {
|
||||||
result = gst_vdp_yuv_to_video_caps (caps, yuv_video->device);
|
result = gst_vdp_yuv_to_video_caps (caps, yuv_video->device);
|
||||||
|
@ -305,7 +306,7 @@ gst_vdp_yuv_video_base_init (gpointer klass)
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class,
|
gst_element_class_set_details_simple (element_class,
|
||||||
"VdpauYUVVideo",
|
"VdpauYUVVideo",
|
||||||
"Coyuv_video/Decoder/Video",
|
"Filter/Converter/Decoder/Video",
|
||||||
"VDPAU video surface to YUV",
|
"VDPAU video surface to YUV",
|
||||||
"Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>");
|
"Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue