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
This commit is contained in:
Warren Dukes 2004-05-19 23:48:34 +00:00
parent c1fbcd03f0
commit a81573ef05
10 changed files with 30 additions and 30 deletions

14
TODO
View File

@ -2,17 +2,9 @@
a) make seekings non-blocking:
1) player:
a) first check that seekWhere isn't already buffered
b) if not current song, stop it and play the song to
seek
c) set dc->seek and dc->seekWhere if not already set
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!
2) check that stream is seekable before seeking forward!
3) deal with seeking forward better by calling seek function
(for mp3 and mp4)!
b) bufferInput in outputBuffer waiting!
1) implement some sort of callback mechanism for this
for abstraction sake

View File

@ -383,7 +383,7 @@ int aac_decode(OutputBuffer * cb, DecoderControl * dc) {
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->end;

View File

@ -101,7 +101,7 @@ int audiofile_decode(OutputBuffer * cb, DecoderControl * dc) {
current = dc->seekWhere *
dc->audioFormat.sampleRate;
afSeekFrame(af_fp, AF_DEFAULT_TRACK,current);
dc->seekChunk = cb->end;
dc->seek = 0;
}
@ -114,7 +114,6 @@ int audiofile_decode(OutputBuffer * cb, DecoderControl * dc) {
(float)dc->audioFormat.sampleRate,
bitRate);
if(dc->stop) break;
else if(dc->seek) continue;
}
}

View File

@ -128,7 +128,7 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) {
pc->channels = dc->audioFormat.channels; \
} \
else if(decodeWaitedOn) { \
my_usleep(10); \
my_usleep(10000); \
continue; \
}
@ -161,7 +161,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
{
int ret = -1;
if(decode_pid && *decode_pid>0) {
if(decode_pid && *decode_pid>0 && !dc->seek) {
cb->next = -1;
if(dc->state==DECODE_STATE_STOP || dc->error ||
strcmp(dc->file,pc->file)!=0)
@ -180,13 +180,14 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
pc->seekWhere;
dc->seekWhere = 0 > dc->seekWhere ? 0 : dc->seekWhere;
dc->seekError = 0;
dc->seekChunk = -1;
dc->seek = 1;
pc->bitRate = 0;
while(*decode_pid>0 && dc->seek) my_usleep(1000);
if(!dc->seekError) {
/*pc->bitRate = 0;*/
/*while(*decode_pid>0 && dc->seek) my_usleep(1000);*/
/*if(!dc->seekError) {*/
ret = 0;
pc->elapsedTime = dc->seekWhere;
}
/*}*/
}
}
pc->seek = 0;
@ -231,6 +232,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
doCrossFade = 0; \
nextChunk = -1; \
bbp = 0; \
seeking = 1; \
} \
} \
if(pc->stop) { \
@ -254,7 +256,6 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
return;
}
dc->seekable = inStream.seekable;
dc->state = DECODE_STATE_START;
dc->start = 0;
@ -386,6 +387,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
int test;
int decodeWaitedOn = 0;
char silence[CHUNK_SIZE];
int seeking = 0;
memset(silence,0,CHUNK_SIZE);
@ -407,6 +409,10 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
while(!quit) {
processDecodeInput();
handleDecodeStart();
if(!dc->seek && seeking) {
if(dc->seekChunk >= 0) cb->begin = dc->seekChunk;
seeking = 0;
}
if(dc->state==DECODE_STATE_STOP &&
pc->queueState==PLAYER_QUEUE_FULL &&
pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
@ -481,7 +487,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) {
else continue;
}
}
pc->elapsedTime = cb->times[cb->begin];
if(!seeking) pc->elapsedTime = cb->times[cb->begin];
pc->bitRate = cb->bitRate[cb->begin];
pcm_volumeChange(cb->chunks+cb->begin*
CHUNK_SIZE,

View File

@ -46,12 +46,12 @@
#define DECODE_SUFFIX_WAVE 6
typedef struct _DecoderControl {
volatile mpd_sint8 seekable;
volatile mpd_sint8 state;
volatile mpd_sint8 stop;
volatile mpd_sint8 start;
volatile mpd_uint16 error;
volatile mpd_sint8 seek;
volatile mpd_sint16 seekChunk;
volatile mpd_sint8 seekError;
volatile mpd_sint8 cycleLogFiles;
volatile double seekWhere;

View File

@ -154,6 +154,7 @@ int flac_decode(OutputBuffer * cb, DecoderControl *dc) {
dc->audioFormat.sampleRate;
data.position = 0;
}
dc->seekChunk = cb->end;
dc->seek = 0;
}
}

View File

@ -461,6 +461,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
if(!dc->seek) data->muteFrame = 0;
else if(dc->seekWhere<=data->elapsedTime) {
clearOutputBuffer(cb);
dc->seekChunk = cb->end;
data->muteFrame = 0;
dc->seek = 0;
}
@ -517,6 +518,7 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
data->frameOffset[i]) == 0)
{
clearOutputBuffer(cb);
dc->seekChunk = cb->end;
data->currentFrame = i;
data->muteFrame = 0;
}
@ -529,13 +531,13 @@ int mp3Read(mp3DecodeData * data, OutputBuffer * cb, DecoderControl * dc) {
while(1) {
skip = 0;
while((ret = decodeNextFrameHeader(data))==DECODE_CONT &&
!dc->seek && !dc->stop);
!dc->stop);
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) {
while((ret = decodeNextFrame(data))==DECODE_CONT &&
!dc->seek && !dc->stop);
if(ret==DECODE_BREAK || dc->seek || dc->stop) break;
!dc->stop);
if(ret==DECODE_BREAK || dc->stop) break;
}
if(!skip && ret==DECODE_OK) break;
}

View File

@ -221,6 +221,7 @@ int mp4_decode(OutputBuffer * cb, DecoderControl * dc) {
seekPositionFound = 0;
chunkLen = 0;
clearOutputBuffer(cb);
dc->seekChunk = cb->end;
dc->seek = 0;
}

View File

@ -192,6 +192,7 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc)
if(dc->seek) {
clearOutputBuffer(cb);
chunkpos = 0;
dc->seekChunk = cb->end;
ov_time_seek_page(&vf,dc->seekWhere);
dc->seek = 0;
}

View File

@ -73,13 +73,11 @@ int sendDataToOutputBuffer(OutputBuffer * cb, DecoderControl * dc,
while(datalen) {
if(currentChunk != cb->end) {
while(cb->begin==cb->end && cb->wrap && !dc->stop &&
!dc->seek)
while(cb->begin==cb->end && cb->wrap && !dc->stop)
{
my_usleep(10000);
}
if(dc->stop) return OUTPUT_BUFFER_DC_STOP;
if(dc->seek) return OUTPUT_BUFFER_DC_SEEK;
currentChunk = cb->end;
cb->chunkSize[currentChunk] = 0;