From 4db5224b4773c48d9699f21f8bb4629b176fe43b Mon Sep 17 00:00:00 2001 From: Warren Dukes Date: Thu, 20 May 2004 03:44:33 +0000 Subject: ogg stream playing! some non-blocking seek bug fixes git-svn-id: https://svn.musicpd.org/mpd/trunk@1105 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/decode.c | 86 +++++++++++++++++++++++++++++++------------------- src/inputStream_http.c | 1 + src/mp3_decode.c | 7 ++-- src/ogg_decode.c | 78 +++++++++++++++++++++++++++++---------------- src/ogg_decode.h | 3 +- src/player.c | 1 + 6 files changed, 114 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/decode.c b/src/decode.c index af5e39259..82865b39b 100644 --- a/src/decode.c +++ b/src/decode.c @@ -89,6 +89,7 @@ void stopDecode(DecoderControl * dc) { void quitDecode(PlayerControl * pc, DecoderControl * dc) { stopDecode(dc); pc->state = PLAYER_STATE_STOP; + dc->seek = 0; pc->play = 0; pc->stop = 0; pc->pause = 0; @@ -113,23 +114,34 @@ int calculateCrossFadeChunks(PlayerControl * pc, AudioFormat * af) { } #define handleDecodeStart() \ - if(decodeWaitedOn && dc->state==DECODE_STATE_DECODE) { \ - decodeWaitedOn = 0; \ - if(openAudioDevice(&(cb->audioFormat))<0) { \ + if(decodeWaitedOn) { \ + if(dc->state!=DECODE_STATE_START && *decode_pid > 0 && \ + dc->error==DECODE_ERROR_NOERROR) \ + { \ + decodeWaitedOn = 0; \ + if(openAudioDevice(&(cb->audioFormat))<0) { \ + strncpy(pc->erroredFile,pc->file,MAXPATHLEN); \ + pc->erroredFile[MAXPATHLEN] = '\0'; \ + pc->error = PLAYER_ERROR_AUDIO; \ + quitDecode(pc,dc); \ + return; \ + } \ + pc->totalTime = dc->totalTime; \ + pc->sampleRate = dc->audioFormat.sampleRate; \ + pc->bits = dc->audioFormat.bits; \ + pc->channels = dc->audioFormat.channels; \ + } \ + else if(dc->state!=DECODE_STATE_START || *decode_pid <= 0) { \ strncpy(pc->erroredFile,pc->file,MAXPATHLEN); \ pc->erroredFile[MAXPATHLEN] = '\0'; \ - pc->error = PLAYER_ERROR_AUDIO; \ + pc->error = PLAYER_ERROR_FILE; \ quitDecode(pc,dc); \ return; \ - } \ - pc->totalTime = dc->totalTime; \ - pc->sampleRate = dc->audioFormat.sampleRate; \ - pc->bits = dc->audioFormat.bits; \ - pc->channels = dc->audioFormat.channels; \ - } \ - else if(decodeWaitedOn) { \ - my_usleep(10000); \ - continue; \ + } \ + else { \ + my_usleep(10000); \ + continue; \ + } \ } int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, @@ -226,7 +238,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, if(decodeSeek(pc,dc,cb,&decodeWaitedOn) == 0) { \ doCrossFade = 0; \ nextChunk = -1; \ - bbp = 0; \ + bbp = 0; \ seeking = 1; \ } \ } \ @@ -255,7 +267,7 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { dc->start = 0; while(!inputStreamAtEOF(&inStream) && bufferInputStream(&inStream) < 0 - && !dc->stop); + && !pc->stop); if(dc->stop) { dc->state = DECODE_STATE_STOP; @@ -265,6 +277,14 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { switch(pc->decodeType) { case DECODE_TYPE_URL: +#ifdef HAVE_OGG + if(pc->fileSuffix == DECODE_SUFFIX_OGG || (inStream.mime && + 0 == strcmp(inStream.mime, "application/ogg"))) + { + ret = ogg_decode(cb, dc, &inStream); + break; + } +#endif #ifdef HAVE_MAD /*if(pc->fileSuffix == DECODE_SUFFIX_MP3 || (inStream.mime && 0 == strcmp(inStream.mime, "audio/mpeg")))*/ @@ -281,6 +301,12 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { break; } #endif +#ifdef HAVE_OGG + if(pc->fileSuffix == DECODE_SUFFIX_OGG) { + ret = ogg_decode(cb, dc, &inStream); + break; + } +#endif #ifdef HAVE_FAAD if(pc->fileSuffix == DECODE_SUFFIX_AAC) { closeInputStream(&inStream); @@ -293,13 +319,6 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { break; } #endif -#ifdef HAVE_OGG - if(pc->fileSuffix == DECODE_SUFFIX_OGG) { - closeInputStream(&inStream); - ret = ogg_decode(cb,dc); - break; - } -#endif #ifdef HAVE_FLAC if(pc->fileSuffix == DECODE_SUFFIX_FLAC) { closeInputStream(&inStream); @@ -321,8 +340,10 @@ void decodeStart(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { strncpy(pc->erroredFile, dc->file, MAXPATHLEN); pc->erroredFile[MAXPATHLEN] = '\0'; if(ret != DECODE_ERROR_UNKTYPE) dc->error = DECODE_ERROR_FILE; - else closeInputStream(&inStream); - dc->start = 0; + else { + dc->error = DECODE_ERROR_UNKTYPE; + closeInputStream(&inStream); + } dc->stop = 0; dc->state = DECODE_STATE_STOP; } @@ -341,16 +362,15 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) { unblockSignals(); while(1) { - if(dc->start) decodeStart(pc, cb, dc); - else if(dc->stop) { - dc->state = DECODE_STATE_STOP; - dc->stop = 0; - } - else if(dc->seek) dc->start = 1; if(dc->cycleLogFiles) { myfprintfCloseAndOpenLogFile(); dc->cycleLogFiles = 0; } + else if(dc->start) decodeStart(pc, cb, dc); + else if(dc->stop) { + dc->state = DECODE_STATE_STOP; + dc->stop = 0; + } else my_usleep(10000); } @@ -392,7 +412,7 @@ void decodeParent(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb) { pc->play = 0; pc->beginTime = pc->elapsedTime; kill(getppid(),SIGUSR1); - + while(*decode_pid>0 && !cb->wrap && cb->end-cb->beginstate!=DECODE_STATE_STOP) { @@ -578,8 +598,10 @@ void decode() { pc = &(getPlayerData()->playerControl); dc = &(getPlayerData()->decoderControl); dc->error = 0; - dc->start = 1; cb->next = -1; + dc->seek = 0; + dc->stop = 0; + dc->start = 1; if(decode_pid==NULL || *decode_pid<=0) { if(decoderInit(pc,cb,dc)<0) return; diff --git a/src/inputStream_http.c b/src/inputStream_http.c index 0080792ad..3e97b8ffa 100644 --- a/src/inputStream_http.c +++ b/src/inputStream_http.c @@ -41,6 +41,7 @@ #define HTTP_BUFFER_SIZE 524289 #define HTTP_PREBUFFER_SIZE (HTTP_BUFFER_SIZE >> 2) +//#define HTTP_PREBUFFER_SIZE 0 #define HTTP_REDIRECT_MAX 10 diff --git a/src/mp3_decode.c b/src/mp3_decode.c index 69d336e99..3836af8e2 100644 --- a/src/mp3_decode.c +++ b/src/mp3_decode.c @@ -556,9 +556,12 @@ int mp3_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) { mp3DecodeData data; if(openMp3FromInputStream(inStream, &data, dc) < 0) { - ERROR("Input does not appear to be a mp3 bit stream.\n"); closeInputStream(inStream); - return -1; + if(!dc->stop) { + ERROR("Input does not appear to be a mp3 bit stream.\n"); + return -1; + } + return 0; } initAudioFormatFromMp3DecodeData(&data, &(dc->audioFormat)); diff --git a/src/ogg_decode.c b/src/ogg_decode.c index 6f8ffe535..9bd24de01 100644 --- a/src/ogg_decode.c +++ b/src/ogg_decode.c @@ -42,6 +42,11 @@ #define OGG_DECODE_USE_BIGENDIAN 0 #endif +typedef struct _OggCallbackData { + InputStream * inStream; + DecoderControl * dc; +} OggCallbackData; + /* this is just for tag parsing for db import! */ int getOggTotalTime(char * file) { OggVorbis_File vf; @@ -62,26 +67,42 @@ int getOggTotalTime(char * file) { return totalTime; } -size_t ogg_read_cb(void * ptr, size_t size, size_t nmemb, void * inStream) +size_t ogg_read_cb(void * ptr, size_t size, size_t nmemb, void * vdata) { - size_t ret; - ret = readFromInputStream((InputStream *)inStream,ptr,size,nmemb); + size_t ret = 0; + OggCallbackData * data = (OggCallbackData *)vdata; - if(ret<0) errno = ((InputStream *)inStream)->error; + while(1) { + ret = readFromInputStream(data->inStream,ptr,size,nmemb); + if(ret == 0 && !inputStreamAtEOF(data->inStream) && + !data->dc->stop) + { + my_usleep(10000); + } + else break; + } + errno = 0; + /*if(ret<0) errno = ((InputStream *)inStream)->error;*/ return ret; } -int ogg_seek_cb(void * inStream, ogg_int64_t offset, int whence) { - return seekInputStream((InputStream *)inStream,offset,whence); +int ogg_seek_cb(void * vdata, ogg_int64_t offset, int whence) { + OggCallbackData * data = (OggCallbackData *)vdata; + + return seekInputStream(data->inStream,offset,whence); } -int ogg_close_cb(void * inStream) { - return closeInputStream((InputStream *)inStream); +int ogg_close_cb(void * vdata) { + OggCallbackData * data = (OggCallbackData *)vdata; + + return closeInputStream(data->inStream); } -long ogg_tell_cb(void * inStream) { - return ((InputStream *)inStream)->offset; +long ogg_tell_cb(void * vdata) { + OggCallbackData * data = (OggCallbackData *)vdata; + + return (long)(data->inStream->offset); } char * ogg_parseComment(char * comment, char * needle) { @@ -142,27 +163,27 @@ float ogg_getReplayGainScale(char ** comments) { return 1.0; } -int ogg_decode(OutputBuffer * cb, DecoderControl * dc) +int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream) { OggVorbis_File vf; ov_callbacks callbacks; - InputStream inStream; - + OggCallbackData data; + + data.inStream = inStream; + data.dc = dc; callbacks.read_func = ogg_read_cb; callbacks.seek_func = ogg_seek_cb; callbacks.close_func = ogg_close_cb; callbacks.tell_func = ogg_tell_cb; - if(openInputStream(&inStream,dc->file)<0) { - ERROR("failed to open ogg\n"); - return -1; - } - - if(ov_open_callbacks(&inStream, &vf, NULL, 0, callbacks) < 0) { - ERROR("Input does not appear to be an Ogg bit stream.\n"); - closeInputStream(&inStream); - return -1; + if(ov_open_callbacks(&data, &vf, NULL, 0, callbacks) < 0) { + closeInputStream(inStream); + if(!dc->stop) { + ERROR("Input does not appear to be an Ogg Vorbis stream.\n"); + return -1; + } + return 0; } { @@ -190,20 +211,23 @@ int ogg_decode(OutputBuffer * cb, DecoderControl * dc) while(!eof) { if(dc->seek) { - clearOutputBuffer(cb); - chunkpos = 0; - dc->seekChunk = cb->end; - ov_time_seek_page(&vf,dc->seekWhere); + if(0 == ov_time_seek_page(&vf,dc->seekWhere)) { + clearOutputBuffer(cb); + chunkpos = 0; + dc->seekChunk = cb->end; + } dc->seek = 0; } ret = ov_read(&vf, chunk+chunkpos, OGG_CHUNK_SIZE-chunkpos, OGG_DECODE_USE_BIGENDIAN, 2, 1, ¤t_section); - if(ret<=0) { + + if(ret <= 0 && ret != OV_HOLE) { eof = 1; break; } + if(ret == OV_HOLE) ret = 0; chunkpos+=ret; diff --git a/src/ogg_decode.h b/src/ogg_decode.h index 16928eac6..03f1364a5 100644 --- a/src/ogg_decode.h +++ b/src/ogg_decode.h @@ -22,10 +22,11 @@ #include "../config.h" #include "playerData.h" +#include "inputStream.h" #include -int ogg_decode(OutputBuffer * cb, DecoderControl * dc); +int ogg_decode(OutputBuffer * cb, DecoderControl * dc, InputStream * inStream); int getOggTotalTime(char * file); diff --git a/src/player.c b/src/player.c index 82f3101cd..814509307 100644 --- a/src/player.c +++ b/src/player.c @@ -419,6 +419,7 @@ void playerQueueUnlock() { } int playerSeek(FILE * fp, Song * song, float time) { + printf("seek called\n"); PlayerControl * pc = &(getPlayerData()->playerControl); char * file; int decodeType; -- cgit v1.2.3