Commit a81573ef authored by Warren Dukes's avatar Warren Dukes

non-blocking seeking, needs some testing! (this is not just for streams

but new code for files seeking as well) git-svn-id: https://svn.musicpd.org/mpd/trunk@1099 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent c1fbcd03
...@@ -2,17 +2,9 @@ ...@@ -2,17 +2,9 @@
a) make seekings non-blocking: a) make seekings non-blocking:
1) player: 1) player:
a) first check that seekWhere isn't already buffered a) first check that seekWhere isn't already buffered
b) if not current song, stop it and play the song to 2) check that stream is seekable before seeking forward!
seek 3) deal with seeking forward better by calling seek function
c) set dc->seek and dc->seekWhere if not already set (for mp3 and mp4)!
and set elapsed time to seekWhere and
then set pc->seek = 0
d) while seeking just continue to play buffer
until seek is done
2) decoder:
a) seek no longer blocks so don't worry about checking
seek in blocking portions, only check stop!
b) yay, less code mess!
b) bufferInput in outputBuffer waiting! b) bufferInput in outputBuffer waiting!
1) implement some sort of callback mechanism for this 1) implement some sort of callback mechanism for this
for abstraction sake for abstraction sake
......
...@@ -383,7 +383,7 @@ int aac_decode(OutputBuffer * cb, DecoderControl * dc) { ...@@ -383,7 +383,7 @@ int aac_decode(OutputBuffer * cb, DecoderControl * dc) {
if(dc->state != DECODE_STATE_DECODE) return -1; if(dc->state != DECODE_STATE_DECODE) return -1;
if(!dc->stop && !dc->seek && chunkLen>0) { if(!dc->stop && chunkLen>0) {
cb->chunkSize[cb->end] = chunkLen; cb->chunkSize[cb->end] = chunkLen;
++cb->end; ++cb->end;
......
...@@ -101,7 +101,7 @@ int audiofile_decode(OutputBuffer * cb, DecoderControl * dc) { ...@@ -101,7 +101,7 @@ int audiofile_decode(OutputBuffer * cb, DecoderControl * dc) {
current = dc->seekWhere * current = dc->seekWhere *
dc->audioFormat.sampleRate; dc->audioFormat.sampleRate;
afSeekFrame(af_fp, AF_DEFAULT_TRACK,current); afSeekFrame(af_fp, AF_DEFAULT_TRACK,current);
dc->seekChunk = cb->end;
dc->seek = 0; dc->seek = 0;
} }
...@@ -114,7 +114,6 @@ int audiofile_decode(OutputBuffer * cb, DecoderControl * dc) { ...@@ -114,7 +114,6 @@ int audiofile_decode(OutputBuffer * cb, DecoderControl * dc) {
(float)dc->audioFormat.sampleRate, (float)dc->audioFormat.sampleRate,
bitRate); bitRate);
if(dc->stop) break; if(dc->stop) break;
else if(dc->seek) continue;
} }
} }
......
...@@ -128,7 +128,7 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) { ...@@ -128,7 +128,7 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) {
pc->channels = dc->audioFormat.channels; \ pc->channels = dc->audioFormat.channels; \
} \ } \
else if(decodeWaitedOn) { \ else if(decodeWaitedOn) { \
my_usleep(10); \ my_usleep(10000); \
continue; \ continue; \
} }
...@@ -161,7 +161,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, ...@@ -161,7 +161,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
{ {
int ret = -1; int ret = -1;
if(decode_pid && *decode_pid>0) { if(decode_pid && *decode_pid>0 && !dc->seek) {
cb->next = -1; cb->next = -1;
if(dc->state==DECODE_STATE_STOP || dc->error || if(dc->state==DECODE_STATE_STOP || dc->error ||
strcmp(dc->file,pc->file)!=0) strcmp(dc->file,pc->file)!=0)
...@@ -180,13 +180,14 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, ...@@ -180,13 +180,14 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
pc->seekWhere; pc->seekWhere;
dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere; dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere;
dc->seekError = 0; dc->seekError = 0;
dc->seekChunk = -1;
dc->seek = 1; dc->seek = 1;
pc->bitRate = 0; /*pc->bitRate = 0;*/
while(*decode_pid>0 && dc->seek) my_usleep(1000); /*while(*decode_pid>0 && dc->seek) my_usleep(1000);*/
if(!dc->seekError) { /*if(!dc->seekError) {*/
ret = 0; ret = 0;
pc->elapsedTime = dc->seekWhere; pc->elapsedTime = dc->seekWhere;
} /*}*/
} }
} }
pc->seek = 0; pc->seek = 0;
...@@ -231,6 +232,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, ...@@ -231,6 +232,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
doCrossFade = 0; \ doCrossFade = 0; \
nextChunk = -1; \ nextChunk = -1; \
bbp = 0; \ bbp = 0; \
seeking = 1; \
} \ } \
} \ } \
if(pc->stop) { \ if(pc->stop) { \
...@@ -254,7 +256,6 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { ...@@ -254,7 +256,6 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return; return;
} }
dc->seekable = inStream.seekable;
dc->state = DECODE_STATE_START; dc->state = DECODE_STATE_START;
dc->start = 0; dc->start = 0;
...@@ -386,6 +387,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -386,6 +387,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
int test; int test;
int decodeWaitedOn = 0; int decodeWaitedOn = 0;
char silence[CHUNK_SIZE]; char silence[CHUNK_SIZE];
int seeking = 0;
memset(silence,0,CHUNK_SIZE); memset(silence,0,CHUNK_SIZE);
...@@ -407,6 +409,10 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -407,6 +409,10 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
while(!quit) { while(!quit) {
processDecodeInput(); processDecodeInput();
handleDecodeStart(); handleDecodeStart();
if(!dc->seek && seeking) {
if(dc->seekChunk >= 0) cb->begin = dc->seekChunk;
seeking = 0;
}
if(dc->state==DECODE_STATE_STOP && if(dc->state==DECODE_STATE_STOP &&
pc->queueState==PLAYER_QUEUE_FULL && pc->queueState==PLAYER_QUEUE_FULL &&
pc->queueLockState==PLAYER_QUEUE_UNLOCKED) pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
...@@ -481,7 +487,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { ...@@ -481,7 +487,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
else continue; else continue;
} }
} }
pc->elapsedTime = cb->times[cb->begin]; if(!seeking) pc->elapsedTime = cb->times[cb->begin];
pc->bitRate = cb->bitRate[cb->begin]; pc->bitRate = cb->bitRate[cb->begin];
pcm_volumeChange(cb->chunks+cb->begin* pcm_volumeChange(cb->chunks+cb->begin*
CHUNK_SIZE, CHUNK_SIZE,
......
...@@ -46,12 +46,12 @@ ...@@ -46,12 +46,12 @@
#define DECODE_SUFFIX_WAVE 6 #define DECODE_SUFFIX_WAVE 6
typedef struct _DecoderControl { typedef struct _DecoderControl {
volatile mpd_sint8 seekable;
volatile mpd_sint8 state; volatile mpd_sint8 state;
volatile mpd_sint8 stop; volatile mpd_sint8 stop;
volatile mpd_sint8 start; volatile mpd_sint8 start;
volatile mpd_uint16 error; volatile mpd_uint16 error;
volatile mpd_sint8 seek; volatile mpd_sint8 seek;
volatile mpd_sint16 seekChunk;
volatile mpd_sint8 seekError; volatile mpd_sint8 seekError;
volatile mpd_sint8 cycleLogFiles; volatile mpd_sint8 cycleLogFiles;
volatile double seekWhere; volatile double seekWhere;
......
...@@ -154,6 +154,7 @@ int flac_decode(OutputBuffer * cb, DecoderControl *dc) { ...@@ -154,6 +154,7 @@ int flac_decode(OutputBuffer * cb, DecoderControl *dc) {
dc->audioFormat.sampleRate; dc->audioFormat.sampleRate;
data.position = 0; data.position = 0;
} }
dc->seekChunk = cb->end;
dc->seek = 0; dc->seek = 0;
} }
} }
......
...@@ -461,6 +461,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) { ...@@ -461,6 +461,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
if(!dc->seek) data->muteFrame = 0; if(!dc->seek) data->muteFrame = 0;
else if(dc->seekWhere<=data->elapsedTime) { else if(dc->seekWhere<=data->elapsedTime) {
clearOutputBuffer(cb); clearOutputBuffer(cb);
dc->seekChunk = cb->end;
data->muteFrame = 0; data->muteFrame = 0;
dc->seek = 0; dc->seek = 0;
} }
...@@ -517,6 +518,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) { ...@@ -517,6 +518,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
data->frameOffset[i]) == 0) data->frameOffset[i]) == 0)
{ {
clearOutputBuffer(cb); clearOutputBuffer(cb);
dc->seekChunk = cb->end;
data->currentFrame = i; data->currentFrame = i;
data->muteFrame = 0; data->muteFrame = 0;
} }
...@@ -529,13 +531,13 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) { ...@@ -529,13 +531,13 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
while(1) { while(1) {
skip = 0; skip = 0;
while((ret = decodeNextFrameHeader(data))==DECODE_CONT && while((ret = decodeNextFrameHeader(data))==DECODE_CONT &&
!dc->seek && !dc->stop); !dc->stop);
if(ret==DECODE_SKIP) skip = 1; if(ret==DECODE_SKIP) skip = 1;
else if(ret==DECODE_BREAK || dc->stop || dc->seek) break; else if(ret==DECODE_BREAK || dc->stop) break;
if(!data->muteFrame) { if(!data->muteFrame) {
while((ret = decodeNextFrame(data))==DECODE_CONT && while((ret = decodeNextFrame(data))==DECODE_CONT &&
!dc->seek && !dc->stop); !dc->stop);
if(ret==DECODE_BREAK || dc->seek || dc->stop) break; if(ret==DECODE_BREAK || dc->stop) break;
} }
if(!skip && ret==DECODE_OK) break; if(!skip && ret==DECODE_OK) break;
} }
......
...@@ -221,6 +221,7 @@ int mp4_decode(OutputBuffer * cb, DecoderControl * dc) { ...@@ -221,6 +221,7 @@ int mp4_decode(OutputBuffer * cb, DecoderControl * dc) {
seekPositionFound = 0; seekPositionFound = 0;
chunkLen = 0; chunkLen = 0;
clearOutputBuffer(cb); clearOutputBuffer(cb);
dc->seekChunk = cb->end;
dc->seek = 0; dc->seek = 0;
} }
......
...@@ -192,6 +192,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc) ...@@ -192,6 +192,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc)
if(dc->seek) { if(dc->seek) {
clearOutputBuffer(cb); clearOutputBuffer(cb);
chunkpos = 0; chunkpos = 0;
dc->seekChunk = cb->end;
ov_time_seek_page(&vf,dc->seekWhere); ov_time_seek_page(&vf,dc->seekWhere);
dc->seek = 0; dc->seek = 0;
} }
......
...@@ -73,13 +73,11 @@ int sendDataToOutputBuffer(OutputBuffer * cb, DecoderControl * dc, ...@@ -73,13 +73,11 @@ int sendDataToOutputBuffer(OutputBuffer * cb, DecoderControl * dc,
while(datalen) { while(datalen) {
if(currentChunk != cb->end) { if(currentChunk != cb->end) {
while(cb->begin==cb->end && cb->wrap && !dc->stop && while(cb->begin==cb->end && cb->wrap && !dc->stop)
!dc->seek)
{ {
my_usleep(10000); my_usleep(10000);
} }
if(dc->stop) return OUTPUT_BUFFER_DC_STOP; if(dc->stop) return OUTPUT_BUFFER_DC_STOP;
if(dc->seek) return OUTPUT_BUFFER_DC_SEEK;
currentChunk = cb->end; currentChunk = cb->end;
cb->chunkSize[currentChunk] = 0; cb->chunkSize[currentChunk] = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment