summaryrefslogtreecommitdiffstats
path: root/gst/mpegdemux
diff options
context:
space:
mode:
Diffstat (limited to 'gst/mpegdemux')
-rw-r--r--gst/mpegdemux/gstmpegdemux.c73
-rw-r--r--gst/mpegdemux/gstmpegtsdemux.c48
-rw-r--r--gst/mpegdemux/gstpesfilter.c49
-rw-r--r--gst/mpegdemux/mpegtspacketizer.c10
-rw-r--r--gst/mpegdemux/mpegtsparse.c55
5 files changed, 201 insertions, 34 deletions
diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c
index ce1d0978..75d5960f 100644
--- a/gst/mpegdemux/gstmpegdemux.c
+++ b/gst/mpegdemux/gstmpegdemux.c
@@ -845,6 +845,7 @@ gst_flups_demux_close_segment (GstFluPSDemux * demux)
{
gint id;
GstEvent *event = NULL;
+ guint64 base_time;
#if POST_10_10
GST_INFO_OBJECT (demux, "closing running segment %" GST_SEGMENT_FORMAT,
@@ -855,14 +856,17 @@ gst_flups_demux_close_segment (GstFluPSDemux * demux)
* last_seg_start != clock_time_none, as that indicates a sparse-stream
* event was sent there */
+ if ((base_time = demux->base_time) == (guint64) - 1)
+ base_time = 0;
+
+
/* Close the current segment for a linear playback */
if (demux->src_segment.rate >= 0) {
/* for forward playback, we played from start to last_stop */
event = gst_event_new_new_segment (TRUE,
demux->src_segment.rate, demux->src_segment.format,
- demux->src_segment.start + demux->base_time,
- demux->src_segment.last_stop + demux->base_time,
- demux->src_segment.time);
+ demux->src_segment.start + base_time,
+ demux->src_segment.last_stop + base_time, demux->src_segment.time);
} else {
gint64 stop;
@@ -872,8 +876,8 @@ gst_flups_demux_close_segment (GstFluPSDemux * demux)
/* for reverse playback, we played from stop to last_stop. */
event = gst_event_new_new_segment (TRUE,
demux->src_segment.rate, demux->src_segment.format,
- demux->src_segment.last_stop + demux->base_time,
- stop + demux->base_time, demux->src_segment.last_stop);
+ demux->src_segment.last_stop + base_time,
+ stop + base_time, demux->src_segment.last_stop);
}
if (event) {
@@ -1383,11 +1387,66 @@ gst_flups_demux_src_query (GstPad * pad, GstQuery * query)
res = TRUE;
break;
}
+ case GST_QUERY_SEEKING:{
+ GstFormat fmt;
+
+ gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
+
+ res = TRUE;
+ if (demux->random_access) {
+ /* In pull mode we can seek in TIME format if we have the SCR */
+ if (fmt != GST_FORMAT_TIME || demux->scr_rate_n == G_MAXUINT64
+ || demux->scr_rate_d == G_MAXUINT64)
+ gst_query_set_seeking (query, fmt, FALSE, -1, -1);
+ else
+ gst_query_set_seeking (query, fmt, TRUE, 0, -1);
+ } else {
+ if (fmt == GST_FORMAT_BYTES) {
+ /* Seeking in BYTES format not supported at all */
+ gst_query_set_seeking (query, fmt, FALSE, -1, -1);
+ } else {
+ GstQuery *peerquery;
+ gboolean seekable;
+
+ /* Then ask upstream */
+ res = gst_pad_peer_query (demux->sinkpad, query);
+ if (res) {
+ /* If upstream can handle seeks we're done, if it
+ * can't we still have our TIME->BYTES conversion seek
+ */
+ gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
+ if (seekable || fmt != GST_FORMAT_TIME)
+ goto beach;
+ }
+
+ /* We can seek if upstream supports BYTES seeks and we
+ * have the SCR
+ */
+ peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
+ res = gst_pad_peer_query (demux->sinkpad, query);
+ if (!res || demux->scr_rate_n == G_MAXUINT64
+ || demux->scr_rate_d == G_MAXUINT64) {
+ gst_query_set_seeking (query, fmt, FALSE, -1, -1);
+ } else {
+ gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
+ if (seekable)
+ gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1);
+ else
+ gst_query_set_seeking (query, fmt, FALSE, -1, -1);
+ }
+
+ gst_query_unref (peerquery);
+ res = TRUE;
+ }
+ }
+ break;
+ }
default:
res = gst_pad_query_default (pad, query);
break;
}
+beach:
gst_object_unref (demux);
return res;
@@ -2540,7 +2599,7 @@ gst_flups_demux_loop (GstPad * pad)
{
GstFluPSDemux *demux;
GstFlowReturn ret = GST_FLOW_OK;
- guint offset = 0;
+ guint64 offset = 0;
demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
@@ -2579,7 +2638,7 @@ gst_flups_demux_loop (GstPad * pad)
goto pause;
}
} else { /* Reverse playback */
- guint size = MIN (offset, BLOCK_SZ);
+ guint64 size = MIN (offset, BLOCK_SZ);
/* pull in data */
ret = gst_flups_demux_pull_block (pad, demux, offset - size, size);
diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c
index cb082a2b..8de7cc75 100644
--- a/gst/mpegdemux/gstmpegtsdemux.c
+++ b/gst/mpegdemux/gstmpegtsdemux.c
@@ -1697,7 +1697,8 @@ gst_mpegts_demux_parse_adaptation_field (GstMpegTSStream * stream,
memset (pmts_checked, 0, sizeof (gboolean) * (MPEGTS_MAX_PID + 1));
for (j = 0; j < MPEGTS_MAX_PID + 1; j++) {
- if (demux->streams[j] && demux->streams[j]->PMT_pid) {
+ if (demux->streams[j]
+ && demux->streams[j]->PMT_pid <= MPEGTS_MAX_PID) {
if (!pmts_checked[demux->streams[j]->PMT_pid]) {
/* check if this is correct pcr for pmt */
if (demux->streams[demux->streams[j]->PMT_pid] &&
@@ -2777,9 +2778,54 @@ gst_mpegts_demux_src_pad_query (GstPad * pad, GstQuery * query)
}
break;
}
+ case GST_QUERY_SEEKING:{
+ GstFormat fmt;
+
+ gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
+ if (fmt == GST_FORMAT_BYTES) {
+ /* Seeking in BYTES format not supported at all */
+ gst_query_set_seeking (query, fmt, FALSE, -1, -1);
+ } else {
+ GstQuery *peerquery;
+ gboolean seekable;
+
+ /* Then ask upstream */
+ res = gst_pad_peer_query (demux->sinkpad, query);
+ if (res) {
+ /* If upstream can handle seeks we're done, if it
+ * can't we still have our TIME->BYTES conversion seek
+ */
+ gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
+ if (seekable || fmt != GST_FORMAT_TIME)
+ goto beach;
+ }
+
+ /* We can seek if upstream supports BYTES seeks and we
+ * have a bitrate
+ */
+ peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
+ res = gst_pad_peer_query (demux->sinkpad, query);
+ if (!res || demux->bitrate == -1) {
+ gst_query_set_seeking (query, fmt, FALSE, -1, -1);
+ } else {
+ gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
+ if (seekable)
+ gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1);
+ else
+ gst_query_set_seeking (query, fmt, FALSE, -1, -1);
+ }
+
+ gst_query_unref (peerquery);
+ res = TRUE;
+ }
+ break;
+ }
default:
res = gst_pad_query_default (pad, query);
+ break;
}
+
+beach:
gst_object_unref (demux);
return res;
diff --git a/gst/mpegdemux/gstpesfilter.c b/gst/mpegdemux/gstpesfilter.c
index b520c766..736d4960 100644
--- a/gst/mpegdemux/gstpesfilter.c
+++ b/gst/mpegdemux/gstpesfilter.c
@@ -151,6 +151,7 @@ gst_pes_filter_parse (GstPESFilter * filter)
* to set the allow_unbounded flag if they want */
if (filter->length == 0 &&
((filter->start_code & 0xFFFFFFF0) == PACKET_VIDEO_START_CODE ||
+ filter->start_code == ID_EXTENDED_STREAM_ID ||
filter->allow_unbounded)) {
GST_DEBUG ("id 0x%02x, unbounded length", filter->id);
filter->unbounded_packet = TRUE;
@@ -389,9 +390,53 @@ gst_pes_filter_parse (GstPESFilter * filter)
}
/* PES_extension_flag */
if ((flags & 0x01)) {
- GST_DEBUG ("%x PES_extension", filter->id);
+ flags = *data++;
+ header_data_length -= 1;
+ datalen -= 1;
+ GST_DEBUG ("%x PES_extension, flags 0x%02x", filter->id, flags);
+ /* PES_private_data_flag */
+ if ((flags & 0x80)) {
+ GST_DEBUG ("%x PES_private_data_flag", filter->id);
+ data += 16;
+ header_data_length -= 16;
+ datalen -= 16;
+ }
+ /* pack_header_field_flag */
+ if ((flags & 0x40)) {
+ guint8 pack_field_length = *data;
+ GST_DEBUG ("%x pack_header_field_flag, pack_field_length %d",
+ filter->id, pack_field_length);
+ data += pack_field_length + 1;
+ header_data_length -= pack_field_length + 1;
+ datalen -= pack_field_length + 1;
+ }
+ /* program_packet_sequence_counter_flag */
+ if ((flags & 0x20)) {
+ GST_DEBUG ("%x program_packet_sequence_counter_flag", filter->id);
+ data += 2;
+ header_data_length -= 2;
+ datalen -= 2;
+ }
+ /* P-STD_buffer_flag */
+ if ((flags & 0x10)) {
+ GST_DEBUG ("%x P-STD_buffer_flag", filter->id);
+ data += 2;
+ header_data_length -= 2;
+ datalen -= 2;
+ }
+ /* PES_extension_flag_2 */
+ if ((flags & 0x01)) {
+ guint8 PES_extension_field_length = *data++;
+ GST_DEBUG ("%x PES_extension_flag_2, len %d",
+ filter->id, PES_extension_field_length & 0x7f);
+ if (PES_extension_field_length == 0x81) {
+ GST_DEBUG ("%x substream id 0x%02x", filter->id, *data);
+ }
+ data += PES_extension_field_length & 0x7f;
+ header_data_length -= (PES_extension_field_length & 0x7f) + 1;
+ datalen -= (PES_extension_field_length & 0x7f) + 1;
+ }
}
-
/* calculate the amount of real data in this PES packet */
data += header_data_length;
datalen -= header_data_length;
diff --git a/gst/mpegdemux/mpegtspacketizer.c b/gst/mpegdemux/mpegtspacketizer.c
index 5ed71f0c..da53a926 100644
--- a/gst/mpegdemux/mpegtspacketizer.c
+++ b/gst/mpegdemux/mpegtspacketizer.c
@@ -1749,7 +1749,9 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer * packetizer,
break;
}
component = gst_structure_new ("video", "high-definition",
- G_TYPE_BOOLEAN, TRUE, "frequency", G_TYPE_INT, freq, NULL);
+ G_TYPE_BOOLEAN, TRUE, "frequency", G_TYPE_INT, freq,
+ "tag", G_TYPE_INT, DESC_DVB_COMPONENT_tag (comp_descriptor),
+ NULL);
if (widescreen == 0) {
gst_structure_set (component, "aspect-ratio",
G_TYPE_STRING, "4:3", NULL);
@@ -1787,7 +1789,8 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer * packetizer,
break;
}
component = gst_structure_new ("audio", "type", G_TYPE_STRING,
- comptype, NULL);
+ comptype, "tag", G_TYPE_INT,
+ DESC_DVB_COMPONENT_tag (comp_descriptor), NULL);
break;
case 0x03: /* subtitles/teletext/vbi */
comptype = "reserved";
@@ -1827,7 +1830,8 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer * packetizer,
break;
}
component = gst_structure_new ("teletext", "type", G_TYPE_STRING,
- comptype, NULL);
+ comptype, "tag", G_TYPE_INT,
+ DESC_DVB_COMPONENT_tag (comp_descriptor), NULL);
break;
}
if (component) {
diff --git a/gst/mpegdemux/mpegtsparse.c b/gst/mpegdemux/mpegtsparse.c
index 976935f2..90a8ea3b 100644
--- a/gst/mpegdemux/mpegtsparse.c
+++ b/gst/mpegdemux/mpegtsparse.c
@@ -553,6 +553,35 @@ mpegts_parse_program_remove_stream (MpegTSParse * parse,
g_hash_table_remove (program->streams, GINT_TO_POINTER ((gint) pid));
}
+static void
+mpegts_parse_deactivate_pmt (MpegTSParse * parse, MpegTSParseProgram * program)
+{
+ gint i;
+ guint pid;
+ guint stream_type;
+ GstStructure *stream;
+ const GValue *streams;
+ const GValue *value;
+
+ if (program->pmt_info) {
+ streams = gst_structure_get_value (program->pmt_info, "streams");
+
+ for (i = 0; i < gst_value_list_get_size (streams); ++i) {
+ value = gst_value_list_get_value (streams, i);
+ stream = g_value_get_boxed (value);
+ gst_structure_get_uint (stream, "pid", &pid);
+ gst_structure_get_uint (stream, "stream-type", &stream_type);
+ mpegts_parse_program_remove_stream (parse, program, (guint16) pid);
+ g_hash_table_remove (parse->pes_pids, GINT_TO_POINTER ((gint) pid));
+ }
+
+ /* remove pcr stream */
+ mpegts_parse_program_remove_stream (parse, program, program->pcr_pid);
+ g_hash_table_remove (parse->pes_pids,
+ GINT_TO_POINTER ((gint) program->pcr_pid));
+ }
+}
+
static MpegTSParsePad *
mpegts_parse_create_tspad (MpegTSParse * parse, const gchar * pad_name)
{
@@ -940,6 +969,7 @@ mpegts_parse_apply_pat (MpegTSParse * parse, GstStructure * pat_info)
parse->pads_to_remove = g_list_append (parse->pads_to_remove,
mpegts_parse_deactivate_program (parse, program));
+ mpegts_parse_deactivate_pmt (parse, program);
mpegts_parse_remove_program (parse, program_number);
g_hash_table_remove (parse->psi_pids, GINT_TO_POINTER ((gint) pid));
mpegts_packetizer_remove_stream (parse->packetizer, pid);
@@ -964,7 +994,6 @@ mpegts_parse_apply_pmt (MpegTSParse * parse,
guint stream_type;
GstStructure *stream;
gint i;
- const GValue *old_streams;
const GValue *new_streams;
const GValue *value;
@@ -975,27 +1004,11 @@ mpegts_parse_apply_pmt (MpegTSParse * parse,
GST_OBJECT_LOCK (parse);
program = mpegts_parse_get_program (parse, program_number);
if (program) {
- if (program->pmt_info) {
- /* deactivate old pmt */
- old_streams = gst_structure_get_value (program->pmt_info, "streams");
-
- for (i = 0; i < gst_value_list_get_size (old_streams); ++i) {
- value = gst_value_list_get_value (old_streams, i);
- stream = g_value_get_boxed (value);
- gst_structure_get_uint (stream, "pid", &pid);
- gst_structure_get_uint (stream, "stream-type", &stream_type);
- mpegts_parse_program_remove_stream (parse, program, (guint16) pid);
- g_hash_table_remove (parse->pes_pids, GINT_TO_POINTER ((gint) pid));
- }
-
- /* remove pcr stream */
- mpegts_parse_program_remove_stream (parse, program, program->pcr_pid);
- g_hash_table_remove (parse->pes_pids,
- GINT_TO_POINTER ((gint) program->pcr_pid));
-
+ /* deactivate old pmt */
+ mpegts_parse_deactivate_pmt (parse, program);
+ if (program->pmt_info)
gst_structure_free (program->pmt_info);
- program->pmt_info = NULL;
- }
+ program->pmt_info = NULL;
} else {
/* no PAT?? */
g_hash_table_insert (parse->psi_pids,