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> @protocol CogSource <NSObject>
+ (NSArray *)schemes; //http, file, etc + (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; - (BOOL)open:(NSURL *)url;
- (NSDictionary *)properties; //Perhaps contains header info for HTTP stream, or path for a regular file. - (NSDictionary *)properties; //Perhaps contains header info for HTTP stream, or path for a regular file.

View File

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

View File

@ -28,166 +28,24 @@
@implementation CoreAudioDecoder @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 - (void) close
{ {
OSStatus err; OSStatus err;
#ifdef _USE_WRAPPER_
if (_inFd)
close(_inFd);
AudioFileClose(_audioID);
#endif
err = ExtAudioFileDispose(_in); err = ExtAudioFileDispose(_in);
if(noErr != err) { if(noErr != err) {
NSLog(@"Error closing ExtAudioFile"); NSLog(@"Error closing ExtAudioFile");
} }
} }
- (BOOL) open:(NSURL *)url - (BOOL)open:(id<CogSource>)source;
{ {
OSStatus err; 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; FSRef ref;
close(_inFd);
_inFd = 0;
err = FSPathMakeRef((const UInt8 *)[[url path] UTF8String], &ref, NULL); NSURL *url = [source url];
if(noErr != err) { if (![[url scheme] isEqualToString:@"file"])
return NO; 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 // Open the input file
err = FSPathMakeRef((const UInt8 *)[[url path] UTF8String], &ref, NULL); 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); NSLog(@"Error opening file: %s", &err);
return NO; return NO;
} }
#endif
return [self readInfoFromExtAudioFileRef]; return [self readInfoFromExtAudioFileRef];
} }
@ -226,21 +84,8 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
return NO; 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? //Is there a way to get bitrate with extAudioFile?
bitrate = 0; bitrate = 0;
#endif
// Set our properties // Set our properties
bitsPerSample = asbd.mBitsPerChannel; bitsPerSample = asbd.mBitsPerChannel;
@ -276,6 +121,9 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
return NO; return NO;
} }
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
return YES; return YES;
} }
@ -340,5 +188,10 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
nil]; 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 @end

View File

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

View File

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

View File

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

View File

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

View File

@ -18,6 +18,7 @@
- (BOOL)open:(NSURL *)url - (BOOL)open:(NSURL *)url
{ {
[self setURL:url];
unsigned int port = [[url port] unsignedIntValue]; unsigned int port = [[url port] unsignedIntValue];
if (!port) if (!port)
@ -112,6 +113,26 @@
[_socket close]; [_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 + (NSArray *)schemes
{ {
return [NSArray arrayWithObject:@"http"]; return [NSArray arrayWithObject:@"http"];