diff options
Diffstat (limited to 'ext/mplex')
-rw-r--r-- | ext/mplex/Makefile.am | 20 | ||||
-rw-r--r-- | ext/mplex/gstmplex.cc | 741 | ||||
-rw-r--r-- | ext/mplex/gstmplex.h | 103 | ||||
-rw-r--r-- | ext/mplex/gstmplex.hh | 64 | ||||
-rw-r--r-- | ext/mplex/gstmplexibitstream.cc | 112 | ||||
-rw-r--r-- | ext/mplex/gstmplexibitstream.hh | 50 | ||||
-rw-r--r-- | ext/mplex/gstmplexjob.cc | 232 | ||||
-rw-r--r-- | ext/mplex/gstmplexjob.hh | 42 | ||||
-rw-r--r-- | ext/mplex/gstmplexoutputstream.cc | 101 | ||||
-rw-r--r-- | ext/mplex/gstmplexoutputstream.hh | 54 |
10 files changed, 942 insertions, 577 deletions
diff --git a/ext/mplex/Makefile.am b/ext/mplex/Makefile.am index 5f9d847f..d99b5b7c 100644 --- a/ext/mplex/Makefile.am +++ b/ext/mplex/Makefile.am @@ -1,11 +1,17 @@ - plugin_LTLIBRARIES = libgstmplex.la -libgstmplex_la_SOURCES = gstmplex.cc -libgstmplex_la_CXXFLAGS = $(GST_CFLAGS) -I$(top_srcdir)/gst-libs/ext/mplex/ -libgstmplex_la_LIBADD = $(LIBM_LIBS) $(top_builddir)/gst-libs/ext/mplex/libmplex.la -libgstmplex_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) - -noinst_HEADERS = gstmplex.h +libgstmplex_la_SOURCES = \ + gstmplex.cc \ + gstmplexibitstream.cc \ + gstmplexjob.cc \ + gstmplexoutputstream.cc +libgstmplex_la_CXXFLAGS = $(GST_CFLAGS) $(MPLEX_CFLAGS) +libgstmplex_la_LIBADD = $(MPLEX_LIBS) +libgstmplex_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +noinst_HEADERS = \ + gstmplex.hh \ + gstmplexibitstream.hh \ + gstmplexjob.hh \ + gstmplexoutputstream.hh diff --git a/ext/mplex/gstmplex.cc b/ext/mplex/gstmplex.cc index 7de9ab56..1ad948af 100644 --- a/ext/mplex/gstmplex.cc +++ b/ext/mplex/gstmplex.cc @@ -1,5 +1,7 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> +/* GStreamer mplex (mjpegtools) wrapper + * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * gstmplex.cc: gstreamer mplex wrapper * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,562 +23,368 @@ #include "config.h" #endif -#include <string.h> - -#include "gstmplex.h" - -#include "videostrm.hh" -#include "audiostrm.hh" - - -/* elementfactory information */ -static GstElementDetails gst_mplex_details = { - "MPlex multiplexer", - "Codec/Muxer", - "multiplex mpeg audio and video into a system stream", - "Wim Taymans <wim.taymans@chello.be> ", -}; - -/* Sidec signals and args */ -enum { - /* FILL ME */ - LAST_SIGNAL -}; - -enum { - ARG_0, - ARG_MUX_FORMAT, - ARG_MUX_BITRATE, - ARG_VIDEO_BUFFER, - ARG_SYNC_OFFSET, - ARG_SECTOR_SIZE, - ARG_VBR, - ARG_PACKETS_PER_PACK, - ARG_SYSTEM_HEADERS, - /* FILL ME */ -}; - -static GstStaticPadTemplate src_factory = +#include "gstmplex.hh" +#include "gstmplexoutputstream.hh" +#include "gstmplexibitstream.hh" +#include "gstmplexjob.hh" + +static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ( "src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/mpeg, " - "mpegversion = (int) [ 1, 2 ], " + GST_STATIC_CAPS ( + "video/mpeg, " "systemstream = (boolean) true" ) ); -static GstStaticPadTemplate video_sink_factory = +static GstStaticPadTemplate video_sink_templ = GST_STATIC_PAD_TEMPLATE ( "video_%d", GST_PAD_SINK, GST_PAD_REQUEST, - GST_STATIC_CAPS ("video/mpeg, " + GST_STATIC_CAPS ( + "video/mpeg, " "mpegversion = (int) [ 1, 2 ], " "systemstream = (boolean) false" ) ); - -static GstStaticPadTemplate audio_sink_factory = + +static GstStaticPadTemplate audio_sink_templ = GST_STATIC_PAD_TEMPLATE ( "audio_%d", GST_PAD_SINK, GST_PAD_REQUEST, - GST_STATIC_CAPS ("audio/mpeg, " + GST_STATIC_CAPS ( + "audio/mpeg, " "mpegversion = (int) 1, " - "layer = (int) [ 1, 3 ]" + "layer = (int) [ 1, 2 ]; " + "audio/x-ac3; " + "audio/x-dts; " + "audio/x-raw-int, " + "endianness = (int) BYTE_ORDER, " + "signed = (boolean) TRUE, " + "width = (int) { 16, 20, 24 }, " + "depth = (int) { 16, 20, 24 }, " + "rate = (int) { 48000, 96000 }, " + "channels = (int) [ 1, 6 ]" ) ); -static GstStaticPadTemplate private_1_sink_factory = -GST_STATIC_PAD_TEMPLATE ( - "private_stream_1_%d", - GST_PAD_SINK, - GST_PAD_REQUEST, - GST_STATIC_CAPS ("audio/x-ac3") -); +/* FIXME: subtitles */ -static GstStaticPadTemplate private_2_sink_factory = -GST_STATIC_PAD_TEMPLATE ( - "private_stream_2", - GST_PAD_SINK, - GST_PAD_REQUEST, - GST_STATIC_CAPS_ANY -); +static void gst_mplex_base_init (GstMplexClass *klass); +static void gst_mplex_class_init (GstMplexClass *klass); +static void gst_mplex_init (GstMplex *enc); +static void gst_mplex_dispose (GObject *object); -#define GST_TYPE_MPLEX_MUX_FORMAT (gst_mplex_mux_format_get_type()) -static GType -gst_mplex_mux_format_get_type (void) -{ - static GType mplex_mux_format_type = 0; - static GEnumValue mplex_mux_format[] = { - { MPEG_FORMAT_MPEG1, "0", "Generic MPEG1" }, - { MPEG_FORMAT_VCD, "1", "VCD" }, - { MPEG_FORMAT_VCD_NSR, "2", "user-rate VCD" }, - { MPEG_FORMAT_MPEG2, "3", "Generic MPEG2" }, - { MPEG_FORMAT_SVCD, "4", "SVCD" }, - { MPEG_FORMAT_SVCD_NSR, "5", "user-rate SVCD" }, - { MPEG_FORMAT_VCD_STILL, "6", "VCD Stills" }, - { MPEG_FORMAT_SVCD_STILL, "7", "SVCD Stills" }, - { MPEG_FORMAT_DVD, "8", "DVD" }, - {0, NULL, NULL}, - }; - if (!mplex_mux_format_type) { - mplex_mux_format_type = g_enum_register_static("GstMPlexMuxFormat", mplex_mux_format); - } - return mplex_mux_format_type; -} +static void gst_mplex_loop (GstElement *element); + +static GstPad *gst_mplex_request_new_pad (GstElement *element, + GstPadTemplate *templ, + const gchar *name); + +static GstElementStateReturn + gst_mplex_change_state (GstElement *element); -static void gst_mplex_base_init (gpointer g_class); -static void gst_mplex_class_init (GstMPlex *klass); -static void gst_mplex_init (GstMPlex *mplex); - -static GstPad* gst_mplex_request_new_pad (GstElement *element, - GstPadTemplate *templ, - const gchar *req_name); -static void gst_mplex_loop (GstElement *element); -static size_t gst_mplex_read_callback (BitStream *bitstream, - uint8_t *dest, size_t size, - void *user_data); -static size_t gst_mplex_write_callback (PS_Stream *stream, - uint8_t *data, size_t size, - void *user_data); - -static void gst_mplex_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); -static void gst_mplex_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec); +static void gst_mplex_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void gst_mplex_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); static GstElementClass *parent_class = NULL; -//static guint gst_mplex_signals[LAST_SIGNAL] = { 0 }; GType -gst_mplex_get_type (void) +gst_mplex_get_type (void) { - static GType mplex_type = 0; + static GType gst_mplex_type = 0; - if (!mplex_type) { - static const GTypeInfo mplex_info = { - sizeof(GstMPlexClass), - gst_mplex_base_init, + if (!gst_mplex_type) { + static const GTypeInfo gst_mplex_info = { + sizeof (GstMplexClass), + (GBaseInitFunc) gst_mplex_base_init, NULL, (GClassInitFunc) gst_mplex_class_init, NULL, NULL, - sizeof(GstMPlex), + sizeof (GstMplex), 0, (GInstanceInitFunc) gst_mplex_init, - NULL }; - mplex_type = g_type_register_static (GST_TYPE_ELEMENT, "GstMPlex", &mplex_info, (GTypeFlags)0); + + gst_mplex_type = + g_type_register_static (GST_TYPE_ELEMENT, + "GstMplex", + &gst_mplex_info, + (GTypeFlags) 0); } - return mplex_type; + return gst_mplex_type; } static void -gst_mplex_base_init (gpointer g_class) +gst_mplex_base_init (GstMplexClass *klass) { - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory)); - gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&audio_sink_factory)); - gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&video_sink_factory)); - gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&private_1_sink_factory)); - gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&private_2_sink_factory)); - - gst_element_class_set_details (element_class, &gst_mplex_details); + static GstElementDetails gst_mplex_details = { + "mplex video multiplexer", + "Codec/Muxer", + "High-quality MPEG/DVD/SVCD/VCD video/audio multiplexer", + "Andrew Stevens <andrew.stevens@nexgo.de>\n" + "Ronald Bultje <rbultje@ronald.bitfreak.net>" + }; + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&video_sink_templ)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&audio_sink_templ)); + gst_element_class_set_details (element_class, + &gst_mplex_details); } static void -gst_mplex_class_init (GstMPlex *klass) +gst_mplex_class_init (GstMplexClass *klass) { - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass*)klass; - gstelement_class = (GstElementClass*)klass; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); parent_class = GST_ELEMENT_CLASS (g_type_class_ref (GST_TYPE_ELEMENT)); - gobject_class->set_property = gst_mplex_set_property; - gobject_class->get_property = gst_mplex_get_property; - - g_object_class_install_property (gobject_class, ARG_MUX_FORMAT, - g_param_spec_enum ("mux_format", "Mux format", "Set defaults for particular MPEG profiles", - GST_TYPE_MPLEX_MUX_FORMAT, MPEG_FORMAT_MPEG1, (GParamFlags) G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, ARG_MUX_BITRATE, - g_param_spec_int ("mux_bitrate", "Mux bitrate", "Specify data rate of output stream in kbit/sec" - "(0 = Compute from source streams)", - 0, G_MAXINT, 0, (GParamFlags) G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, ARG_VIDEO_BUFFER, - g_param_spec_int ("video_buffer", "Video buffer", "Specifies decoder buffers size in kB", - 20, 2000, 20, (GParamFlags) G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, ARG_SYNC_OFFSET, - g_param_spec_int ("sync_offset", "Sync offset", "Specify offset of timestamps (video-audio) in mSec", - G_MININT, G_MAXINT, 0, (GParamFlags) G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, ARG_SECTOR_SIZE, - g_param_spec_int ("sector_size", "Sector size", "Specify sector size in bytes for generic formats", - 256, 16384, 2028, (GParamFlags) G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, ARG_VBR, - g_param_spec_boolean ("vbr", "VBR", "Multiplex variable bit-rate video", - TRUE, (GParamFlags) G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, ARG_PACKETS_PER_PACK, - g_param_spec_int ("packets_per_pack", "Packets per pack", - "Number of packets per pack generic formats", - 1, 100, 1, (GParamFlags) G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, ARG_SYSTEM_HEADERS, - g_param_spec_boolean ("system_headers", "System headers", - " Create System header in every pack in generic formats", - TRUE, (GParamFlags) G_PARAM_READWRITE)); - - gstelement_class->request_new_pad = gst_mplex_request_new_pad; -} - -static void -gst_mplex_init (GstMPlex *mplex) -{ - mplex->srcpad = gst_pad_new_from_template ( - gst_static_pad_template_get (&src_factory), "src"); - gst_element_add_pad (GST_ELEMENT (mplex), mplex->srcpad); - - gst_element_set_loop_function (GST_ELEMENT (mplex), gst_mplex_loop); + /* register arguments */ + mjpeg_default_handler_verbosity (0); + GstMplexJob::initProperties (object_class); - mplex->ostrm = new OutputStream (); - mplex->strms = new vector<ElementaryStream *>(); + object_class->set_property = gst_mplex_set_property; + object_class->get_property = gst_mplex_get_property; - mplex->state = GST_MPLEX_OPEN_STREAMS; + object_class->dispose = gst_mplex_dispose; - mplex->ostrm->opt_mux_format = 0; - - (void)mjpeg_default_handler_verbosity(mplex->ostrm->opt_verbosity); + element_class->change_state = gst_mplex_change_state; + element_class->request_new_pad = gst_mplex_request_new_pad; } -static GstPadLinkReturn -gst_mplex_video_link (GstPad *pad, const GstCaps *caps) -{ - GstMPlex *mplex; - gint version; - GstMPlexStream *stream; - GstStructure *structure; - - mplex = GST_MPLEX (gst_pad_get_parent (pad)); - - stream = (GstMPlexStream *) gst_pad_get_element_private (pad); - - structure = gst_caps_get_structure (caps, 0); - - if (!gst_structure_get_int (structure, "mpegversion", &version)){ - return GST_PAD_LINK_REFUSED; - } +static void +gst_mplex_dispose (GObject *object) +{ + GstMplex *mplex = GST_MPLEX (object); - if (version == 2) { - stream->type = GST_MPLEX_STREAM_DVD_VIDEO; - } - else { - stream->type = GST_MPLEX_STREAM_VIDEO; + if (mplex->mux) { + delete mplex->mux; + mplex->mux = NULL; } - - return GST_PAD_LINK_OK; + delete mplex->job; } - -static GstPad* -gst_mplex_request_new_pad (GstElement *element, - GstPadTemplate *templ, - const gchar *req_name) +static void +gst_mplex_init (GstMplex *mplex) { - GstMPlexStream *stream; - GstMPlex *mplex; - GstPad *pad = NULL; + GstElement *element = GST_ELEMENT (mplex); - mplex = GST_MPLEX (element); - - stream = g_new0 (GstMPlexStream, 1); + GST_FLAG_SET (element, GST_ELEMENT_EVENT_AWARE); - if (!strncmp (templ->name_template, "audio", 5)) { - gchar *name = g_strdup_printf (templ->name_template, mplex->num_audio); - - pad = gst_pad_new (name, GST_PAD_SINK); - g_free (name); - - stream->type = GST_MPLEX_STREAM_MPA; - } - else if (!strncmp (templ->name_template, "video", 5)) { - gchar *name = g_strdup_printf (templ->name_template, mplex->num_video); + mplex->srcpad = gst_pad_new_from_template ( + gst_element_get_pad_template (element, "src"), "src"); + gst_element_add_pad (element, mplex->srcpad); - pad = gst_pad_new (name, GST_PAD_SINK); - /* we still need to figure out the mpeg version */ - gst_pad_set_link_function (pad, gst_mplex_video_link); - g_free (name); + mplex->job = new GstMplexJob (); + mplex->mux = NULL; + mplex->num_apads = 0; + mplex->num_vpads = 0; - stream->type = GST_MPLEX_STREAM_UNKOWN; - } - else if (!strncmp (templ->name_template, "private_stream_1", 16)) { - gchar *name = g_strdup_printf (templ->name_template, mplex->num_private1); + gst_element_set_loop_function (element, gst_mplex_loop); +} - pad = gst_pad_new (name, GST_PAD_SINK); - g_free (name); +static void +gst_mplex_loop (GstElement *element) +{ + GstMplex *mplex = GST_MPLEX (element); + + if (!mplex->mux) { + GstMplexOutputStream *out; + const GList *item; + + for (item = gst_element_get_pad_list (element); + item != NULL; item = item->next) { + StreamKind type; + GstMplexIBitStream *inputstream; + JobStream *jobstream; + GstPad *pad = GST_PAD (item->data); + GstStructure *structure; + const GstCaps *caps; + const gchar *mime; + + /* skip our source pad */ + if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) + continue; + + /* create inputstream, assure we've got caps */ + inputstream = new GstMplexIBitStream (pad); + + /* skip unnegotiated pads */ + if (!(caps = GST_PAD_CAPS (pad))) { + delete inputstream; + continue; + } - stream->type = GST_MPLEX_STREAM_AC3; - } - else if (!strncmp (templ->name_template, "private_stream_2", 16)) { - pad = gst_pad_new ("private_stream_2", GST_PAD_SINK); + /* get format */ + structure = gst_caps_get_structure (caps, 0); + mime = gst_structure_get_name (structure); + + if (!strcmp (mime, "video/mpeg")) { + VideoParams *params; + + type = MPEG_VIDEO; + + params = VideoParams::Default (mplex->job->mux_format); + mplex->job->video_param.push_back (params); + mplex->job->video_tracks++; + } else if (!strcmp (mime, "audio/mpeg")) { + type = MPEG_AUDIO; + mplex->job->audio_tracks++; + } else if (!strcmp (mime, "audio/x-ac3")) { + type = AC3_AUDIO; + mplex->job->audio_tracks++; + } else if (!strcmp (mime, "audio/x-dts")) { + type = DTS_AUDIO; + mplex->job->audio_tracks++; + } else if (!strcmp (mime, "audio/x-raw-int")) { + LpcmParams *params; + gint bits, chans, rate; + + type = LPCM_AUDIO; + + /* set LPCM params */ + gst_structure_get_int (structure, "depth", &bits); + gst_structure_get_int (structure, "rate", &rate); + gst_structure_get_int (structure, "channels", &chans); + params = LpcmParams::Checked (rate, chans, bits); + + mplex->job->lpcm_param.push_back (params); + mplex->job->audio_tracks++; + mplex->job->lpcm_tracks++; + } else { + delete inputstream; + continue; + } - stream->type = GST_MPLEX_STREAM_UNKOWN; - } - - if (pad) { - stream->pad = pad; - stream->bitstream = new IBitStream(); - stream->bytestream = gst_bytestream_new (pad); - stream->eos = FALSE; + jobstream = new JobStream (inputstream, type); + mplex->job->streams.push_back (jobstream); + } - mplex->streams = g_list_prepend (mplex->streams, stream); + if (!mplex->job->video_tracks && !mplex->job->audio_tracks) { + gst_element_error (element, + "No input stream set-up"); + return; + } - gst_element_add_pad (element, pad); - gst_pad_set_element_private (pad, stream); - } - else { - /* no pad, free our stream again */ - g_free (stream); + /* create new encoder with inputs/output */ + out = new GstMplexOutputStream (element, mplex->srcpad); + mplex->mux = new Multiplexor (*mplex->job, *out); } - return pad; + mplex->mux->Multiplex (); } - -static size_t -gst_mplex_read_callback (BitStream *bitstream, uint8_t *dest, size_t size, void *user_data) +static GstPadLinkReturn +gst_mplex_sink_link (GstPad *pad, + const GstCaps *caps) { - GstMPlexStream *stream; - guint8 *data; - guint32 len; - - stream = (GstMPlexStream *) user_data; - - if (stream->eos) - return 0; - - do { - len = gst_bytestream_peek_bytes (stream->bytestream, &data, size); - if (len < size) { - guint32 avail= 0; - GstEvent *event = NULL; - - gst_bytestream_get_status (stream->bytestream, &avail, &event); - if (event != NULL) { - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - stream->eos = TRUE; - break; - default: - break; - } - gst_event_unref (event); - } - } - } - while (len == 0); - - memcpy (dest, data, len); - - gst_bytestream_flush_fast (stream->bytestream, len); - - return len; -} + GstStructure *structure = gst_caps_get_structure (caps, 0); + const gchar *mime = gst_structure_get_name (structure); -static size_t -gst_mplex_write_callback (PS_Stream *stream, uint8_t *data, size_t size, void *user_data) -{ - GstMPlex *mplex; - GstBuffer *outbuf; + /* raw audio caps needs to be fixed */ + if (!strcmp (mime, "audio/x-raw-int")) { + gint width, depth; - mplex = GST_MPLEX (user_data); + if (!gst_caps_is_fixed (caps)) + return GST_PAD_LINK_DELAYED; - if (GST_PAD_IS_USABLE (mplex->srcpad)) { - outbuf = gst_buffer_new_and_alloc (size); - memcpy (GST_BUFFER_DATA (outbuf), data, size); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "depth", &depth); - gst_pad_push (mplex->srcpad, GST_DATA (outbuf)); + if (depth != width) + return GST_PAD_LINK_REFUSED; } - return size; + /* we do the actual inputstream setup in our first loopfunc cycle */ +g_print ("Pad %s linked with caps %s\n", + gst_pad_get_name (pad), + gst_caps_to_string (caps)); + return GST_PAD_LINK_OK; } -static void -gst_mplex_loop (GstElement *element) +static GstPad * +gst_mplex_request_new_pad (GstElement *element, + GstPadTemplate *templ, + const gchar *name) { - GstMPlex *mplex; - - mplex = GST_MPLEX (element); - - switch (mplex->state) { - case GST_MPLEX_OPEN_STREAMS: - { - mplex->ostrm->InitSyntaxParameters(); - - GList *walk = mplex->streams; - while (walk) { - GstMPlexStream *stream = (GstMPlexStream *) walk->data; - - stream->bitstream->open (gst_mplex_read_callback, stream); - - switch (stream->type) { - case GST_MPLEX_STREAM_MPA: - { - MPAStream *mpastream; - - mpastream = new MPAStream(*stream->bitstream, *mplex->ostrm); - mpastream->Init(0); - stream->elem_stream = mpastream; - break; - } - case GST_MPLEX_STREAM_AC3: - { - AC3Stream *ac3stream; - - ac3stream = new AC3Stream(*stream->bitstream, *mplex->ostrm); - ac3stream->Init(0); - stream->elem_stream = ac3stream; - break; - } - case GST_MPLEX_STREAM_DVD_VIDEO: - { - DVDVideoStream *dvdstream; - - dvdstream = new DVDVideoStream(*stream->bitstream, *mplex->ostrm); - dvdstream->Init(0); - stream->elem_stream = dvdstream; - break; - } - case GST_MPLEX_STREAM_VIDEO: - { - VideoStream *videostream; - - videostream = new VideoStream(*stream->bitstream, *mplex->ostrm); - videostream->Init(0); - stream->elem_stream = videostream; - break; - } - default: - break; - } - mplex->strms->push_back(stream->elem_stream); - - walk = g_list_next (walk); - } - - mplex->ps_stream = new PS_Stream (gst_mplex_write_callback, mplex); - mplex->ostrm->Init (mplex->strms, mplex->ps_stream); - - /* move to running state after this */ - mplex->state = GST_MPLEX_RUN; - break; - } - case GST_MPLEX_RUN: - if (!mplex->ostrm->OutputMultiplex()) { - mplex->state = GST_MPLEX_END; - } - break; - case GST_MPLEX_END: - { - mplex->ostrm->Close (); - gst_pad_push (mplex->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS))); - gst_element_set_eos (element); - break; - } - default: - break; + GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); + GstMplex *mplex = GST_MPLEX (element); + gchar *padname; + GstPad *newpad; + + if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) { + padname = g_strdup_printf ("audio_%d", mplex->num_apads++); + } else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) { + padname = g_strdup_printf ("video_%d", mplex->num_vpads++); + } else { + g_warning ("mplex: this is not our template!"); + return NULL; } + newpad = gst_pad_new_from_template (templ, padname); + gst_pad_set_link_function (newpad, gst_mplex_sink_link); + gst_element_add_pad (element, newpad); + g_free (padname); + + return newpad; } -static void -gst_mplex_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +static void +gst_mplex_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - GstMPlex *mplex; - - mplex = GST_MPLEX(object); - - switch(prop_id) { - case ARG_MUX_FORMAT: - mplex->ostrm->opt_mux_format = g_value_get_enum (value); - break; - case ARG_MUX_BITRATE: - mplex->data_rate = g_value_get_int (value); - mplex->ostrm->opt_data_rate = ((mplex->data_rate * 1000 / 8 + 49) / 50) * 50; - break; - case ARG_VIDEO_BUFFER: - mplex->ostrm->opt_buffer_size = g_value_get_int (value); - break; - case ARG_SYNC_OFFSET: - { - mplex->sync_offset = g_value_get_int (value); - if (mplex->sync_offset < 0) { - mplex->ostrm->opt_audio_offset = -mplex->sync_offset; - mplex->ostrm->opt_video_offset = 0; - } - else { - mplex->ostrm->opt_video_offset = mplex->sync_offset; - } - break; - } - case ARG_SECTOR_SIZE: - mplex->ostrm->opt_sector_size = g_value_get_int (value); - break; - case ARG_VBR: - mplex->ostrm->opt_VBR = g_value_get_boolean (value); - break; - case ARG_PACKETS_PER_PACK: - mplex->ostrm->opt_packets_per_pack = g_value_get_int (value); - break; - case ARG_SYSTEM_HEADERS: - mplex->ostrm->opt_always_system_headers = g_value_get_boolean (value); - break; - default: - //G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - return; - } + GST_MPLEX (object)->job->getProperty (prop_id, value); } -static void -gst_mplex_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +static void +gst_mplex_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - GstMPlex *mplex; - - mplex = GST_MPLEX(object); + GST_MPLEX (object)->job->setProperty (prop_id, value); +} - switch(prop_id) { - case ARG_MUX_FORMAT: - g_value_set_enum (value, mplex->ostrm->opt_mux_format); - break; - case ARG_MUX_BITRATE: - g_value_set_int (value, mplex->data_rate); - break; - case ARG_VIDEO_BUFFER: - g_value_set_int (value, mplex->ostrm->opt_buffer_size); - break; - case ARG_SYNC_OFFSET: - g_value_set_int (value, mplex->sync_offset); - break; - case ARG_SECTOR_SIZE: - g_value_set_int (value, mplex->ostrm->opt_sector_size); - break; - case ARG_VBR: - g_value_set_boolean (value, mplex->ostrm->opt_VBR); - break; - case ARG_PACKETS_PER_PACK: - g_value_set_int (value, mplex->ostrm->opt_packets_per_pack); - break; - case ARG_SYSTEM_HEADERS: - g_value_set_boolean (value, mplex->ostrm->opt_always_system_headers); +static GstElementStateReturn +gst_mplex_change_state (GstElement *element) +{ + GstMplex *mplex = GST_MPLEX (element); + + switch (GST_STATE_TRANSITION (element)) { + case GST_STATE_PAUSED_TO_READY: + delete mplex->mux; + mplex->mux = NULL; + mplex->num_apads = 0; + mplex->num_vpads = 0; break; default: - //G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + + if (parent_class->change_state) + return parent_class->change_state (element); + + return GST_STATE_SUCCESS; } static gboolean @@ -585,20 +393,19 @@ plugin_init (GstPlugin *plugin) if (!gst_library_load ("gstbytestream")) return FALSE; - if (!gst_element_register (plugin, "mplex", GST_RANK_NONE, GST_TYPE_MPLEX)) - return FALSE; - - return TRUE; + return gst_element_register (plugin, "mplex", + GST_RANK_NONE, + GST_TYPE_MPLEX); } GST_PLUGIN_DEFINE ( GST_VERSION_MAJOR, GST_VERSION_MINOR, "mplex", - "MPlexs an audio and video stream into a system stream", + "High-quality MPEG/DVD/SVCD/VCD video/audio multiplexer", plugin_init, VERSION, - "LGPL", + "GPL", GST_PACKAGE, - GST_ORIGIN) - + GST_ORIGIN +) diff --git a/ext/mplex/gstmplex.h b/ext/mplex/gstmplex.h deleted file mode 100644 index 20107252..00000000 --- a/ext/mplex/gstmplex.h +++ /dev/null @@ -1,103 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * 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_MPLEX_H__ -#define __GST_MPLEX_H__ - - -#include <stdlib.h> - -#include <gst/gst.h> -#include <gst/bytestream/bytestream.h> - -#include "outputstream.hh" -#include "bits.hh" - - -G_BEGIN_DECLS - -#define GST_TYPE_MPLEX \ - (gst_mplex_get_type()) -#define GST_MPLEX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MPLEX,GstMPlex)) -#define GST_MPLEX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MPLEX,GstMPlex)) -#define GST_IS_MPLEX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MPLEX)) -#define GST_IS_MPLEX_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MPLEX)) - -typedef enum { - GST_MPLEX_INIT, - GST_MPLEX_OPEN_STREAMS, - GST_MPLEX_RUN, - GST_MPLEX_END -} GstMPlexState; - -typedef enum { - GST_MPLEX_STREAM_UNKOWN, - GST_MPLEX_STREAM_AC3, - GST_MPLEX_STREAM_MPA, - GST_MPLEX_STREAM_LPCM, - GST_MPLEX_STREAM_VIDEO, - GST_MPLEX_STREAM_DVD_VIDEO, -} GstMPlexStreamType; - -typedef struct _GstMPlex GstMPlex; -typedef struct _GstMPlexStream GstMPlexStream; -typedef struct _GstMPlexClass GstMPlexClass; - -struct _GstMPlexStream { - IBitStream *bitstream; - ElementaryStream *elem_stream; - GstPad *pad; - GstMPlexStreamType type; - GstByteStream *bytestream; - gboolean eos; -}; - -struct _GstMPlex { - GstElement element; - - GstMPlexState state; - /* pads */ - GstPad *srcpad; - GList *streams; - - vector<ElementaryStream *> *strms; - OutputStream *ostrm; - PS_Stream *ps_stream; - gint data_rate; - gint sync_offset; - - gint num_video; - gint num_audio; - gint num_private1; -}; - -struct _GstMPlexClass { - GstElementClass parent_class; -}; - -GType gst_mplex_get_type (void); - -G_END_DECLS - -#endif /* __GST_MPLEX_H__ */ diff --git a/ext/mplex/gstmplex.hh b/ext/mplex/gstmplex.hh new file mode 100644 index 00000000..e8497ed6 --- /dev/null +++ b/ext/mplex/gstmplex.hh @@ -0,0 +1,64 @@ +/* GStreamer mplex (mjpegtools) wrapper + * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * gstmplex.hh: gstreamer mplex wrapper + * + * 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_MPLEX_H__ +#define __GST_MPLEX_H__ + +#include <gst/gst.h> +#include <multiplexor.hpp> +#include "gstmplexjob.hh" + +G_BEGIN_DECLS + +#define GST_TYPE_MPLEX \ + (gst_mplex_get_type ()) +#define GST_MPLEX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MPLEX, GstMplex)) +#define GST_MPLEX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MPLEX, GstMplex)) +#define GST_IS_MPLEX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MPLEX)) +#define GST_IS_MPLEX_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MPLEX)) + +typedef struct _GstMplex { + GstElement parent; + + /* pads */ + GstPad *sinkpad, *srcpad; + guint num_apads, num_vpads; + + /* options wrapper */ + GstMplexJob *job; + + /* general muxing object (contains rest) */ + Multiplexor *mux; +} GstMplex; + +typedef struct _GstMplexClass { + GstElementClass parent; +} GstMplexClass; + +GType gst_mplex_get_type (void); + +G_END_DECLS + +#endif /* __GST_MPLEX_H__ */ diff --git a/ext/mplex/gstmplexibitstream.cc b/ext/mplex/gstmplexibitstream.cc new file mode 100644 index 00000000..59f913a6 --- /dev/null +++ b/ext/mplex/gstmplexibitstream.cc @@ -0,0 +1,112 @@ +/* GStreamer mplex (mjpegtools) wrapper + * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * gstmplexibitstream.hh: gstreamer/mplex input bitstream wrapper + * + * 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 <string.h> + +#include "gstmplexibitstream.hh" + +/* + * Class init/exit functions. + */ + +GstMplexIBitStream::GstMplexIBitStream (GstPad *_pad, + guint buf_size) : + IBitStream () +{ + guint8 *data; + + pad = _pad; + bs = gst_bytestream_new (pad); + eos = FALSE; + + streamname = g_strdup (gst_pad_get_name (_pad)); + + SetBufSize (buf_size); + eobs = false; + byteidx = 0; + + /* we peek 1 byte (not even caring about the return value) so we + * are sure that we have data and thus capsnego must be completed + * when we return. */ + gst_bytestream_peek_bytes (bs, &data, 1); + + if (!ReadIntoBuffer () && buffered == 0) { + gst_element_error (gst_pad_get_parent (_pad), + "Failed to read from input stream %s", + gst_pad_get_name (pad)); + } +} + +GstMplexIBitStream::~GstMplexIBitStream (void) +{ + gst_bytestream_destroy (bs); +} + +/* + * Read data. + */ + +size_t +GstMplexIBitStream::ReadStreamBytes (uint8_t *buf, + size_t size) +{ + guint8 *data; + guint read; + + if (eos) + return 0; + + if ((read = gst_bytestream_peek_bytes (bs, &data, size)) != size) { + GstEvent *event; + guint pending; + + gst_bytestream_get_status (bs, &pending, &event); + if (event) { + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + eos = TRUE; + break; + default: + break; + } + gst_event_unref (event); + } + } + + memcpy (buf, data, read); + gst_bytestream_flush_fast (bs, read); + + return read; +} + +/* + * Are we at EOS? + */ + +bool +GstMplexIBitStream::EndOfStream (void) +{ + return eos; +} diff --git a/ext/mplex/gstmplexibitstream.hh b/ext/mplex/gstmplexibitstream.hh new file mode 100644 index 00000000..504835a4 --- /dev/null +++ b/ext/mplex/gstmplexibitstream.hh @@ -0,0 +1,50 @@ +/* GStreamer mplex (mjpegtools) wrapper + * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * gstmplexibitstream.hh: gstreamer/mplex input bitstream wrapper + * + * 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_MPLEXIBITSTREAM_H__ +#define __GST_MPLEXIBITSTREAM_H__ + +#include <gst/gst.h> +#include <gst/bytestream/bytestream.h> +#include <mjpeg_types.h> +#include <bits.hpp> + +class GstMplexIBitStream : public IBitStream { +public: + GstMplexIBitStream (GstPad *pad, + guint buf_size = BUFFER_SIZE); + ~GstMplexIBitStream (void); + +protected: + /* read data */ + size_t ReadStreamBytes (uint8_t *buf, + size_t number); + + /* are we at EOS? */ + bool EndOfStream (void); + +private: + GstPad *pad; + GstByteStream *bs; + gboolean eos; +}; + +#endif /* __GST_MPLEXIBITSTREAM_H__ */ diff --git a/ext/mplex/gstmplexjob.cc b/ext/mplex/gstmplexjob.cc new file mode 100644 index 00000000..058ff9a4 --- /dev/null +++ b/ext/mplex/gstmplexjob.cc @@ -0,0 +1,232 @@ +/* GStreamer mplex (mjpegtools) wrapper + * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * gstmplexjob.hh: gstreamer/mplex multiplex-job wrapper + * + * 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 "gstmplexjob.hh" + + +enum { + ARG_0, + ARG_FORMAT, + ARG_MUX_BITRATE, + ARG_VBR, + ARG_SYSTEM_HEADERS, + ARG_SPLIT_SEQUENCE, + ARG_SEGMENT_SIZE, + ARG_PACKETS_PER_PACK, + ARG_SECTOR_SIZE, + ARG_WORKAROUND_MPLAYER_HDR + /* FILL ME */ +}; + +/* + * Property enumeration types. + */ + +#define GST_TYPE_MPLEX_FORMAT \ + (gst_mplex_format_get_type ()) + +static GType +gst_mplex_format_get_type (void) +{ + static GType mplex_format_type = 0; + + if (!mplex_format_type) { + static const GEnumValue mplex_formats[] = { + { 0, "0", "Generic MPEG-1" }, + { 1, "1", "Standard VCD" }, + { 2, "2", "User VCD" }, + { 3, "3", "Generic MPEG-2" }, + { 4, "4", "Standard SVCD" }, + { 5, "5", "User SVCD" }, + { 6, "6", "VCD Stills sequences" }, + { 7, "7", "SVCD Stills sequences" }, + { 8, "8", "DVD MPEG-2 for dvdauthor" }, + { 9, "9", "DVD MPEG-2" }, + { 0, NULL, NULL }, + }; + + mplex_format_type = + g_enum_register_static ("GstMplexFormat", + mplex_formats); + } + + return mplex_format_type; +} + +/* + * Class init functions. + */ + +GstMplexJob::GstMplexJob (void) : + MultiplexJob () +{ + /* blabla */ +} + +/* + * GObject properties. + */ + +void +GstMplexJob::initProperties (GObjectClass *klass) +{ + /* encoding profile */ + g_object_class_install_property (klass, ARG_FORMAT, + g_param_spec_enum ("format", "Format", "Encoding profile format", + GST_TYPE_MPLEX_FORMAT, 0, + (GParamFlags) G_PARAM_READWRITE)); + + /* total stream datarate. Normally, this shouldn't be needed, but + * some DVD/VCD/SVCD players really need strict values to handle + * the created files correctly. */ + g_object_class_install_property (klass, ARG_MUX_BITRATE, + g_param_spec_int ("mux-bitrate", "Mux. bitrate", + "Bitrate of output stream in kbps (0 = autodetect)", + 0, 15 * 1024, 0, (GParamFlags) G_PARAM_READWRITE)); + +#if 0 + { "video-buffer", 1, 0, 'b' }, +#endif + + /* some boolean stuff for headers */ + g_object_class_install_property (klass, ARG_VBR, + g_param_spec_boolean ("vbr", "VBR", + "Whether the input video stream is variable bitrate", + FALSE, (GParamFlags) G_PARAM_READWRITE)); + g_object_class_install_property (klass, ARG_SYSTEM_HEADERS, + g_param_spec_boolean ("system-headers", "System headers", + "Create system header in every pack for generic formats", + FALSE, (GParamFlags) G_PARAM_READWRITE)); + g_object_class_install_property (klass, ARG_SPLIT_SEQUENCE, + g_param_spec_boolean ("split-sequence", "Split sequence", + "Simply split a sequence across files " + "(rather than building run-out/run-in)", + FALSE, (GParamFlags) G_PARAM_READWRITE)); + + /* size of a segment (followed by EOS) */ + g_object_class_install_property (klass, ARG_SEGMENT_SIZE, + g_param_spec_int ("max-segment-size", "Max. segment size", + "Max. size per segment/file in MB (0 = unlimited)", + 0, 10 * 1024, 0, (GParamFlags) G_PARAM_READWRITE)); + + /* packets per pack (generic formats) */ + g_object_class_install_property (klass, ARG_PACKETS_PER_PACK, + g_param_spec_int ("packets-per-pack", "Packets per pack", + "Number of packets per pack for generic formats", + 1, 100, 1, (GParamFlags) G_PARAM_READWRITE)); + + /* size of one sector */ + g_object_class_install_property (klass, ARG_SECTOR_SIZE, + g_param_spec_int ("sector-size", "Sector size", + "Specify sector size in bytes for generic formats", + 256, 16384, 2048, (GParamFlags) G_PARAM_READWRITE)); + + /* workarounds */ + g_object_class_install_property (klass, ARG_WORKAROUND_MPLAYER_HDR, + g_param_spec_boolean ("mplayer-hdr-workaround", "MPlayer header workaround", + "Enable a workaround for bugs in MPlayer LCPM header parsing", + FALSE, (GParamFlags) G_PARAM_READWRITE)); +} + +/* + * set/get gobject properties. + */ + +void +GstMplexJob::getProperty (guint prop_id, + GValue *value) +{ + switch (prop_id) { + case ARG_FORMAT: + g_value_set_enum (value, mux_format); + break; + case ARG_MUX_BITRATE: + g_value_set_int (value, data_rate / 1000); + break; + case ARG_VBR: + g_value_set_boolean (value, VBR); + break; + case ARG_SYSTEM_HEADERS: + g_value_set_boolean (value, always_system_headers); + break; + case ARG_SPLIT_SEQUENCE: + g_value_set_boolean (value, multifile_segment); + break; + case ARG_SEGMENT_SIZE: + g_value_set_int (value, max_segment_size); + break; + case ARG_PACKETS_PER_PACK: + g_value_set_int (value, packets_per_pack); + break; + case ARG_SECTOR_SIZE: + g_value_set_int (value, sector_size); + break; + case ARG_WORKAROUND_MPLAYER_HDR: + g_value_set_boolean (value, workarounds.mplayer_pes_headers); + break; + default: + break; + } +} + +void +GstMplexJob::setProperty (guint prop_id, + const GValue *value) +{ + switch (prop_id) { + case ARG_FORMAT: + mux_format = g_value_get_enum (value); + break; + case ARG_MUX_BITRATE: + /* data_rate expects bytes (don't ask me why the property itself is + * in bits, I'm just staying compatible to mjpegtools options), and + * rounded up to 50-bytes. */ + data_rate = ((g_value_get_int (value) * 1000 / 8 + 49) / 50 ) * 50; + break; + case ARG_VBR: + VBR = g_value_get_boolean (value); + break; + case ARG_SYSTEM_HEADERS: + always_system_headers = g_value_get_boolean (value); + break; + case ARG_SPLIT_SEQUENCE: + multifile_segment = g_value_get_boolean (value); + break; + case ARG_SEGMENT_SIZE: + max_segment_size = g_value_get_int (value); + break; + case ARG_PACKETS_PER_PACK: + packets_per_pack = g_value_get_int (value); + break; + case ARG_SECTOR_SIZE: + sector_size = g_value_get_int (value); + break; + case ARG_WORKAROUND_MPLAYER_HDR: + workarounds.mplayer_pes_headers = g_value_get_boolean (value); + break; + default: + break; + } +} diff --git a/ext/mplex/gstmplexjob.hh b/ext/mplex/gstmplexjob.hh new file mode 100644 index 00000000..8aa5b14d --- /dev/null +++ b/ext/mplex/gstmplexjob.hh @@ -0,0 +1,42 @@ +/* GStreamer mplex (mjpegtools) wrapper + * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * gstmplexjob.hh: gstreamer/mplex multiplex-job wrapper + * + * 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_MPLEXJOB_H__ +#define __GST_MPLEXJOB_H__ + +#include <glib-object.h> +#include <interact.hpp> + +class GstMplexJob : public MultiplexJob { +public: + GstMplexJob (void); + + /* gobject properties */ + static void initProperties (GObjectClass *klass); + + /* set/get gobject properties */ + void getProperty (guint prop_id, + GValue *value); + void setProperty (guint prop_id, + const GValue *value); +}; + +#endif /* __GST_MPLEXJOB_H__ */ diff --git a/ext/mplex/gstmplexoutputstream.cc b/ext/mplex/gstmplexoutputstream.cc new file mode 100644 index 00000000..c0a2976d --- /dev/null +++ b/ext/mplex/gstmplexoutputstream.cc @@ -0,0 +1,101 @@ +/* GStreamer mplex (mjpegtools) wrapper + * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * gstmplexoutputstream.hh: gstreamer/mplex output stream wrapper + * + * 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 <string.h> + +#include "gstmplexoutputstream.hh" + +/* + * Class init functions. + */ + +GstMplexOutputStream::GstMplexOutputStream (GstElement *_element, + GstPad *_pad) : + OutputStream () +{ + element = _element; + pad = _pad; + size = 0; +} + +/* + * Open/close. Basically 'no-op's (close() sets EOS). + * + * Open (): -1 means failure, 0 means success. + */ + +int +GstMplexOutputStream::Open (void) +{ + return 0; +} + +void +GstMplexOutputStream::Close (void) +{ + gst_pad_push (pad, GST_DATA (gst_event_new (GST_EVENT_EOS))); + gst_element_set_eos (element); +} + +/* + * Get size of current segment. + */ + +off_t +GstMplexOutputStream::SegmentSize (void) +{ + return size; +} + +/* + * Next segment. + */ + +void +GstMplexOutputStream::NextSegment (void) +{ + size = 0; + + /* send EOS. The filesink (or whatever) handles that + * and opens a new file. */ + gst_pad_push (pad, GST_DATA (gst_event_new (GST_EVENT_EOS))); +} + +/* + * Write data. + */ + +void +GstMplexOutputStream::Write (guint8 *data, + guint len) +{ + GstBuffer *buf; + + buf = gst_buffer_new_and_alloc (len); + memcpy (GST_BUFFER_DATA (buf), data, len); + + size += len; + gst_pad_push (pad, GST_DATA (buf)); +} diff --git a/ext/mplex/gstmplexoutputstream.hh b/ext/mplex/gstmplexoutputstream.hh new file mode 100644 index 00000000..c67040b7 --- /dev/null +++ b/ext/mplex/gstmplexoutputstream.hh @@ -0,0 +1,54 @@ +/* GStreamer mplex (mjpegtools) wrapper + * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * gstmplexoutputstream.hh: gstreamer/mplex output stream wrapper + * + * 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_MPLEXOUTPUTSTREAM_H__ +#define __GST_MPLEXOUTPUTSTREAM_H__ + +#include <gst/gst.h> +#include <mjpeg_types.h> +#include <outputstrm.hpp> + +class GstMplexOutputStream : public OutputStream { +public: + GstMplexOutputStream (GstElement *element, + GstPad *pad); + + /* open/close. Basically 'no-op's (close() sets EOS). */ + int Open (void); + void Close (void); + + /* get size of current segment */ + off_t SegmentSize (void); + + /* next segment */ + void NextSegment (void); + + /* write data */ + void Write (guint8 *data, + guint len); + +private: + GstElement *element; + GstPad *pad; + guint64 size; +}; + +#endif /* __GST_MPLEXOUTPUTSTREAM_H__ */ |