Add position-based seeking independent from seekpoints.
authorLorenzo Desole <lorenzodes@fastwebnet.it>
Sat, 22 Nov 2008 12:20:00 +0100
changeset 95911e78a206fd61
parent 9590 ab1212efd5e1
child 9592 e9b57f7f5399
Add position-based seeking independent from seekpoints.
When it comes to FLAC audio files, seeking relies on seekpoints which are
not always present, and even when they are, sometimes it fails. Also, as far
as I can see, xine is unable to play a FLAC stream starting at an arbitrary
position.

Other players (namely mplayer) do not rely on seekpoints when they handle
FLAC files and they don't suffer from these problems.

With this patch, time-based seeking doesn't change, while position-based
seeking is completely independent from seekpoints.
ChangeLog
src/demuxers/demux_flac.c
     1.1 --- a/ChangeLog	Sat Nov 22 14:04:03 2008 +0000
     1.2 +++ b/ChangeLog	Sat Nov 22 12:20:00 2008 +0100
     1.3 @@ -8,6 +8,7 @@
     1.4    * Add a new meta-tag, "Composer", and use it in the FLAC demuxer.
     1.5    * Correct AAC channel ordering for multi-channel audio, at least for FLAC
     1.6      when using ALSA or PulseAudio. (Needs a proper fix.)
     1.7 +  * Add position-based seeking independent from seekpoints.
     1.8  
     1.9  xine-lib (1.1.15) 2008-08-14
    1.10    * Security fixes:
     2.1 --- a/src/demuxers/demux_flac.c	Sat Nov 22 14:04:03 2008 +0000
     2.2 +++ b/src/demuxers/demux_flac.c	Sat Nov 22 12:20:00 2008 +0100
     2.3 @@ -393,12 +393,13 @@
     2.4    demux_flac_t *this = (demux_flac_t *) this_gen;
     2.5    int seekpoint_index = 0;
     2.6    int64_t start_pts;
     2.7 +  unsigned char buf[4];
     2.8    
     2.9    start_pos = (off_t) ( (double) start_pos / 65535 *
    2.10                this->data_size );
    2.11  
    2.12    /* if thread is not running, initialize demuxer */
    2.13 -  if( !playing ) {
    2.14 +  if( !playing && !start_pos) {
    2.15  
    2.16      /* send new pts */
    2.17      _x_demux_control_newpts(this->stream, 0, 0);
    2.18 @@ -406,28 +407,39 @@
    2.19      this->status = DEMUX_OK;
    2.20    } else {
    2.21  
    2.22 -    if (this->seekpoints == NULL) {
    2.23 +    if (this->seekpoints == NULL && !start_pos) {
    2.24        /* cannot seek if there is no seekpoints */
    2.25        this->status = DEMUX_OK;
    2.26        return this->status;
    2.27      }
    2.28  
    2.29 -    /* do a lazy, linear seek based on the assumption that there are not
    2.30 -     * that many seek points */
    2.31 +    /* Don't use seekpoints if start_pos != 0. This allows smooth seeking */
    2.32      if (start_pos) {
    2.33        /* offset-based seek */
    2.34 -      if (start_pos < this->seekpoints[0].offset)
    2.35 -        seekpoint_index = 0;
    2.36 -      else {
    2.37 -        for (seekpoint_index = 0; seekpoint_index < this->seekpoint_count - 1;
    2.38 -          seekpoint_index++) {
    2.39 -          if (start_pos < this->seekpoints[seekpoint_index + 1].offset) {
    2.40 -            break;
    2.41 -          }
    2.42 -        }
    2.43 +      this->status = DEMUX_OK;
    2.44 +      start_pos += this->data_start;
    2.45 +      this->input->seek(this->input, start_pos, SEEK_SET);
    2.46 +      while(1){ /* here we try to find something that resembles a frame header */
    2.47 +
    2.48 +	if (this->input->read(this->input, buf, 2) != 2){
    2.49 +	  this->status = DEMUX_FINISHED; /* we sought past the end of stream ? */
    2.50 +	  break;
    2.51 +	}
    2.52 +
    2.53 +	if (buf[0] == 0xff && buf[1] == 0xf8)
    2.54 +	  break; /* this might be the frame header... or it may be not. We pass it to the decoder
    2.55 +		  * to decide, but this way we reduce the number of warnings */
    2.56 +	start_pos +=2;
    2.57        }
    2.58 +
    2.59 +      _x_demux_flush_engine(this->stream);
    2.60 +      this->input->seek(this->input, start_pos, SEEK_SET);
    2.61 +      _x_demux_control_newpts(this->stream, 0, BUF_FLAG_SEEK);
    2.62 +      return this->status;
    2.63 +
    2.64      } else {
    2.65 -      /* time-based seek */
    2.66 +      /* do a lazy, linear seek based on the assumption that there are not
    2.67 +       * that many seek points; time-based seek */
    2.68        start_pts = start_time;
    2.69        start_pts *= 90;
    2.70        if (start_pts < this->seekpoints[0].pts)