mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-08 00:18:54 +00:00
gst/realmedia/rmdemux.*: Remember first timestamp encountered in stream and re-timestamp stream to start from zero (f...
Original commit message from CVS: * gst/realmedia/rmdemux.c: (gst_rmdemux_init), (gst_rmdemux_sink_event), (gst_rmdemux_perform_seek), (gst_rmdemux_reset), (gst_rmdemux_chain), (gst_rmdemux_add_stream), (gst_rmdemux_parse_packet): * gst/realmedia/rmdemux.h: Remember first timestamp encountered in stream and re-timestamp stream to start from zero (fixes #397219); only send one newsegment event, not two; when seeking, send newsegment events from the streaming thread and not from the seeking thread.
This commit is contained in:
parent
971b4e3614
commit
286a2c0edb
3 changed files with 73 additions and 37 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2007-05-16 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
|
* gst/realmedia/rmdemux.c: (gst_rmdemux_init),
|
||||||
|
(gst_rmdemux_sink_event), (gst_rmdemux_perform_seek),
|
||||||
|
(gst_rmdemux_reset), (gst_rmdemux_chain), (gst_rmdemux_add_stream),
|
||||||
|
(gst_rmdemux_parse_packet):
|
||||||
|
* gst/realmedia/rmdemux.h:
|
||||||
|
Remember first timestamp encountered in stream and re-timestamp
|
||||||
|
stream to start from zero (fixes #397219); only send one newsegment
|
||||||
|
event, not two; when seeking, send newsegment events from the
|
||||||
|
streaming thread and not from the seeking thread.
|
||||||
|
|
||||||
2007-05-16 Tim-Philipp Müller <tim at centricular dot net>
|
2007-05-16 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
Based on patch by: Mark Nauwelaerts <manauw skynet be>
|
Based on patch by: Mark Nauwelaerts <manauw skynet be>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* GStreamer
|
/* GStreamer RealMedia demuxer
|
||||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
* Copyright (C) <2003> David A. Schleef <ds@schleef.org>
|
* Copyright (C) <2003> David A. Schleef <ds@schleef.org>
|
||||||
* Copyright (C) <2004> Stephane Loeuillet <gstreamer@leroutier.net>
|
* Copyright (C) <2004> Stephane Loeuillet <gstreamer@leroutier.net>
|
||||||
|
@ -77,6 +77,8 @@ struct _GstRMDemuxStream
|
||||||
gboolean needs_descrambling;
|
gboolean needs_descrambling;
|
||||||
guint subpackets_needed; /* subpackets needed for descrambling */
|
guint subpackets_needed; /* subpackets needed for descrambling */
|
||||||
GPtrArray *subpackets; /* array containing subpacket GstBuffers */
|
GPtrArray *subpackets; /* array containing subpacket GstBuffers */
|
||||||
|
|
||||||
|
GstTagList *pending_tags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRMDemuxIndex
|
struct _GstRMDemuxIndex
|
||||||
|
@ -244,29 +246,31 @@ gst_rmdemux_init (GstRMDemux * rmdemux)
|
||||||
gst_element_add_pad (GST_ELEMENT (rmdemux), rmdemux->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (rmdemux), rmdemux->sinkpad);
|
||||||
|
|
||||||
rmdemux->adapter = gst_adapter_new ();
|
rmdemux->adapter = gst_adapter_new ();
|
||||||
|
rmdemux->first_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
rmdemux->need_newsegment = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rmdemux_sink_event (GstPad * pad, GstEvent * event)
|
gst_rmdemux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
{
|
{
|
||||||
gboolean ret = TRUE;
|
GstRMDemux *rmdemux;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
rmdemux = GST_RMDEMUX (gst_pad_get_parent (pad));
|
||||||
GstRMDemux *rmdemux = GST_RMDEMUX (GST_PAD_PARENT (pad));
|
|
||||||
#endif
|
GST_LOG_OBJECT (pad, "%s event", GST_EVENT_TYPE_NAME (event));
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_NEWSEGMENT:
|
case GST_EVENT_NEWSEGMENT:
|
||||||
GST_LOG_OBJECT (rmdemux, "Event on sink: NEWSEGMENT");
|
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
ret = TRUE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GST_LOG_OBJECT (rmdemux, "Event on sink: type=%d",
|
|
||||||
GST_EVENT_TYPE (event));
|
|
||||||
ret = gst_pad_event_default (pad, event);
|
ret = gst_pad_event_default (pad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_object_unref (rmdemux);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,23 +566,14 @@ gst_rmdemux_perform_seek (GstRMDemux * rmdemux, GstEvent * event)
|
||||||
|
|
||||||
/* now we have a new position, prepare for streaming again */
|
/* now we have a new position, prepare for streaming again */
|
||||||
{
|
{
|
||||||
GstEvent *event;
|
|
||||||
|
|
||||||
/* Reset the demuxer state */
|
/* Reset the demuxer state */
|
||||||
rmdemux->state = RMDEMUX_STATE_DATA_PACKET;
|
rmdemux->state = RMDEMUX_STATE_DATA_PACKET;
|
||||||
|
|
||||||
if (flush)
|
if (flush)
|
||||||
gst_rmdemux_send_event (rmdemux, gst_event_new_flush_stop ());
|
gst_rmdemux_send_event (rmdemux, gst_event_new_flush_stop ());
|
||||||
|
|
||||||
/* create the discont event we are going to send out */
|
/* must send newsegment event from streaming thread, so just set flag */
|
||||||
event = gst_event_new_new_segment (FALSE, rmdemux->segment.rate,
|
rmdemux->need_newsegment = TRUE;
|
||||||
rmdemux->segment.format, rmdemux->segment.start,
|
|
||||||
rmdemux->segment.stop, rmdemux->segment.time);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rmdemux,
|
|
||||||
"sending NEWSEGMENT event to all src pads with segment.start= %"
|
|
||||||
GST_TIME_FORMAT, GST_TIME_ARGS (rmdemux->segment.start));
|
|
||||||
gst_rmdemux_send_event (rmdemux, event);
|
|
||||||
|
|
||||||
/* notify start of new segment */
|
/* notify start of new segment */
|
||||||
if (rmdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
|
if (rmdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
|
||||||
|
@ -586,6 +581,7 @@ gst_rmdemux_perform_seek (GstRMDemux * rmdemux, GstEvent * event)
|
||||||
gst_message_new_segment_start (GST_OBJECT_CAST (rmdemux),
|
gst_message_new_segment_start (GST_OBJECT_CAST (rmdemux),
|
||||||
GST_FORMAT_TIME, rmdemux->segment.last_stop));
|
GST_FORMAT_TIME, rmdemux->segment.last_stop));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restart our task since it might have been stopped when we did the
|
/* restart our task since it might have been stopped when we did the
|
||||||
* flush. */
|
* flush. */
|
||||||
gst_pad_start_task (rmdemux->sinkpad, (GstTaskFunction) gst_rmdemux_loop,
|
gst_pad_start_task (rmdemux->sinkpad, (GstTaskFunction) gst_rmdemux_loop,
|
||||||
|
@ -685,6 +681,8 @@ gst_rmdemux_reset (GstRMDemux * rmdemux)
|
||||||
|
|
||||||
gst_rmdemux_stream_clear_cached_subpackets (rmdemux, stream);
|
gst_rmdemux_stream_clear_cached_subpackets (rmdemux, stream);
|
||||||
gst_element_remove_pad (GST_ELEMENT (rmdemux), stream->pad);
|
gst_element_remove_pad (GST_ELEMENT (rmdemux), stream->pad);
|
||||||
|
if (stream->pending_tags)
|
||||||
|
gst_tag_list_free (stream->pending_tags);
|
||||||
if (stream->subpackets)
|
if (stream->subpackets)
|
||||||
g_ptr_array_free (stream->subpackets, TRUE);
|
g_ptr_array_free (stream->subpackets, TRUE);
|
||||||
g_free (stream->index);
|
g_free (stream->index);
|
||||||
|
@ -700,6 +698,8 @@ gst_rmdemux_reset (GstRMDemux * rmdemux)
|
||||||
rmdemux->have_pads = FALSE;
|
rmdemux->have_pads = FALSE;
|
||||||
|
|
||||||
gst_segment_init (&rmdemux->segment, GST_FORMAT_UNDEFINED);
|
gst_segment_init (&rmdemux->segment, GST_FORMAT_UNDEFINED);
|
||||||
|
rmdemux->first_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
rmdemux->need_newsegment = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -1084,18 +1084,14 @@ gst_rmdemux_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
/* If we haven't already done so then signal there are no more pads */
|
/* If we haven't already done so then signal there are no more pads */
|
||||||
if (!rmdemux->have_pads) {
|
if (!rmdemux->have_pads) {
|
||||||
|
GST_LOG_OBJECT (rmdemux, "no more pads");
|
||||||
gst_element_no_more_pads (GST_ELEMENT (rmdemux));
|
gst_element_no_more_pads (GST_ELEMENT (rmdemux));
|
||||||
rmdemux->have_pads = TRUE;
|
rmdemux->have_pads = TRUE;
|
||||||
|
|
||||||
GST_LOG_OBJECT (rmdemux, "no more pads.");
|
|
||||||
gst_rmdemux_send_event (rmdemux,
|
|
||||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
|
|
||||||
(gint64) 0, (gint64) - 1, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The actual header is only 8 bytes */
|
/* The actual header is only 8 bytes */
|
||||||
rmdemux->size = DATA_SIZE;
|
rmdemux->size = DATA_SIZE;
|
||||||
GST_DEBUG_OBJECT (rmdemux, "data available %d",
|
GST_LOG_OBJECT (rmdemux, "data available %d",
|
||||||
gst_adapter_available (rmdemux->adapter));
|
gst_adapter_available (rmdemux->adapter));
|
||||||
if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
|
if (gst_adapter_available (rmdemux->adapter) < rmdemux->size)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
@ -1444,16 +1440,11 @@ gst_rmdemux_add_stream (GstRMDemux * rmdemux, GstRMDemuxStream * stream)
|
||||||
gst_pad_set_active (stream->pad, TRUE);
|
gst_pad_set_active (stream->pad, TRUE);
|
||||||
gst_element_add_pad (GST_ELEMENT_CAST (rmdemux), stream->pad);
|
gst_element_add_pad (GST_ELEMENT_CAST (rmdemux), stream->pad);
|
||||||
|
|
||||||
gst_pad_push_event (stream->pad,
|
/* save for later, we must send the tags after the newsegment event */
|
||||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, (gint64) 0,
|
if (codec_name != NULL && codec_tag != NULL) {
|
||||||
(gint64) - 1, 0));
|
stream->pending_tags = gst_tag_list_new ();
|
||||||
|
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_KEEP,
|
||||||
if (codec_name && codec_tag) {
|
codec_tag, codec_name, NULL);
|
||||||
GstTagList *tags = NULL;
|
|
||||||
|
|
||||||
tags = gst_tag_list_new ();
|
|
||||||
gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, codec_tag, codec_name, NULL);
|
|
||||||
gst_element_found_tags_for_pad (GST_ELEMENT (rmdemux), stream->pad, tags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1988,6 +1979,33 @@ gst_rmdemux_parse_packet (GstRMDemux * rmdemux, const guint8 * data,
|
||||||
if (!stream || !stream->pad)
|
if (!stream || !stream->pad)
|
||||||
goto unknown_stream;
|
goto unknown_stream;
|
||||||
|
|
||||||
|
if (rmdemux->first_ts == GST_CLOCK_TIME_NONE) {
|
||||||
|
GST_DEBUG_OBJECT (rmdemux, "First timestamp: %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (timestamp));
|
||||||
|
rmdemux->first_ts = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rmdemux->need_newsegment) {
|
||||||
|
GstEvent *event;
|
||||||
|
|
||||||
|
event = gst_event_new_new_segment (FALSE, rmdemux->segment.rate,
|
||||||
|
rmdemux->segment.format, rmdemux->segment.start,
|
||||||
|
rmdemux->segment.stop, rmdemux->segment.time);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rmdemux, "sending NEWSEGMENT event, segment.start= %"
|
||||||
|
GST_TIME_FORMAT, GST_TIME_ARGS (rmdemux->segment.start));
|
||||||
|
|
||||||
|
gst_rmdemux_send_event (rmdemux, event);
|
||||||
|
rmdemux->need_newsegment = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->pending_tags != NULL) {
|
||||||
|
GST_LOG_OBJECT (stream->pad, "tags %" GST_PTR_FORMAT, stream->pending_tags);
|
||||||
|
gst_element_found_tags_for_pad (GST_ELEMENT_CAST (rmdemux), stream->pad,
|
||||||
|
stream->pending_tags);
|
||||||
|
stream->pending_tags = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if ((rmdemux->offset + packet_size) <= stream->seek_offset) {
|
if ((rmdemux->offset + packet_size) <= stream->seek_offset) {
|
||||||
GST_DEBUG_OBJECT (rmdemux,
|
GST_DEBUG_OBJECT (rmdemux,
|
||||||
"Stream %d is skipping: seek_offset=%d, offset=%d, packet_size=%u",
|
"Stream %d is skipping: seek_offset=%d, offset=%d, packet_size=%u",
|
||||||
|
@ -2004,7 +2022,7 @@ gst_rmdemux_parse_packet (GstRMDemux * rmdemux, const guint8 * data,
|
||||||
goto alloc_failed;
|
goto alloc_failed;
|
||||||
|
|
||||||
memcpy (GST_BUFFER_DATA (buffer), (guint8 *) data, packet_size);
|
memcpy (GST_BUFFER_DATA (buffer), (guint8 *) data, packet_size);
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = timestamp;
|
GST_BUFFER_TIMESTAMP (buffer) = timestamp - rmdemux->first_ts;
|
||||||
|
|
||||||
if (stream->needs_descrambling) {
|
if (stream->needs_descrambling) {
|
||||||
ret = gst_rmdemux_handle_scrambled_packet (rmdemux, stream, buffer, key);
|
ret = gst_rmdemux_handle_scrambled_packet (rmdemux, stream, buffer, key);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* GStreamer
|
/* GStreamer RealMedia demuxer
|
||||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
|
@ -106,9 +106,15 @@ struct _GstRMDemux {
|
||||||
gboolean segment_running;
|
gboolean segment_running;
|
||||||
gboolean running;
|
gboolean running;
|
||||||
|
|
||||||
|
/* Whether we need to send a newsegment event */
|
||||||
|
gboolean need_newsegment;
|
||||||
|
|
||||||
/* Current timestamp */
|
/* Current timestamp */
|
||||||
GstClockTime cur_timestamp;
|
GstClockTime cur_timestamp;
|
||||||
|
|
||||||
|
/* First timestamp */
|
||||||
|
GstClockTime first_ts;
|
||||||
|
|
||||||
int n_chunks;
|
int n_chunks;
|
||||||
int chunk_index;
|
int chunk_index;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue