diff options
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | sys/Makefile.am | 10 | ||||
-rw-r--r-- | sys/dxr3/Makefile.am | 11 | ||||
-rw-r--r-- | sys/dxr3/gstdxr3.c | 37 | ||||
-rw-r--r-- | sys/dxr3/gstdxr3videosink.c | 382 | ||||
-rw-r--r-- | sys/dxr3/gstdxr3videosink.h | 85 |
6 files changed, 530 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index bea6e4ab..d8fe94ab 100644 --- a/configure.ac +++ b/configure.ac @@ -190,6 +190,12 @@ dnl ============================= sys plugins ================================ dnl ========================================================================== +dnl *** DXR3 card *** +translit(dnm, m, l) AM_CONDITIONAL(USE_DXR3, true) +GST_CHECK_FEATURE(DXR3, [DXR3 hardware mpeg video decoder], dxr3videosink, [ + AC_CHECK_HEADER(linux/em8000.h, HAVE_DXR3="yes", HAVE_DXR3="no") +]) + dnl *** OSS audio *** translit(dnm, m, l) AM_CONDITIONAL(USE_OSS, true) GST_CHECK_FEATURE(OSS, [OSS audio], osssrc osssink, [ @@ -762,6 +768,7 @@ gst/vumeter/Makefile gst/wavparse/Makefile gst/y4m/Makefile sys/Makefile +sys/dxr3/Makefile sys/oss/Makefile sys/qcam/Makefile sys/v4l/Makefile diff --git a/sys/Makefile.am b/sys/Makefile.am index c915c897..8c6db9af 100644 --- a/sys/Makefile.am +++ b/sys/Makefile.am @@ -1,3 +1,9 @@ +if USE_DXR3 +DXR3_DIR=dxr3 +else +DXR3_DIR= +endif + if USE_OSS OSS_DIR=oss else @@ -34,8 +40,8 @@ else XVIDEO_DIR= endif -SUBDIRS=$(OSS_DIR) $(QCAM_DIR) $(V4L_DIR) $(VCD_DIR) \ +SUBDIRS=$(OSS_DIR) $(DXR3_DIR) $(QCAM_DIR) $(V4L_DIR) $(VCD_DIR) \ $(VGA_DIR) $(XVIDEO_DIR) -DIST_SUBDIRS=oss qcam v4l vcd vga xvideo videosink +DIST_SUBDIRS=oss dxr3 qcam v4l vcd vga xvideo videosink diff --git a/sys/dxr3/Makefile.am b/sys/dxr3/Makefile.am new file mode 100644 index 00000000..3edc8384 --- /dev/null +++ b/sys/dxr3/Makefile.am @@ -0,0 +1,11 @@ +plugindir = $(libdir)/gst + +plugin_LTLIBRARIES = libgstdxr3.la + +libgstdxr3_la_SOURCES = gstdxr3videosink.c gstdxr3.c +libgstdxr3_la_CFLAGS = $(GST_CFLAGS) +libgstdxr3_la_LIBADD = +libgstdxr3_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = gstdxr3videosink.h + diff --git a/sys/dxr3/gstdxr3.c b/sys/dxr3/gstdxr3.c new file mode 100644 index 00000000..594afd89 --- /dev/null +++ b/sys/dxr3/gstdxr3.c @@ -0,0 +1,37 @@ +#include "gstdxr3video.h" + + +static GstElementDetails dxr3_video_sink_details = { + "dxr3/Hollywood+ mpeg decoder board plugin", + "video/mpeg", + "Outputs PAL/NTSC video via the dxr3/Hollywood+ mpeg decoder board", + VERSION, + "Rehan Khwaja <rehankhwaja@yahoo.com>", + "(C) 2002", +}; + + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *video_factory; + + video_factory = gst_elementfactory_new("dxr3videosink", GST_TYPE_DXR3_VIDEO_SINK, &dxr3_video_sink_details); + g_return_val_if_fail(video_factory != NULL, FALSE); + + gst_elementfactory_add_padtemplate (video_factory, GST_PADTEMPLATE_GET (dxr3_video_sink_factory)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (video_factory)); + + return TRUE; +} + + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "dxr3", + plugin_init +}; + + diff --git a/sys/dxr3/gstdxr3videosink.c b/sys/dxr3/gstdxr3videosink.c new file mode 100644 index 00000000..24dbed39 --- /dev/null +++ b/sys/dxr3/gstdxr3videosink.c @@ -0,0 +1,382 @@ +/* GStreamer DXR3 Hardware MPEG video decoder plugin + * Copyright (C) <2002> Rehan Khwaja <rehankhwaja@yahoo.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. + */ + + +#include <string.h> +#include <fcntl.h> +#include "gstdxr3videosink.h" +#include <sys/ioctl.h> +#include <linux/em8300.h> + + +enum { + ARG_0, + ARG_TV_MODE, + ARG_DEVICE, + ARG_ASPECT_RATIO + /* TODO - + * DIGITAL/ANALOG AUDIO OUT + * OVERLAY MODE + * SET BCS?? what's that? + * OVERLAY ATTRIBUTES - where on the screen to put image + * OVERLAY WINDOW - as above + * OVERLAY KEYCOLOR + * OVERLAY SIGNAL MODE + * PLAYMODE - pausing, playing, slow forward etc + */ +}; + +static void gst_dxr3_video_sink_class_init (GstDxr3VideoSinkClass *klass); +static void gst_dxr3_video_sink_init (GstDxr3VideoSink *example); + +static void gst_dxr3_video_sink_chain (GstPad *pad, GstBuffer *buf); + +static void gst_dxr3_video_sink_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +static void gst_dxr3_video_sink_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); +static gboolean gst_dxr3_video_sink_handle_event (GstPad *pad, GstEvent *event); +static void gst_dxr3_video_sink_set_clock (GstElement *element, GstClock *clock); + + +static GstElementClass *parent_class = NULL; + + +#define GST_TYPE_DXR3_VIDEO_SINK_ASPECT_RATIOS (gst_dxr3_video_sink_aspect_ratios_get_type()) +static GType +gst_dxr3_video_sink_aspect_ratios_get_type(void) { + static GType dxr3_video_sink_aspect_ratio_type = 0; + static GEnumValue dxr3_video_sink_aspect_ratios[] = { + {0, "0", "4:3"}, + {1, "1", "16:9"}, + {0, NULL, NULL}, + }; + if (!dxr3_video_sink_aspect_ratio_type) { + dxr3_video_sink_aspect_ratio_type = g_enum_register_static("GstDxr3VideoSinkAspectRatios", dxr3_video_sink_aspect_ratios); + } + return dxr3_video_sink_aspect_ratio_type; +} + +#define GST_TYPE_DXR3_VIDEO_SINK_TV_MODES (gst_dxr3_video_sink_tv_modes_get_type()) +static GType +gst_dxr3_video_sink_tv_modes_get_type(void) { + static GType dxr3_video_sink_tv_mode_type = 0; + static GEnumValue dxr3_video_sink_tv_modes[] = { + {0, "0", "NTSC"}, + {1, "1", "PAL"}, + {0, NULL, NULL}, + }; + if (!dxr3_video_sink_tv_mode_type) { + dxr3_video_sink_tv_mode_type = g_enum_register_static("GstDxr3VideoSinkTvModes", dxr3_video_sink_tv_modes); + } + return dxr3_video_sink_tv_mode_type; +} + +static void +gst_dxr3_video_sink_set_clock(GstElement *element, GstClock *clock) +{ + GstDxr3VideoSink *dxr3_video_sink; + + dxr3_video_sink = GST_DXR3_VIDEO_SINK(element); + dxr3_video_sink->clock = clock; +} + +GType +gst_dxr3_video_sink_get_type(void) +{ + static GType dxr3_video_sink_type = 0; + + if (!dxr3_video_sink_type) { + static const GTypeInfo dxr3_video_sink_info = { + sizeof(GstDxr3VideoSinkClass), NULL, + NULL, + (GClassInitFunc)gst_dxr3_video_sink_class_init, + NULL, + NULL, + sizeof(GstDxr3VideoSink), + 0, + (GInstanceInitFunc)gst_dxr3_video_sink_init, + }; + dxr3_video_sink_type = g_type_register_static(GST_TYPE_ELEMENT, "GstDxr3VideoSink", &dxr3_video_sink_info, 0); + } + return dxr3_video_sink_type; +} + +static gchar * +gst_dxr3_video_sink_get_control_device(GstDxr3VideoSink *dxr3_video_sink) +{ + return g_strdup_printf("/dev/em8300-%d", dxr3_video_sink->device_number); +} + +static gchar * +gst_dxr3_video_sink_get_video_device(GstDxr3VideoSink *dxr3_video_sink) +{ + return g_strdup_printf("/dev/em8300_mv-%d", dxr3_video_sink->device_number); +} + +static void +gst_dxr3_video_sink_class_init (GstDxr3VideoSinkClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = g_type_class_ref(GST_TYPE_ELEMENT); + + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TV_MODE, + g_param_spec_enum("tv-mode","tv-mode","sets NTSC/PAL output format", + GST_TYPE_DXR3_VIDEO_SINK_TV_MODES, 0, G_PARAM_READWRITE)); + + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE, + g_param_spec_int("device","device","sets/returns board number", + 0,3,0,G_PARAM_READWRITE)); + + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ASPECT_RATIO, + g_param_spec_enum("aspect-ratio", "aspect-ratio", "sets/returns aspect ratio", + GST_TYPE_DXR3_VIDEO_SINK_ASPECT_RATIOS, 0, G_PARAM_READWRITE)); + + gobject_class->set_property = gst_dxr3_video_sink_set_property; + gobject_class->get_property = gst_dxr3_video_sink_get_property; +} + +static void +gst_dxr3_video_sink_open_device(GstDxr3VideoSink *dxr3_video_sink) +{ + gchar *video_device_path; + + video_device_path = gst_dxr3_video_sink_get_video_device(dxr3_video_sink); + if (dxr3_video_sink->device){ + fclose(dxr3_video_sink->device); + } + /* this is what disksink uses */ + dxr3_video_sink->device = fopen(video_device_path, "w"); + + g_free(video_device_path); +} + +static void +gst_dxr3_video_sink_init(GstDxr3VideoSink *dxr3_video_sink) +{ + dxr3_video_sink->sinkpad = gst_pad_new_from_template ( + GST_PADTEMPLATE_GET (dxr3_video_sink_factory), "video_sink"); + gst_pad_set_chain_function(dxr3_video_sink->sinkpad, gst_dxr3_video_sink_chain); + gst_element_add_pad(GST_ELEMENT(dxr3_video_sink),dxr3_video_sink->sinkpad); + + dxr3_video_sink->device_number = 0; + dxr3_video_sink->device = 0; + /* FIXME - should only have device open when necessary + * which probably requires handling events? + * also, when is this device closed? + */ + gst_dxr3_video_sink_open_device(dxr3_video_sink); + + GST_FLAG_SET (GST_ELEMENT(dxr3_video_sink), GST_ELEMENT_EVENT_AWARE); + gst_pad_set_event_function(dxr3_video_sink->sinkpad, gst_dxr3_video_sink_handle_event); + + dxr3_video_sink->clock = NULL; + GST_ELEMENT(dxr3_video_sink)->setclockfunc = gst_dxr3_video_sink_set_clock; +} + +static gboolean +gst_dxr3_video_sink_handle_event(GstPad *pad, GstEvent *event) +{ + GstEventType type; + + type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN; + + switch (type) { + case GST_EVENT_SEEK: + g_print("seek event\n\n"); + break; + case GST_EVENT_NEW_MEDIA: + g_print("new media event\n\n"); + break; + case GST_EVENT_FLUSH: + g_print("flush event\n\n"); + break; + default: + g_print("event\n\n"); + gst_pad_event_default (pad, event); + break; + } + + return TRUE; +} + +static void +gst_dxr3_video_sink_chain (GstPad *pad, GstBuffer *buf) +{ + GstDxr3VideoSink *dxr3_video_sink; + long pts; + + /* Some of these checks are of dubious value, since if there were not + * already true, the chain function would never be called. + */ + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + dxr3_video_sink = GST_DXR3_VIDEO_SINK(gst_pad_get_parent (pad)); + + g_return_if_fail(dxr3_video_sink != NULL); + g_return_if_fail(GST_IS_DXR3_VIDEO_SINK(dxr3_video_sink)); + + /* Copy the data in the incoming buffer onto the device. */ + fwrite(GST_BUFFER_DATA (buf), 1, GST_BUFFER_SIZE (buf), dxr3_video_sink->device); + pts = (long)GST_BUFFER_TIMESTAMP(buf); + if (-1 == ioctl((int)dxr3_video_sink->device, EM8300_IOCTL_VIDEO_SETPTS, &pts)){ + GST_DEBUG(0, "FAILED call to EM8300_IOCTL_VIDEO_SETPTS\n"); + } + + gst_buffer_unref (buf); +} + +static void +gst_dxr3_video_sink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstDxr3VideoSink *dxr3_video_sink; + int device; + gchar *device_path; + int tv_mode_ioctl, aspect_ratio_ioctl; + + g_return_if_fail(GST_IS_DXR3_VIDEO_SINK(object)); + + dxr3_video_sink = GST_DXR3_VIDEO_SINK(object); + + switch (prop_id) { + case ARG_TV_MODE: + device_path = gst_dxr3_video_sink_get_control_device(dxr3_video_sink); + device = open(device_path, O_WRONLY); + if (device == -1){ + GST_DEBUG(0, "failed to open control device\n"); + break; + } + switch(g_value_get_int(value)){ + case 0: + tv_mode_ioctl = EM8300_VIDEOMODE_NTSC; + break; + case 1: + tv_mode_ioctl = EM8300_VIDEOMODE_PAL; + break; + case 2: + tv_mode_ioctl = EM8300_VIDEOMODE_PAL60; + break; + } + if (-1 == ioctl(device, EM8300_IOCTL_SET_VIDEOMODE, &tv_mode_ioctl)){ + GST_DEBUG (0,"failed to set tv-mode\n"); + } + close(device); + break; + case ARG_DEVICE: + dxr3_video_sink->device_number = g_value_get_int(value); + gst_dxr3_video_sink_open_device(dxr3_video_sink); + break; + case ARG_ASPECT_RATIO: + device_path = gst_dxr3_video_sink_get_control_device(dxr3_video_sink); + device = open(device_path, O_WRONLY); + if (device == -1){ + GST_DEBUG(0, "failed to open control device\n"); + break; + } + switch(g_value_get_enum(value)){ + case 0: + aspect_ratio_ioctl = EM8300_ASPECTRATIO_4_3; + break; + case 1: + aspect_ratio_ioctl = EM8300_ASPECTRATIO_16_9; + break; + } + if (-1 == ioctl(device, EM8300_IOCTL_SET_ASPECTRATIO, &aspect_ratio_ioctl)){ + GST_DEBUG(0, "failed to set aspect-ratio\n"); + } + break; + default: + break; + } +} + +static void +gst_dxr3_video_sink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstDxr3VideoSink *dxr3_video_sink; + gint device; + gchar *device_path; + int tv_mode_ioctl, aspect_ratio_ioctl; + + g_return_if_fail(GST_IS_DXR3_VIDEO_SINK(object)); + dxr3_video_sink = GST_DXR3_VIDEO_SINK(object); + + switch (prop_id) { + case ARG_TV_MODE: + device_path = gst_dxr3_video_sink_get_control_device(dxr3_video_sink); + tv_mode_ioctl = 0; + device = open(device_path, O_WRONLY); + if (-1 == device){ + GST_DEBUG(0, "failed to open control device\n"); + break; + } + if (-1 == ioctl(device, EM8300_IOCTL_GET_VIDEOMODE, &tv_mode_ioctl)){ + GST_DEBUG(0, "failed to get tv-mode\n"); + } + close(device); + + switch(tv_mode_ioctl){ + case EM8300_VIDEOMODE_NTSC: + g_value_set_enum(value, 0); + break; + case EM8300_VIDEOMODE_PAL: + g_value_set_enum(value, 1); + break; + case EM8300_VIDEOMODE_PAL60: + g_value_set_enum(value, 2); + break; + } + break; + case ARG_DEVICE: + g_value_set_int(value, dxr3_video_sink->device_number); + break; + case ARG_ASPECT_RATIO: + device_path = gst_dxr3_video_sink_get_control_device(dxr3_video_sink); + aspect_ratio_ioctl = 0; + device = open(device_path, O_WRONLY); + if (-1 == device){ + GST_DEBUG(0, "failed to open control device\n"); + break; + } + if (-1 == ioctl(device, EM8300_IOCTL_GET_ASPECTRATIO, &aspect_ratio_ioctl)){ + GST_DEBUG(0, "failed to get aspect ratio\n"); + } + close(device); + + switch(aspect_ratio_ioctl){ + case EM8300_ASPECTRATIO_4_3: + g_value_set_enum(value, 0); + break; + case EM8300_ASPECTRATIO_16_9: + g_value_set_enum(value, 1); + break; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/dxr3/gstdxr3videosink.h b/sys/dxr3/gstdxr3videosink.h new file mode 100644 index 00000000..48adfc84 --- /dev/null +++ b/sys/dxr3/gstdxr3videosink.h @@ -0,0 +1,85 @@ +/* GStreamer DXR3 Hardware MPEG video decoder plugin + * Copyright (C) <2002> Rehan Khwaja <rehankhwaja@yahoo.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_DXR3_VIDEO_SINK_H__ +#define __GST_DXR3_VIDEO_SINK_H__ + +#include <gst/gst.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +typedef struct _GstDxr3VideoSink GstDxr3VideoSink; +struct _GstDxr3VideoSink; + +struct _GstDxr3VideoSink { + GstElement element; + + /* board number */ + gint device_number; + + /* file handle for the video device */ + FILE *device; + + GstClock *clock; + + /* our only pad */ + GstPad *sinkpad; +}; + + +typedef struct _GstDxr3VideoSinkClass GstDxr3VideoSinkClass; + +struct _GstDxr3VideoSinkClass { + GstElementClass parent_class; +}; + + +#define GST_TYPE_DXR3_VIDEO_SINK \ + (gst_dxr3_video_sink_get_type()) +#define GST_DXR3_VIDEO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DXR3_VIDEO_SINK,GstDxr3VideoSink)) +#define GST_DXR3_VIDEO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DXR3_VIDEO_SINK,GstDxr3VideoSink)) +#define GST_IS_DXR3_VIDEO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DXR3_VIDEO_SINK)) +#define GST_IS_DXR3_VIDEO_SINK_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DXR3_VIDEO_SINK)) + + +GType gst_dxr3_video_sink_get_type(void); + + +GST_PADTEMPLATE_FACTORY (dxr3_video_sink_factory, + "sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + gst_caps_new ("video_sink", "video/mpeg", NULL) +); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_DXR3_VIDEO_SINK_H__ */ |