aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-08-26 08:27:05 +0200
committerMax Kellermann <max@duempel.org>2008-08-26 08:27:05 +0200
commit2a83ccdb8f71d224341ea5a6ddbc002693d887fb (patch)
tree7a6c3f2a480739e2951fe3141c8ca8a1aacc0db7
parent8814c0c898162f25ef4851df5cf8c9e68ff83942 (diff)
downloadmpd-2a83ccdb8f71d224341ea5a6ddbc002693d887fb.tar.gz
mpd-2a83ccdb8f71d224341ea5a6ddbc002693d887fb.tar.xz
mpd-2a83ccdb8f71d224341ea5a6ddbc002693d887fb.zip
added decoder_data()
Moved all of the player-waiting code to decoder_data(), to make OutputBuffer more generic.
-rw-r--r--src/decoder_api.c80
-rw-r--r--src/decoder_api.h15
-rw-r--r--src/inputPlugins/_flac_common.h11
-rw-r--r--src/inputPlugins/aac_plugin.c6
-rw-r--r--src/inputPlugins/audiofile_plugin.c14
-rw-r--r--src/inputPlugins/mod_plugin.c6
-rw-r--r--src/inputPlugins/mp3_plugin.c31
-rw-r--r--src/inputPlugins/mp4_plugin.c6
-rw-r--r--src/inputPlugins/mpc_plugin.c16
-rw-r--r--src/inputPlugins/oggvorbis_plugin.c19
-rw-r--r--src/inputPlugins/wavpack_plugin.c8
-rw-r--r--src/outputBuffer.c82
-rw-r--r--src/outputBuffer.h19
13 files changed, 177 insertions, 136 deletions
diff --git a/src/decoder_api.c b/src/decoder_api.c
index dfd1850b5..681f593f8 100644
--- a/src/decoder_api.c
+++ b/src/decoder_api.c
@@ -19,6 +19,8 @@
#include "decoder_api.h"
+#include "utils.h"
+#include "normalize.h"
#include "playerData.h"
#include "gcc.h"
@@ -29,3 +31,81 @@ void decoder_initialized(mpd_unused struct decoder * decoder)
dc.state = DECODE_STATE_DECODE;
notify_signal(&pc.notify);
}
+
+/**
+ * All chunks are full of decoded data; wait for the player to free
+ * one.
+ */
+static int need_chunks(InputStream * inStream, int seekable)
+{
+ if (dc.command == DECODE_COMMAND_STOP)
+ return OUTPUT_BUFFER_DC_STOP;
+
+ if (dc.command == DECODE_COMMAND_SEEK) {
+ if (seekable) {
+ return OUTPUT_BUFFER_DC_SEEK;
+ } else {
+ dc.seekError = 1;
+ dc_command_finished();
+ }
+ }
+
+ if (!inStream ||
+ bufferInputStream(inStream) <= 0) {
+ notify_wait(&dc.notify);
+ notify_signal(&pc.notify);
+ }
+
+ return 0;
+}
+
+int decoder_data(mpd_unused struct decoder *decoder, InputStream * inStream,
+ int seekable,
+ void *dataIn, size_t dataInLen,
+ float data_time, mpd_uint16 bitRate,
+ ReplayGainInfo * replayGainInfo)
+{
+ size_t nbytes;
+ char *data;
+ size_t datalen;
+ static char *convBuffer;
+ static size_t convBufferLen;
+ int ret;
+
+ if (cmpAudioFormat(&(ob.audioFormat), &(dc.audioFormat)) == 0) {
+ data = dataIn;
+ datalen = dataInLen;
+ } else {
+ datalen = pcm_sizeOfConvBuffer(&(dc.audioFormat), dataInLen,
+ &(ob.audioFormat));
+ if (datalen > convBufferLen) {
+ if (convBuffer != NULL)
+ free(convBuffer);
+ convBuffer = xmalloc(datalen);
+ convBufferLen = datalen;
+ }
+ data = convBuffer;
+ datalen = pcm_convertAudioFormat(&(dc.audioFormat), dataIn,
+ dataInLen, &(ob.audioFormat),
+ data, &(ob.convState));
+ }
+
+ if (replayGainInfo != NULL && (replayGainState != REPLAYGAIN_OFF))
+ doReplayGain(replayGainInfo, data, datalen, &ob.audioFormat);
+ else if (normalizationEnabled)
+ normalizeData(data, datalen, &ob.audioFormat);
+
+ while (datalen > 0) {
+ nbytes = ob_append(data, datalen, data_time, bitRate);
+ datalen -= nbytes;
+ data += nbytes;
+
+ if (datalen > 0) {
+ ret = need_chunks(inStream, seekable);
+ if (ret != 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/decoder_api.h b/src/decoder_api.h
index c9ab3ebbb..a56b7ef55 100644
--- a/src/decoder_api.h
+++ b/src/decoder_api.h
@@ -27,6 +27,8 @@
*/
#include "inputPlugin.h"
+#include "inputStream.h"
+#include "replayGain.h"
/**
* Opaque handle which the decoder plugin passes to the functions in
@@ -40,4 +42,17 @@ struct decoder;
*/
void decoder_initialized(struct decoder * decoder);
+/**
+ * This function is called by the decoder plugin when it has
+ * successfully decoded block of input data.
+ *
+ * We send inStream for buffering the inputStream while waiting to
+ * send the next chunk
+ */
+int decoder_data(struct decoder *decoder, InputStream * inStream,
+ int seekable,
+ void *data, size_t datalen,
+ float data_time, mpd_uint16 bitRate,
+ ReplayGainInfo * replayGainInfo);
+
#endif
diff --git a/src/inputPlugins/_flac_common.h b/src/inputPlugins/_flac_common.h
index 2d59f4d9d..9eb916b8c 100644
--- a/src/inputPlugins/_flac_common.h
+++ b/src/inputPlugins/_flac_common.h
@@ -165,12 +165,11 @@ MpdTag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block,
/* keep this inlined, this is just macro but prettier :) */
static inline int flacSendChunk(FlacData * data)
{
- if (ob_send(data->inStream,
- 1, data->chunk,
- data->chunk_length, data->time,
- data->bitRate,
- data->replayGainInfo) ==
- OUTPUT_BUFFER_DC_STOP)
+ if (decoder_data(data->decoder, data->inStream,
+ 1, data->chunk,
+ data->chunk_length, data->time,
+ data->bitRate,
+ data->replayGainInfo) == OUTPUT_BUFFER_DC_STOP)
return -1;
return 0;
diff --git a/src/inputPlugins/aac_plugin.c b/src/inputPlugins/aac_plugin.c
index d03826c8f..c6bd99850 100644
--- a/src/inputPlugins/aac_plugin.c
+++ b/src/inputPlugins/aac_plugin.c
@@ -391,9 +391,9 @@ static int aac_decode(struct decoder * mpd_decoder, char *path)
sampleBufferLen = sampleCount * 2;
- ob_send(NULL, 0, sampleBuffer,
- sampleBufferLen, file_time,
- bitRate, NULL);
+ decoder_data(mpd_decoder, NULL, 0, sampleBuffer,
+ sampleBufferLen, file_time,
+ bitRate, NULL);
if (dc.command == DECODE_COMMAND_SEEK) {
dc.seekError = 1;
dc_command_finished();
diff --git a/src/inputPlugins/audiofile_plugin.c b/src/inputPlugins/audiofile_plugin.c
index faa58fe64..fc257263e 100644
--- a/src/inputPlugins/audiofile_plugin.c
+++ b/src/inputPlugins/audiofile_plugin.c
@@ -106,13 +106,13 @@ static int audiofile_decode(struct decoder * decoder, char *path)
eof = 1;
else {
current += ret;
- ob_send(NULL,
- 1,
- chunk, ret * fs,
- (float)current /
- (float)dc.audioFormat.
- sampleRate, bitRate,
- NULL);
+ decoder_data(decoder, NULL,
+ 1,
+ chunk, ret * fs,
+ (float)current /
+ (float)dc.audioFormat.
+ sampleRate, bitRate,
+ NULL);
if (dc.command == DECODE_COMMAND_STOP)
break;
}
diff --git a/src/inputPlugins/mod_plugin.c b/src/inputPlugins/mod_plugin.c
index c09803ee4..792cb0c87 100644
--- a/src/inputPlugins/mod_plugin.c
+++ b/src/inputPlugins/mod_plugin.c
@@ -200,9 +200,9 @@ static int mod_decode(struct decoder * decoder, char *path)
ret = VC_WriteBytes(data->audio_buffer, MIKMOD_FRAME_SIZE);
total_time += ret * secPerByte;
- ob_send(NULL, 0,
- (char *)data->audio_buffer, ret,
- total_time, 0, NULL);
+ decoder_data(decoder, NULL, 0,
+ (char *)data->audio_buffer, ret,
+ total_time, 0, NULL);
}
ob_flush();
diff --git a/src/inputPlugins/mp3_plugin.c b/src/inputPlugins/mp3_plugin.c
index f91895358..399491d0e 100644
--- a/src/inputPlugins/mp3_plugin.c
+++ b/src/inputPlugins/mp3_plugin.c
@@ -812,7 +812,8 @@ static int openMp3FromInputStream(InputStream * inStream, mp3DecodeData * data,
return 0;
}
-static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo)
+static int mp3Read(mp3DecodeData * data, struct decoder *decoder,
+ ReplayGainInfo ** replayGainInfo)
{
int samplesPerFrame;
int samplesLeft;
@@ -926,13 +927,13 @@ static int mp3Read(mp3DecodeData * data, ReplayGainInfo ** replayGainInfo)
}
if (data->outputPtr >= data->outputBufferEnd) {
- ret = ob_send(data->inStream,
- data->inStream->seekable,
- data->outputBuffer,
- data->outputPtr - data->outputBuffer,
- data->elapsedTime,
- data->bitRate / 1000,
- (replayGainInfo != NULL) ? *replayGainInfo : NULL);
+ ret = decoder_data(decoder, data->inStream,
+ data->inStream->seekable,
+ data->outputBuffer,
+ data->outputPtr - data->outputBuffer,
+ data->elapsedTime,
+ data->bitRate / 1000,
+ (replayGainInfo != NULL) ? *replayGainInfo : NULL);
if (ret == OUTPUT_BUFFER_DC_STOP) {
data->flush = 0;
return DECODE_BREAK;
@@ -1063,16 +1064,16 @@ static int mp3_decode(struct decoder * decoder, InputStream * inStream)
decoder_initialized(decoder);
- while (mp3Read(&data, &replayGainInfo) != DECODE_BREAK) ;
+ while (mp3Read(&data, decoder, &replayGainInfo) != DECODE_BREAK) ;
/* send last little bit if not DECODE_COMMAND_STOP */
if (dc.command != DECODE_COMMAND_STOP &&
data.outputPtr != data.outputBuffer && data.flush) {
- ob_send(NULL,
- data.inStream->seekable,
- data.outputBuffer,
- data.outputPtr - data.outputBuffer,
- data.elapsedTime, data.bitRate / 1000,
- replayGainInfo);
+ decoder_data(decoder, NULL,
+ data.inStream->seekable,
+ data.outputBuffer,
+ data.outputPtr - data.outputBuffer,
+ data.elapsedTime, data.bitRate / 1000,
+ replayGainInfo);
}
if (replayGainInfo)
diff --git a/src/inputPlugins/mp4_plugin.c b/src/inputPlugins/mp4_plugin.c
index de658511f..197d00627 100644
--- a/src/inputPlugins/mp4_plugin.c
+++ b/src/inputPlugins/mp4_plugin.c
@@ -270,9 +270,9 @@ static int mp4_decode(struct decoder * mpd_decoder, InputStream * inStream)
sampleBuffer += offset * channels * 2;
- ob_send(inStream, 1, sampleBuffer,
- sampleBufferLen, file_time,
- bitRate, NULL);
+ decoder_data(mpd_decoder, inStream, 1, sampleBuffer,
+ sampleBufferLen, file_time,
+ bitRate, NULL);
if (dc.command == DECODE_COMMAND_STOP) {
eof = 1;
break;
diff --git a/src/inputPlugins/mpc_plugin.c b/src/inputPlugins/mpc_plugin.c
index d4ee40f93..abdf44c63 100644
--- a/src/inputPlugins/mpc_plugin.c
+++ b/src/inputPlugins/mpc_plugin.c
@@ -215,11 +215,11 @@ static int mpc_decode(struct decoder * mpd_decoder, InputStream * inStream)
bitRate = vbrUpdateBits *
dc.audioFormat.sampleRate / 1152 / 1000;
- ob_send(inStream,
- inStream->seekable,
- chunk, chunkpos,
- total_time,
- bitRate, replayGainInfo);
+ decoder_data(mpd_decoder, inStream,
+ inStream->seekable,
+ chunk, chunkpos,
+ total_time,
+ bitRate, replayGainInfo);
chunkpos = 0;
s16 = (mpd_sint16 *) chunk;
@@ -237,9 +237,9 @@ static int mpc_decode(struct decoder * mpd_decoder, InputStream * inStream)
bitRate =
vbrUpdateBits * dc.audioFormat.sampleRate / 1152 / 1000;
- ob_send(NULL, inStream->seekable,
- chunk, chunkpos, total_time, bitRate,
- replayGainInfo);
+ decoder_data(mpd_decoder, NULL, inStream->seekable,
+ chunk, chunkpos, total_time, bitRate,
+ replayGainInfo);
}
ob_flush();
diff --git a/src/inputPlugins/oggvorbis_plugin.c b/src/inputPlugins/oggvorbis_plugin.c
index 0867de69d..1333bc15c 100644
--- a/src/inputPlugins/oggvorbis_plugin.c
+++ b/src/inputPlugins/oggvorbis_plugin.c
@@ -309,12 +309,11 @@ static int oggvorbis_decode(struct decoder * decoder, InputStream * inStream)
if ((test = ov_bitrate_instant(&vf)) > 0) {
bitRate = test / 1000;
}
- ob_send(inStream,
- inStream->seekable,
- chunk, chunkpos,
- ov_pcm_tell(&vf) /
- dc.audioFormat.sampleRate,
- bitRate, replayGainInfo);
+ decoder_data(decoder, inStream,
+ inStream->seekable,
+ chunk, chunkpos,
+ ov_pcm_tell(&vf) / dc.audioFormat.sampleRate,
+ bitRate, replayGainInfo);
chunkpos = 0;
if (dc.command == DECODE_COMMAND_STOP)
break;
@@ -322,10 +321,10 @@ static int oggvorbis_decode(struct decoder * decoder, InputStream * inStream)
}
if (dc.command != DECODE_COMMAND_STOP && chunkpos > 0) {
- ob_send(NULL, inStream->seekable,
- chunk, chunkpos,
- ov_time_tell(&vf), bitRate,
- replayGainInfo);
+ decoder_data(decoder, NULL, inStream->seekable,
+ chunk, chunkpos,
+ ov_time_tell(&vf), bitRate,
+ replayGainInfo);
}
if (replayGainInfo)
diff --git a/src/inputPlugins/wavpack_plugin.c b/src/inputPlugins/wavpack_plugin.c
index cd832fdc4..e4134bb31 100644
--- a/src/inputPlugins/wavpack_plugin.c
+++ b/src/inputPlugins/wavpack_plugin.c
@@ -207,10 +207,10 @@ static void wavpack_decode(struct decoder * decoder,
format_samples(Bps, chunk,
samplesgot * dc.audioFormat.channels);
- ob_send(NULL, 0, chunk,
- samplesgot * outsamplesize,
- file_time, bitrate,
- replayGainInfo);
+ decoder_data(decoder, NULL, 0, chunk,
+ samplesgot * outsamplesize,
+ file_time, bitrate,
+ replayGainInfo);
}
} while (samplesgot == samplesreq);
diff --git a/src/outputBuffer.c b/src/outputBuffer.c
index ff8cf7587..97a9e78bd 100644
--- a/src/outputBuffer.c
+++ b/src/outputBuffer.c
@@ -17,10 +17,9 @@
*/
#include "outputBuffer.h"
+#include "playerData.h"
#include "utils.h"
-#include "normalize.h"
-#include "playerData.h"
void ob_init(unsigned int size)
{
@@ -148,16 +147,12 @@ ob_chunk * ob_get_chunk(const unsigned i)
}
/**
- * Return the tail chunk which has room for additional data. If there
- * is no room in the queue, this function blocks until the player
- * thread has finished playing its current chunk.
+ * Return the tail chunk which has room for additional data.
*
- * @return the positive index of the new chunk; OUTPUT_BUFFER_DC_SEEK
- * if another thread requested seeking; OUTPUT_BUFFER_DC_STOP if
- * another thread requested stopping the decoder.
+ * @return the positive index of the new chunk; -1 if there is no
+ * room.
*/
-static int tailChunk(InputStream * inStream,
- int seekable, float data_time, mpd_uint16 bitRate)
+static int tailChunk(float data_time, mpd_uint16 bitRate)
{
unsigned int next;
ob_chunk *chunk;
@@ -167,26 +162,9 @@ static int tailChunk(InputStream * inStream,
if (chunk->chunkSize == sizeof(chunk->data)) {
/* this chunk is full; allocate a new chunk */
next = successor(ob.end);
- while (ob.begin == next) {
- /* all chunks are full of decoded data; wait
- for the player to free one */
-
- if (dc.command == DECODE_COMMAND_STOP)
- return OUTPUT_BUFFER_DC_STOP;
-
- if (dc.command == DECODE_COMMAND_SEEK) {
- if (seekable) {
- return OUTPUT_BUFFER_DC_SEEK;
- } else {
- dc.seekError = 1;
- dc_command_finished();
- }
- }
- if (!inStream || bufferInputStream(inStream) <= 0) {
- notify_wait(&dc.notify);
- notify_signal(&pc.notify);
- }
- }
+ if (ob.begin == next)
+ /* no chunks available */
+ return -1;
output_buffer_expand(next);
chunk = ob_get_chunk(next);
@@ -204,46 +182,17 @@ static int tailChunk(InputStream * inStream,
return ob.end;
}
-int ob_send(InputStream * inStream,
- int seekable, void *dataIn,
- size_t dataInLen, float data_time, mpd_uint16 bitRate,
- ReplayGainInfo * replayGainInfo)
+size_t ob_append(const void *data0, size_t datalen,
+ float data_time, mpd_uint16 bitRate)
{
- size_t dataToSend;
- char *data;
- size_t datalen;
- static char *convBuffer;
- static size_t convBufferLen;
+ const unsigned char *data = data0;
+ size_t ret = 0, dataToSend;
ob_chunk *chunk = NULL;
- if (cmpAudioFormat(&(ob.audioFormat), &(dc.audioFormat)) == 0) {
- data = dataIn;
- datalen = dataInLen;
- } else {
- datalen = pcm_sizeOfConvBuffer(&(dc.audioFormat), dataInLen,
- &(ob.audioFormat));
- if (datalen > convBufferLen) {
- if (convBuffer != NULL)
- free(convBuffer);
- convBuffer = xmalloc(datalen);
- convBufferLen = datalen;
- }
- data = convBuffer;
- datalen = pcm_convertAudioFormat(&(dc.audioFormat), dataIn,
- dataInLen, &(ob.audioFormat),
- data, &(ob.convState));
- }
-
- if (replayGainInfo && (replayGainState != REPLAYGAIN_OFF))
- doReplayGain(replayGainInfo, data, datalen, &ob.audioFormat);
- else if (normalizationEnabled)
- normalizeData(data, datalen, &ob.audioFormat);
-
while (datalen) {
- int chunk_index = tailChunk(inStream, seekable,
- data_time, bitRate);
+ int chunk_index = tailChunk(data_time, bitRate);
if (chunk_index < 0)
- return chunk_index;
+ return ret;
chunk = ob_get_chunk(chunk_index);
@@ -255,12 +204,13 @@ int ob_send(InputStream * inStream,
chunk->chunkSize += dataToSend;
datalen -= dataToSend;
data += dataToSend;
+ ret += dataToSend;
}
if (chunk != NULL && chunk->chunkSize == sizeof(chunk->data))
ob_flush();
- return 0;
+ return ret;
}
void ob_skip(unsigned num)
diff --git a/src/outputBuffer.h b/src/outputBuffer.h
index da574f4b5..ebbc0d228 100644
--- a/src/outputBuffer.h
+++ b/src/outputBuffer.h
@@ -20,9 +20,6 @@
#define OUTPUT_BUFFER_H
#include "pcm_utils.h"
-#include "mpd_types.h"
-#include "inputStream.h"
-#include "replayGain.h"
#define OUTPUT_BUFFER_DC_STOP -1
#define OUTPUT_BUFFER_DC_SEEK -2
@@ -98,15 +95,15 @@ int ob_absolute(const unsigned relative);
ob_chunk * ob_get_chunk(const unsigned i);
-/* we send inStream for buffering the inputStream while waiting to
- send the next chunk */
-int ob_send(InputStream * inStream,
- int seekable,
- void *data,
- size_t datalen,
- float data_time,
- mpd_uint16 bitRate, ReplayGainInfo * replayGainInfo);
+/**
+ * Append a data block to the buffer.
+ *
+ * @return the number of bytes actually written
+ */
+size_t ob_append(const void *data, size_t datalen,
+ float data_time, mpd_uint16 bitRate);
void ob_skip(unsigned num);
#endif
+