mpegtsmux: provide API for subclasses to override stream creation

This commit is contained in:
Mathieu Duponchelle 2019-04-25 20:23:03 +02:00 committed by Mathieu Duponchelle
parent 80bfa16c95
commit ea011a3266
5 changed files with 90 additions and 8 deletions

View file

@ -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 <mathieu@centricular.com>");
mpegtsmux_class->create_ts_mux = atscmux_create_ts_mux;
}
static void

View file

@ -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;
}

View file

@ -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 {

View file

@ -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++;

View file

@ -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);