mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
gst/asfdemux/gstasfdemux.*: Don't crash in the seek event handling code when playtime is 0, as may be the case with l...
Original commit message from CVS: * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_handle_seek_event), (gst_asf_demux_process_data), (gst_asf_demux_process_file), (gst_asf_demux_handle_src_query), (gst_asf_demux_change_state): * gst/asfdemux/gstasfdemux.h: Don't crash in the seek event handling code when playtime is 0, as may be the case with live streams (#386218). Implement SEEKING query so applications can query seekability without second-guessing based on whether we have a duration or not.
This commit is contained in:
parent
b4a1a4cda2
commit
7e1371c41e
3 changed files with 77 additions and 24 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
2006-12-15 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* gst/asfdemux/gstasfdemux.c: (gst_asf_demux_handle_seek_event),
|
||||
(gst_asf_demux_process_data), (gst_asf_demux_process_file),
|
||||
(gst_asf_demux_handle_src_query), (gst_asf_demux_change_state):
|
||||
* gst/asfdemux/gstasfdemux.h:
|
||||
Don't crash in the seek event handling code when playtime is 0,
|
||||
as may be the case with live streams (#386218). Implement SEEKING
|
||||
query so applications can query seekability without second-guessing
|
||||
based on whether we have a duration or not.
|
||||
|
||||
2006-12-15 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* Makefile.am:
|
||||
|
|
|
@ -227,18 +227,25 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
|
|||
gdouble rate;
|
||||
gint64 cur, stop;
|
||||
gint64 seek_offset;
|
||||
gint64 seek_time;
|
||||
guint64 seek_packet;
|
||||
|
||||
if (demux->seekable == FALSE || demux->packet_size == 0 ||
|
||||
demux->num_packets == 0 || demux->play_time == 0) {
|
||||
GST_LOG_OBJECT (demux, "stream is not seekable");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
|
||||
&stop_type, &stop);
|
||||
|
||||
if (format != GST_FORMAT_TIME) {
|
||||
GST_LOG ("seeking is only supported in TIME format");
|
||||
GST_LOG_OBJECT (demux, "seeking is only supported in TIME format");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (rate <= 0.0) {
|
||||
GST_LOG ("backward playback is not supported yet");
|
||||
GST_LOG_OBJECT (demux, "backward playback is not supported yet");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -260,31 +267,24 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
|
|||
GST_DEBUG ("trying to seek to time %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (segment.start));
|
||||
|
||||
if (demux->packet_size > 0) {
|
||||
gint64 seek_time = segment.start;
|
||||
seek_time = segment.start;
|
||||
|
||||
/* Hackety hack, this sucks. We just seek to an earlier position
|
||||
* and let the sinks throw away the stuff before the segment start */
|
||||
if (flush && (accurate || keyunit_sync)) {
|
||||
seek_time -= 5 * GST_SECOND;
|
||||
if (seek_time < 0)
|
||||
seek_time = 0;
|
||||
}
|
||||
|
||||
seek_packet = demux->num_packets * seek_time / demux->play_time;
|
||||
|
||||
if (seek_packet > demux->num_packets)
|
||||
seek_packet = demux->num_packets;
|
||||
|
||||
seek_offset = seek_packet * demux->packet_size + demux->data_offset;
|
||||
/* demux->next_byte_offset will be set via newsegment event */
|
||||
} else {
|
||||
/* FIXME */
|
||||
g_message ("IMPLEMENT ME: seeking for packet_size == 0 (asfdemux)");
|
||||
ret = FALSE;
|
||||
goto done;
|
||||
/* Hackety hack, this sucks. We just seek to an earlier position
|
||||
* and let the sinks throw away the stuff before the segment start */
|
||||
if (flush && (accurate || keyunit_sync)) {
|
||||
seek_time -= 5 * GST_SECOND;
|
||||
if (seek_time < 0)
|
||||
seek_time = 0;
|
||||
}
|
||||
|
||||
seek_packet = demux->num_packets * seek_time / demux->play_time;
|
||||
|
||||
if (seek_packet > demux->num_packets)
|
||||
seek_packet = demux->num_packets;
|
||||
|
||||
seek_offset = seek_packet * demux->packet_size + demux->data_offset;
|
||||
/* demux->next_byte_offset will be set via newsegment event */
|
||||
|
||||
GST_LOG ("seeking to byte offset %" G_GINT64_FORMAT, seek_offset);
|
||||
|
||||
ret = gst_pad_push_event (demux->sinkpad,
|
||||
|
@ -1407,6 +1407,9 @@ gst_asf_demux_process_data (GstASFDemux * demux, guint64 object_size,
|
|||
demux->packet = 0;
|
||||
demux->num_packets = data_object.packets;
|
||||
|
||||
if (demux->num_packets == 0)
|
||||
demux->seekable = FALSE;
|
||||
|
||||
/* minus object header and data object header */
|
||||
demux->data_size =
|
||||
object_size - ASF_DEMUX_OBJECT_HEADER_SIZE - (16 + 8 + 1 + 1);
|
||||
|
@ -1451,22 +1454,40 @@ gst_asf_demux_process_file (GstASFDemux * demux, guint8 ** p_data,
|
|||
guint64 * p_size)
|
||||
{
|
||||
asf_obj_file object;
|
||||
gboolean broadcast;
|
||||
|
||||
/* Get the rest of the header's header */
|
||||
if (!gst_asf_demux_get_obj_file (&object, p_data, p_size))
|
||||
return ASF_FLOW_NEED_MORE_DATA;
|
||||
|
||||
broadcast = !!(object.flags & 0x01);
|
||||
demux->seekable = !!(object.flags & 0x02);
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", broadcast);
|
||||
GST_DEBUG_OBJECT (demux, "flags::seekable = %d", demux->seekable);
|
||||
|
||||
if (broadcast) {
|
||||
/* these fields are invalid if the broadcast flag is set */
|
||||
object.play_time = 0;
|
||||
object.file_size = 0;
|
||||
}
|
||||
|
||||
if (object.min_pktsize == object.max_pktsize) {
|
||||
demux->packet_size = object.max_pktsize;
|
||||
} else {
|
||||
demux->packet_size = (guint32) - 1;
|
||||
GST_WARNING ("Non-const packet size, seeking disabled");
|
||||
demux->seekable = FALSE;
|
||||
}
|
||||
|
||||
/* FIXME: do we need object.send_time as well? what is it? */
|
||||
|
||||
demux->play_time = (guint64) object.play_time * (GST_SECOND / 10000000);
|
||||
demux->preroll = object.preroll;
|
||||
|
||||
if (demux->play_time == 0)
|
||||
demux->seekable = FALSE;
|
||||
|
||||
GST_DEBUG_OBJECT (demux,
|
||||
"play_time %" GST_TIME_FORMAT " preroll %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (demux->play_time), GST_TIME_ARGS (demux->preroll));
|
||||
|
@ -2788,6 +2809,24 @@ gst_asf_demux_handle_src_query (GstPad * pad, GstQuery * query)
|
|||
break;
|
||||
}
|
||||
|
||||
case GST_QUERY_SEEKING:{
|
||||
GstFormat format;
|
||||
|
||||
gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
|
||||
if (format == GST_FORMAT_TIME) {
|
||||
gint64 duration;
|
||||
|
||||
GST_OBJECT_LOCK (demux);
|
||||
duration = demux->segment.duration;
|
||||
GST_OBJECT_UNLOCK (demux);
|
||||
|
||||
gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable,
|
||||
0, duration);
|
||||
res = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
res = gst_pad_query_default (pad, query);
|
||||
break;
|
||||
|
@ -2838,6 +2877,7 @@ gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
|
|||
g_slist_free (demux->ext_stream_props);
|
||||
demux->ext_stream_props = NULL;
|
||||
memset (demux->stream, 0, sizeof (demux->stream));
|
||||
demux->seekable = FALSE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -116,6 +116,8 @@ struct _GstASFDemux {
|
|||
guint64 preroll;
|
||||
guint64 pts;
|
||||
|
||||
gboolean seekable;
|
||||
|
||||
/* expected byte offset of next buffer to be received by chain
|
||||
* function. Used to calculate the current byte offset into the
|
||||
* file from the adapter state and the data parser state */
|
||||
|
|
Loading…
Reference in a new issue