*
* The Original Code is Fluendo MPEG Demuxer plugin.
*
- * The Initial Developer of the Original Code is Fluendo, S.L.
- * Portions created by Fluendo, S.L. are Copyright (C) 2005
- * Fluendo, S.L. All Rights Reserved.
+ * The Initial Developer of the Original Code is Fluendo, S.A.
+ * Portions created by Fluendo, S.L. are Copyright (C) 2005,2006,2007,2008,2009
+ * Fluendo, S.A. All Rights Reserved.
*
* Contributor(s): Wim Taymans <wim@fluendo.com>
*/
PROP_M2TS
};
+#define GSTTIME_TO_BYTES(time) \
+ ((time != -1) ? gst_util_uint64_scale (MAX(0,(gint64) ((time))), \
+ demux->bitrate, GST_SECOND) : -1)
+#define BYTES_TO_GSTTIME(bytes) \
+ ((bytes != -1) ? (gst_util_uint64_scale (bytes, GST_SECOND, \
+ demux->bitrate)) : -1)
+
#define VIDEO_CAPS \
GST_STATIC_CAPS (\
"video/mpeg, " \
static gboolean gst_mpegts_demux_is_PMT (GstMpegTSDemux * demux, guint16 PID);
static gboolean gst_mpegts_demux_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_mpegts_demux_src_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_mpegts_demux_chain (GstPad * pad, GstBuffer * buffer);
static gboolean gst_mpegts_demux_sink_setcaps (GstPad * pad, GstCaps * caps);
demux->m2ts_mode = FALSE;
demux->sync_lut = NULL;
demux->sync_lut_len = 0;
-
+ demux->bitrate = -1;
+ demux->num_packets = 0;
+ demux->pcr[0] = -1;
+ demux->pcr[1] = -1;
+ demux->cache_duration = GST_CLOCK_TIME_NONE;
+ demux->base_pts = GST_CLOCK_TIME_NONE;
#ifdef USE_LIBOIL
oil_init ();
#endif
gst_caps_unref (caps);
gst_pad_set_query_function (stream->pad,
GST_DEBUG_FUNCPTR (gst_mpegts_demux_src_pad_query));
+ gst_pad_set_event_function (stream->pad,
+ GST_DEBUG_FUNCPTR (gst_mpegts_demux_src_event));
g_free (name);
return TRUE;
}
base_PCR = PCR_stream->base_PCR;
- time = MPEGTIME_TO_GSTTIME (base_PCR);
+ demux->base_pts = time = MPEGTIME_TO_GSTTIME (base_PCR);
GST_DEBUG_OBJECT (demux, "segment PTS to (%" G_GUINT64_FORMAT ") time: %"
G_GUINT64_FORMAT, base_PCR, time);
"valid pcr: %d last PCR difference: %" G_GUINT64_FORMAT, valid_pcr,
stream->last_PCR_difference);
if (valid_pcr) {
-
+ if (demux->pcr[0] == -1) {
+ demux->pcr[0] = pcr;
+ demux->num_packets = 0;
+ } /* Considering a difference of 1 sec ie 90000 ticks */
+ else if (demux->pcr[1] == -1 && ((pcr - demux->pcr[0]) >= 90000)) {
+ demux->pcr[1] = pcr;
+ }
stream->last_PCR = pcr;
if (demux->clock && demux->clock_base != GST_CLOCK_TIME_NONE) {
}
static FORCE_INLINE GstFlowReturn
-gst_mpegts_stream_pes_buffer_flush (GstMpegTSStream * stream)
+gst_mpegts_stream_pes_buffer_flush (GstMpegTSStream * stream, gboolean discard)
{
GstFlowReturn ret = GST_FLOW_OK;
if (stream->pes_buffer) {
- GST_BUFFER_SIZE (stream->pes_buffer) = stream->pes_buffer_used;
- ret = gst_pes_filter_push (&stream->filter, stream->pes_buffer);
- if (ret == GST_FLOW_LOST_SYNC)
+ if (discard) {
+ gst_buffer_unref (stream->pes_buffer);
stream->pes_buffer_in_sync = FALSE;
+ } else {
+ GST_BUFFER_SIZE (stream->pes_buffer) = stream->pes_buffer_used;
+ ret = gst_pes_filter_push (&stream->filter, stream->pes_buffer);
+ if (ret == GST_FLOW_LOST_SYNC)
+ stream->pes_buffer_in_sync = FALSE;
+ }
stream->pes_buffer = NULL;
}
return ret;
if (stream->pes_buffer_size < (MPEGTS_MAX_PES_BUFFER_SIZE >> 1))
stream->pes_buffer_size <<= 1;
- ret = gst_mpegts_stream_pes_buffer_flush (stream);
+ ret = gst_mpegts_stream_pes_buffer_flush (stream, FALSE);
if (ret == GST_FLOW_LOST_SYNC)
goto done;
}
}
static FORCE_INLINE GstFlowReturn
-gst_mpegts_demux_pes_buffer_flush (GstMpegTSDemux * demux)
+gst_mpegts_demux_pes_buffer_flush (GstMpegTSDemux * demux, gboolean discard)
{
gint i;
GstFlowReturn ret = GST_FLOW_OK;
for (i = 0; i < MPEGTS_MAX_PID + 1; i++) {
GstMpegTSStream *stream = demux->streams[i];
if (stream && stream->pad) {
- gst_mpegts_stream_pes_buffer_flush (stream);
+ gst_mpegts_stream_pes_buffer_flush (stream, discard);
stream->pes_buffer_in_sync = FALSE;
}
}
"bytes of %u bytes in the PES buffer",
PID, stream->pes_buffer_used, stream->pes_buffer_size);
/* Flush buffered PES data */
- gst_mpegts_stream_pes_buffer_flush (stream);
+ gst_mpegts_stream_pes_buffer_flush (stream, FALSE);
gst_pes_filter_drain (&stream->filter);
/* Resize the buffer to half if no overflow detected and
* had been used less than half of it */
ret = gst_mpegts_demux_parse_stream (demux, stream, data,
MPEGTS_NORMAL_TS_PACKETSIZE - 1);
+ if (demux->pcr[1] != -1 && demux->bitrate == -1) {
+ GST_DEBUG_OBJECT (demux, "stream->last_PCR_difference: %" G_GINT64_FORMAT
+ ", demux->num_packets %" G_GUINT64_FORMAT,
+ demux->pcr[1] - demux->pcr[0], demux->num_packets);
+ demux->bitrate = gst_util_uint64_scale (GST_SECOND,
+ MPEGTS_NORMAL_TS_PACKETSIZE * demux->num_packets,
+ MPEGTIME_TO_GSTTIME (demux->pcr[1] - demux->pcr[0]));
+ GST_DEBUG_OBJECT (demux, "bitrate is %" G_GINT64_FORMAT
+ " bytes per second", demux->bitrate);
+ }
+ demux->num_packets++;
return ret;
/* ERRORS */
}
static gboolean
+gst_mpegts_demux_handle_seek_push (GstMpegTSDemux * demux, GstEvent * event)
+{
+ gboolean res = FALSE;
+ gdouble rate;
+ GstFormat format;
+ GstSeekFlags flags;
+ GstSeekType start_type, stop_type;
+ gint64 start, stop, bstart, bstop;
+ GstEvent *bevent;
+
+ gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
+ &stop_type, &stop);
+
+ GST_DEBUG_OBJECT (demux, "seek event, rate: %f start: %" GST_TIME_FORMAT
+ " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start),
+ GST_TIME_ARGS (stop));
+
+ if (format == GST_FORMAT_BYTES) {
+ GST_DEBUG_OBJECT (demux, "seek not supported on format %d", format);
+ goto beach;
+ }
+
+ GST_DEBUG_OBJECT (demux, "seek - trying directly upstream first");
+
+ /* first try original format seek */
+ res = gst_pad_push_event (demux->sinkpad, gst_event_ref (event));
+ if (res == TRUE)
+ goto beach;
+ GST_DEBUG_OBJECT (demux, "seek - no upstream");
+
+ if (format != GST_FORMAT_TIME) {
+ /* From here down, we only support time based seeks */
+ GST_DEBUG_OBJECT (demux, "seek not supported on format %d", format);
+ goto beach;
+ }
+
+ /* We need to convert to byte based seek and we need a scr_rate for that. */
+ if (demux->bitrate == -1) {
+ GST_DEBUG_OBJECT (demux, "seek not possible, no bitrate");
+ goto beach;
+ }
+
+ GST_DEBUG_OBJECT (demux, "try with bitrate");
+
+ bstart = GSTTIME_TO_BYTES (start);
+ bstop = GSTTIME_TO_BYTES (stop);
+
+ GST_DEBUG_OBJECT (demux, "in bytes bstart %" G_GINT64_FORMAT " bstop %"
+ G_GINT64_FORMAT, bstart, bstop);
+ bevent = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, start_type,
+ bstart, stop_type, bstop);
+
+ res = gst_pad_push_event (demux->sinkpad, bevent);
+
+beach:
+ gst_event_unref (event);
+ return res;
+}
+
+static gboolean
+gst_mpegts_demux_src_event (GstPad * pad, GstEvent * event)
+{
+ GstMpegTSDemux *demux = GST_MPEGTS_DEMUX (gst_pad_get_parent (pad));
+ gboolean res = FALSE;
+
+ GST_DEBUG_OBJECT (demux, "got event %s",
+ gst_event_type_get_name (GST_EVENT_TYPE (event)));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_SEEK:
+ res = gst_mpegts_demux_handle_seek_push (demux, event);
+ break;
+ default:
+ res = gst_pad_push_event (demux->sinkpad, event);
+ break;
+ }
+
+ gst_object_unref (demux);
+
+ return res;
+}
+
+static void
+gst_mpegts_demux_flush (GstMpegTSDemux * demux, gboolean discard)
+{
+ GstMpegTSStream *PCR_stream;
+ GstMpegTSStream *PMT_stream;
+
+ GST_DEBUG_OBJECT (demux, "flushing MPEG TS demuxer (discard %d)", discard);
+
+ /* Start by flushing internal buffers */
+ gst_mpegts_demux_pes_buffer_flush (demux, discard);
+
+ /* Clear adapter */
+ gst_adapter_clear (demux->adapter);
+
+ /* Try resetting the last_PCR value as we will have a discont */
+ if (demux->current_PMT == 0)
+ goto beach;
+
+ PMT_stream = demux->streams[demux->current_PMT];
+ if (PMT_stream == NULL)
+ goto beach;
+
+ PCR_stream = demux->streams[PMT_stream->PMT.PCR_PID];
+ if (PCR_stream == NULL)
+ goto beach;
+
+ PCR_stream->last_PCR = -1;
+
+beach:
+ return;
+}
+
+static gboolean
gst_mpegts_demux_send_event (GstMpegTSDemux * demux, GstEvent * event)
{
gint i;
gst_mpegts_demux_sink_event (GstPad * pad, GstEvent * event)
{
GstMpegTSDemux *demux = GST_MPEGTS_DEMUX (gst_pad_get_parent (pad));
- gboolean res;
+ gboolean res = FALSE;
GST_DEBUG_OBJECT (demux, "got event %s",
gst_event_type_get_name (GST_EVENT_TYPE (event)));
break;
case GST_EVENT_FLUSH_STOP:
gst_adapter_clear (demux->adapter);
+ gst_mpegts_demux_flush (demux, TRUE);
res = gst_mpegts_demux_send_event (demux, event);
break;
case GST_EVENT_EOS:
- /* Flush buffered PES data */
- gst_mpegts_demux_pes_buffer_flush (demux);
+ gst_mpegts_demux_flush (demux, FALSE);
/* Send the EOS event on each stream */
if (!(res = gst_mpegts_demux_send_event (demux, event))) {
/* we have no streams */
}
break;
case GST_EVENT_NEWSEGMENT:
- res = gst_mpegts_demux_send_event (demux, event);
+ {
+ gboolean update;
+ gdouble rate;
+ GstFormat format;
+ gint64 start, stop, time;
+
+ gst_event_parse_new_segment (event, &update, &rate, &format,
+ &start, &stop, &time);
+
+ gst_event_unref (event);
+ GST_INFO_OBJECT (demux, "received new segment: rate %g "
+ "format %d, start: %" G_GINT64_FORMAT ", stop: %" G_GINT64_FORMAT
+ ", time: %" G_GINT64_FORMAT, rate, format, start, stop, time);
+ if (format == GST_FORMAT_BYTES && demux->bitrate != -1) {
+ gint64 tstart = 0, tstop = 0, pos = 0;
+
+ if (demux->base_pts != GST_CLOCK_TIME_NONE) {
+ tstart = tstop = demux->base_pts;
+ }
+ tstart += BYTES_TO_GSTTIME (start);
+ tstop += BYTES_TO_GSTTIME (stop);
+ pos = BYTES_TO_GSTTIME (time);
+
+ event = gst_event_new_new_segment (update, rate,
+ GST_FORMAT_TIME, tstart, tstop, pos);
+ GST_DEBUG_OBJECT (demux, "pushing time newsegment from %"
+ GST_TIME_FORMAT " to %" GST_TIME_FORMAT " pos %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (tstart), GST_TIME_ARGS (tstop), GST_TIME_ARGS (pos));
+
+ res = gst_mpegts_demux_send_event (demux, event);
+ }
break;
+ }
default:
res = gst_mpegts_demux_send_event (demux, event);
break;
}
gst_object_unref (demux);
- return TRUE;
+ return res;
}
static gboolean
case GST_QUERY_DURATION:
{
GstFormat format;
- gint64 duration;
+ GstPad *peer;
- gst_query_parse_duration (query, &format, &duration);
+ gst_query_parse_duration (query, &format, NULL);
- if (format == GST_FORMAT_BYTES) {
- res = FALSE;
- } else {
- res = gst_pad_query_default (pad, query);
+ /* Try query upstream first */
+ peer = gst_pad_get_peer (demux->sinkpad);
+ if (peer) {
+ res = gst_pad_query (peer, query);
+ /* Try doing something with that query if it failed */
+ if (!res && format == GST_FORMAT_TIME && demux->bitrate != -1) {
+ /* Try using cache first */
+ if (GST_CLOCK_TIME_IS_VALID (demux->cache_duration)) {
+ GST_LOG_OBJECT (demux, "replying duration query from cache %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (demux->cache_duration));
+ gst_query_set_duration (query, GST_FORMAT_TIME,
+ demux->cache_duration);
+ res = TRUE;
+ } else { /* Query upstream and approximate */
+ GstQuery *bquery = gst_query_new_duration (GST_FORMAT_BYTES);
+ gint64 duration = 0;
+
+ /* Query peer for duration in bytes */
+ res = gst_pad_query (peer, bquery);
+ if (res) {
+ /* Convert to time format */
+ gst_query_parse_duration (bquery, &format, &duration);
+ GST_DEBUG_OBJECT (demux, "query on peer pad reported bytes %"
+ G_GUINT64_FORMAT, duration);
+ demux->cache_duration = BYTES_TO_GSTTIME (duration);
+ GST_DEBUG_OBJECT (demux, "converted to time %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (demux->cache_duration));
+ gst_query_set_duration (query, GST_FORMAT_TIME,
+ demux->cache_duration);
+ }
+ gst_query_unref (bquery);
+ }
+ } else {
+ GST_WARNING_OBJECT (demux, "unsupported query format or no bitrate "
+ "yet to approximate duration from bytes");
+ }
+ gst_object_unref (peer);
}
-
break;
}
default:
res = gst_pad_query_default (pad, query);
}
+ gst_object_unref (demux);
return res;
}
guint sync_count;
if (GST_BUFFER_IS_DISCONT (buffer)) {
- /* Flush buffered PES data */
- gst_mpegts_demux_pes_buffer_flush (demux);
- gst_adapter_clear (demux->adapter);
+ gst_mpegts_demux_flush (demux, FALSE);
}
/* first push the new buffer into the adapter */
gst_adapter_push (demux->adapter, buffer);
*
* The Original Code is Fluendo MPEG Demuxer plugin.
*
- * The Initial Developer of the Original Code is Fluendo, S.L.
- * Portions created by Fluendo, S.L. are Copyright (C) 2005
- * Fluendo, S.L. All Rights Reserved.
+ * The Initial Developer of the Original Code is Fluendo, S.A.
+ * Portions created by Fluendo, S.A. are Copyright (C) 2005,2006,2007,2008,2009
+ * Fluendo, S.A. All Rights Reserved.
*
* Contributor(s): Wim Taymans <wim@fluendo.com>
*/
#include "gstsectionfilter.h"
G_BEGIN_DECLS
-
#define MPEGTS_MIN_PES_BUFFER_SIZE 4 * 1024
#define MPEGTS_MAX_PES_BUFFER_SIZE 256 * 1024
-
#define MPEGTS_MAX_PID 0x1fff
#define MPEGTS_NORMAL_TS_PACKETSIZE 188
#define MPEGTS_M2TS_TS_PACKETSIZE 192
-
#define IS_MPEGTS_SYNC(data) (((data)[0] == 0x47) && \
(((data)[1] & 0x80) == 0x00) && \
(((data)[3] & 0x10) == 0x10))
-
#define GST_TYPE_MPEGTS_DEMUX (gst_mpegts_demux_get_type())
#define GST_MPEGTS_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
GST_TYPE_MPEGTS_DEMUX,GstMpegTSDemux))
GST_TYPE_MPEGTS_DEMUX))
#define GST_IS_MPEGTS_DEMUX_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),\
GST_TYPE_MPEGTS_DEMUX))
-
typedef struct _GstMpegTSStream GstMpegTSStream;
typedef struct _GstMpegTSPMTEntry GstMpegTSPMTEntry;
typedef struct _GstMpegTSPMT GstMpegTSPMT;
typedef struct _GstMpegTSDemux GstMpegTSDemux;
typedef struct _GstMpegTSDemuxClass GstMpegTSDemuxClass;
-struct _GstMpegTSPMTEntry {
- guint16 PID;
+struct _GstMpegTSPMTEntry
+{
+ guint16 PID;
};
-struct _GstMpegTSPMT {
- guint16 program_number;
- guint8 version_number;
- gboolean current_next_indicator;
- guint8 section_number;
- guint8 last_section_number;
- guint16 PCR_PID;
- guint16 program_info_length;
- GstMPEGDescriptor * program_info;
-
- GArray * entries;
+struct _GstMpegTSPMT
+{
+ guint16 program_number;
+ guint8 version_number;
+ gboolean current_next_indicator;
+ guint8 section_number;
+ guint8 last_section_number;
+ guint16 PCR_PID;
+ guint16 program_info_length;
+ GstMPEGDescriptor *program_info;
+
+ GArray *entries;
};
-struct _GstMpegTSPATEntry {
- guint16 program_number;
- guint16 PID;
+struct _GstMpegTSPATEntry
+{
+ guint16 program_number;
+ guint16 PID;
};
-struct _GstMpegTSPAT {
- guint16 transport_stream_id;
- guint8 version_number;
- gboolean current_next_indicator;
- guint8 section_number;
- guint8 last_section_number;
+struct _GstMpegTSPAT
+{
+ guint16 transport_stream_id;
+ guint8 version_number;
+ gboolean current_next_indicator;
+ guint8 section_number;
+ guint8 last_section_number;
- GArray * entries;
+ GArray *entries;
};
-typedef enum _MpegTsStreamFlags {
+typedef enum _MpegTsStreamFlags
+{
MPEGTS_STREAM_FLAG_STREAM_TYPE_UNKNOWN = 0x01,
MPEGTS_STREAM_FLAG_PMT_VALID = 0x02,
- MPEGTS_STREAM_FLAG_IS_VIDEO = 0x04
+ MPEGTS_STREAM_FLAG_IS_VIDEO = 0x04
} MpegTsStreamFlags;
/* Information associated to a single MPEG stream. */
-struct _GstMpegTSStream {
- GstMpegTSDemux * demux;
+struct _GstMpegTSStream
+{
+ GstMpegTSDemux *demux;
- MpegTsStreamFlags flags;
+ MpegTsStreamFlags flags;
/* PID and type */
- guint16 PID;
- guint8 PID_type;
+ guint16 PID;
+ guint8 PID_type;
/* adaptation_field data */
- guint64 last_PCR;
- guint64 base_PCR;
- guint64 last_OPCR;
- guint64 last_PCR_difference;
- gboolean discont_PCR;
- GstClockTimeDiff discont_difference;
+ guint64 last_PCR;
+ guint64 base_PCR;
+ guint64 last_OPCR;
+ guint64 last_PCR_difference;
+ gboolean discont_PCR;
+ GstClockTimeDiff discont_difference;
/* for PAT streams */
- GstMpegTSPAT PAT;
+ GstMpegTSPAT PAT;
/* for PMT streams */
- GstMpegTSPMT PMT;
+ GstMpegTSPMT PMT;
/* for CA streams */
/* for PAT, PMT, CA and private streams */
- GstSectionFilter section_filter;
+ GstSectionFilter section_filter;
/* for PES streams */
- guint8 id;
- guint8 stream_type;
- GstBuffer * pes_buffer;
- guint32 pes_buffer_size;
- guint32 pes_buffer_used;
- gboolean pes_buffer_overflow;
- gboolean pes_buffer_in_sync;
- GstPESFilter filter;
- GstPad * pad;
- GstFlowReturn last_ret;
+ guint8 id;
+ guint8 stream_type;
+ GstBuffer *pes_buffer;
+ guint32 pes_buffer_size;
+ guint32 pes_buffer_used;
+ gboolean pes_buffer_overflow;
+ gboolean pes_buffer_in_sync;
+ GstPESFilter filter;
+ GstPad *pad;
+ GstFlowReturn last_ret;
GstMPEGDescriptor *ES_info;
/* needed because 33bit mpeg timestamps wrap around every (approx) 26.5 hrs */
- GstClockTimeDiff base_time;
- GstClockTime last_time;
+ GstClockTimeDiff base_time;
+ GstClockTime last_time;
/* pid of PMT that this stream belongs to */
- guint16 PMT_pid;
+ guint16 PMT_pid;
};
-struct _GstMpegTSDemux {
- GstElement parent;
+struct _GstMpegTSDemux
+{
+ GstElement parent;
/* properties */
- gboolean check_crc;
+ gboolean check_crc;
/* sink pad and adapter */
- GstPad * sinkpad;
- GstAdapter * adapter;
- guint8 ** sync_lut;
- guint sync_lut_len;
+ GstPad *sinkpad;
+ GstAdapter *adapter;
+ guint8 **sync_lut;
+ guint sync_lut_len;
/* current PMT PID */
- guint16 current_PMT;
+ guint16 current_PMT;
/* Array of MPEGTS_MAX_PID + 1 stream entries */
- GstMpegTSStream ** streams;
+ GstMpegTSStream **streams;
/* Array to perform pmts checks at gst_mpegts_demux_parse_adaptation_field */
- gboolean pmts_checked[MPEGTS_MAX_PID + 1];
-
+ gboolean pmts_checked[MPEGTS_MAX_PID + 1];
+
/* Array of Elementary Stream pids for ts with PMT */
- guint16 * elementary_pids;
- guint nb_elementary_pids;
+ guint16 *elementary_pids;
+ guint nb_elementary_pids;
/* Program number to use */
- gint program_number;
+ gint program_number;
/* indicates that we need to close our pad group, because we've added
* at least one pad */
- gboolean need_no_more_pads;
- guint16 packetsize;
- gboolean m2ts_mode;
+ gboolean need_no_more_pads;
+ guint16 packetsize;
+ gboolean m2ts_mode;
/* clocking */
- GstClock * clock;
- GstClockTime clock_base;
+ GstClock *clock;
+ GstClockTime clock_base;
+ /* Additional information required for seeking */
+ guint64 num_packets;
+ gint64 bitrate;
+ /* Two PCRs observations to calculate bitrate */
+ gint64 pcr[2];
+ GstClockTime cache_duration;
+ /* Cached base_PCR in GStreamer time. */
+ GstClockTime base_pts;
};
-struct _GstMpegTSDemuxClass {
- GstElementClass parent_class;
+struct _GstMpegTSDemuxClass
+{
+ GstElementClass parent_class;
- GstPadTemplate * sink_template;
- GstPadTemplate * video_template;
- GstPadTemplate * audio_template;
- GstPadTemplate * private_template;
+ GstPadTemplate *sink_template;
+ GstPadTemplate *video_template;
+ GstPadTemplate *audio_template;
+ GstPadTemplate *private_template;
};
-GType gst_mpegts_demux_get_type (void);
+GType gst_mpegts_demux_get_type (void);
-gboolean gst_mpegts_demux_plugin_init (GstPlugin *plugin);
+gboolean gst_mpegts_demux_plugin_init (GstPlugin * plugin);
G_END_DECLS
-
#endif /* __GST_MPEGTS_DEMUX_H__ */