diff options
Diffstat (limited to 'ext/mplex/gstmplex.cc')
-rw-r--r-- | ext/mplex/gstmplex.cc | 741 |
1 files changed, 274 insertions, 467 deletions
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 +) |