summaryrefslogtreecommitdiffstats
path: root/ext/mplex/gstmplex.cc
diff options
context:
space:
mode:
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>2004-01-01 22:45:57 +0000
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>2004-01-01 22:45:57 +0000
commit9003ed34ba8e694b44433597c890affac369c368 (patch)
treedca1fa1b1decb37f42397813935add00b4f13182 /ext/mplex/gstmplex.cc
parent0e3024712e2a935d1f5b216cd4d7794a0132c522 (diff)
downloadgst-plugins-bad-9003ed34ba8e694b44433597c890affac369c368.tar.gz
gst-plugins-bad-9003ed34ba8e694b44433597c890affac369c368.tar.bz2
gst-plugins-bad-9003ed34ba8e694b44433597c890affac369c368.zip
configure.ac: Fix configure check for mpeg2enc. We need 1.6.1.93 instead of 1.6.1.92, since the pkg-config file of 1....
Original commit message from CVS: 2004-01-01 Ronald Bultje <rbultje@ronald.bitfreak.net> * configure.ac: Fix configure check for mpeg2enc. We need 1.6.1.93 instead of 1.6.1.92, since the pkg-config file of 1.6.1.92 is borked and it therefore uses the wrong include paths. Too bad... Note that 1.6.1.93 is not release yet. ;). Also add a check for mplex, which is now using the lib'ified mplex from mjpegtools, too. * ext/ffmpeg/gstffmpegcodecmap.c: Add codec_tag for 3ivx/xvid. For xvid, this should fix playback issues. I don't think ffmpeg handles 3ivx correctly, so this probably won't work. But it won't hurt either. * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_connect), (gst_ffmpegdec_chain): * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_connect), (gst_ffmpegenc_chain_audio): Fix memleak in audio encoding. Close codec if open fails, this calls the cleanup routines so we can re-use the context. * ext/mpeg2enc/gstmpeg2enc.cc: Fix pad template names/types, fix memory issue with getcaps(). * ext/mpeg2enc/gstmpeg2encoder.cc: * ext/mpeg2enc/gstmpeg2encoder.hh: Fix compile issue with new caps system (const thingy). * ext/mpeg2enc/gstmpeg2encpicturereader.cc: * ext/mpeg2enc/gstmpeg2encpicturereader.hh: We read a first frame right on initing, so that we have a caps when we init the output. This caps is cached in padprivate and read as first frame. * ext/mplex/Makefile.am: * ext/mplex/gstmplex.cc: * ext/mplex/gstmplex.h: * ext/mplex/gstmplex.hh: * ext/mplex/gstmplexibitstream.cc: * ext/mplex/gstmplexibitstream.hh: * ext/mplex/gstmplexjob.cc: * ext/mplex/gstmplexjob.hh: * ext/mplex/gstmplexoutputstream.cc: * ext/mplex/gstmplexoutputstream.hh: We wrap mjpegtools mplex. So I rewrote the plugin. The old plugin had issues, didn't do capsnego, supported only a subset of the mplex features and required a mplex fork in our local CVS. Plus that it worked agaist a very old mplex version. Rewriting was faster than updating it. * gst-libs/ext/Makefile.am: * gst-libs/ext/mplex/INSTRUCT: * gst-libs/ext/mplex/Makefile.am: * gst-libs/ext/mplex/README: * gst-libs/ext/mplex/TODO: * gst-libs/ext/mplex/ac3strm_in.cc: * gst-libs/ext/mplex/audiostrm.hh: * gst-libs/ext/mplex/audiostrm_out.cc: * gst-libs/ext/mplex/aunit.hh: * gst-libs/ext/mplex/bits.cc: * gst-libs/ext/mplex/bits.hh: * gst-libs/ext/mplex/buffer.cc: * gst-libs/ext/mplex/buffer.hh: * gst-libs/ext/mplex/fastintfns.h: * gst-libs/ext/mplex/format_codes.h: * gst-libs/ext/mplex/inputstrm.cc: * gst-libs/ext/mplex/inputstrm.hh: * gst-libs/ext/mplex/lpcmstrm_in.cc: * gst-libs/ext/mplex/mjpeg_logging.cc: * gst-libs/ext/mplex/mjpeg_logging.h: * gst-libs/ext/mplex/mjpeg_types.h: * gst-libs/ext/mplex/mpastrm_in.cc: * gst-libs/ext/mplex/mpegconsts.cc: * gst-libs/ext/mplex/mpegconsts.h: * gst-libs/ext/mplex/mplexconsts.hh: * gst-libs/ext/mplex/multplex.cc: * gst-libs/ext/mplex/outputstream.hh: * gst-libs/ext/mplex/padstrm.cc: * gst-libs/ext/mplex/padstrm.hh: * gst-libs/ext/mplex/stillsstream.cc: * gst-libs/ext/mplex/stillsstream.hh: * gst-libs/ext/mplex/systems.cc: * gst-libs/ext/mplex/systems.hh: * gst-libs/ext/mplex/vector.cc: * gst-libs/ext/mplex/vector.hh: * gst-libs/ext/mplex/videostrm.hh: * gst-libs/ext/mplex/videostrm_in.cc: * gst-libs/ext/mplex/videostrm_out.cc: * gst-libs/ext/mplex/yuv4mpeg.cc: * gst-libs/ext/mplex/yuv4mpeg.h: * gst-libs/ext/mplex/yuv4mpeg_intern.h: * gst-libs/ext/mplex/yuv4mpeg_ratio.cc: We don't fork mjpegtools' mplex in our CVS anymore. * gst/avi/gstavidemux.c: (gst_avi_demux_src_getcaps), (gst_avi_demux_add_stream): * gst/avi/gstavidemux.h: Add getcaps() function for proper caps nego. This makes some parts of AVI playback/reading work. * sys/ximage/ximagesink.c: (gst_ximagesink_sinkconnect): Resize window on new capsnego. This is probably wrong, but I'm still committing it because with current capsnego, the first successfull capsnego is auto-fixated, therefore rounded down to the lowest values in the caps. this results in a 16x16 XWindow that is not reized when real capsnego finishes. Dave, I see more cases of this, do you know a proper solution? * tools/gst-launch-ext.in: Fix MPEG-4 AAC (Apple iPod/iTunes) file commandline.
Diffstat (limited to 'ext/mplex/gstmplex.cc')
-rw-r--r--ext/mplex/gstmplex.cc741
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
+)