summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenzo Desole <lorenzodes@fastwebnet.it>2008-11-22 12:20:00 +0100
committerLorenzo Desole <lorenzodes@fastwebnet.it>2008-11-22 12:20:00 +0100
commit6602e33cf3ffd421d68e17c0259375956ae5ef3c (patch)
treed4d6fc09afd0e4c8af99b276a0627376c7cf0339
parent8b028895638903ad165125f43180d137778940bb (diff)
downloadxine-lib-6602e33cf3ffd421d68e17c0259375956ae5ef3c.tar.gz
xine-lib-6602e33cf3ffd421d68e17c0259375956ae5ef3c.tar.bz2
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.
-rw-r--r--ChangeLog1
-rw-r--r--src/demuxers/demux_flac.c40
2 files changed, 27 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 1190df6b1..7ea8d77c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,7 @@ xine-lib (1.1.16) 2008-??-??
* Add a new meta-tag, "Composer", and use it in the FLAC demuxer.
* Correct AAC channel ordering for multi-channel audio, at least for FLAC
when using ALSA or PulseAudio. (Needs a proper fix.)
+ * Add position-based seeking independent from seekpoints.
xine-lib (1.1.15) 2008-08-14
* Security fixes:
diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c
index 0cc2fc6b6..c14536040 100644
--- a/src/demuxers/demux_flac.c
+++ b/src/demuxers/demux_flac.c
@@ -393,12 +393,13 @@ static int demux_flac_seek (demux_plugin_t *this_gen,
demux_flac_t *this = (demux_flac_t *) this_gen;
int seekpoint_index = 0;
int64_t start_pts;
+ unsigned char buf[4];
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
/* if thread is not running, initialize demuxer */
- if( !playing ) {
+ if( !playing && !start_pos) {
/* send new pts */
_x_demux_control_newpts(this->stream, 0, 0);
@@ -406,28 +407,39 @@ static int demux_flac_seek (demux_plugin_t *this_gen,
this->status = DEMUX_OK;
} else {
- if (this->seekpoints == NULL) {
+ if (this->seekpoints == NULL && !start_pos) {
/* cannot seek if there is no seekpoints */
this->status = DEMUX_OK;
return this->status;
}
- /* do a lazy, linear seek based on the assumption that there are not
- * that many seek points */
+ /* Don't use seekpoints if start_pos != 0. This allows smooth seeking */
if (start_pos) {
/* offset-based seek */
- if (start_pos < this->seekpoints[0].offset)
- seekpoint_index = 0;
- else {
- for (seekpoint_index = 0; seekpoint_index < this->seekpoint_count - 1;
- seekpoint_index++) {
- if (start_pos < this->seekpoints[seekpoint_index + 1].offset) {
- break;
- }
- }
+ this->status = DEMUX_OK;
+ start_pos += this->data_start;
+ this->input->seek(this->input, start_pos, SEEK_SET);
+ while(1){ /* here we try to find something that resembles a frame header */
+
+ if (this->input->read(this->input, buf, 2) != 2){
+ this->status = DEMUX_FINISHED; /* we sought past the end of stream ? */
+ break;
+ }
+
+ if (buf[0] == 0xff && buf[1] == 0xf8)
+ break; /* this might be the frame header... or it may be not. We pass it to the decoder
+ * to decide, but this way we reduce the number of warnings */
+ start_pos +=2;
}
+
+ _x_demux_flush_engine(this->stream);
+ this->input->seek(this->input, start_pos, SEEK_SET);
+ _x_demux_control_newpts(this->stream, 0, BUF_FLAG_SEEK);
+ return this->status;
+
} else {
- /* time-based seek */
+ /* do a lazy, linear seek based on the assumption that there are not
+ * that many seek points; time-based seek */
start_pts = start_time;
start_pts *= 90;
if (start_pts < this->seekpoints[0].pts)