Modified CoreAudioDecoder to use new source based system. It just ignores the source and uses its own, since the ExtAudioFile API is absolutely hopeless when it comes to streaming.

CQTexperiment
vspader 2007-03-04 04:36:10 +00:00
parent e452cbe3db
commit eb96a75a1f
8 changed files with 61 additions and 173 deletions

View File

@ -17,7 +17,7 @@
@protocol CogSource <NSObject>
+ (NSArray *)schemes; //http, file, etc
- (BOOL)buffered; //Return YES if the input should be buffered, NO if it shouldn't. Used for remote connections (HTTP), not local stuff (file).
- (NSURL *)url;
- (BOOL)open:(NSURL *)url;
- (NSDictionary *)properties; //Perhaps contains header info for HTTP stream, or path for a regular file.

View File

@ -24,20 +24,11 @@
#import "Plugin.h"
#undef _USE_WRAPPER_
@interface CoreAudioDecoder : NSObject <CogDecoder>
{
ExtAudioFileRef _in;
#ifdef _USE_WRAPPER_
int _inFd;
AudioFileID _audioID;
SInt64 _fileSize;
SInt64 _startOffset;
#endif
int bitrate;
int bitsPerSample;
int channels;

View File

@ -28,166 +28,24 @@
@implementation CoreAudioDecoder
#ifdef _USE_WRAPPER_
OSStatus readFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, void *buffer, ByteCount* actualCount)
{
CoreAudioFile *caf = (CoreAudioFile *)inRefCon;
int fd = caf->_inFd;
// fseek(fd, inPosition, SEEK_SET);
// NSLog(@"Requesting %u", requestCount);
// NSLog(@"Currently at %lli", inPosition);
*actualCount = pread(fd, buffer, requestCount, inPosition+caf->_startOffset);
if (*actualCount <= 0)
{
return -1000; //Error?
}
return noErr;
}
SInt64 getSizeFunc(void *inRefCon)
{
CoreAudioFile *caf = (CoreAudioFile *)inRefCon;
int fd = caf->_inFd;
if (caf->_fileSize != 0)
{
return caf->_fileSize;
}
/* long curPos;
curPos = ftell(fd);
fseek(fd, 0, SEEK_END);
caf->_fileSize = ftell(fd);
fseek(fd, curPos, SEEK_SET);
*/
caf->_fileSize = lseek(fd, 0, SEEK_END) - caf->_startOffset;
NSLog(@"SIZE at %lli", caf->_fileSize);
NSLog(@"ERROR: %i = %i %i %i", errno, EBADF, ESPIPE, EINVAL);
return caf->_fileSize;
}
OSStatus setSizeFunc(void * inRefCon, SInt64 inSize)
{
NSLog(@"setsize FUNC");
return -1000; //Not supported at the moment
}
OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, const void *buffer, ByteCount* actualCount)
{
NSLog(@"WRITE FUNC");
return -1000; //Not supported at the moment
}
#endif
- (void) close
{
OSStatus err;
#ifdef _USE_WRAPPER_
if (_inFd)
close(_inFd);
AudioFileClose(_audioID);
#endif
err = ExtAudioFileDispose(_in);
if(noErr != err) {
NSLog(@"Error closing ExtAudioFile");
}
}
- (BOOL) open:(NSURL *)url
- (BOOL)open:(id<CogSource>)source;
{
OSStatus err;
#ifdef _USE_WRAPPER_
AudioFileTypeID type = 0;
NSString *ext;
// Open the input file
_inFd = open([[url path] UTF8String], O_RDONLY, 0777);
if (_inFd < 0)
{
NSLog(@"Error operning file: %s", url);
return NO;
}
_startOffset = 0;
ext = [[url path] pathExtension];
//Find first sync frame for MP3
if([ext caseInsensitiveCompare:@"mp3"] == NSOrderedSame) {
size_t bytesRead;
uint8_t buf[2];
type = kAudioFileMP3Type;
for(;;) {
bytesRead = read(_inFd, buf, 2);
if(2 != bytesRead) {
NSLog(@"Error finding mp3 sync frame");
close(_inFd);
return NO;
}
// found some kind of data
if(0x00 != buf[0] || 0x00 != buf[1]) {
_startOffset = lseek(_inFd, 0, SEEK_CUR) - 2;
NSLog(@"Found sync frame at: %llx", _startOffset);
break;
}
}
}
else if([ext caseInsensitiveCompare:@"aac"] == NSOrderedSame) {
type = kAudioFileAAC_ADTSType;
}
else if([ext caseInsensitiveCompare:@"m4a"] == NSOrderedSame) {
type = kAudioFileM4AType;
}
else if([ext caseInsensitiveCompare:@"mp4"] == NSOrderedSame) {
type = kAudioFileMPEG4Type;
}
//Using callbacks with fopen, ftell, fseek, fclose, because the default pread hangs when accessing the same file from multiple threads.
err = AudioFileOpenWithCallbacks(self, readFunc, writeFunc, getSizeFunc, setSizeFunc, type, &_audioID);
if(noErr != err)
{
NSLog(@"Error opening with callbacks, falling back: %s", (char *)&err);
FSRef ref;
close(_inFd);
_inFd = 0;
err = FSPathMakeRef((const UInt8 *)[[url path] UTF8String], &ref, NULL);
if(noErr != err) {
NSURL *url = [source url];
if (![[url scheme] isEqualToString:@"file"])
return NO;
}
err = AudioFileOpen(&ref, fsRdPerm, type, &_audioID);
if(noErr != err) {
NSLog(@"Error opening AudioFile: %s", (char *)&err);
return NO;
}
}
err = ExtAudioFileWrapAudioFileID(_audioID, NO, &_in);
if(noErr != err) {
return NO;
}
#else
FSRef ref;
// Open the input file
err = FSPathMakeRef((const UInt8 *)[[url path] UTF8String], &ref, NULL);
@ -200,7 +58,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
NSLog(@"Error opening file: %s", &err);
return NO;
}
#endif
return [self readInfoFromExtAudioFileRef];
}
@ -226,21 +84,8 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
return NO;
}
#ifdef _USE_WRAPPER_
SInt64 totalBytes;
size = sizeof(totalBytes);
err = AudioFileGetProperty(_audioID, kAudioFilePropertyAudioDataByteCount, &size, &totalBytes);
if(err != noErr) {
[self close];
return NO;
}
bitrate = round(((totalBytes*8.0)/((double)(totalFrames)/asbd.mSampleRate))/1000.0);
#else
//Is there a way to get bitrate with extAudioFile?
bitrate = 0;
#endif
// Set our properties
bitsPerSample = asbd.mBitsPerChannel;
@ -276,6 +121,9 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
return NO;
}
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
return YES;
}
@ -340,5 +188,10 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
nil];
}
- (BOOL)seekable
{
return YES; //Are you kidding me? it HAS to be seekable. The AudioFile API is 100% impossible to stream in any way. Even using callbacks gives problems. Sigh.
}
@end

View File

@ -11,13 +11,13 @@
@implementation CoreAudioPropertiesReader
- (NSDictionary *)propertiesForURL:(NSURL *)url
+ (NSDictionary *)propertiesForSource:(id<CogSource>)source
{
NSDictionary *properties;
CoreAudioDecoder *decoder;
decoder = [[CoreAudioDecoder alloc] init];
if (![decoder open:url])
if (![decoder open:source])
{
return nil;
}

View File

@ -13,6 +13,10 @@
@interface FileSource : NSObject <CogSource>
{
FILE *_fd;
NSURL *_url;
}
- (void)setURL:(NSURL *)url;
@end

View File

@ -18,6 +18,8 @@
- (BOOL)open:(NSURL *)url
{
[self setURL:url];
_fd = fopen([[url path] UTF8String], "r");
return (_fd != NULL);
@ -53,6 +55,19 @@
fclose(_fd);
}
- (NSURL *)url
{
return _url;
}
- (void)setURL:(NSURL *)url
{
[url retain];
[_url release];
_url = url;
}
+ (NSArray *)schemes
{
return [NSArray arrayWithObject:@"file"];

View File

@ -15,9 +15,13 @@
{
Socket *_socket;
NSURL *_url;
BOOL pastHeader;
long byteCount;
}
- (void)setURL:(NSURL *)url;
@end

View File

@ -18,6 +18,7 @@
- (BOOL)open:(NSURL *)url
{
[self setURL:url];
unsigned int port = [[url port] unsignedIntValue];
if (!port)
@ -112,6 +113,26 @@
[_socket close];
}
- (void)dealloc
{
[_socket release];
[_url release];
[super dealloc];
}
- (NSURL *)url
{
return _url;
}
- (void)setURL:(NSURL *)url
{
[url retain];
[_url release];
_url = url;
}
+ (NSArray *)schemes
{
return [NSArray arrayWithObject:@"http"];