mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
ext/ogg/gstoggdemux.c: Parse seeking events better.
Original commit message from CVS: * ext/ogg/gstoggdemux.c: (gst_ogg_pad_src_query), (gst_ogg_pad_event), (gst_ogg_demux_factory_filter), (gst_ogg_pad_submit_packet), (gst_ogg_chain_new), (gst_ogg_demux_init), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_loop), (gst_ogg_print): Parse seeking events better. Unref static caps. Generate correct newsegment events, fixes seeking in live oggs. * ext/theora/theoradec.c: (theora_dec_src_query), (theora_dec_src_event), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_dec_push), (theora_dec_chain): Use newsegment values to report correct play time. * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query), (vorbis_dec_src_event), (vorbis_dec_sink_event): * ext/vorbis/vorbisdec.h: Parse and use newsegment values to report correct play time. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_event), (gst_base_audio_sink_render): Clear ringbuffer on flush. Use newsegment values to calculate playback time. * sys/ximage/ximagesink.c: (gst_ximagesink_get_times): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Basesink does newsegment calculations for us now.
This commit is contained in:
parent
2136419a0a
commit
7824216cef
8 changed files with 240 additions and 75 deletions
31
ChangeLog
31
ChangeLog
|
@ -1,3 +1,34 @@
|
|||
2005-08-24 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* ext/ogg/gstoggdemux.c: (gst_ogg_pad_src_query),
|
||||
(gst_ogg_pad_event), (gst_ogg_demux_factory_filter),
|
||||
(gst_ogg_pad_submit_packet), (gst_ogg_chain_new),
|
||||
(gst_ogg_demux_init), (gst_ogg_demux_perform_seek),
|
||||
(gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info),
|
||||
(gst_ogg_demux_chain), (gst_ogg_demux_loop), (gst_ogg_print):
|
||||
Parse seeking events better.
|
||||
Unref static caps.
|
||||
Generate correct newsegment events, fixes seeking in live oggs.
|
||||
|
||||
* ext/theora/theoradec.c: (theora_dec_src_query),
|
||||
(theora_dec_src_event), (theora_dec_src_getcaps),
|
||||
(theora_dec_sink_event), (theora_dec_push), (theora_dec_chain):
|
||||
Use newsegment values to report correct play time.
|
||||
|
||||
* ext/vorbis/vorbisdec.c: (vorbis_dec_src_query),
|
||||
(vorbis_dec_src_event), (vorbis_dec_sink_event):
|
||||
* ext/vorbis/vorbisdec.h:
|
||||
Parse and use newsegment values to report correct play time.
|
||||
|
||||
* gst-libs/gst/audio/gstbaseaudiosink.c:
|
||||
(gst_base_audio_sink_event), (gst_base_audio_sink_render):
|
||||
Clear ringbuffer on flush.
|
||||
Use newsegment values to calculate playback time.
|
||||
|
||||
* sys/ximage/ximagesink.c: (gst_ximagesink_get_times):
|
||||
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times):
|
||||
Basesink does newsegment calculations for us now.
|
||||
|
||||
2005-08-24 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* check/Makefile.am:
|
||||
|
|
|
@ -75,11 +75,12 @@ typedef struct _GstOggChain
|
|||
|
||||
GstClockTime total_time; /* the total time of this chain, this is the MAX of
|
||||
the totals of all streams */
|
||||
GstClockTime start_time; /* the timestamp of the first sample, this is the MIN of
|
||||
the start times of all streams. */
|
||||
GstClockTime last_time; /* the timestamp of the last page, this is the MAX of the
|
||||
streams. */
|
||||
GstClockTime begin_time; /* when this chain starts in the stream */
|
||||
|
||||
GstClockTime segment_start; /* the timestamp of the first sample, this is the MIN of
|
||||
the start times of all streams. */
|
||||
GstClockTime segment_stop; /* the timestamp of the last page, this is the MAX of the
|
||||
streams. */
|
||||
} GstOggChain;
|
||||
|
||||
/* different modes for the pad */
|
||||
|
@ -151,7 +152,6 @@ struct _GstOggDemux
|
|||
/* state */
|
||||
GMutex *chain_lock; /* we need the lock to protect the chains */
|
||||
GArray *chains; /* list of chains we know */
|
||||
GstClockTime start_time; /* the start time of the first chain */
|
||||
GstClockTime total_time; /* the total time of this ogg, this is the sum of
|
||||
the totals of all chains */
|
||||
GstOggChain *current_chain;
|
||||
|
@ -161,6 +161,7 @@ struct _GstOggDemux
|
|||
GstClockTime segment_start;
|
||||
GstClockTime segment_stop;
|
||||
gboolean segment_play;
|
||||
gdouble segment_rate;
|
||||
|
||||
gint64 current_granule;
|
||||
GstClockTime current_time;
|
||||
|
@ -185,7 +186,8 @@ static gboolean gst_ogg_demux_collect_chain_info (GstOggDemux * ogg,
|
|||
static gboolean gst_ogg_demux_activate_chain (GstOggDemux * ogg,
|
||||
GstOggChain * chain, GstEvent * event);
|
||||
|
||||
static gboolean gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush);
|
||||
static gboolean gst_ogg_demux_perform_seek (GstOggDemux * ogg,
|
||||
gboolean accurate, gboolean flush);
|
||||
|
||||
static void gst_ogg_pad_class_init (GstOggPadClass * klass);
|
||||
static void gst_ogg_pad_init (GstOggPad * pad);
|
||||
|
@ -360,8 +362,20 @@ gst_ogg_pad_src_query (GstPad * pad, GstQuery * query)
|
|||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_POSITION:
|
||||
{
|
||||
GstFormat format;
|
||||
|
||||
gst_query_parse_position (query, &format, NULL, NULL);
|
||||
/* can only get position in time */
|
||||
if (format != GST_FORMAT_TIME) {
|
||||
GST_DEBUG ("only query position on TIME is supported");
|
||||
res = FALSE;
|
||||
goto done;
|
||||
}
|
||||
/* can only return the total time position */
|
||||
gst_query_set_position (query, GST_FORMAT_TIME, -1, ogg->total_time);
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_CONVERT:
|
||||
/* hmm .. */
|
||||
res = FALSE;
|
||||
|
@ -370,7 +384,7 @@ gst_ogg_pad_src_query (GstPad * pad, GstQuery * query)
|
|||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -388,8 +402,9 @@ gst_ogg_pad_event (GstPad * pad, GstEvent * event)
|
|||
case GST_EVENT_SEEK:
|
||||
{
|
||||
gboolean running;
|
||||
gboolean flush;
|
||||
gboolean flush, accurate;
|
||||
GstFormat format;
|
||||
gdouble rate;
|
||||
GstSeekFlags flags;
|
||||
GstSeekType cur_type, stop_type;
|
||||
gint64 cur, stop;
|
||||
|
@ -398,23 +413,40 @@ gst_ogg_pad_event (GstPad * pad, GstEvent * event)
|
|||
* seek query upstream after converting it to bytes using
|
||||
* the average bitrate of the stream. */
|
||||
if (!ogg->seekable) {
|
||||
res = FALSE;
|
||||
GST_DEBUG ("seek on non seekable stream");
|
||||
goto done_unref;
|
||||
goto error;
|
||||
}
|
||||
gst_event_parse_seek (event, NULL, &format, &flags,
|
||||
|
||||
gst_event_parse_seek (event, &rate, &format, &flags,
|
||||
&cur_type, &cur, &stop_type, &stop);
|
||||
|
||||
/* we can only seek on time */
|
||||
if (format != GST_FORMAT_TIME) {
|
||||
res = FALSE;
|
||||
GST_DEBUG ("can only seek on TIME");
|
||||
goto done_unref;
|
||||
goto error;
|
||||
}
|
||||
/* cannot yet do backwards playback */
|
||||
if (rate <= 0.0) {
|
||||
GST_DEBUG ("can only seek with positive rate");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* store start and stop values */
|
||||
GST_LOCK (ogg);
|
||||
if (cur_type == GST_SEEK_TYPE_SET)
|
||||
ogg->segment_start = cur;
|
||||
else if (cur_type == GST_SEEK_TYPE_CUR)
|
||||
ogg->segment_start += cur;
|
||||
|
||||
if (stop_type != GST_SEEK_TYPE_NONE)
|
||||
ogg->segment_stop = stop;
|
||||
else if (stop_type == GST_SEEK_TYPE_CUR)
|
||||
ogg->segment_stop += cur;
|
||||
|
||||
ogg->segment_rate = rate;
|
||||
ogg->segment_play = !!(flags & GST_SEEK_FLAG_SEGMENT);
|
||||
flush = !!(flags & GST_SEEK_FLAG_FLUSH);
|
||||
flush = (flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH;
|
||||
accurate = (flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE;
|
||||
gst_event_unref (event);
|
||||
|
||||
GST_DEBUG ("segment positions set to %" GST_TIME_FORMAT "-%"
|
||||
|
@ -422,13 +454,12 @@ gst_ogg_pad_event (GstPad * pad, GstEvent * event)
|
|||
GST_TIME_ARGS (ogg->segment_stop));
|
||||
|
||||
/* check if we can do the seek now */
|
||||
GST_LOCK (ogg);
|
||||
running = ogg->running;
|
||||
GST_UNLOCK (ogg);
|
||||
|
||||
/* now do the seek */
|
||||
if (running) {
|
||||
res = gst_ogg_demux_perform_seek (ogg, flush);
|
||||
res = gst_ogg_demux_perform_seek (ogg, accurate, flush);
|
||||
} else
|
||||
res = TRUE;
|
||||
break;
|
||||
|
@ -437,13 +468,12 @@ gst_ogg_pad_event (GstPad * pad, GstEvent * event)
|
|||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
done_unref:
|
||||
error:
|
||||
GST_DEBUG ("error handling event");
|
||||
gst_event_unref (event);
|
||||
return res;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -454,7 +484,7 @@ gst_ogg_pad_reset (GstOggPad * pad)
|
|||
}
|
||||
|
||||
/* the filter function for selecting the elements we can use in
|
||||
* * autoplugging */
|
||||
* autoplugging */
|
||||
static gboolean
|
||||
gst_ogg_demux_factory_filter (GstPluginFeature * feature, GstCaps * caps)
|
||||
{
|
||||
|
@ -493,18 +523,22 @@ gst_ogg_demux_factory_filter (GstPluginFeature * feature, GstCaps * caps)
|
|||
/* we only care about the sink templates */
|
||||
if (templ->direction == GST_PAD_SINK) {
|
||||
GstCaps *intersect;
|
||||
GstCaps *scaps;
|
||||
gboolean empty;
|
||||
|
||||
/* try to intersect the caps with the caps of the template */
|
||||
intersect = gst_caps_intersect (caps,
|
||||
gst_static_caps_get (&templ->static_caps));
|
||||
scaps = gst_static_caps_get (&templ->static_caps);
|
||||
intersect = gst_caps_intersect (caps, scaps);
|
||||
gst_caps_unref (scaps);
|
||||
|
||||
empty = gst_caps_is_empty (intersect);
|
||||
gst_caps_unref (intersect);
|
||||
|
||||
/* check if the intersection is empty */
|
||||
if (!gst_caps_is_empty (intersect)) {
|
||||
if (!empty) {
|
||||
/* non empty intersection, we can use this element */
|
||||
gst_caps_unref (intersect);
|
||||
goto found;
|
||||
}
|
||||
gst_caps_unref (intersect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -527,6 +561,9 @@ compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
|
|||
gst_plugin_feature_get_name (f1));
|
||||
}
|
||||
|
||||
/* function called by the internal decoder elements when it outputs
|
||||
* a buffer. We use it to get the first timestamp of the stream
|
||||
*/
|
||||
static GstFlowReturn
|
||||
gst_ogg_pad_internal_chain (GstPad * pad, GstBuffer * buffer)
|
||||
{
|
||||
|
@ -780,9 +817,10 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
|||
GstEvent *event;
|
||||
|
||||
/* create the discont event we are going to send out */
|
||||
event = gst_event_new_newsegment (1.0,
|
||||
GST_FORMAT_TIME, (gint64) chain->start_time - chain->begin_time,
|
||||
(gint64) chain->last_time - chain->begin_time, (gint64) 0);
|
||||
event = gst_event_new_newsegment (ogg->segment_rate,
|
||||
GST_FORMAT_TIME,
|
||||
chain->segment_start - chain->begin_time,
|
||||
chain->segment_stop - chain->begin_time, 0);
|
||||
|
||||
gst_ogg_demux_activate_chain (ogg, chain, event);
|
||||
|
||||
|
@ -876,7 +914,7 @@ gst_ogg_chain_new (GstOggDemux * ogg)
|
|||
chain->have_bos = FALSE;
|
||||
chain->streams = g_array_new (FALSE, TRUE, sizeof (GstOggPad *));
|
||||
chain->begin_time = GST_CLOCK_TIME_NONE;
|
||||
chain->start_time = GST_CLOCK_TIME_NONE;
|
||||
chain->segment_start = GST_CLOCK_TIME_NONE;
|
||||
chain->total_time = GST_CLOCK_TIME_NONE;
|
||||
|
||||
return chain;
|
||||
|
@ -1062,6 +1100,7 @@ gst_ogg_demux_init (GstOggDemux * ogg)
|
|||
ogg->current_granule = -1;
|
||||
ogg->current_time = 0;
|
||||
|
||||
ogg->segment_rate = 1.0;
|
||||
ogg->segment_start = GST_CLOCK_TIME_NONE;
|
||||
ogg->segment_stop = GST_CLOCK_TIME_NONE;
|
||||
ogg->segment_play = FALSE;
|
||||
|
@ -1339,7 +1378,8 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
||||
gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean accurate,
|
||||
gboolean flush)
|
||||
{
|
||||
GstOggChain *chain = NULL;
|
||||
gint64 begin, end;
|
||||
|
@ -1348,19 +1388,9 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
|||
gint64 best;
|
||||
gint64 total;
|
||||
gint64 result = 0;
|
||||
gint64 start, stop;
|
||||
gint i;
|
||||
|
||||
/* nothing configured, play complete file */
|
||||
if (ogg->segment_start == GST_CLOCK_TIME_NONE)
|
||||
ogg->segment_start = ogg->start_time;
|
||||
if (ogg->segment_stop == GST_CLOCK_TIME_NONE)
|
||||
ogg->segment_stop = ogg->total_time;
|
||||
|
||||
ogg->segment_start =
|
||||
CLAMP (ogg->segment_start, ogg->start_time, ogg->total_time);
|
||||
ogg->segment_stop =
|
||||
CLAMP (ogg->segment_stop, ogg->start_time, ogg->total_time);
|
||||
|
||||
/* first step is to unlock the streaming thread if it is
|
||||
* blocked in a chain call, we do this by starting the flush. because
|
||||
* we cannot yet hold any streaming lock, we have to protect the chains
|
||||
|
@ -1391,6 +1421,20 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
|||
* forever. */
|
||||
GST_STREAM_LOCK (ogg->sinkpad);
|
||||
|
||||
GST_LOCK (ogg);
|
||||
/* nothing configured, play complete file */
|
||||
if (ogg->segment_start == GST_CLOCK_TIME_NONE)
|
||||
ogg->segment_start = 0;
|
||||
if (ogg->segment_stop == GST_CLOCK_TIME_NONE)
|
||||
ogg->segment_stop = ogg->total_time;
|
||||
|
||||
ogg->segment_start = CLAMP (ogg->segment_start, 0, ogg->total_time);
|
||||
ogg->segment_stop = CLAMP (ogg->segment_stop, 0, ogg->total_time);
|
||||
|
||||
start = ogg->segment_start;
|
||||
stop = ogg->segment_stop;
|
||||
GST_UNLOCK (ogg);
|
||||
|
||||
/* we need to stop flushing on the srcpad as we're going to use it
|
||||
* next. We can do this as we have the STREAM lock now. */
|
||||
gst_pad_push_event (ogg->sinkpad, gst_event_new_flush_stop ());
|
||||
|
@ -1417,7 +1461,7 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
|||
for (i = ogg->chains->len - 1; i >= 0; i--) {
|
||||
chain = g_array_index (ogg->chains, GstOggChain *, i);
|
||||
total -= chain->total_time;
|
||||
if (ogg->segment_start >= total)
|
||||
if (start >= total)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1425,13 +1469,18 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
|||
end = chain->end_offset;
|
||||
begintime = chain->begin_time;
|
||||
endtime = chain->begin_time + chain->total_time;
|
||||
target = ogg->segment_start - total + begintime;
|
||||
target = start - total + begintime;
|
||||
if (accurate) {
|
||||
/* FIXME, seek 4 seconds early to catch keyframes, better implement
|
||||
* keyframe detection. */
|
||||
target = target - (gint64) 4 *GST_SECOND;
|
||||
}
|
||||
target = MAX (target, 0);
|
||||
best = begin;
|
||||
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"seeking to %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT " in chain %p",
|
||||
GST_TIME_ARGS (ogg->segment_start), GST_TIME_ARGS (ogg->segment_stop),
|
||||
chain);
|
||||
GST_TIME_ARGS (start), GST_TIME_ARGS (stop), chain);
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"chain offset %" G_GINT64_FORMAT ", end offset %" G_GINT64_FORMAT, begin,
|
||||
end);
|
||||
|
@ -1502,6 +1551,8 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
|||
(gint64 *) & granuletime)) {
|
||||
g_warning ("could not convert granulepos to time");
|
||||
granuletime = target;
|
||||
} else {
|
||||
granuletime -= pad->first_time;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
|
@ -1554,8 +1605,8 @@ gst_ogg_demux_perform_seek (GstOggDemux * ogg, gboolean flush)
|
|||
|
||||
/* create the discont event we are going to send out */
|
||||
event = gst_event_new_newsegment (1.0,
|
||||
GST_FORMAT_TIME, (gint64) ogg->segment_start,
|
||||
(gint64) ogg->segment_stop, 0);
|
||||
GST_FORMAT_TIME,
|
||||
start + chain->segment_start, stop + chain->segment_start, start);
|
||||
|
||||
if (chain != ogg->current_chain) {
|
||||
/* switch to different chain, send discont on new chain */
|
||||
|
@ -1869,8 +1920,8 @@ gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, GstOggChain * chain)
|
|||
gint i;
|
||||
|
||||
chain->total_time = 0;
|
||||
chain->start_time = G_MAXINT64;
|
||||
chain->last_time = 0;
|
||||
chain->segment_start = G_MAXINT64;
|
||||
chain->segment_stop = 0;
|
||||
|
||||
for (i = 0; i < chain->streams->len; i++) {
|
||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||
|
@ -1882,13 +1933,13 @@ gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, GstOggChain * chain)
|
|||
if (pad->last_time != GST_CLOCK_TIME_NONE) {
|
||||
pad->total_time = pad->last_time - pad->start_time;
|
||||
chain->total_time = MAX (chain->total_time, pad->total_time);
|
||||
chain->last_time = MAX (chain->last_time, pad->last_time);
|
||||
chain->segment_stop = MAX (chain->segment_stop, pad->last_time);
|
||||
} else {
|
||||
pad->total_time = GST_CLOCK_TIME_NONE;
|
||||
chain->total_time = GST_CLOCK_TIME_NONE;
|
||||
chain->last_time = GST_CLOCK_TIME_NONE;
|
||||
chain->segment_stop = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
chain->start_time = MIN (chain->start_time, pad->start_time);
|
||||
chain->segment_start = MIN (chain->segment_start, pad->start_time);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
|
@ -1896,8 +1947,8 @@ gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, GstOggChain * chain)
|
|||
no_start_time:
|
||||
{
|
||||
chain->total_time = GST_CLOCK_TIME_NONE;
|
||||
chain->start_time = GST_CLOCK_TIME_NONE;
|
||||
chain->last_time = GST_CLOCK_TIME_NONE;
|
||||
chain->segment_start = GST_CLOCK_TIME_NONE;
|
||||
chain->segment_stop = GST_CLOCK_TIME_NONE;
|
||||
chain->begin_time = GST_CLOCK_TIME_NONE;
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1909,7 +1960,6 @@ gst_ogg_demux_collect_info (GstOggDemux * ogg)
|
|||
gint i;
|
||||
|
||||
/* collect all info */
|
||||
ogg->start_time = G_MAXINT64;
|
||||
ogg->total_time = 0;
|
||||
|
||||
for (i = 0; i < ogg->chains->len; i++) {
|
||||
|
@ -1919,7 +1969,6 @@ gst_ogg_demux_collect_info (GstOggDemux * ogg)
|
|||
|
||||
gst_ogg_demux_collect_chain_info (ogg, chain);
|
||||
|
||||
ogg->start_time = MIN (ogg->start_time, chain->start_time);
|
||||
ogg->total_time += chain->total_time;
|
||||
}
|
||||
}
|
||||
|
@ -2059,7 +2108,7 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
|
|||
GstClockTime duration;
|
||||
|
||||
/* this was the duration of the previous chain */
|
||||
duration = ogg->current_time - current_chain->start_time;
|
||||
duration = ogg->current_time - current_chain->segment_start;
|
||||
/* the new chain time starts at duration + begin_time */
|
||||
chain_time = duration + current_chain->begin_time;
|
||||
|
||||
|
@ -2168,7 +2217,7 @@ gst_ogg_demux_loop (GstOggPad * pad)
|
|||
GST_UNLOCK (ogg);
|
||||
|
||||
/* and seek to configured positions without FLUSH */
|
||||
gst_ogg_demux_perform_seek (ogg, FALSE);
|
||||
gst_ogg_demux_perform_seek (ogg, TRUE, FALSE);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (ogg, "pull data %lld", ogg->offset);
|
||||
|
@ -2422,10 +2471,9 @@ gst_ogg_print (GstOggDemux * ogg)
|
|||
{
|
||||
guint j, i;
|
||||
|
||||
GST_INFO_OBJECT (ogg, "%u chains, start time: %" GST_TIME_FORMAT,
|
||||
ogg->chains->len, GST_TIME_ARGS (ogg->start_time));
|
||||
GST_INFO_OBJECT (ogg, "%u chains", ogg->chains->len);
|
||||
GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
|
||||
ogg->chains->len, GST_TIME_ARGS (ogg->total_time));
|
||||
GST_TIME_ARGS (ogg->total_time));
|
||||
|
||||
for (i = 0; i < ogg->chains->len; i++) {
|
||||
GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
|
||||
|
@ -2433,12 +2481,14 @@ gst_ogg_print (GstOggDemux * ogg)
|
|||
GST_INFO_OBJECT (ogg, " chain %d (%u streams):", i, chain->streams->len);
|
||||
GST_INFO_OBJECT (ogg, " offset: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT,
|
||||
chain->offset, chain->end_offset);
|
||||
GST_INFO_OBJECT (ogg, " start time: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->start_time));
|
||||
GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->total_time));
|
||||
GST_INFO_OBJECT (ogg, " begin time: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->begin_time));
|
||||
GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->total_time));
|
||||
GST_INFO_OBJECT (ogg, " segment start: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->segment_start));
|
||||
GST_INFO_OBJECT (ogg, " segment stop: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->segment_stop));
|
||||
|
||||
for (j = 0; j < chain->streams->len; j++) {
|
||||
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j);
|
||||
|
|
|
@ -66,6 +66,11 @@ struct _GstTheoraDec
|
|||
gboolean crop;
|
||||
|
||||
GList *queued;
|
||||
|
||||
gdouble segment_rate;
|
||||
gint64 segment_start;
|
||||
gint64 segment_stop;
|
||||
gint64 segment_base;
|
||||
};
|
||||
|
||||
struct _GstTheoraDecClass
|
||||
|
@ -449,6 +454,8 @@ theora_dec_src_query (GstPad * pad, GstQuery * query)
|
|||
granulepos, &my_format, &time)))
|
||||
goto error;
|
||||
|
||||
time = (time - dec->segment_start) + dec->segment_base;
|
||||
|
||||
GST_LOG_OBJECT (dec,
|
||||
"query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
|
||||
|
||||
|
@ -589,7 +596,7 @@ theora_dec_src_getcaps (GstPad * pad)
|
|||
static gboolean
|
||||
theora_dec_sink_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
gboolean ret = FALSE;
|
||||
GstTheoraDec *dec;
|
||||
|
||||
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
|
||||
|
@ -602,20 +609,56 @@ theora_dec_sink_event (GstPad * pad, GstEvent * event)
|
|||
GST_STREAM_UNLOCK (pad);
|
||||
break;
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
GstFormat format;
|
||||
gdouble rate;
|
||||
gint64 start, stop, base;
|
||||
|
||||
GST_STREAM_LOCK (pad);
|
||||
gst_event_parse_newsegment (event, &rate, &format, &start, &stop, &base);
|
||||
|
||||
/* we need TIME and a positive rate */
|
||||
if (format != GST_FORMAT_TIME)
|
||||
goto newseg_wrong_format;
|
||||
|
||||
if (rate <= 0.0)
|
||||
goto newseg_wrong_rate;
|
||||
|
||||
/* now copy over the values */
|
||||
dec->segment_rate = rate;
|
||||
dec->segment_start = start;
|
||||
dec->segment_stop = stop;
|
||||
dec->segment_base = base;
|
||||
|
||||
dec->need_keyframe = TRUE;
|
||||
dec->granulepos = -1;
|
||||
dec->last_timestamp = -1;
|
||||
ret = gst_pad_push_event (dec->srcpad, event);
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = gst_pad_push_event (dec->srcpad, event);
|
||||
break;
|
||||
}
|
||||
done:
|
||||
gst_object_unref (dec);
|
||||
|
||||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
newseg_wrong_format:
|
||||
{
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_DEBUG ("received non TIME newsegment");
|
||||
goto done;
|
||||
}
|
||||
newseg_wrong_rate:
|
||||
{
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_DEBUG ("negative rates not supported yet");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
#define ROUND_UP_2(x) (((x) + 1) & ~1)
|
||||
|
|
|
@ -271,6 +271,8 @@ vorbis_dec_src_query (GstPad * pad, GstQuery * query)
|
|||
&value)))
|
||||
goto error;
|
||||
|
||||
value = (value - dec->segment_start) + dec->segment_base;
|
||||
|
||||
gst_query_set_position (query, format, value, total);
|
||||
|
||||
GST_LOG_OBJECT (dec,
|
||||
|
@ -368,7 +370,7 @@ vorbis_dec_src_event (GstPad * pad, GstEvent * event)
|
|||
real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
|
||||
flags, cur_type, tcur, stop_type, tstop);
|
||||
|
||||
res = gst_pad_send_event (GST_PAD_PEER (dec->sinkpad), real_seek);
|
||||
res = gst_pad_push_event (dec->sinkpad, real_seek);
|
||||
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
|
@ -388,7 +390,7 @@ error:
|
|||
static gboolean
|
||||
vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
gboolean ret = FALSE;
|
||||
GstVorbisDec *dec;
|
||||
|
||||
dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
|
||||
|
@ -401,7 +403,26 @@ vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
|
|||
GST_STREAM_UNLOCK (pad);
|
||||
break;
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
GstFormat format;
|
||||
gdouble rate;
|
||||
gint64 start, stop, base;
|
||||
|
||||
GST_STREAM_LOCK (pad);
|
||||
gst_event_parse_newsegment (event, &rate, &format, &start, &stop, &base);
|
||||
|
||||
if (format != GST_FORMAT_TIME)
|
||||
goto newseg_wrong_format;
|
||||
|
||||
if (rate <= 0.0)
|
||||
goto newseg_wrong_rate;
|
||||
|
||||
/* now copy over the values */
|
||||
dec->segment_rate = rate;
|
||||
dec->segment_start = start;
|
||||
dec->segment_stop = stop;
|
||||
dec->segment_base = base;
|
||||
|
||||
dec->granulepos = -1;
|
||||
#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
|
||||
vorbis_synthesis_restart (&dec->vd);
|
||||
|
@ -409,13 +430,29 @@ vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
|
|||
ret = gst_pad_push_event (dec->srcpad, event);
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = gst_pad_push_event (dec->srcpad, event);
|
||||
break;
|
||||
}
|
||||
done:
|
||||
gst_object_unref (dec);
|
||||
|
||||
return ret;
|
||||
/* ERRORS */
|
||||
newseg_wrong_format:
|
||||
{
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_DEBUG ("received non TIME newsegment");
|
||||
goto done;
|
||||
}
|
||||
newseg_wrong_rate:
|
||||
{
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
GST_DEBUG ("negative rates not supported yet");
|
||||
goto done;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
|
|
|
@ -58,6 +58,11 @@ struct _GstVorbisDec {
|
|||
gboolean initialized;
|
||||
|
||||
GList *queued;
|
||||
|
||||
gdouble segment_rate;
|
||||
gint64 segment_start;
|
||||
gint64 segment_stop;
|
||||
gint64 segment_base;
|
||||
};
|
||||
|
||||
struct _GstVorbisDecClass {
|
||||
|
|
|
@ -292,6 +292,7 @@ gst_base_audio_sink_event (GstBaseSink * bsink, GstEvent * event)
|
|||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH_START:
|
||||
gst_ring_buffer_pause (sink->ringbuffer);
|
||||
gst_ring_buffer_clear_all (sink->ringbuffer);
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
break;
|
||||
|
@ -342,11 +343,11 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
|||
time = GST_BUFFER_TIMESTAMP (buf);
|
||||
|
||||
GST_DEBUG ("time %" GST_TIME_FORMAT ", offset %llu, start %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (time), in_offset, GST_TIME_ARGS (bsink->discont_start));
|
||||
GST_TIME_ARGS (time), in_offset, GST_TIME_ARGS (bsink->segment_start));
|
||||
|
||||
render_diff = time - bsink->discont_start;
|
||||
render_diff = time - bsink->segment_start;
|
||||
/* samples should be rendered based on their timestamp. All samples
|
||||
* arriving before the discont_start are to be thrown away */
|
||||
* arriving before the segment_start are to be thrown away */
|
||||
/* FIXME, for now we drop the sample completely, we should
|
||||
* in fact clip the sample. Same for the segment_stop, actually. */
|
||||
if (render_diff < 0)
|
||||
|
|
|
@ -1195,7 +1195,6 @@ gst_ximagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
|
|||
|
||||
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
||||
*start = GST_BUFFER_TIMESTAMP (buf);
|
||||
*start -= bsink->discont_start;
|
||||
if (GST_BUFFER_DURATION_IS_VALID (buf)) {
|
||||
*end = *start + GST_BUFFER_DURATION (buf);
|
||||
} else {
|
||||
|
|
|
@ -1496,7 +1496,6 @@ gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
|
|||
|
||||
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
||||
*start = GST_BUFFER_TIMESTAMP (buf);
|
||||
*start -= bsink->discont_start;
|
||||
if (GST_BUFFER_DURATION_IS_VALID (buf)) {
|
||||
*end = *start + GST_BUFFER_DURATION (buf);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue