From ea011a3266ad0dce040bfa5adb2b830e2be2985f Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Thu, 25 Apr 2019 20:23:03 +0200 Subject: [PATCH] mpegtsmux: provide API for subclasses to override stream creation --- gst/mpegtsmux/atscmux.c | 23 ++++++++++++++++++++++- gst/mpegtsmux/mpegtsmux.c | 36 ++++++++++++++++++++++++++++++------ gst/mpegtsmux/mpegtsmux.h | 8 ++++++++ gst/mpegtsmux/tsmux/tsmux.c | 26 +++++++++++++++++++++++++- gst/mpegtsmux/tsmux/tsmux.h | 5 +++++ 5 files changed, 90 insertions(+), 8 deletions(-) diff --git a/gst/mpegtsmux/atscmux.c b/gst/mpegtsmux/atscmux.c index c9f2777608..93c803fc63 100644 --- a/gst/mpegtsmux/atscmux.c +++ b/gst/mpegtsmux/atscmux.c @@ -25,10 +25,29 @@ GST_DEBUG_CATEGORY (atscmux_debug); #define GST_CAT_DEFAULT atscmux_debug G_DEFINE_TYPE (ATSCMux, atscmux, GST_TYPE_MPEG_TSMUX) +#define parent_class atscmux_parent_class + static TsMuxStream *atscmux_create_new_stream (guint16 new_pid, + TsMuxStreamType stream_type, MpegTsMux * mpegtsmux) +{ + return tsmux_stream_new (new_pid, stream_type); +} - static void atscmux_class_init (ATSCMuxClass * klass) +static TsMux * +atscmux_create_ts_mux (MpegTsMux * mpegtsmux) +{ + TsMux *ret = ((MpegTsMuxClass *) parent_class)->create_ts_mux (mpegtsmux); + + tsmux_set_new_stream_func (ret, + (TsMuxNewStreamFunc) atscmux_create_new_stream, mpegtsmux); + + return ret; +} + +static void +atscmux_class_init (ATSCMuxClass * klass) { GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + MpegTsMuxClass *mpegtsmux_class = (MpegTsMuxClass *) klass; GST_DEBUG_CATEGORY_INIT (atscmux_debug, "atscmux", 0, "ATSC muxer"); @@ -36,6 +55,8 @@ G_DEFINE_TYPE (ATSCMux, atscmux, GST_TYPE_MPEG_TSMUX) "ATSC Transport Stream Muxer", "Codec/Muxer", "Multiplexes media streams into an ATSC-compliant Transport Stream", "Mathieu Duponchelle "); + + mpegtsmux_class->create_ts_mux = atscmux_create_ts_mux; } static void diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c index d0f82b6eb4..c21d6865f8 100644 --- a/gst/mpegtsmux/mpegtsmux.c +++ b/gst/mpegtsmux/mpegtsmux.c @@ -171,6 +171,7 @@ static void gst_mpegtsmux_get_property (GObject * object, guint prop_id, static void mpegtsmux_reset (MpegTsMux * mux, gboolean alloc); static void mpegtsmux_dispose (GObject * object); +static void mpegtsmux_constructed (GObject * object); static void alloc_packet_cb (GstBuffer ** _buf, void *user_data); static gboolean new_packet_cb (GstBuffer * buf, void *user_data, gint64 new_pcr); @@ -200,6 +201,8 @@ static void mpegtsmux_set_header_on_caps (MpegTsMux * mux); static gboolean mpegtsmux_src_event (GstPad * pad, GstObject * parent, GstEvent * event); +static TsMux *mpegtsmux_default_create_ts_mux (MpegTsMux * mux); + #if 0 static void mpegtsmux_set_index (GstElement * element, GstIndex * index); static GstIndex *mpegtsmux_get_index (GstElement * element); @@ -260,12 +263,15 @@ mpegtsmux_class_init (MpegTsMuxClass * klass) gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_mpegtsmux_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_mpegtsmux_get_property); gobject_class->dispose = mpegtsmux_dispose; + gobject_class->constructed = mpegtsmux_constructed; gstelement_class->request_new_pad = mpegtsmux_request_new_pad; gstelement_class->release_pad = mpegtsmux_release_pad; gstelement_class->change_state = mpegtsmux_change_state; gstelement_class->send_event = mpegtsmux_send_event; + klass->create_ts_mux = mpegtsmux_default_create_ts_mux; + #if 0 gstelement_class->set_index = GST_DEBUG_FUNCPTR (mpegtsmux_set_index); gstelement_class->get_index = GST_DEBUG_FUNCPTR (mpegtsmux_get_index); @@ -347,9 +353,6 @@ mpegtsmux_init (MpegTsMux * mux) mux->prog_map = NULL; mux->alignment = MPEGTSMUX_DEFAULT_ALIGNMENT; mux->bitrate = TSMUX_DEFAULT_BITRATE; - - /* initial state */ - mpegtsmux_reset (mux, TRUE); } static void @@ -437,9 +440,11 @@ mpegtsmux_reset (MpegTsMux * mux, gboolean alloc) } if (alloc) { - mux->tsmux = tsmux_new (); - tsmux_set_write_func (mux->tsmux, new_packet_cb, mux); - tsmux_set_alloc_func (mux->tsmux, alloc_packet_cb, mux); + MpegTsMuxClass *klass = GST_MPEG_TSMUX_GET_CLASS (mux); + + g_assert (klass->create_ts_mux); + + mux->tsmux = klass->create_ts_mux (mux); } } @@ -473,6 +478,15 @@ mpegtsmux_dispose (GObject * object) GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } +static void +mpegtsmux_constructed (GObject * object) +{ + MpegTsMux *mux = GST_MPEG_TSMUX (object); + + /* initial state */ + mpegtsmux_reset (mux, TRUE); +} + static void gst_mpegtsmux_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -2063,3 +2077,13 @@ mpegtsmux_send_event (GstElement * element, GstEvent * event) return FALSE; } + +static TsMux * +mpegtsmux_default_create_ts_mux (MpegTsMux * mux) +{ + TsMux *tsmux = tsmux_new (); + tsmux_set_write_func (tsmux, new_packet_cb, mux); + tsmux_set_alloc_func (tsmux, alloc_packet_cb, mux); + + return tsmux; +} diff --git a/gst/mpegtsmux/mpegtsmux.h b/gst/mpegtsmux/mpegtsmux.h index 52381f6898..1ec4107d97 100644 --- a/gst/mpegtsmux/mpegtsmux.h +++ b/gst/mpegtsmux/mpegtsmux.h @@ -93,6 +93,7 @@ G_BEGIN_DECLS #define GST_TYPE_MPEG_TSMUX (mpegtsmux_get_type()) #define GST_MPEG_TSMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_MPEG_TSMUX, MpegTsMux)) +#define GST_MPEG_TSMUX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_MPEG_TSMUX,MpegTsMuxClass)) #define CLOCK_BASE 9LL #define CLOCK_FREQ (CLOCK_BASE * 10000) /* 90 kHz PTS clock */ @@ -172,8 +173,15 @@ struct MpegTsMux { #endif }; +/** + * MpegTsMuxClass: + * @create_ts_mux: Optional. + * Called in order to create the #TsMux object. + */ struct MpegTsMuxClass { GstElementClass parent_class; + + TsMux * (*create_ts_mux) (MpegTsMux *mux); }; struct MpegTsPadData { diff --git a/gst/mpegtsmux/tsmux/tsmux.c b/gst/mpegtsmux/tsmux/tsmux.c index f22ce24066..aa2cc436e1 100644 --- a/gst/mpegtsmux/tsmux/tsmux.c +++ b/gst/mpegtsmux/tsmux/tsmux.c @@ -153,6 +153,9 @@ tsmux_new (void) mux->si_sections = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) tsmux_section_free); + mux->new_stream_func = (TsMuxNewStreamFunc) tsmux_stream_new; + mux->new_stream_data = NULL; + return mux; } @@ -193,6 +196,26 @@ tsmux_set_alloc_func (TsMux * mux, TsMuxAllocFunc func, void *user_data) mux->alloc_func_data = user_data; } +/** + * tsmux_set_new_stream_func: + * @mux: a #TsMux + * @func: a user callback function + * @user_data: user data passed to @func + * + * Set the callback function and user data to be called when @mux needs + * to create a new stream. + * @user_data will be passed as user data in @func. + */ +void +tsmux_set_new_stream_func (TsMux * mux, TsMuxNewStreamFunc func, + void *user_data) +{ + g_return_if_fail (mux != NULL); + + mux->new_stream_func = func; + mux->new_stream_data = user_data; +} + /** * tsmux_set_pat_interval: * @mux: a #TsMux @@ -556,6 +579,7 @@ tsmux_create_stream (TsMux * mux, TsMuxStreamType stream_type, guint16 pid, guint16 new_pid; g_return_val_if_fail (mux != NULL, NULL); + g_return_val_if_fail (mux->new_stream_func != NULL, NULL); if (pid == TSMUX_PID_AUTO) { new_pid = tsmux_get_new_pid (mux); @@ -567,7 +591,7 @@ tsmux_create_stream (TsMux * mux, TsMuxStreamType stream_type, guint16 pid, if (tsmux_find_stream (mux, new_pid)) return NULL; - stream = tsmux_stream_new (new_pid, stream_type); + stream = mux->new_stream_func (new_pid, stream_type, mux->new_stream_data); mux->streams = g_list_prepend (mux->streams, stream); mux->nb_streams++; diff --git a/gst/mpegtsmux/tsmux/tsmux.h b/gst/mpegtsmux/tsmux/tsmux.h index a8da29b7f5..42b877593a 100644 --- a/gst/mpegtsmux/tsmux/tsmux.h +++ b/gst/mpegtsmux/tsmux/tsmux.h @@ -102,6 +102,7 @@ typedef struct TsMux TsMux; typedef gboolean (*TsMuxWriteFunc) (GstBuffer * buf, void *user_data, gint64 new_pcr); typedef void (*TsMuxAllocFunc) (GstBuffer ** buf, void *user_data); +typedef TsMuxStream * (*TsMuxNewStreamFunc) (guint16 new_pid, TsMuxStreamType stream_type, void *user_data); struct TsMuxSection { TsMuxPacketInfo pi; @@ -175,6 +176,9 @@ struct TsMux { /* callback to alloc new packet buffer */ TsMuxAllocFunc alloc_func; void *alloc_func_data; + /* callback to create a new stream */ + TsMuxNewStreamFunc new_stream_func; + void *new_stream_data; /* scratch space for writing ES_info descriptors */ guint8 es_info_buf[TSMUX_MAX_ES_INFO_LENGTH]; @@ -190,6 +194,7 @@ void tsmux_free (TsMux *mux); /* Setting muxing session properties */ void tsmux_set_write_func (TsMux *mux, TsMuxWriteFunc func, void *user_data); void tsmux_set_alloc_func (TsMux *mux, TsMuxAllocFunc func, void *user_data); +void tsmux_set_new_stream_func (TsMux * mux, TsMuxNewStreamFunc func, void *user_data); void tsmux_set_pat_interval (TsMux *mux, guint interval); guint tsmux_get_pat_interval (TsMux *mux); void tsmux_resend_pat (TsMux *mux);