oggdemux: implement push mode seeking

This patch implements seeking in push mode (eg, over the net)
in Ogg, using the double bisection method.
As a side effect, it also fixes duration determination of network
streams, by seeking to the end to check the actual duration.

Known issues:
- Getting an EOS while seeking stops the streaming task, I can't
  find a way to prevent this (eg, by issuing a seek in the event
  handler).
- Seeking twice in a VERY short succession with playbin2 fails
  for streams with subtitles, we end up pushing in a dataqueue
  which is flushing. Rare in normal use AFAICT.
- Seeking is slow on slow links - byte ranges guesses could be
  made better, decreasing the number of required requests
- If no granule position is found in the last 64 KB of a stream,
  duration will be left unknown (should be pretty rare)

https://bugzilla.gnome.org/show_bug.cgi?id=621897
This commit is contained in:
Vincent Penquerc'h 2011-08-13 14:18:56 +01:00 committed by Tim-Philipp Müller
parent a330ff0721
commit 0173afa38c
2 changed files with 865 additions and 48 deletions

File diff suppressed because it is too large Load diff

View file

@ -113,6 +113,10 @@ struct _GstOggPad
gboolean is_eos;
gboolean added;
/* push mode seeking */
GstClockTime push_kf_time;
GstClockTime push_sync_time;
};
struct _GstOggPadClass
@ -162,6 +166,29 @@ struct _GstOggDemux
gint64 basetime;
gint64 prestime;
/* push mode seeking support */
GMutex *push_lock; /* we need the lock to protect the push mode variables */
gint64 push_byte_offset; /* where were are at in the stream, in bytes */
gint64 push_byte_length; /* length in bytes of the stream, -1 if unknown */
GstClockTime push_time_length; /* length in time of the stream */
GstClockTime push_start_time; /* start time of the stream */
GstClockTime push_time_offset; /* where were are at in the stream, in time */
enum { PUSH_PLAYING, PUSH_DURATION, PUSH_BISECT1, PUSH_LINEAR1, PUSH_BISECT2, PUSH_LINEAR2 } push_state;
GstClockTime push_seek_time_original_target;
GstClockTime push_seek_time_target;
gint64 push_last_seek_offset;
GstClockTime push_last_seek_time;
gint64 push_offset0, push_offset1; /* bisection search offset bounds */
GstClockTime push_time0, push_time1; /* bisection search time bounds */
double push_seek_rate;
GstSeekFlags push_seek_flags;
GstEvent *push_mode_seek_delayed_event;
gboolean push_disable_seeking;
gint push_bisection_steps[2];
/* ogg stuff */
ogg_sync_state sync;
};