implement input abstraction for ogg and mp3
git-svn-id: https://svn.musicpd.org/mpd/trunk@904 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
638817fc5b
commit
659df58671
|
@ -23,7 +23,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
int initInputStreamFromFile(InputStream * inStream, char * filename) {
|
int openInputStreamFromFile(InputStream * inStream, char * filename) {
|
||||||
inStream->fp = fopen(filename,"r");
|
inStream->fp = fopen(filename,"r");
|
||||||
if(!inStream->fp) {
|
if(!inStream->fp) {
|
||||||
inStream->error = errno;
|
inStream->error = errno;
|
||||||
|
@ -39,14 +39,9 @@ int initInputStreamFromFile(InputStream * inStream, char * filename) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int seekInputStream(InputStream * inStream, long offset) {
|
int seekInputStream(InputStream * inStream, long offset, int whence) {
|
||||||
if(offset<0) {
|
if(fseek(inStream->fp,offset,whence)==0) {
|
||||||
inStream->error = EINVAL;
|
inStream->offset = ftell(inStream->fp);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fseek(inStream->fp,offset,SEEK_SET)==0) {
|
|
||||||
inStream->offset = offset;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
inStream->error = errno;
|
inStream->error = errno;
|
||||||
|
@ -56,19 +51,19 @@ int seekInputStream(InputStream * inStream, long offset) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fillBufferFromInputStream(InputStream * inStream, char * buffer,
|
size_t readFromInputStream(InputStream * inStream, void * ptr, size_t size,
|
||||||
size_t buflen)
|
size_t nmemb)
|
||||||
{
|
{
|
||||||
size_t readSize;
|
size_t readSize;
|
||||||
|
|
||||||
readSize = fread(buffer,1,buflen,inStream->fp);
|
readSize = fread(ptr,size,nmemb,inStream->fp);
|
||||||
|
|
||||||
if(readSize>0) inStream->offset+=readSize;
|
if(readSize>0) inStream->offset+=readSize;
|
||||||
|
|
||||||
return readSize;
|
return readSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int finishInputStream(InputStream * inStream) {
|
int closeInputStream(InputStream * inStream) {
|
||||||
if(fclose(inStream->fp)<0) {
|
if(fclose(inStream->fp)<0) {
|
||||||
inStream->error = errno;
|
inStream->error = errno;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,11 @@ typedef struct _InputStream {
|
||||||
|
|
||||||
/* if an error occurs for these 3 functions, then -1 is returned and errno
|
/* if an error occurs for these 3 functions, then -1 is returned and errno
|
||||||
for the input stream is set */
|
for the input stream is set */
|
||||||
int initInputStreamFromFile(InputStream * inStream, char * filename);
|
int openInputStreamFromFile(InputStream * inStream, char * filename);
|
||||||
int seekInputStream(InputStream * inStream, long offset);
|
int seekInputStream(InputStream * inStream, long offset, int whence);
|
||||||
int finishInputStream(InputStream * inStream);
|
int closeInputStream(InputStream * inStream);
|
||||||
|
|
||||||
size_t fillBufferFromInputStream(InputStream * inStream, char * buffer,
|
size_t readFromInputStream(InputStream * inStream, void * ptr, size_t size,
|
||||||
size_t buflen);
|
size_t nmemb);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -136,7 +136,7 @@ typedef struct _mp3DecodeData {
|
||||||
int initMp3DecodeData(mp3DecodeData * data, char * file) {
|
int initMp3DecodeData(mp3DecodeData * data, char * file) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
while(((ret = initInputStreamFromFile(&(data->inStream),file))<0) &&
|
while(((ret = openInputStreamFromFile(&(data->inStream),file))<0) &&
|
||||||
data->inStream.error==EINTR);
|
data->inStream.error==EINTR);
|
||||||
if(ret<0) return -1;
|
if(ret<0) return -1;
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ int fillMp3InputBuffer(mp3DecodeData * data, long offset) {
|
||||||
unsigned char * readStart;
|
unsigned char * readStart;
|
||||||
|
|
||||||
if(offset>=0) {
|
if(offset>=0) {
|
||||||
seekInputStream(&(data->inStream),offset);
|
seekInputStream(&(data->inStream),offset,SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(offset==-1 && (data->stream).next_frame!=NULL) {
|
if(offset==-1 && (data->stream).next_frame!=NULL) {
|
||||||
|
@ -179,8 +179,7 @@ int fillMp3InputBuffer(mp3DecodeData * data, long offset) {
|
||||||
remaining = 0;
|
remaining = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
readSize = fillBufferFromInputStream(&(data->inStream),readStart,
|
readSize = readFromInputStream(&(data->inStream),readStart,1,readSize);
|
||||||
readSize);
|
|
||||||
if(readSize<=0) return -1;
|
if(readSize<=0) return -1;
|
||||||
|
|
||||||
mad_stream_buffer(&data->stream,data->readBuffer,readSize+remaining);
|
mad_stream_buffer(&data->stream,data->readBuffer,readSize+remaining);
|
||||||
|
@ -375,7 +374,7 @@ void mp3DecodeDataFinalize(mp3DecodeData * data) {
|
||||||
mad_frame_finish(&data->frame);
|
mad_frame_finish(&data->frame);
|
||||||
mad_stream_finish(&data->stream);
|
mad_stream_finish(&data->stream);
|
||||||
|
|
||||||
while(finishInputStream(&(data->inStream))<0 &&
|
while(closeInputStream(&(data->inStream))<0 &&
|
||||||
data->inStream.error==EINTR);
|
data->inStream.error==EINTR);
|
||||||
if(data->frameOffset) free(data->frameOffset);
|
if(data->frameOffset) free(data->frameOffset);
|
||||||
if(data->times) free(data->times);
|
if(data->times) free(data->times);
|
||||||
|
|
|
@ -25,12 +25,14 @@
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "pcm_utils.h"
|
#include "pcm_utils.h"
|
||||||
|
#include "inputStream.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vorbis/vorbisfile.h>
|
#include <vorbis/vorbisfile.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
#define OGG_DECODE_USE_BIGENDIAN 1
|
#define OGG_DECODE_USE_BIGENDIAN 1
|
||||||
|
@ -38,6 +40,7 @@
|
||||||
#define OGG_DECODE_USE_BIGENDIAN 0
|
#define OGG_DECODE_USE_BIGENDIAN 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* this is just for tag parsing for db import! */
|
||||||
int getOggTotalTime(char * file) {
|
int getOggTotalTime(char * file) {
|
||||||
OggVorbis_File vf;
|
OggVorbis_File vf;
|
||||||
FILE * oggfp;
|
FILE * oggfp;
|
||||||
|
@ -57,19 +60,47 @@ int getOggTotalTime(char * file) {
|
||||||
return totalTime;
|
return totalTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ogg_read_cb(void * ptr, size_t size, size_t nmemb, void * inStream)
|
||||||
|
{
|
||||||
|
size_t ret;
|
||||||
|
ret = readFromInputStream((InputStream *)inStream,ptr,size,nmemb);
|
||||||
|
|
||||||
|
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_close_cb(void * inStream) {
|
||||||
|
return closeInputStream((InputStream *)inStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
long ogg_tell_cb(void * inStream) {
|
||||||
|
return ((InputStream *)inStream)->offset;
|
||||||
|
}
|
||||||
|
|
||||||
int ogg_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
|
int ogg_decode(Buffer * cb, AudioFormat * af, DecoderControl * dc)
|
||||||
{
|
{
|
||||||
OggVorbis_File vf;
|
OggVorbis_File vf;
|
||||||
FILE * oggfp;
|
ov_callbacks callbacks;
|
||||||
|
InputStream inStream;
|
||||||
|
|
||||||
if(!(oggfp = fopen(dc->file,"r"))) {
|
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(openInputStreamFromFile(&inStream,dc->file)<0) {
|
||||||
ERROR("failed to open ogg\n");
|
ERROR("failed to open ogg\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ov_open(oggfp, &vf, NULL, 0) < 0) {
|
if(ov_open_callbacks(&inStream, &vf, NULL, 0, callbacks) < 0) {
|
||||||
ERROR("Input does not appear to be an Ogg bit stream.\n");
|
ERROR("Input does not appear to be an Ogg bit stream.\n");
|
||||||
fclose(oggfp);
|
closeInputStream(&inStream);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue