diff options
-rw-r--r-- | gst/mpegdemux/gstmpegtsdemux.c | 272 | ||||
-rw-r--r-- | gst/mpegdemux/gstmpegtsdemux.h | 186 |
2 files changed, 341 insertions, 117 deletions
diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 4464cdf8..99a499a0 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -34,9 +34,9 @@ * * 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> */ @@ -126,6 +126,13 @@ enum 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, " \ @@ -189,6 +196,7 @@ static void gst_mpegts_demux_get_property (GObject * object, guint prop_id, 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); @@ -327,7 +335,12 @@ gst_mpegts_demux_init (GstMpegTSDemux * demux) 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 @@ -668,6 +681,8 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, 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; @@ -730,7 +745,7 @@ gst_mpegts_demux_send_new_segment (GstMpegTSDemux * demux, } 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); @@ -1680,7 +1695,13 @@ gst_mpegts_demux_parse_adaptation_field (GstMpegTSStream * stream, "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) { @@ -1955,15 +1976,20 @@ gst_mpegts_demux_is_PMT (GstMpegTSDemux * demux, guint16 PID) } 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; @@ -1985,7 +2011,7 @@ gst_mpegts_stream_pes_buffer_push (GstMpegTSStream * stream, 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; } @@ -2010,7 +2036,7 @@ 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; @@ -2018,7 +2044,7 @@ gst_mpegts_demux_pes_buffer_flush (GstMpegTSDemux * demux) 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; } } @@ -2233,7 +2259,7 @@ gst_mpegts_demux_parse_stream (GstMpegTSDemux * demux, GstMpegTSStream * stream, "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 */ @@ -2319,12 +2345,138 @@ gst_mpegts_demux_parse_transport_packet (GstMpegTSDemux * demux, 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; @@ -2347,7 +2499,7 @@ static gboolean 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))); @@ -2358,11 +2510,11 @@ gst_mpegts_demux_sink_event (GstPad * pad, GstEvent * 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 */ @@ -2371,15 +2523,46 @@ gst_mpegts_demux_sink_event (GstPad * pad, GstEvent * event) } 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 @@ -2455,21 +2638,54 @@ gst_mpegts_demux_src_pad_query (GstPad * pad, GstQuery * query) 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; } @@ -2554,9 +2770,7 @@ gst_mpegts_demux_chain (GstPad * pad, GstBuffer * buffer) 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); diff --git a/gst/mpegdemux/gstmpegtsdemux.h b/gst/mpegdemux/gstmpegtsdemux.h index 8a4ca3d2..c4a907a5 100644 --- a/gst/mpegdemux/gstmpegtsdemux.h +++ b/gst/mpegdemux/gstmpegtsdemux.h @@ -34,9 +34,9 @@ * * 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> */ @@ -52,18 +52,14 @@ #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)) @@ -75,7 +71,6 @@ G_BEGIN_DECLS 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; @@ -84,142 +79,157 @@ typedef struct _GstMpegTSPAT GstMpegTSPAT; 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__ */ |