asfdemux: fixes/enhancements for streaming mode

* Do not rock the boat by reacting to FLUSH_START.
* Try to handle TIME seeking by seeking upstream in BYTES.
* Handle SEEKING query.
This commit is contained in:
Mark Nauwelaerts 2009-05-01 18:08:15 +02:00
parent 95ddda57e2
commit 2bd14c7153

View file

@ -337,7 +337,6 @@ gst_asf_demux_sink_event (GstPad * pad, GstEvent * event)
break; break;
} }
case GST_EVENT_FLUSH_START:
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
GST_OBJECT_LOCK (demux); GST_OBJECT_LOCK (demux);
gst_asf_demux_reset_stream_state_after_discont (demux); gst_asf_demux_reset_stream_state_after_discont (demux);
@ -424,6 +423,52 @@ gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
} }
} }
/* do a seek in push based mode */
static gboolean
gst_asf_demux_handle_seek_push (GstASFDemux * demux, GstEvent * event)
{
gdouble rate;
GstFormat format;
GstSeekFlags flags;
GstSeekType cur_type, stop_type;
gint64 cur, stop;
guint packet;
gboolean res;
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
&stop_type, &stop);
stop_type = GST_SEEK_TYPE_NONE;
stop = -1;
GST_DEBUG_OBJECT (demux, "seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
/* determine packet, by index or by estimation */
if (!gst_asf_demux_seek_index_lookup (demux, &packet, cur, NULL)) {
packet = (guint) gst_util_uint64_scale (demux->num_packets,
cur, demux->play_time);
}
if (packet > demux->num_packets) {
GST_DEBUG_OBJECT (demux, "could not determine packet to seek to, "
"seek aborted.");
return FALSE;
}
GST_DEBUG_OBJECT (demux, "seeking to packet %d", packet);
cur = demux->data_offset + (packet * demux->packet_size);
GST_DEBUG_OBJECT (demux, "Pushing BYTE seek rate %g, "
"start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur, stop);
/* BYTE seek event */
event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
stop_type, stop);
res = gst_pad_push_event (demux->sinkpad, event);
return res;
}
static gboolean static gboolean
gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event) gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
{ {
@ -447,6 +492,11 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
return FALSE; return FALSE;
} }
if (!demux->activated_streams) {
GST_LOG_OBJECT (demux, "streams not yet activated, ignoring seek");
return FALSE;
}
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
&stop_type, &stop); &stop_type, &stop);
@ -465,8 +515,23 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT); keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT);
if (demux->streaming) { if (demux->streaming) {
/* support it safely needs more segment handling, e.g. closing etc */
if (!flush) {
GST_LOG_OBJECT (demux, "streaming; non-flushing seek not supported");
return FALSE;
}
/* we can (re)construct the start later on, but not the end */
if (stop_type != GST_SEEK_TYPE_NONE) {
GST_LOG_OBJECT (demux, "streaming; end type must be NONE");
return FALSE;
}
gst_event_ref (event); gst_event_ref (event);
return gst_pad_push_event (demux->sinkpad, event); /* upstream might handle TIME seek, e.g. mms or rtsp,
* or not, e.g. http, then we give it a hand */
if (!gst_pad_push_event (demux->sinkpad, event))
return gst_asf_demux_handle_seek_push (demux, event);
else
return TRUE;
} }
/* unlock the streaming thread */ /* unlock the streaming thread */
@ -3315,10 +3380,40 @@ gst_asf_demux_handle_src_query (GstPad * pad, GstQuery * query)
duration = demux->segment.duration; duration = demux->segment.duration;
GST_OBJECT_UNLOCK (demux); GST_OBJECT_UNLOCK (demux);
gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, if (!demux->streaming || !demux->seekable) {
0, duration); gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
res = TRUE; duration);
} res = TRUE;
} else {
GstFormat fmt;
gboolean seekable;
/* try downstream first in TIME */
res = gst_pad_query_default (pad, query);
gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
GST_LOG_OBJECT (demux, "upstream %s seekable %d",
GST_STR_NULL (gst_format_get_name (fmt)), seekable);
/* if no luck, maybe in BYTES */
if (!seekable || fmt != GST_FORMAT_TIME) {
GstQuery *q;
q = gst_query_new_seeking (GST_FORMAT_BYTES);
if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
GST_LOG_OBJECT (demux, "upstream %s seekable %d",
GST_STR_NULL (gst_format_get_name (fmt)), seekable);
if (fmt != GST_FORMAT_BYTES)
seekable = FALSE;
}
gst_query_unref (q);
gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
duration);
res = TRUE;
}
}
} else
GST_LOG_OBJECT (demux, "only support seeking in TIME format");
break; break;
} }