From 4ff0d1fe525b9aa612464c37dc7e2ae6ef5e9fac Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 26 Jan 2009 09:57:26 +0100 Subject: [PATCH 1/4] Drop packets with an invalid replicated data length Drop packets with an invalid replicated data length instead of continuing with an invalid timestamp and uninitialized payload metadata. All other code assumes that the timestamps are valid. --- gst/asfdemux/asfpacket.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gst/asfdemux/asfpacket.c b/gst/asfdemux/asfpacket.c index fcccf3f1a3..077d7442b7 100644 --- a/gst/asfdemux/asfpacket.c +++ b/gst/asfdemux/asfpacket.c @@ -317,6 +317,9 @@ gst_asf_demux_parse_payload (GstASFDemux * demux, AsfPacket * packet, GST_TIME_ARGS (payload.duration)); } else if (payload.rep_data_len != 0) { GST_WARNING_OBJECT (demux, "invalid replicated data length, very bad"); + *p_data += payload_len; + *p_size -= payload_len; + return FALSE; } GST_LOG_OBJECT (demux, "media object offset : %u", payload.mo_offset); From 3bcd050fab33a4b9390eab5d5fdd1996e8f6f7bf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 26 Jan 2009 10:00:57 +0100 Subject: [PATCH 2/4] Add seeking support to asfdemux in push mode Fixes bug #568836. --- gst/asfdemux/asfpacket.c | 8 +++++++- gst/asfdemux/gstasfdemux.c | 27 ++++++++++++++++++++++++--- gst/asfdemux/gstasfdemux.h | 1 + 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/gst/asfdemux/asfpacket.c b/gst/asfdemux/asfpacket.c index 077d7442b7..c7abe7a48e 100644 --- a/gst/asfdemux/asfpacket.c +++ b/gst/asfdemux/asfpacket.c @@ -127,6 +127,11 @@ gst_asf_payload_queue_for_stream (GstASFDemux * demux, AsfPayload * payload, GST_DEBUG_OBJECT (demux, "first ts: %" GST_TIME_FORMAT, GST_TIME_ARGS (payload->ts)); demux->first_ts = payload->ts; + if (demux->push_mode) { + gst_segment_set_seek (&demux->segment, demux->segment.rate, + GST_FORMAT_TIME, demux->segment.flags, GST_SEEK_TYPE_SET, + demux->first_ts, GST_SEEK_TYPE_NONE, 0, NULL); + } } /* better drop a few frames at the beginning than send bogus timestamps */ @@ -140,7 +145,8 @@ gst_asf_payload_queue_for_stream (GstASFDemux * demux, AsfPayload * payload, } /* make timestamps start from 0 */ - payload->ts -= demux->first_ts; + if (!demux->push_mode) + payload->ts -= demux->first_ts; /* remove any incomplete payloads that will never be completed */ while (stream->payloads->len > 0) { diff --git a/gst/asfdemux/gstasfdemux.c b/gst/asfdemux/gstasfdemux.c index ab5732436b..2454c3bee2 100644 --- a/gst/asfdemux/gstasfdemux.c +++ b/gst/asfdemux/gstasfdemux.c @@ -23,9 +23,6 @@ * - _loop(): * stop if at end of segment if != end of file, ie. demux->segment.stop * - * - _chain(): fix newsegment events for live streams where timestamps don't - * start at zero (need sample files/streams for this) - * * - fix packet parsing: * there's something wrong with timestamps for packets with keyframes, * and durations too. @@ -264,6 +261,7 @@ gst_asf_demux_activate_push (GstPad * sinkpad, gboolean active) demux = GST_ASF_DEMUX (GST_OBJECT_PARENT (sinkpad)); + demux->push_mode = TRUE; demux->state = GST_ASF_DEMUX_STATE_HEADER; demux->streaming = TRUE; @@ -276,6 +274,7 @@ gst_asf_demux_activate_pull (GstPad * pad, gboolean active) GstASFDemux *demux; demux = GST_ASF_DEMUX (GST_OBJECT_PARENT (pad)); + demux->push_mode = FALSE; if (active) { demux->state = GST_ASF_DEMUX_STATE_HEADER; @@ -313,8 +312,17 @@ gst_asf_demux_sink_event (GstPad * pad, GstEvent * event) } GST_OBJECT_LOCK (demux); + if (demux->packet_size && newsegment_start > demux->data_offset) + demux->packet = (newsegment_start - demux->data_offset) / + demux->packet_size; + else + demux->packet = 0; + demux->first_ts = GST_CLOCK_TIME_NONE; + demux->need_newsegment = TRUE; gst_asf_demux_reset_stream_state_after_discont (demux); GST_OBJECT_UNLOCK (demux); + + gst_event_unref (event); break; } case GST_EVENT_EOS:{ @@ -331,6 +339,14 @@ gst_asf_demux_sink_event (GstPad * pad, GstEvent * event) break; } + case GST_EVENT_FLUSH_START: + case GST_EVENT_FLUSH_STOP: + GST_OBJECT_LOCK (demux); + gst_asf_demux_reset_stream_state_after_discont (demux); + GST_OBJECT_UNLOCK (demux); + gst_asf_demux_send_event_unlocked (demux, event); + break; + default: ret = gst_pad_event_default (pad, event); break; @@ -450,6 +466,11 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event) accurate = ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE); keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT); + if (demux->push_mode) { + gst_event_ref (event); + return gst_pad_push_event (demux->sinkpad, event); + } + /* unlock the streaming thread */ if (flush) { gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ()); diff --git a/gst/asfdemux/gstasfdemux.h b/gst/asfdemux/gstasfdemux.h index 92293b490c..db4394d06d 100644 --- a/gst/asfdemux/gstasfdemux.h +++ b/gst/asfdemux/gstasfdemux.h @@ -171,6 +171,7 @@ struct _GstASFDemux { gboolean need_newsegment; /* do we need to send a new-segment event? */ gboolean segment_running; /* if we've started the current segment */ gboolean streaming; /* TRUE if we are operating chain-based */ + gboolean push_mode; /* are we operating in push_mode? */ /* Descrambler settings */ guint8 span; From 9ce447007ed093acf673c91293d83a95395f010e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 26 Jan 2009 20:10:36 +0100 Subject: [PATCH 3/4] Add method to get RDT flags Add a method to get the RDT flags. We need these flags to mark keyframes to reset the descrambing queue. See #556714. --- gst/realmedia/gstrdtbuffer.c | 32 ++++++++++++++++++++++++++++++++ gst/realmedia/gstrdtbuffer.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/gst/realmedia/gstrdtbuffer.c b/gst/realmedia/gstrdtbuffer.c index 735f66bf9e..7f09f2331c 100644 --- a/gst/realmedia/gstrdtbuffer.c +++ b/gst/realmedia/gstrdtbuffer.c @@ -423,3 +423,35 @@ gst_rdt_packet_data_get_timestamp (GstRDTPacket * packet) return result; } + +guint8 +gst_rdt_packet_data_get_flags (GstRDTPacket * packet) +{ + guint8 result; + guint header; + gboolean length_included_flag; + guint8 *bufdata; + guint bufsize; + + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (GST_RDT_IS_DATA_TYPE (packet->type), 0); + + bufdata = GST_BUFFER_DATA (packet->buffer); + bufsize = GST_BUFFER_SIZE (packet->buffer); + + header = packet->offset; + + length_included_flag = (bufdata[header] & 0x80) == 0x80; + + /* skip seq_no and header bits */ + header += 3; + + if (length_included_flag) { + /* skip length */ + header += 2; + } + /* get flags */ + result = bufdata[header]; + + return result; +} diff --git a/gst/realmedia/gstrdtbuffer.h b/gst/realmedia/gstrdtbuffer.h index 4e659e2571..b452922e70 100644 --- a/gst/realmedia/gstrdtbuffer.h +++ b/gst/realmedia/gstrdtbuffer.h @@ -109,6 +109,8 @@ gboolean gst_rdt_packet_data_peek_data (GstRDTPacket *packet, guint8 guint16 gst_rdt_packet_data_get_stream_id (GstRDTPacket *packet); guint32 gst_rdt_packet_data_get_timestamp (GstRDTPacket *packet); +guint8 gst_rdt_packet_data_get_flags (GstRDTPacket * packet); + /* utils */ gint gst_rdt_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2); From 2dbb5a392392ac8aa225c32dd733808259d88878 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 26 Jan 2009 20:12:41 +0100 Subject: [PATCH 4/4] Set flags on the realmedia chunks Set the keyframe flags from the RDT packet to the realmedia chunk so that the descrambler can be reset on keyframes. Fixes #556714. --- gst/realmedia/rdtdepay.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gst/realmedia/rdtdepay.c b/gst/realmedia/rdtdepay.c index 552b75987e..20cccc7555 100644 --- a/gst/realmedia/rdtdepay.c +++ b/gst/realmedia/rdtdepay.c @@ -326,6 +326,8 @@ gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime, guint32 timestamp; gint gap; guint16 seqnum; + guint8 flags; + guint16 outflags; /* get pointers to the packet data */ gst_rdt_packet_data_peek_data (packet, &data, &size); @@ -339,11 +341,12 @@ gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime, /* copy over some things */ stream_id = gst_rdt_packet_data_get_stream_id (packet); timestamp = gst_rdt_packet_data_get_timestamp (packet); + flags = gst_rdt_packet_data_get_flags (packet); seqnum = gst_rdt_packet_data_get_seq (packet); - GST_DEBUG_OBJECT (rdtdepay, "stream_id %u, timestamp %u, seqnum %d", - stream_id, timestamp, seqnum); + GST_DEBUG_OBJECT (rdtdepay, "stream_id %u, timestamp %u, seqnum %d, flags %d", + stream_id, timestamp, seqnum, flags); if (rdtdepay->next_seqnum != -1) { gap = gst_rdt_buffer_compare_seqnum (seqnum, rdtdepay->next_seqnum); @@ -375,11 +378,16 @@ gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime, if (rdtdepay->next_seqnum == 0xff00) rdtdepay->next_seqnum = 0; + if ((flags & 1) == 0) + outflags = 2; + else + outflags = 0; + GST_WRITE_UINT16_BE (outdata + 0, 0); /* version */ GST_WRITE_UINT16_BE (outdata + 2, size + 12); /* length */ GST_WRITE_UINT16_BE (outdata + 4, stream_id); /* stream */ GST_WRITE_UINT32_BE (outdata + 6, timestamp); /* timestamp */ - GST_WRITE_UINT16_BE (outdata + 10, 0); /* flags */ + GST_WRITE_UINT16_BE (outdata + 10, outflags); /* flags */ memcpy (outdata + 12, data, size); GST_DEBUG_OBJECT (rdtdepay, "Pushing packet, outtime %" GST_TIME_FORMAT,