diff --git a/Classes/AppleAudioFileStreamParser.h b/Classes/AppleAudioFileStreamParser.h new file mode 100644 index 0000000..6114ff9 --- /dev/null +++ b/Classes/AppleAudioFileStreamParser.h @@ -0,0 +1,19 @@ +// +// AppleAudioFileStreamParser.h +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/16/13. +// +// + +#import + +#include + +#include "BKAudioFileStreamParser.h" + +@interface AppleAudioFileStreamParser : NSObject + +- (id) initWithHint:(AudioFileTypeID)fileTypeHint; + +@end diff --git a/Classes/AppleAudioFileStreamParser.m b/Classes/AppleAudioFileStreamParser.m new file mode 100644 index 0000000..76a6868 --- /dev/null +++ b/Classes/AppleAudioFileStreamParser.m @@ -0,0 +1,216 @@ +// +// AppleAudioFileStreamParser.m +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/16/13. +// +// + +#import "AppleAudioFileStreamParser.h" +#import "AudioStreamer.h" + +@interface AppleAudioFileStreamParser () { + AudioFileStreamID audioFileStream; + AudioFileTypeID _fileTypeHint; +} +@end + +static void ASPropertyListenerProc(void * inClientData, + AudioFileStreamID inAudioFileStream, + AudioFileStreamPropertyID inPropertyID, + UInt32 * ioFlags) +{ + // this is called by audio file stream when it finds property values + AppleAudioFileStreamParser* streamer = (AppleAudioFileStreamParser *)inClientData; + [streamer.delegate + handlePropertyChangeForFileStream:streamer fileStreamPropertyID:inPropertyID]; +} + +static void ASPacketsProc(void * inClientData, + UInt32 inNumberBytes, + UInt32 inNumberPackets, + const void * inInputData, + AudioStreamPacketDescription *inPacketDescriptions) +{ + // this is called by audio file stream when it finds packets of audio + AppleAudioFileStreamParser* streamer = (AppleAudioFileStreamParser *)inClientData; + [streamer.delegate + handleAudioPackets:inInputData + numberBytes:inNumberBytes + numberPackets:inNumberPackets + packetDescriptions:inPacketDescriptions]; +} + + +@implementation AppleAudioFileStreamParser + +@synthesize delegate = _delegate; + +- (id) initWithHint:(AudioFileTypeID)fileTypeHint +{ + self = [super init]; + if (self) { + _fileTypeHint = fileTypeHint; + + } + return self; +} + +- (BOOL) open +{ + OSStatus err = AudioFileStreamOpen(self, ASPropertyListenerProc, ASPacketsProc, + _fileTypeHint, &audioFileStream); + if (err) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_OPEN_FAILED]; + return FALSE; + } + + return err == 0; +} + +- (BOOL) parseData:(const void *)data length:(UInt32)length flags:(UInt32)flags +{ + OSStatus err = AudioFileStreamParseBytes(audioFileStream, length, data, flags); + if (err) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_PARSE_BYTES_FAILED]; + return FALSE; + } + return TRUE; +} + +- (BOOL) seekOffset:(SInt64)inAbsolutePacketOffset outOffset:(SInt64 *)outAbsoluteByteOffset flags:(UInt32 *)flags +{ + OSStatus err; + err = AudioFileStreamSeek(audioFileStream, inAbsolutePacketOffset, outAbsoluteByteOffset, flags); + + return err == 0; +} + +- (void) close +{ + OSStatus err = AudioFileStreamClose(audioFileStream); + audioFileStream = nil; + if (err) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_CLOSE_FAILED]; + } +} + +- (SInt64) dataOffset +{ + SInt64 offset; + UInt32 offsetSize = sizeof(offset); + OSStatus err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_DataOffset, &offsetSize, &offset); + if (err) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; + return -1; + } + + return offset; +} + +- (UInt64) audioDataByteCount +{ + UInt64 audioDataByteCount; + UInt32 byteCountSize = sizeof(UInt64); + OSStatus err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &audioDataByteCount); + if (err) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; + return 0; + } + + return audioDataByteCount; +} + +- (BOOL) getDataFormat:(AudioStreamBasicDescription *)dataFormat +{ + UInt32 asbdSize = sizeof(*dataFormat); + + // get the stream format. + OSStatus err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, dataFormat); + if (err) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; + return FALSE; + } + return TRUE; +} + +- (AudioFormatListItem *) getFormatListWithLen:(UInt32 *)formatListSize +{ + Boolean outWriteable; + OSStatus err; + + err = AudioFileStreamGetPropertyInfo(audioFileStream, kAudioFileStreamProperty_FormatList, formatListSize, &outWriteable); + if (err) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; + return NULL; + } + + AudioFormatListItem *formatList = malloc(*formatListSize); + err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_FormatList, formatListSize, formatList); + if (err) + { + free(formatList); + [self.delegate failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; + return NULL; + } + + return formatList; +} + +- (UInt32) packetSizeUpperBound +{ + UInt32 packetBufferSize; + UInt32 sizeOfUInt32 = sizeof(UInt32); + OSStatus err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &packetBufferSize); + if (err) + { + return 0; + } + return packetBufferSize; +} + +- (UInt32) maxPacketSize +{ + UInt32 result; + + UInt32 sizeOfUInt32 = sizeof(UInt32); + OSStatus err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &result); + if (err) + { + result = 0; + } + return result; +} + +- (void *) getMagicCookieDataWithLen:(UInt32*)outCookieSize +{ + // get the cookie size + UInt32 cookieSize; + Boolean writable; + OSStatus ignorableError; + ignorableError = AudioFileStreamGetPropertyInfo(audioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable); + if (ignorableError) + { + return NULL; + } + *outCookieSize = cookieSize; + + // get the cookie data + void* cookieData = calloc(1, cookieSize); + ignorableError = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData); + if (ignorableError) + { + return NULL; + } + + return cookieData; +} + +@end diff --git a/Classes/AudioStreamer.h b/Classes/AudioStreamer.h index bab7498..e7b01b7 100644 --- a/Classes/AudioStreamer.h +++ b/Classes/AudioStreamer.h @@ -29,6 +29,7 @@ #include #include +#include "BKAudioFileStreamParser.h" #define LOG_QUEUED_BUFFERS 0 @@ -107,7 +108,34 @@ typedef enum extern NSString * const ASStatusChangedNotification; -@interface AudioStreamer : NSObject +enum { + // make sure ASAudioFileTypeID is in-sync with Apple's AudioFileTypeID enum + kASAudioFileAIFFType = kAudioFileAIFFType, + kASAudioFileAIFCType, + kASAudioFileWAVEType, + kASAudioFileSoundDesigner2Type, + kASAudioFileNextType, + kASAudioFileMP3Type, + kASAudioFileMP2Type, + kASAudioFileMP1Type, + kASAudioFileAC3Type, + kASAudioFileAAC_ADTSType, + kASAudioFileMPEG4Type, + kASAudioFileM4AType, + kASAudioFileM4BType, + kASAudioFileCAFType, + kASAudioFile3GPType, + kASAudioFile3GP2Type, + kASAudioFileAMRType, + + // any enum larger than >= ASAudioFileOggVorbisType is considered AS extension + kASAudioFileOggVorbisType, + kASAudioFileOggOpusType +}; +typedef UInt32 ASAudioFileTypeID; + + +@interface AudioStreamer : NSObject { NSURL *url; @@ -117,7 +145,8 @@ extern NSString * const ASStatusChangedNotification; // synchronized(self) block and only *after* checking that ![self isFinishing] // AudioQueueRef audioQueue; - AudioFileStreamID audioFileStream; // the audio file stream parser +// AudioFileStreamID audioFileStream; // the audio file stream parser + id audioFileStreamParser; AudioStreamBasicDescription asbd; // description of the audio NSThread *internalThread; // the thread where the download and // audio file stream parsing occurs diff --git a/Classes/AudioStreamer.m b/Classes/AudioStreamer.m index 44b31a2..cf05eca 100644 --- a/Classes/AudioStreamer.m +++ b/Classes/AudioStreamer.m @@ -22,6 +22,13 @@ // #import "AudioStreamer.h" + +#import + +#import "AppleAudioFileStreamParser.h" +#import "OggVorbisStreamParser.h" +#import "OggOpusStreamParser.h" + #if TARGET_OS_IPHONE #import #endif @@ -59,9 +66,6 @@ @interface AudioStreamer () @property (readwrite) AudioStreamerState state; @property (readwrite) AudioStreamerState laststate; -- (void)handlePropertyChangeForFileStream:(AudioFileStreamID)inAudioFileStream - fileStreamPropertyID:(AudioFileStreamPropertyID)inPropertyID - ioFlags:(UInt32 *)ioFlags; - (void)handleAudioPackets:(const void *)inInputData numberBytes:(UInt32)inNumberBytes numberPackets:(UInt32)inNumberPackets @@ -84,56 +88,6 @@ - (void)handleReadFromStream:(CFReadStreamRef)aStream #pragma mark Audio Callback Function Implementations -// -// ASPropertyListenerProc -// -// Receives notification when the AudioFileStream has audio packets to be -// played. In response, this function creates the AudioQueue, getting it -// ready to begin playback (playback won't begin until audio packets are -// sent to the queue in ASEnqueueBuffer). -// -// This function is adapted from Apple's example in AudioFileStreamExample with -// kAudioQueueProperty_IsRunning listening added. -// -static void ASPropertyListenerProc(void * inClientData, - AudioFileStreamID inAudioFileStream, - AudioFileStreamPropertyID inPropertyID, - UInt32 * ioFlags) -{ - // this is called by audio file stream when it finds property values - AudioStreamer* streamer = (AudioStreamer *)inClientData; - [streamer - handlePropertyChangeForFileStream:inAudioFileStream - fileStreamPropertyID:inPropertyID - ioFlags:ioFlags]; -} - -// -// ASPacketsProc -// -// When the AudioStream has packets to be played, this function gets an -// idle audio buffer and copies the audio packets into it. The calls to -// ASEnqueueBuffer won't return until there are buffers available (or the -// playback has been stopped). -// -// This function is adapted from Apple's example in AudioFileStreamExample with -// CBR functionality added. -// -static void ASPacketsProc( void * inClientData, - UInt32 inNumberBytes, - UInt32 inNumberPackets, - const void * inInputData, - AudioStreamPacketDescription *inPacketDescriptions) -{ - // this is called by audio file stream when it finds packets of audio - AudioStreamer* streamer = (AudioStreamer *)inClientData; - [streamer - handleAudioPackets:inInputData - numberBytes:inNumberBytes - numberPackets:inNumberPackets - packetDescriptions:inPacketDescriptions]; -} - // // ASAudioQueueOutputCallback // @@ -359,7 +313,7 @@ - (void)presentAlertWithTitle:(NSString*)title message:(NSString*)message [[UIAlertView alloc] initWithTitle:title message:message - delegate:self + delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles: nil] autorelease]; @@ -427,7 +381,8 @@ - (void)failWithErrorCode:(AudioStreamerErrorCode)anErrorCode } [self presentAlertWithTitle:NSLocalizedStringFromTable(@"File Error", @"Errors", nil) - message:NSLocalizedStringFromTable(@"Unable to configure network read stream.", @"Errors", nil)]; + message:[NSString + stringWithFormat:NSLocalizedStringFromTable(@"Unable to configure network read stream: %d (%@)", @"Errors", nil), anErrorCode, [AudioStreamer stringForErrorCode:anErrorCode]]]; } } @@ -572,41 +527,49 @@ - (BOOL)isIdle // // returns a file type hint that can be passed to the AudioFileStream // -+ (AudioFileTypeID)hintForFileExtension:(NSString *)fileExtension ++ (ASAudioFileTypeID)hintForFileExtension:(NSString *)fileExtension { - AudioFileTypeID fileTypeHint = kAudioFileAAC_ADTSType; + ASAudioFileTypeID fileTypeHint = kAudioFileAAC_ADTSType; if ([fileExtension isEqual:@"mp3"]) { - fileTypeHint = kAudioFileMP3Type; + fileTypeHint = kASAudioFileMP3Type; } else if ([fileExtension isEqual:@"wav"]) { - fileTypeHint = kAudioFileWAVEType; + fileTypeHint = kASAudioFileWAVEType; } else if ([fileExtension isEqual:@"aifc"]) { - fileTypeHint = kAudioFileAIFCType; + fileTypeHint = kASAudioFileAIFCType; } else if ([fileExtension isEqual:@"aiff"]) { - fileTypeHint = kAudioFileAIFFType; + fileTypeHint = kASAudioFileAIFFType; } else if ([fileExtension isEqual:@"m4a"]) { - fileTypeHint = kAudioFileM4AType; + fileTypeHint = kASAudioFileM4AType; } else if ([fileExtension isEqual:@"mp4"]) { - fileTypeHint = kAudioFileMPEG4Type; + fileTypeHint = kASAudioFileMPEG4Type; } else if ([fileExtension isEqual:@"caf"]) { - fileTypeHint = kAudioFileCAFType; + fileTypeHint = kASAudioFileCAFType; } else if ([fileExtension isEqual:@"aac"]) { - fileTypeHint = kAudioFileAAC_ADTSType; + fileTypeHint = kASAudioFileAAC_ADTSType; } + else if ([fileExtension isEqual:@"ogg"] || [fileExtension isEqual:@"vorbis"]) + { + fileTypeHint = kASAudioFileOggVorbisType; + } + else if ([fileExtension isEqual:@"opus"]) + { + fileTypeHint = kASAudioFileOggOpusType; + } return fileTypeHint; } @@ -655,7 +618,7 @@ - (BOOL)openReadStream kCFBooleanTrue) == false) { [self presentAlertWithTitle:NSLocalizedStringFromTable(@"File Error", @"Errors", nil) - message:NSLocalizedStringFromTable(@"Unable to configure network read stream.", @"Errors", nil)]; + message:NSLocalizedStringFromTable(@"Failed to set Autoredirect property.", @"Errors", nil)]; return NO; } @@ -696,7 +659,7 @@ - (BOOL)openReadStream { CFRelease(stream); [self presentAlertWithTitle:NSLocalizedStringFromTable(@"File Error", @"Errors", nil) - message:NSLocalizedStringFromTable(@"Unable to configure network read stream.", @"Errors", nil)]; + message:NSLocalizedStringFromTable(@"Failed to open stream.", @"Errors", nil)]; return NO; } @@ -763,19 +726,26 @@ - (void)startInternal // Set the audio session category so that we continue to play if the // iPhone/iPod auto-locks. // - AudioSessionInitialize ( - NULL, // 'NULL' to use the default (main) run loop - NULL, // 'NULL' to use the default run loop mode - ASAudioSessionInterruptionListener, // a reference to your interruption callback - self // data to pass to your interruption listener callback - ); - UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback; - AudioSessionSetProperty ( - kAudioSessionProperty_AudioCategory, - sizeof (sessionCategory), - &sessionCategory - ); - AudioSessionSetActive(true); + + NSError *error; + AVAudioSession *myAudioSession = [AVAudioSession sharedInstance]; + BOOL success = [myAudioSession setCategory: AVAudioSessionCategoryPlayback error:&error]; + if (!success) { + NSLog(@"Failed to set category in audio sesssion: (%d) %@", [error code], [error localizedDescription]); + } + else { + BOOL success = [myAudioSession setActive: YES error: &error]; + if (success) { + + // set interrupt callbacks when receiving system interruption e.g. phone calls + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedSystemNotification:) name:AVAudioSessionInterruptionNotification object:nil]; + + NSLog(@"Audio session activated"); + } else { + NSLog(@"Failed to activate audio sesssion: (%d) %@", [error code], [error localizedDescription]); + } + + } #endif // initialize a mutex and condition so that we can block on buffers in use. @@ -839,15 +809,10 @@ - (void)startInternal // // Close the audio file strea, // - if (audioFileStream) - { - err = AudioFileStreamClose(audioFileStream); - audioFileStream = nil; - if (err) - { - [self failWithErrorCode:AS_FILE_STREAM_CLOSE_FAILED]; - } - } + if (audioFileStreamParser != nil) { + [audioFileStreamParser close]; + audioFileStreamParser = nil; + } // // Dispose of the Audio Queue @@ -865,8 +830,14 @@ - (void)startInternal pthread_mutex_destroy(&queueBuffersMutex); pthread_cond_destroy(&queueBufferReadyCondition); -#if TARGET_OS_IPHONE - AudioSessionSetActive(false); +#if TARGET_OS_IPHONE + + // deactive AudioSession category and remove system interrupt callbacks + NSError *error; + AVAudioSession *myAudioSession = [AVAudioSession sharedInstance]; + [myAudioSession setActive: NO error: &error]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionInterruptionNotification object:nil]; + #endif [httpHeaders release]; @@ -958,8 +929,8 @@ - (void)internalSeekToTime:(double)newSeekTime UInt32 ioFlags = 0; SInt64 packetAlignedByteOffset; SInt64 seekPacket = floor(newSeekTime / packetDuration); - err = AudioFileStreamSeek(audioFileStream, seekPacket, &packetAlignedByteOffset, &ioFlags); - if (!err && !(ioFlags & kAudioFileStreamSeekFlag_OffsetIsEstimated)) + BOOL succeed = [audioFileStreamParser seekOffset:seekPacket outOffset:&packetAlignedByteOffset flags:&ioFlags]; + if (succeed && !(ioFlags & kAudioFileStreamSeekFlag_OffsetIsEstimated)) { seekTime -= ((seekByteOffset - dataOffset) - packetAlignedByteOffset) * 8.0 / calculatedBitRate; seekByteOffset = packetAlignedByteOffset + dataOffset; @@ -1033,6 +1004,9 @@ - (double)progress AudioTimeStamp queueTime; Boolean discontinuity; err = AudioQueueGetCurrentTime(audioQueue, NULL, &queueTime, &discontinuity); + + // use this simulate interruption +// if (lastProgress > 10 && lastProgress < 13) {} const OSStatus AudioQueueStopped = 0x73746F70; // 0x73746F70 is 'stop' if (err == AudioQueueStopped) @@ -1041,7 +1015,14 @@ - (double)progress } else if (err) { - [self failWithErrorCode:AS_GET_AUDIO_TIME_FAILED]; +// [self failWithErrorCode:AS_GET_AUDIO_TIME_FAILED]; + + NSException* myException = [NSException + exceptionWithName:@"GetAudioTimeFailed" + reason:@"get current audio queue time failed" + userInfo:nil]; + @throw myException; + } double progress = seekTime + queueTime.mSampleTime / sampleRate; @@ -1287,7 +1268,7 @@ - (void)handleReadFromStream:(CFReadStreamRef)aStream } } - if (!audioFileStream) + if (!audioFileStreamParser) { // // Attempt to guess the file type from the URL. Reading the MIME type @@ -1300,17 +1281,25 @@ - (void)handleReadFromStream:(CFReadStreamRef)aStream { self.fileExtension = [[url path] pathExtension]; } - AudioFileTypeID fileTypeHint = - [AudioStreamer hintForFileExtension:self.fileExtension]; + ASAudioFileTypeID fileTypeHint = [AudioStreamer hintForFileExtension:self.fileExtension]; + + switch (fileTypeHint) { + case kASAudioFileOggVorbisType: + audioFileStreamParser = [[OggVorbisStreamParser alloc] initWithHint:fileTypeHint]; + break; + + case kASAudioFileOggOpusType: + audioFileStreamParser = [[OggOpusStreamParser alloc] initWithHint:fileTypeHint]; + break; + + default: + audioFileStreamParser = [[AppleAudioFileStreamParser alloc] initWithHint:fileTypeHint]; + break; + } // create an audio file stream parser - err = AudioFileStreamOpen(self, ASPropertyListenerProc, ASPacketsProc, - fileTypeHint, &audioFileStream); - if (err) - { - [self failWithErrorCode:AS_FILE_STREAM_OPEN_FAILED]; - return; - } + audioFileStreamParser.delegate = self; + [audioFileStreamParser open]; } UInt8 bytes[kAQDefaultBufSize]; @@ -1341,21 +1330,11 @@ - (void)handleReadFromStream:(CFReadStreamRef)aStream if (discontinuous) { - err = AudioFileStreamParseBytes(audioFileStream, length, bytes, kAudioFileStreamParseFlag_Discontinuity); - if (err) - { - [self failWithErrorCode:AS_FILE_STREAM_PARSE_BYTES_FAILED]; - return; - } + [audioFileStreamParser parseData:bytes length:length flags:kAudioFileStreamParseFlag_Discontinuity]; } else { - err = AudioFileStreamParseBytes(audioFileStream, length, bytes, 0); - if (err) - { - [self failWithErrorCode:AS_FILE_STREAM_PARSE_BYTES_FAILED]; - return; - } + [audioFileStreamParser parseData:bytes length:length flags:0]; } } } @@ -1487,17 +1466,19 @@ - (void)createQueue } // get the packet size if it is available - UInt32 sizeOfUInt32 = sizeof(UInt32); - err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &packetBufferSize); - if (err || packetBufferSize == 0) + packetBufferSize = audioFileStreamParser.packetSizeUpperBound; +// err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_PacketSizeUpperBound, &sizeOfUInt32, &packetBufferSize); + if (packetBufferSize == 0) { - err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &packetBufferSize); - if (err || packetBufferSize == 0) +// err = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MaximumPacketSize, &sizeOfUInt32, &packetBufferSize); + packetBufferSize = audioFileStreamParser.maxPacketSize; + if (packetBufferSize == 0) { // No packet size available, just use the default packetBufferSize = kAQDefaultBufSize; } } + NSLog(@"packetBufferSize %ld", packetBufferSize); // allocate audio queue buffers for (unsigned int i = 0; i < kNumAQBufs; ++i) @@ -1512,24 +1493,13 @@ - (void)createQueue // get the cookie size UInt32 cookieSize; - Boolean writable; - OSStatus ignorableError; - ignorableError = AudioFileStreamGetPropertyInfo(audioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable); - if (ignorableError) - { - return; - } - - // get the cookie data - void* cookieData = calloc(1, cookieSize); - ignorableError = AudioFileStreamGetProperty(audioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData); - if (ignorableError) - { - return; - } + void *cookieData = [audioFileStreamParser getMagicCookieDataWithLen:&cookieSize]; + if (cookieData == NULL) { + return; + } // set the cookie on the queue. - ignorableError = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_MagicCookie, cookieData, cookieSize); + OSStatus ignorableError = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_MagicCookie, cookieData, cookieSize); free(cookieData); if (ignorableError) { @@ -1547,9 +1517,8 @@ - (void)createQueue // inPropertyID - the property that changed // ioFlags - the ioFlags passed in // -- (void)handlePropertyChangeForFileStream:(AudioFileStreamID)inAudioFileStream - fileStreamPropertyID:(AudioFileStreamPropertyID)inPropertyID - ioFlags:(UInt32 *)ioFlags + +- (void) handlePropertyChangeForFileStream:(id)fileStreamParser fileStreamPropertyID:(AudioFileStreamPropertyID)inPropertyID { @synchronized(self) { @@ -1565,9 +1534,8 @@ - (void)handlePropertyChangeForFileStream:(AudioFileStreamID)inAudioFileStream else if (inPropertyID == kAudioFileStreamProperty_DataOffset) { SInt64 offset; - UInt32 offsetSize = sizeof(offset); - err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataOffset, &offsetSize, &offset); - if (err) + offset = fileStreamParser.dataOffset; + if (offset < 0) { [self failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; return; @@ -1581,9 +1549,8 @@ - (void)handlePropertyChangeForFileStream:(AudioFileStreamID)inAudioFileStream } else if (inPropertyID == kAudioFileStreamProperty_AudioDataByteCount) { - UInt32 byteCountSize = sizeof(UInt64); - err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &audioDataByteCount); - if (err) + audioDataByteCount = fileStreamParser.audioDataByteCount; + if (audioDataByteCount == 0) { [self failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; return; @@ -1594,36 +1561,15 @@ - (void)handlePropertyChangeForFileStream:(AudioFileStreamID)inAudioFileStream { if (asbd.mSampleRate == 0) { - UInt32 asbdSize = sizeof(asbd); - - // get the stream format. - err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, &asbd); - if (err) - { - [self failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; + if (![fileStreamParser getDataFormat:&asbd]) { return; } } } else if (inPropertyID == kAudioFileStreamProperty_FormatList) { - Boolean outWriteable; UInt32 formatListSize; - err = AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, &outWriteable); - if (err) - { - [self failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; - return; - } - - AudioFormatListItem *formatList = malloc(formatListSize); - err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_FormatList, &formatListSize, formatList); - if (err) - { - free(formatList); - [self failWithErrorCode:AS_FILE_STREAM_GET_PROPERTY_FAILED]; - return; - } + AudioFormatListItem *formatList = [fileStreamParser getFormatListWithLen:&formatListSize]; for (int i = 0; i * sizeof(AudioFormatListItem) < formatListSize; i += sizeof(AudioFormatListItem)) { @@ -1784,7 +1730,7 @@ - (void)handleAudioPackets:(const void *)inInputData { // if the space remaining in the buffer is not enough for this packet, then enqueue the buffer. size_t bufSpaceRemaining = kAQDefaultBufSize - bytesFilled; - if (bufSpaceRemaining < inNumberBytes) + if (bytesFilled > 0 && bufSpaceRemaining < inNumberBytes) { [self enqueueBuffer]; } @@ -1978,7 +1924,8 @@ - (void)handleInterruptionChangeToState:(NSNotification *)notification { } else if (inInterruptionState == kAudioSessionEndInterruption) { - AudioSessionSetActive( true ); + NSError *error; + [[AVAudioSession sharedInstance] setActive:YES error:&error]; if ([self isPaused] && pausedByInterruption) { [self pause]; // this is actually resume @@ -1987,6 +1934,26 @@ - (void)handleInterruptionChangeToState:(NSNotification *)notification { } } } + +- (void) receivedSystemNotification:(NSNotification*)notification +{ + NSDictionary *interuptionDict = notification.userInfo; + + NSUInteger interuptionType = [[interuptionDict valueForKey:AVAudioSessionInterruptionTypeKey] intValue]; + + NSLog(@"received audio interrupt: %d", interuptionType); + + // route system interruption to ASAudioSessionInterruptionListener + if (interuptionType == AVAudioSessionInterruptionTypeBegan) + ASAudioSessionInterruptionListener(NULL, kAudioSessionBeginInterruption); + + else if (interuptionType == AVAudioSessionInterruptionTypeEnded) + ASAudioSessionInterruptionListener(NULL, kAudioSessionEndInterruption); + + else + NSLog(@"unknown interruption type: %d", interuptionType); +} + #endif @end diff --git a/Classes/BKAudioFileStreamParser.h b/Classes/BKAudioFileStreamParser.h new file mode 100644 index 0000000..fc2efd0 --- /dev/null +++ b/Classes/BKAudioFileStreamParser.h @@ -0,0 +1,49 @@ +// +// BKAudioFileStreamParser.h +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/16/13. +// +// + +#import +#include + +@protocol BKAudioFileStreamParser; +@protocol BKAudioFileStreamDelegate + +- (void)handleAudioPackets:(const void *)inInputData + numberBytes:(UInt32)inNumberBytes + numberPackets:(UInt32)inNumberPackets + packetDescriptions:(AudioStreamPacketDescription *)inPacketDescriptions; + +- (void)handlePropertyChangeForFileStream:(id)audioFileStreamParser + fileStreamPropertyID:(AudioFileStreamPropertyID)inPropertyID; + +- (void)failWithErrorCode:(int)anErrorCode; + +@end + +@protocol BKAudioFileStreamParser + +@required +@property (readonly) SInt64 dataOffset; +@property (readonly) UInt64 audioDataByteCount; + +@property (readonly) UInt32 packetSizeUpperBound; +@property (readonly) UInt32 maxPacketSize; + +@property (assign) id delegate; + +- (BOOL) getDataFormat:(AudioStreamBasicDescription *) dataFormat; +- (void *) getMagicCookieDataWithLen:(UInt32*)outCookieSize; +- (AudioFormatListItem *) getFormatListWithLen:(UInt32 *)formatListSize; + +- (BOOL) parseData:(const void *)data length:(UInt32)length flags:(UInt32)flags; +- (BOOL) seekOffset:(SInt64)inAbsolutePacketOffset outOffset:(SInt64 *)outAbsoluteByteOffset flags:(UInt32 *)flags; +- (BOOL) open; +- (void) close; + +@end + + diff --git a/Classes/OggOpusStreamParser.h b/Classes/OggOpusStreamParser.h new file mode 100644 index 0000000..36f46cd --- /dev/null +++ b/Classes/OggOpusStreamParser.h @@ -0,0 +1,17 @@ +// +// OggOpusStreamParser.h +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/28/13. +// +// + +#import + +#import "BKAudioFileStreamParser.h" + +@interface OggOpusStreamParser : NSObject + +- (id) initWithHint:(AudioFileTypeID)fileTypeHint; + +@end diff --git a/Classes/OggOpusStreamParser.mm b/Classes/OggOpusStreamParser.mm new file mode 100644 index 0000000..95c5191 --- /dev/null +++ b/Classes/OggOpusStreamParser.mm @@ -0,0 +1,297 @@ +// +// OggOpusStreamParser.m +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/28/13. +// +// + +#import "OggOpusStreamParser.h" +#import "AudioStreamer.h" + +#import "Ogg/ogg.h" +#import "Opus/opus.h" +#import "Opus/opusfile.h" + +@interface OggOpusStreamParser () { + ogg_sync_state _oggSyncState; + ogg_stream_state _oggStreamState; + + OpusHead _header; + OpusMSDecoder *_opusDecoder; + + int _state; + +} +@end + +@implementation OggOpusStreamParser + +@synthesize delegate = _delegate; + +- (id) initWithHint:(AudioFileTypeID)fileTypeHint +{ + self = [super init]; + if (self) { + _opusDecoder = NULL; + } + return self; +} + +- (BOOL) open +{ + ogg_sync_init(&_oggSyncState); + + _state = 0; + + + return TRUE; +} + +- (BOOL) parseData:(const void *)data length:(UInt32)length flags:(UInt32)flags +{ + char *buffer; + buffer = ogg_sync_buffer(&_oggSyncState, 4096); + memcpy(buffer, data, length); + + int status = ogg_sync_wrote(&_oggSyncState, length); + if (status != 0) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_PARSE_BYTES_FAILED]; + return FALSE; + } + + ogg_page page; + int result = ogg_sync_pageout(&_oggSyncState, &page); + if (result == 0) { + // NSLog(@"more data needed"); + return TRUE; + } + else if (result < 0) { + NSLog(@"Corrupt or missing data in bitstream; continuing..."); + } + else { + // call handles + // NSLog(@"should handle audio packets"); + + if (_state == 0) { + int serialno = ogg_page_serialno(&page); + ogg_stream_init(&_oggStreamState, serialno); + + status = ogg_stream_pagein(&_oggStreamState, &page); + if (status < 0) { + NSLog(@"Error reading first page of Ogg bitstream data."); + return FALSE; + } + + ogg_packet packet; + status = ogg_stream_packetout(&_oggStreamState, &packet); + if (status != 1) { + NSLog(@"Error reading initial header packet"); + return FALSE; + } + + + status = opus_head_parse(&_header, packet.packet, packet.bytes); + if (status < 0) { + NSLog(@"OggOpus parse header error: %d", status); + return FALSE; + } + + if (_opusDecoder != NULL) { + opus_multistream_decoder_destroy(_opusDecoder); + } + + int err; + _opusDecoder = opus_multistream_decoder_create(48000, _header.channel_count, _header.stream_count, + _header.coupled_count, _header.mapping, &err); + + // FIXME set opus gain ... see opusfile.c:op_make_decode_ready + + _state++; + + } + else if (_state > 0 && _state < 2) { + + status = ogg_stream_pagein(&_oggStreamState, &page); + if (status < 0) { + NSLog(@"Error reading first page of Ogg bitstream data."); + return FALSE; + } + + ogg_packet packet; + status = ogg_stream_packetout(&_oggStreamState, &packet); + switch (status) { + case 0: + // insufficient data + break; + + case -1: + // bad header + NSLog(@"bad Opus header"); + return FALSE; + + default: + // got a valid packet + OpusTags tags; + int ret = opus_tags_parse(&tags, packet.packet, packet.bytes); + if (ret < 0) { + NSLog(@"parse Opus tags error: %d", ret); + return FALSE; + } + + ret = ogg_stream_packetout(&_oggStreamState, &packet); + + // The final packet SHOULD complete on the last page, i.e., the final lacing value should be less than 255 + // http://wiki.xiph.org/OggOpus + if (ret != 0 || page.header[page.header_len - 1] == 255) { + // if fail we assume the tags are uninitialized - follow opusfile.c implementation + opus_tags_clear(&tags); + return FALSE; + } + + // valid tags here + NSLog(@"vendor: %s", tags.vendor); + for (int i = 0; i < tags.comments; i++) { + // assuming is a null terminated string + NSLog(@"%d: %s", i, tags.user_comments[i]); + } + + _state++; + + break; + } + + if (status > 0) { + [self.delegate handlePropertyChangeForFileStream:self fileStreamPropertyID:kAudioFileStreamProperty_DataFormat]; + [self.delegate handlePropertyChangeForFileStream:self fileStreamPropertyID:kAudioFileStreamProperty_ReadyToProducePackets]; + } + + + } + else if (_state == 2) { + + // frame_size int: The number of samples per channel of available space in pcm. + // If this is less than the maximum packet duration (120 ms; 5760 for 48kHz), this function will not be capable of decoding some packets. + opus_int16 pcm[120*48*2]; + + status = ogg_stream_pagein(&_oggStreamState, &page); + + BOOL loop = TRUE; + while (loop) { + ogg_packet packet; + status = ogg_stream_packetout(&_oggStreamState, &packet); + switch (status) { + case 0: + loop = FALSE; +// NSLog(@"exiting loop"); + break; + + case -1: + // try again + break; + + default: + int nframes = opus_packet_get_nb_frames(packet.packet, packet.bytes); + if (nframes < 0) { + NSLog(@"audio packet error: opus_packet_get_nb_frames error: %d", nframes); + loop = FALSE; + break; + } + + int frame_size = opus_packet_get_samples_per_frame(packet.packet, 48000); + int nsamples = nframes * frame_size; + + // OggOpus IETF: The duration of an Opus packet may be any multiple of 2.5 ms, up to a maximum of 120 ms + // which comes up to 120*48 max samples + if (nsamples > 120*48) { + NSLog(@"audio packet error: nsamples > 120*48"); + loop = FALSE; + break; + } + + int ret = opus_multistream_decode(_opusDecoder, packet.packet, packet.bytes, pcm, nsamples, 0); + NSAssert(ret < 0 || ret == nsamples, @"decode error"); +// NSLog(@"decoded %d samples", ret); + + UInt32 bytesLen = 2 * _header.channel_count * nsamples; + [self.delegate handleAudioPackets:pcm numberBytes:bytesLen numberPackets:0 packetDescriptions:NULL]; + + break; + } + + } + + if (ogg_page_eos(&page)) { + NSLog(@"received EOS!"); + _state = 0; + } + + + } + } + + return TRUE; +} + +- (BOOL) seekOffset:(SInt64)inAbsolutePacketOffset outOffset:(SInt64 *)outAbsoluteByteOffset flags:(UInt32 *)flags +{ + // OSStatus err; + // err = AudioFileStreamSeek(audioFileStream, inAbsolutePacketOffset, outAbsoluteByteOffset, flags); + // + // return err == 0; + return FALSE; +} + +- (void) close +{ + ogg_sync_clear(&_oggSyncState); + _state = 0; +} + +- (SInt64) dataOffset +{ + return 0; +} + +- (UInt64) audioDataByteCount +{ + return 0; +} + +- (BOOL) getDataFormat:(AudioStreamBasicDescription *)dataFormat +{ + FillOutASBDForLPCM(*dataFormat, + 48000, // sample rate (fps) + _header.channel_count, // channels per frame + 16, // valid bits per channel + 16, // total bits per channel + false, // isFloat + false); // isBigEndian + + return TRUE; +} + +- (AudioFormatListItem *) getFormatListWithLen:(UInt32 *)formatListSize +{ + return NULL; +} + +- (UInt32) packetSizeUpperBound +{ + return 120*48*2; +} + +- (UInt32) maxPacketSize +{ + return 120*48*2; +} + +- (void *) getMagicCookieDataWithLen:(UInt32*)outCookieSize +{ + return NULL; +} + + + +@end diff --git a/Classes/OggVorbisStreamParser.h b/Classes/OggVorbisStreamParser.h new file mode 100644 index 0000000..c884743 --- /dev/null +++ b/Classes/OggVorbisStreamParser.h @@ -0,0 +1,17 @@ +// +// OggVorbisStreamParser.h +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/22/13. +// +// + +#import + +#import "BKAudioFileStreamParser.h" + +@interface OggVorbisStreamParser : NSObject + +- (id) initWithHint:(AudioFileTypeID)fileTypeHint; + +@end diff --git a/Classes/OggVorbisStreamParser.mm b/Classes/OggVorbisStreamParser.mm new file mode 100644 index 0000000..e44d573 --- /dev/null +++ b/Classes/OggVorbisStreamParser.mm @@ -0,0 +1,320 @@ +// +// OggVorbisStreamParser.m +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/22/13. +// +// + +#import "OggVorbisStreamParser.h" +#import "AudioStreamer.h" + +#import "Ogg/ogg.h" +#import "Vorbis/codec.h" + +#import + +//#define PROFILE_CODE 1 + +#ifdef PROFILE_CODE +#include "cputime.h" +#endif + +@interface OggVorbisStreamParser () { + ogg_sync_state _oggSyncState; + ogg_stream_state _oggStreamState; + + vorbis_info _vorbisInfo; + vorbis_comment _vorbisComment; + vorbis_dsp_state _vorbisDspState; + vorbis_block _vorbisBlock; + + int _state; + +#ifdef PROFILE_CODE + int _totalSamples; + double _totalCputimes; +#endif + +} + +@end + +@implementation OggVorbisStreamParser + +@synthesize delegate = _delegate; + +- (id) initWithHint:(AudioFileTypeID)fileTypeHint +{ + self = [super init]; + if (self) { + } + return self; +} + +- (BOOL) open +{ + ogg_sync_init(&_oggSyncState); + + vorbis_info_init(&_vorbisInfo); + vorbis_comment_init(&_vorbisComment); + + _state = 0; + +#ifdef PROFILE_CODE + _totalSamples = 0; + _totalCputimes = 0.0; +#endif + + return TRUE; +} + +- (BOOL) parseData:(const void *)data length:(UInt32)length flags:(UInt32)flags +{ + char *buffer; + buffer = ogg_sync_buffer(&_oggSyncState, 4096); + memcpy(buffer, data, length); + + int status = ogg_sync_wrote(&_oggSyncState, length); + if (status != 0) + { + [self.delegate failWithErrorCode:AS_FILE_STREAM_PARSE_BYTES_FAILED]; + return FALSE; + } + + ogg_page page; + int result = ogg_sync_pageout(&_oggSyncState, &page); + if (result == 0) { +// NSLog(@"more data needed"); + return TRUE; + } + else if (result < 0) { + NSLog(@"Corrupt or missing data in bitstream; continuing..."); + } + else { + // call handles +// NSLog(@"should handle audio packets"); + + if (_state == 0) { + int serialno = ogg_page_serialno(&page); + ogg_stream_init(&_oggStreamState, serialno); + + status = ogg_stream_pagein(&_oggStreamState, &page); + if (status < 0) { + NSLog(@"Error reading first page of Ogg bitstream data."); + return FALSE; + } + + ogg_packet packet; + status = ogg_stream_packetout(&_oggStreamState, &packet); + if (status != 1) { + NSLog(@"Error reading initial header packet"); + return FALSE; + } + + status = vorbis_synthesis_headerin(&_vorbisInfo, &_vorbisComment, &packet); + if (status < 0) { + NSLog(@"This Ogg bitstream does not contain Vorbis"); + return FALSE; + } + + _state++; + + } + else if (_state > 0 && _state < 3) { + status = ogg_stream_pagein(&_oggStreamState, &page); + + int readcount = 0; + while (readcount < 2) { + ogg_packet packet; + status = ogg_stream_packetout(&_oggStreamState, &packet); + if (status == 0) + break; + + if (status != 1) { + NSLog(@"Corrupt secondary header."); + return FALSE; + } + + status = vorbis_synthesis_headerin(&_vorbisInfo, &_vorbisComment, &packet); + if (status < 0) { + NSLog(@"Corrupt secondary Vorbis header."); + return FALSE; + } + + readcount++; + } + + char **ptr=_vorbisComment.user_comments; + while(*ptr){ + fprintf(stderr,"%s\n",*ptr); + NSLog(@"%s", *ptr); + ++ptr; + } + + NSLog(@"Bitstream is %d channel, %ldHz", _vorbisInfo.channels, _vorbisInfo.rate); + NSLog(@"Encoded by: %s", _vorbisComment.vendor); + + // initialize vorbis + status = vorbis_synthesis_init(&_vorbisDspState, &_vorbisInfo); + NSAssert(status == 0, @"corrupt header during playback initialization"); + + vorbis_block_init(&_vorbisDspState, &_vorbisBlock); + + _state += readcount; + + [self.delegate handlePropertyChangeForFileStream:self fileStreamPropertyID:kAudioFileStreamProperty_DataFormat]; + [self.delegate handlePropertyChangeForFileStream:self fileStreamPropertyID:kAudioFileStreamProperty_ReadyToProducePackets]; + } + else if (_state == 3) { +#ifdef PROFILE_CODE + CPUTime starttime, endtime; + + get_cpu_time(&starttime, TRUE); +#endif + + ogg_int16_t convbuffer[4096]; + status = ogg_stream_pagein(&_oggStreamState, &page); + + while (1) { + ogg_packet packet; + status = ogg_stream_packetout(&_oggStreamState, &packet); + if (status == 0) { +// NSLog(@"bailing out loop"); + break; + } + + if (status < 0) { + NSLog(@"read audio packet error"); + } else { + if (vorbis_synthesis(&_vorbisBlock, &packet) == 0) { + vorbis_synthesis_blockin(&_vorbisDspState, &_vorbisBlock); + } + + float **pcm; + int samples; + while((samples=vorbis_synthesis_pcmout(&_vorbisDspState,&pcm))>0){ +// NSLog(@"found %d PCM samples", samples ); + + int bout=(samples<4096?samples:4096); + + for(int i=0;i<_vorbisInfo.channels;i++){ + ogg_int16_t *ptr=convbuffer+i; + float *mono=pcm[i]; + for(int j=0;j32767){ + val=32767; + } + if(val<-32768){ + val=-32768; + } + *ptr=val; + ptr+=_vorbisInfo.channels; + } + } + + UInt32 bytesLen = 2 * _vorbisInfo.channels * bout; + [self.delegate handleAudioPackets:convbuffer numberBytes:bytesLen numberPackets:0 packetDescriptions:NULL]; + + + vorbis_synthesis_read(&_vorbisDspState, bout); + +#ifdef PROFILE_CODE + _totalSamples += samples; +#endif + } + + } + } + + if (ogg_page_eos(&page)) { + NSLog(@"received EOS!"); + _state = 0; + } + +#ifdef PROFILE_CODE + get_cpu_time(&endtime, TRUE); + _totalCputimes += endtime.utime - starttime.utime; +#endif + + } + } + + return TRUE; +} + +- (BOOL) seekOffset:(SInt64)inAbsolutePacketOffset outOffset:(SInt64 *)outAbsoluteByteOffset flags:(UInt32 *)flags +{ +// OSStatus err; +// err = AudioFileStreamSeek(audioFileStream, inAbsolutePacketOffset, outAbsoluteByteOffset, flags); +// +// return err == 0; + return FALSE; +} + +- (void) close +{ + ogg_sync_clear(&_oggSyncState); + _state = 0; + +#ifdef PROFILE_CODE + NSLog(@"total samples %d total cputimes %g rate (samples per sec) %g", _totalSamples, _totalCputimes, + _totalSamples / _totalCputimes); + + _totalSamples = 0; + _totalCputimes = 0.0; +#endif +} + +- (SInt64) dataOffset +{ + return 0; +} + +- (UInt64) audioDataByteCount +{ + return 0; +} + +- (BOOL) getDataFormat:(AudioStreamBasicDescription *)dataFormat +{ + FillOutASBDForLPCM(*dataFormat, + _vorbisInfo.rate, // sample rate (fps) + _vorbisInfo.channels, // channels per frame + 16, // valid bits per channel + 16, // total bits per channel + false, // isFloat + false); // isBigEndian + + return TRUE; +} + +- (AudioFormatListItem *) getFormatListWithLen:(UInt32 *)formatListSize +{ + return NULL; +} + +- (UInt32) packetSizeUpperBound +{ + return 2048; +} + +- (UInt32) maxPacketSize +{ + return 2048; +} + +- (void *) getMagicCookieDataWithLen:(UInt32*)outCookieSize +{ + return NULL; +} + + + +@end diff --git a/Classes/cputime.c b/Classes/cputime.c new file mode 100644 index 0000000..d470ebd --- /dev/null +++ b/Classes/cputime.c @@ -0,0 +1,80 @@ +// +// cputime.c +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/24/13. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cputime.h" + +int get_cpu_time(CPUTime *rpd, boolean_t thread_only) +{ + task_t task; + kern_return_t error; + mach_msg_type_number_t count; + thread_array_t thread_table; + thread_basic_info_t thi; + thread_basic_info_data_t thi_data; + unsigned table_size; + struct task_basic_info ti; + + if (thread_only) { + // just get time of this thread + count = THREAD_BASIC_INFO_COUNT; + thi = &thi_data; + error = thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count); + rpd->utime = thi->user_time.seconds + thi->user_time.microseconds * 1e-6; + rpd->stime = thi->system_time.seconds + thi->system_time.microseconds * 1e-6; + return 0; + } + + + // get total time of the current process + + task = mach_task_self(); + count = TASK_BASIC_INFO_COUNT; + error = task_info(task, TASK_BASIC_INFO, (task_info_t)&ti, &count); +// assert(error == KERN_SUCCESS); + { /* calculate CPU times, adapted from top/libtop.c */ + unsigned i; + // the following times are for threads which have already terminated and gone away + rpd->utime = ti.user_time.seconds + ti.user_time.microseconds * 1e-6; + rpd->stime = ti.system_time.seconds + ti.system_time.microseconds * 1e-6; + error = task_threads(task, &thread_table, &table_size); +// assert(error == KERN_SUCCESS); + thi = &thi_data; + // for each active thread, add up thread time + for (i = 0; i != table_size; ++i) { + count = THREAD_BASIC_INFO_COUNT; + error = thread_info(thread_table[i], THREAD_BASIC_INFO, (thread_info_t)thi, &count); +// assert(error == KERN_SUCCESS); + if ((thi->flags & TH_FLAGS_IDLE) == 0) { + rpd->utime += thi->user_time.seconds + thi->user_time.microseconds * 1e-6; + rpd->stime += thi->system_time.seconds + thi->system_time.microseconds * 1e-6; + } + error = mach_port_deallocate(mach_task_self(), thread_table[i]); +// assert(error == KERN_SUCCESS); + } + error = vm_deallocate(mach_task_self(), (vm_offset_t)thread_table, table_size * sizeof(thread_array_t)); +// assert(error == KERN_SUCCESS); + } + if (task != mach_task_self()) { + mach_port_deallocate(mach_task_self(), task); +// assert(error == KERN_SUCCESS); + } + return 0; +} diff --git a/Classes/cputime.h b/Classes/cputime.h new file mode 100644 index 0000000..eaa9c2f --- /dev/null +++ b/Classes/cputime.h @@ -0,0 +1,26 @@ +// +// cputime.h +// iPhoneStreamingPlayer +// +// Created by Benny Khoo on 9/24/13. +// +// + +#ifndef iPhoneStreamingPlayer_cputime_h +#define iPhoneStreamingPlayer_cputime_h + +typedef struct { + double utime, stime; +} CPUTime; + +#ifdef __cplusplus +extern "C" { +#endif + + int get_cpu_time(CPUTime *rpd, boolean_t thread_only); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Classes/iPhoneStreamingPlayerViewController.m b/Classes/iPhoneStreamingPlayerViewController.m index 4c60558..b4741c0 100644 --- a/Classes/iPhoneStreamingPlayerViewController.m +++ b/Classes/iPhoneStreamingPlayerViewController.m @@ -107,7 +107,7 @@ - (void)createStreamer NSURL *url = [NSURL URLWithString:escapedValue]; streamer = [[AudioStreamer alloc] initWithURL:url]; - + progressUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 @@ -120,6 +120,11 @@ - (void)createStreamer selector:@selector(playbackStateChanged:) name:ASStatusChangedNotification object:streamer]; + + // saving url to defaults database + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults setObject:escapedValue forKey:@"savedUrl"]; + [defaults synchronize]; } // @@ -136,6 +141,12 @@ - (void)viewDidLoad MPVolumeView *volumeView = [[[MPVolumeView alloc] initWithFrame:volumeSlider.bounds] autorelease]; [volumeSlider addSubview:volumeView]; [volumeView sizeToFit]; + + // restore url from defaults database + NSString *savedUrl = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedUrl"]; + if (savedUrl != nil) { + downloadSourceField.text = savedUrl; + } [self setButtonImageNamed:@"playbutton.png"]; } @@ -262,29 +273,40 @@ - (void)playbackStateChanged:(NSNotification *)aNotification // - (void)updateProgress:(NSTimer *)updatedTimer { - if (streamer.bitRate != 0.0) - { - double progress = streamer.progress; - double duration = streamer.duration; - - if (duration > 0) - { - [positionLabel setText: - [NSString stringWithFormat:@"Time Played: %.1f/%.1f seconds", - progress, - duration]]; - [progressSlider setEnabled:YES]; - [progressSlider setValue:100 * progress / duration]; - } - else - { - [progressSlider setEnabled:NO]; - } - } - else - { - positionLabel.text = @"Time Played:"; - } + @try { + if (streamer.bitRate != 0.0) + { + double progress = streamer.progress; + double duration = streamer.duration; + + if (duration > 0) + { + [positionLabel setText: + [NSString stringWithFormat:@"Time Played: %.1f/%.1f seconds", + progress, + duration]]; + [progressSlider setEnabled:YES]; + [progressSlider setValue:100 * progress / duration]; + } + else + { + [progressSlider setEnabled:NO]; + } + } + else + { + positionLabel.text = @"Time Played:"; + } + + } + @catch (NSException *exception) { + [streamer stop]; + [streamer start]; + } + @finally { + ; + } + } // diff --git a/Frameworks/Ogg.framework/Headers/config_types.h b/Frameworks/Ogg.framework/Headers/config_types.h new file mode 100644 index 0000000..1e7d490 --- /dev/null +++ b/Frameworks/Ogg.framework/Headers/config_types.h @@ -0,0 +1,25 @@ +#ifndef __CONFIG_TYPES_H__ +#define __CONFIG_TYPES_H__ + +/* these are filled in by configure */ +#define INCLUDE_INTTYPES_H 1 +#define INCLUDE_STDINT_H 1 +#define INCLUDE_SYS_TYPES_H 1 + +#if INCLUDE_INTTYPES_H +# include +#endif +#if INCLUDE_STDINT_H +# include +#endif +#if INCLUDE_SYS_TYPES_H +# include +#endif + +typedef short ogg_int16_t; +typedef unsigned short ogg_uint16_t; +typedef int ogg_int32_t; +typedef unsigned int ogg_uint32_t; +typedef long long ogg_int64_t; + +#endif diff --git a/Frameworks/Ogg.framework/Headers/ogg.h b/Frameworks/Ogg.framework/Headers/ogg.h new file mode 100644 index 0000000..cea4ebe --- /dev/null +++ b/Frameworks/Ogg.framework/Headers/ogg.h @@ -0,0 +1,210 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel libogg include + last mod: $Id: ogg.h 18044 2011-08-01 17:55:20Z gmaxwell $ + + ********************************************************************/ +#ifndef _OGG_H +#define _OGG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef struct { + void *iov_base; + size_t iov_len; +} ogg_iovec_t; + +typedef struct { + long endbyte; + int endbit; + + unsigned char *buffer; + unsigned char *ptr; + long storage; +} oggpack_buffer; + +/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/ + +typedef struct { + unsigned char *header; + long header_len; + unsigned char *body; + long body_len; +} ogg_page; + +/* ogg_stream_state contains the current encode/decode state of a logical + Ogg bitstream **********************************************************/ + +typedef struct { + unsigned char *body_data; /* bytes from packet bodies */ + long body_storage; /* storage elements allocated */ + long body_fill; /* elements stored; fill mark */ + long body_returned; /* elements of fill returned */ + + + int *lacing_vals; /* The values that will go to the segment table */ + ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact + this way, but it is simple coupled to the + lacing fifo */ + long lacing_storage; + long lacing_fill; + long lacing_packet; + long lacing_returned; + + unsigned char header[282]; /* working space for header encode */ + int header_fill; + + int e_o_s; /* set when we have buffered the last packet in the + logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + long serialno; + long pageno; + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a separate abstraction + layer) also knows about the gap */ + ogg_int64_t granulepos; + +} ogg_stream_state; + +/* ogg_packet is used to encapsulate the data and metadata belonging + to a single raw Ogg/Vorbis packet *************************************/ + +typedef struct { + unsigned char *packet; + long bytes; + long b_o_s; + long e_o_s; + + ogg_int64_t granulepos; + + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a separate abstraction + layer) also knows about the gap */ +} ogg_packet; + +typedef struct { + unsigned char *data; + int storage; + int fill; + int returned; + + int unsynced; + int headerbytes; + int bodybytes; +} ogg_sync_state; + +/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ + +extern void oggpack_writeinit(oggpack_buffer *b); +extern int oggpack_writecheck(oggpack_buffer *b); +extern void oggpack_writetrunc(oggpack_buffer *b,long bits); +extern void oggpack_writealign(oggpack_buffer *b); +extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpack_reset(oggpack_buffer *b); +extern void oggpack_writeclear(oggpack_buffer *b); +extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpack_look(oggpack_buffer *b,int bits); +extern long oggpack_look1(oggpack_buffer *b); +extern void oggpack_adv(oggpack_buffer *b,int bits); +extern void oggpack_adv1(oggpack_buffer *b); +extern long oggpack_read(oggpack_buffer *b,int bits); +extern long oggpack_read1(oggpack_buffer *b); +extern long oggpack_bytes(oggpack_buffer *b); +extern long oggpack_bits(oggpack_buffer *b); +extern unsigned char *oggpack_get_buffer(oggpack_buffer *b); + +extern void oggpackB_writeinit(oggpack_buffer *b); +extern int oggpackB_writecheck(oggpack_buffer *b); +extern void oggpackB_writetrunc(oggpack_buffer *b,long bits); +extern void oggpackB_writealign(oggpack_buffer *b); +extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpackB_reset(oggpack_buffer *b); +extern void oggpackB_writeclear(oggpack_buffer *b); +extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpackB_look(oggpack_buffer *b,int bits); +extern long oggpackB_look1(oggpack_buffer *b); +extern void oggpackB_adv(oggpack_buffer *b,int bits); +extern void oggpackB_adv1(oggpack_buffer *b); +extern long oggpackB_read(oggpack_buffer *b,int bits); +extern long oggpackB_read1(oggpack_buffer *b); +extern long oggpackB_bytes(oggpack_buffer *b); +extern long oggpackB_bits(oggpack_buffer *b); +extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b); + +/* Ogg BITSTREAM PRIMITIVES: encoding **************************/ + +extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); +extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, + int count, long e_o_s, ogg_int64_t granulepos); +extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill); +extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill); + +/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ + +extern int ogg_sync_init(ogg_sync_state *oy); +extern int ogg_sync_clear(ogg_sync_state *oy); +extern int ogg_sync_reset(ogg_sync_state *oy); +extern int ogg_sync_destroy(ogg_sync_state *oy); +extern int ogg_sync_check(ogg_sync_state *oy); + +extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); +extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); +extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); +extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); +extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); +extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); + +/* Ogg BITSTREAM PRIMITIVES: general ***************************/ + +extern int ogg_stream_init(ogg_stream_state *os,int serialno); +extern int ogg_stream_clear(ogg_stream_state *os); +extern int ogg_stream_reset(ogg_stream_state *os); +extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); +extern int ogg_stream_destroy(ogg_stream_state *os); +extern int ogg_stream_check(ogg_stream_state *os); +extern int ogg_stream_eos(ogg_stream_state *os); + +extern void ogg_page_checksum_set(ogg_page *og); + +extern int ogg_page_version(const ogg_page *og); +extern int ogg_page_continued(const ogg_page *og); +extern int ogg_page_bos(const ogg_page *og); +extern int ogg_page_eos(const ogg_page *og); +extern ogg_int64_t ogg_page_granulepos(const ogg_page *og); +extern int ogg_page_serialno(const ogg_page *og); +extern long ogg_page_pageno(const ogg_page *og); +extern int ogg_page_packets(const ogg_page *og); + +extern void ogg_packet_clear(ogg_packet *op); + + +#ifdef __cplusplus +} +#endif + +#endif /* _OGG_H */ diff --git a/Frameworks/Ogg.framework/Headers/os_types.h b/Frameworks/Ogg.framework/Headers/os_types.h new file mode 100644 index 0000000..d6691b7 --- /dev/null +++ b/Frameworks/Ogg.framework/Headers/os_types.h @@ -0,0 +1,147 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + last mod: $Id: os_types.h 17712 2010-12-03 17:10:02Z xiphmont $ + + ********************************************************************/ +#ifndef _OS_TYPES_H +#define _OS_TYPES_H + +/* make it easy on the folks that want to compile the libs with a + different malloc than stdlib */ +#define _ogg_malloc malloc +#define _ogg_calloc calloc +#define _ogg_realloc realloc +#define _ogg_free free + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + typedef uint64_t ogg_uint64_t; +# elif defined(__MINGW32__) +# include + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + typedef unsigned long long ogg_uint64_t; +# elif defined(__MWERKS__) + typedef long long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; +# else + /* MSVC/Borland */ + typedef __int64 ogg_int64_t; + typedef __int32 ogg_int32_t; + typedef unsigned __int32 ogg_uint32_t; + typedef __int16 ogg_int16_t; + typedef unsigned __int16 ogg_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 ogg_int16_t; + typedef UInt16 ogg_uint16_t; + typedef SInt32 ogg_int32_t; + typedef UInt32 ogg_uint32_t; + typedef SInt64 ogg_int64_t; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined(__HAIKU__) + + /* Haiku */ +# include + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short ogg_int16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned ogg_uint32_t; + typedef short ogg_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef signed int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long int ogg_int64_t; + +#elif defined(__TMS320C6X__) + + /* TI C64x compiler */ + typedef signed short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef signed int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long int ogg_int64_t; + +#else + +# include + +#endif + +#endif /* _OS_TYPES_H */ diff --git a/Frameworks/Ogg.framework/Ogg b/Frameworks/Ogg.framework/Ogg new file mode 100644 index 0000000..9564a7c Binary files /dev/null and b/Frameworks/Ogg.framework/Ogg differ diff --git a/Frameworks/Oggz.framework/Headers/oggz.h b/Frameworks/Oggz.framework/Headers/oggz.h new file mode 100644 index 0000000..20c2322 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz.h @@ -0,0 +1,588 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_H__ +#define __OGGZ_H__ + +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \mainpage + * + * \section intro Oggz makes programming with Ogg easy! + * + * This is the documentation for the Oggz C API. Oggz provides a simple + * programming interface for reading and writing Ogg files and streams. + * Ogg is an interleaving data container developed by Monty + * at Xiph.Org, originally to + * support the Ogg Vorbis audio format. + * + * liboggz supports the flexibility afforded by the Ogg file format while + * presenting the following API niceties: + * + * - Strict adherence to the formatting requirements of Ogg + * \link basics bitstreams \endlink, to ensure that only valid bitstreams + * are generated + * - A simple, callback based open/read/close or open/write/close + * \link oggz.h interface \endlink to raw Ogg files + * - A customisable \link seek_api seeking \endlink abstraction for + * seeking on multitrack Ogg data + * - A packet queue for feeding incoming packets for writing, with callback + * based notification when this queue is empty + * - A means of overriding the \link oggz_io.h IO functions \endlink used by + * Oggz, for easier integration with media frameworks and similar systems. + * - A handy \link oggz_table.h table \endlink structure for storing + * information on each logical bitstream + * + * \subsection contents Contents + * + * - \link basics Basics \endlink: + * Information about Ogg required to understand liboggz + * + * - \link oggz.h oggz.h \endlink: + * Documentation of the Oggz C API + * + * - \link configuration Configuration \endlink: + * Customizing liboggz to only read or write. + * + * - \link building Building \endlink: + * Information related to building software that uses liboggz. + * + * \section Licensing + * + * liboggz is provided under the following BSD-style open source license: + * + * \include COPYING + * + */ + +/** \defgroup basics Ogg basics + * + * \section Scope + * + * This section provides a minimal introduction to Ogg concepts, covering + * only that which is required to use liboggz. + * + * For more detailed information, see the + * Ogg homepage + * or IETF RFC 3533 + * The Ogg File Format version 0. + * + * \section Terminology + * + * The monospace text below is quoted directly from RFC 3533. + * For each concept introduced, tips related to liboggz are provided + * in bullet points. + * + * \subsection bitstreams Physical and Logical Bitstreams + * + * The raw data of an Ogg stream, as read directly from a file or network + * socket, is called a physical bitstream. + * +
+   The result of an Ogg encapsulation is called the "Physical (Ogg)
+   Bitstream".  It encapsulates one or several encoder-created
+   bitstreams, which are called "Logical Bitstreams".  A logical
+   bitstream, provided to the Ogg encapsulation process, has a
+   structure, i.e., it is split up into a sequence of so-called
+   "Packets".  The packets are created by the encoder of that logical
+   bitstream and represent meaningful entities for that encoder only
+   (e.g., an uncompressed stream may use video frames as packets).
+
+ * + * \subsection pages Packets and Pages + * + * Within the Ogg format, packets are written into \a pages. You can think + * of pages like pages in a book, and packets as items of the actual text. + * Consider, for example, individual poems or short stories as the packets. + * Pages are of course all the same size, and a few very short packets could + * be written into a single page. On the other hand, a very long packet will + * use many pages. + * + * - liboggz handles the details of writing packets into pages, and of + * reading packets from pages; your application deals only with + * ogg_packet structures. + * - Each ogg_packet structure contains a block of data and its + * length in bytes, plus other information related to the stream structure + * as explained below. + * + * \subsection serialno + * + * Each logical bitstream is uniquely identified by a serial number or + * \a serialno. + * + * - Packets are always associated with a \a serialno. This is not actually + * part of the ogg_packet structure, so wherever you see an + * ogg_packet in the liboggz API, you will see an accompanying + * \a serialno. + * +
+   This unique serial number is created randomly and does not have any
+   connection to the content or encoder of the logical bitstream it
+   represents.
+
+ * + * - Use oggz_serialno_new() to generate a new serial number for each + * logical bitstream you write. + * - Use an \link oggz_table.h OggzTable \endlink, keyed by \a serialno, + * to store and retrieve data related to each logical bitstream. + * + * \subsection boseos b_o_s and e_o_s +
+   bos page: The initial page (beginning of stream) of a logical
+      bitstream which contains information to identify the codec type
+      and other decoding-relevant information.
+
+   eos page: The final page (end of stream) of a logical bitstream.
+
+ * + * - Every ogg_packet contains \a b_o_s and \a e_o_s flags. + * Of course each of these will be set only once per logical bitstream. + * See the Structuring section below for rules on setting \a b_o_s and + * \a e_o_s when interleaving logical bitstreams. + * - This documentation will refer to \a bos and \a eos packets + * (not pages) as that is more closely represented by the API. + * The \a bos packet is the only packet on the \a bos page, and the + * \a eos packet is the last packet on the \a eos page. + * + * \subsection granulepos +
+   granule position: An increasing position number for a specific
+      logical bitstream stored in the page header.  Its meaning is
+      dependent on the codec for that logical bitstream
+
+ * + * - Every ogg_packet contains a \a granulepos. The \a granulepos + * of each packet is used mostly for \link seek_api seeking. \endlink + * + * \section Structuring + * + * The general structure of an Ogg stream is governed by various rules. + * + * \subsection secondaries Secondary header packets + * + * Some data sources require initial setup information such as comments + * and codebooks to be present near the beginning of the stream (directly + * following the b_o_s packets. + * +
+   Ogg also allows but does not require secondary header packets after
+   the bos page for logical bitstreams and these must also precede any
+   data packets in any logical bitstream.  These subsequent header
+   packets are framed into an integral number of pages, which will not
+   contain any data packets.  So, a physical bitstream begins with the
+   bos pages of all logical bitstreams containing one initial header
+   packet per page, followed by the subsidiary header packets of all
+   streams, followed by pages containing data packets.
+
+ * + * - liboggz handles the framing of \a packets into low-level \a pages. To + * ensure that the pages used by secondary headers contain no data packets, + * set the \a flush parameter of oggz_write_feed() to \a OGGZ_FLUSH_AFTER + * when queueing the last of the secondary headers. + * - or, equivalently, set \a flush to \a OGGZ_FLUSH_BEFORE when queueing + * the first of the data packets. + * + * \subsection boseosseq Sequencing b_o_s and e_o_s packets + * + * The following rules apply for sequencing \a bos and \a eos packets in + * a physical bitstream: +
+   ... All bos pages of all logical bitstreams MUST appear together at
+   the beginning of the Ogg bitstream.
+
+   ... eos pages for the logical bitstreams need not all occur
+   contiguously.  Eos pages may be 'nil' pages, that is, pages
+   containing no content but simply a page header with position
+   information and the eos flag set in the page header.
+
+ * + * - oggz_write_feed() will fail with a return value of + * \a OGGZ_ERR_BOS if an attempt is made to queue a late \a bos packet + * + * \subsection interleaving Interleaving logical bitstreams +
+   It is possible to consecutively chain groups of concurrently
+   multiplexed bitstreams.  The groups, when unchained, MUST stand on
+   their own as a valid concurrently multiplexed bitstream.  The
+   following diagram shows a schematic example of such a physical
+   bitstream that obeys all the rules of both grouped and chained
+   multiplexed bitstreams.
+
+               physical bitstream with pages of
+          different logical bitstreams grouped and chained
+      -------------------------------------------------------------
+      |*A*|*B*|*C*|A|A|C|B|A|B|#A#|C|...|B|C|#B#|#C#|*D*|D|...|#D#|
+      -------------------------------------------------------------
+       bos bos bos             eos           eos eos bos       eos
+
+   In this example, there are two chained physical bitstreams, the first
+   of which is a grouped stream of three logical bitstreams A, B, and C.
+   The second physical bitstream is chained after the end of the grouped
+   bitstream, which ends after the last eos page of all its grouped
+   logical bitstreams.  As can be seen, grouped bitstreams begin
+   together - all of the bos pages MUST appear before any data pages.
+   It can also be seen that pages of concurrently multiplexed bitstreams
+   need not conform to a regular order.  And it can be seen that a
+   grouped bitstream can end long before the other bitstreams in the
+   group end.
+
+ * + * - oggz_write_feed() will fail, returning an explicit error value, if + * an attempt is made to queue a packet in violation of these rules. + * + * \section References + * + * This introduction to the Ogg format is derived from + * IETF RFC 3533 + * The Ogg File Format version 0 in accordance with the + * following copyright statement pertaining to the text of RFC 3533: + * +
+   Copyright (C) The Internet Society (2003).  All Rights Reserved.
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ * + */ + +/** \defgroup configuration Configuration + * \section configure ./configure + * + * It is possible to customize the functionality of liboggz + * by using various ./configure flags when + * building it from source. You can build a smaller + * version of liboggz to only read or write. + * By default, both reading and writing support is built. + * + * For general information about using ./configure, see the file + * \link install INSTALL \endlink + * + * \subsection no_encode Removing writing support + * + * Configuring with \a --disable-write will remove all support for writing: + * - All internal write related functions will not be built + * - Any attempt to call oggz_new(), oggz_open() or oggz_open_stdio() + * with \a flags == OGGZ_WRITE will fail, returning NULL + * - Any attempt to call oggz_write(), oggz_write_output(), oggz_write_feed(), + * oggz_write_set_hungry_callback(), or oggz_write_get_next_page_size() + * will return OGGZ_ERR_DISABLED + * + * \subsection no_decode Removing reading support + * + * Configuring with \a --disable-read will remove all support for reading: + * - All internal reading related functions will not be built + * - Any attempt to call oggz_new(), oggz_open() or oggz_open_stdio() + * with \a flags == OGGZ_READ will fail, returning NULL + * - Any attempt to call oggz_read(), oggz_read_input(), + * oggz_set_read_callback(), oggz_seek(), or oggz_seek_units() will return + * OGGZ_ERR_DISABLED + * + */ + +/** \defgroup install Installation + * \section install INSTALL + * + * \include INSTALL + */ + +/** \defgroup building Building against liboggz + * + * + * \section autoconf Using GNU autoconf + * + * If you are using GNU autoconf, you do not need to call pkg-config + * directly. Use the following macro to determine if liboggz is + * available: + * +
+ PKG_CHECK_MODULES(OGGZ, oggz >= 0.6.0,
+                   HAVE_OGGZ="yes", HAVE_OGGZ="no")
+ if test "x$HAVE_OGGZ" = "xyes" ; then
+   AC_SUBST(OGGZ_CFLAGS)
+   AC_SUBST(OGGZ_LIBS)
+ fi
+ 
+ * + * If liboggz is found, HAVE_OGGZ will be set to "yes", and + * the autoconf variables OGGZ_CFLAGS and OGGZ_LIBS will + * be set appropriately. + * + * \section pkg-config Determining compiler options with pkg-config + * + * If you are not using GNU autoconf in your project, you can use the + * pkg-config tool directly to determine the correct compiler options. + * +
+ OGGZ_CFLAGS=`pkg-config --cflags oggz`
+
+ OGGZ_LIBS=`pkg-config --libs oggz`
+ 
+ * + */ + +/** \file + * The liboggz C API. + * + * \section general Generic semantics + * + * All access is managed via an OGGZ handle. This can be instantiated + * in one of three ways: + * + * - oggz_open() - Open a full pathname + * - oggz_open_stdio() - Use an already opened FILE * + * - oggz_new() - Create an anonymous OGGZ object, which you can later + * handle via memory buffers + * + * To finish using an OGGZ handle, it should be closed with oggz_close(). + * + * \section reading Reading Ogg data + * + * To read from Ogg files or streams you must instantiate an OGGZ handle + * with flags set to OGGZ_READ, and provide an OggzReadPacket + * callback with oggz_set_read_callback(). + * See the \ref read_api section for details. + * + * \section writing Writing Ogg data + * + * To write to Ogg files or streams you must instantiate an OGGZ handle + * with flags set to OGGZ_WRITE, and provide an OggzWritePacket + * callback with oggz_set_write_callback(). + * See the \ref write_api section for details. + * + * \section seeking Seeking on Ogg data + * + * To seek while reading Ogg files or streams you must instantiate an OGGZ + * handle for reading, and ensure that an \link metric OggzMetric \endlink + * function is defined to translate packet positions into units such as time. + * See the \ref seek_api section for details. + * + * \section io Overriding the IO methods + * + * When an OGGZ handle is instantiated by oggz_open() or oggz_open_stdio(), + * Oggz uses stdio functions internally to access the raw data. However for + * some applications, the raw data cannot be accessed via stdio -- this + * commonly occurs when integrating with media frameworks. For such + * applications, you can provide Oggz with custom IO methods that it should + * use to access the raw data. Oggz will then use these custom methods, + * rather than using stdio methods, to access the raw data internally. + * + * For details, see \link oggz_io.h \endlink. + * + * \section headers Headers + * + * oggz.h provides direct access to libogg types such as ogg_packet, defined + * in . + */ + +/** + * An opaque handle to an Ogg file. This is returned by oggz_open() or + * oggz_new(), and is passed to all other oggz_* functions. + */ +typedef void OGGZ; + +/** + * Create a new OGGZ object + * \param flags OGGZ_READ or OGGZ_WRITE + * \returns A new OGGZ object + * \retval NULL on system error; check errno for details + */ +OGGZ * oggz_new (int flags); + +/** + * Open an Ogg file, creating an OGGZ handle for it + * \param filename The file to open + * \param flags OGGZ_READ or OGGZ_WRITE + * \return A new OGGZ handle + * \retval NULL System error; check errno for details + */ +OGGZ * oggz_open (const char * filename, int flags); + +/** + * Create an OGGZ handle associated with a stdio stream + * \param file An open FILE handle + * \param flags OGGZ_READ or OGGZ_WRITE + * \returns A new OGGZ handle + * \retval NULL System error; check errno for details + */ +OGGZ * oggz_open_stdio (FILE * file, int flags); + +/** + * Ensure any associated io streams are flushed. + * \param oggz An OGGZ handle + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_SYSTEM System error; check errno for details + */ +int oggz_flush (OGGZ * oggz); + +/** + * Run an OGGZ until completion, or error. + * This is a convenience function which repeatedly calls oggz_read() or + * oggz_write() as appropriate. + * For an OGGZ opened for reading, an OggzReadPacket or OggzReadPage callback + * should have been set before calling this function. + * For an OGGZ opened for writing, either an OggzHungry callback should have + * been set before calling this function, or you can use this function to + * write out all unwritten Ogg pages which are pending. + * \param oggz An OGGZ handle previously opened for either reading or writing + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_SYSTEM System error; check errno for details + * \retval OGGZ_ERR_STOP_OK Operation was stopped by a user callback + * returning OGGZ_STOP_OK + * \retval OGGZ_ERR_STOP_ERR Operation was stopped by a user callback + * returning OGGZ_STOP_ERR + * \retval OGGZ_ERR_RECURSIVE_WRITE Attempt to initiate writing from + * within an OggzHungry callback + */ +long oggz_run (OGGZ * oggz); + +/** + * Set the blocksize to use internally for oggz_run() + * \param oggz An OGGZ handle previously opened for either reading or writing + * \param blocksize The blocksize to use within oggz_run() + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Invalid blocksize (\a run_blocksize <= 0) + */ +int oggz_run_set_blocksize (OGGZ * oggz, long blocksize); + +/** + * Close an OGGZ handle + * \param oggz An OGGZ handle + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_SYSTEM System error; check errno for details + */ +int oggz_close (OGGZ * oggz); + +/** + * Determine if a given logical bitstream is at bos (beginning of stream). + * \param oggz An OGGZ handle + * \param serialno Identify a logical bitstream within \a oggz, or -1 to + * query if all logical bitstreams in \a oggz are at bos + * \retval 1 The given stream is at bos + * \retval 0 The given stream is not at bos + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + */ +int oggz_get_bos (OGGZ * oggz, long serialno); + +/** + * Determine if a given logical bitstream is at eos (end of stream). + * \param oggz An OGGZ handle + * \param serialno Identify a logical bitstream within \a oggz, or -1 to + * query if all logical bitstreams in \a oggz are at eos + * \retval 1 The given stream is at eos + * \retval 0 The given stream is not at eos + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + */ +int oggz_get_eos (OGGZ * oggz, long serialno); + +/** + * Query the number of tracks (logical bitstreams). When reading, this + * number is incremented every time a new track is found, so the returned + * value is only correct once the OGGZ is no longer at bos (beginning of + * stream): see oggz_get_bos() for determining this. + * \param oggz An OGGZ handle + * \return The number of tracks in OGGZ + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + */ +int oggz_get_numtracks (OGGZ * oggz); + +/** + * Request a new serialno, as required for a new stream, ensuring the serialno + * is not yet used for any other streams managed by this OGGZ. + * \param oggz An OGGZ handle + * \returns A new serialno, not already occuring in any logical bitstreams + * in \a oggz. + */ +long oggz_serialno_new (OGGZ * oggz); + +/** + * Return human-readable string representation of a content type + * + * \retval string the name of the content type + * \retval NULL \a content invalid + */ +const char * +oggz_content_type (OggzStreamContent content); + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif /* __OGGZ_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_comments.h b/Frameworks/Oggz.framework/Headers/oggz_comments.h new file mode 100644 index 0000000..b6ba0c6 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_comments.h @@ -0,0 +1,293 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_COMMENT_H__ +#define __OGGZ_COMMENT_H__ + +/** \file + * Reading of comments. + * + * Vorbis, Speex and Theora bitstreams + * use a comment format called "Vorbiscomment", defined + * here. + * Many standard comment names (such as TITLE, COPYRIGHT and GENRE) are + * defined in that document. + * + * The following general features of Vorbiscomment are relevant to this API: + * - Each stream has one comment packet, which occurs before any encoded + * audio data in the stream. + * - When reading, Oggz will decode the comment block before calling + * the second read() callback for each stream. Hence, retrieving comment + * data is possible once the read() callback has been called a second time. + * - When writing, Oggz allows you to set up the comments in memory, and + * provides a single function to generate a corresponding ogg_packet. + * It is your responsibility to then actually write that packet in sequence. + * + * Each comment block contains one Vendor string, which can be retrieved + * with oggz_comment_get_vendor(). + * + * The rest of a comment block consists of \a name = \a value pairs, with + * the following restrictions: + * - Both the \a name and \a value must be non-empty + * - The \a name is case-insensitive and must consist of ASCII within the + * range 0x20 to 0x7D inclusive, 0x3D ('=') excluded. + * - The \a name is not unique; multiple entries may exist with equivalent + * \a name within a Vorbiscomment block. + * - The \a value may be any UTF-8 string. + * + * \section comments_get Reading comments + * + * Oggz contains API methods to iterate through all comments associated + * with the logical bitstreams of an OGGZ* handle (oggz_comment_first() and + * oggz_comment_next(), and to iterate through comments matching a + * particular name (oggz_comment_first_byname() and + * oggz_comment_next_byname()). Given that multiple comments may exist + * with the same \a name, you should not use + * oggz_comment_first_byname() as a simple "get" function. + * + * \section comments_set Writing comments + * + * For writing, Oggz contains API methods for adding comments + * (oggz_comment_add() and oggz_comment_add_byname()), + * for removing comments + * (oggz_comment_remove() and oggz_comment_remove_byname()) + * and for setting the vendor string (oggz_comment_set_vendor()). + */ + +#include + +/** + * A comment. + */ +typedef struct { + /** The name of the comment, eg. "AUTHOR" */ + char * name; + + /** The value of the comment, as UTF-8 */ + char * value; +} OggzComment; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Retrieve the vendor string. + * \param oggz A OGGZ* handle + * \param serialno Identify a logical bitstream within \a oggz + * \returns A read-only copy of the vendor string. + * \retval NULL No vendor string is associated with \a oggz, + * or \a oggz is NULL, or \a serialno does not identify an + * existing logical bitstream in \a oggz. + */ +const char * +oggz_comment_get_vendor (OGGZ * oggz, long serialno); + +/** + * Set the vendor string + * \param oggz A OGGZ* handle + * \param serialno Identify a logical bitstream within \a oggz + * \param vendor_string The contents of the vendor string to add + * \retval 0 Success + * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + * \note The vendor string should identify the library used to produce + * the stream, e.g. libvorbis 1.0 used "Xiph.Org libVorbis I 20020717". + * If copying a bitstream it should be the same as the source. + */ +int +oggz_comment_set_vendor (OGGZ * oggz, long serialno, + const char * vendor_string); + +/** + * Retrieve the first comment. + * \param oggz A OGGZ* handle + * \param serialno Identify a logical bitstream within \a oggz + * \returns A read-only copy of the first comment. + * \retval NULL No comments exist for this OGGZ* object, or \a serialno + * does not identify an existing logical bitstream in \a oggz. + */ +const OggzComment * +oggz_comment_first (OGGZ * oggz, long serialno); + +/** + * Retrieve the next comment. + * \param oggz A OGGZ* handle + * \param serialno Identify a logical bitstream within \a oggz + * \param comment The previous comment. + * \returns A read-only copy of the comment immediately following the given + * comment. + * \retval NULL \a serialno does not identify an existing + * logical bitstream in \a oggz. + */ +const OggzComment * +oggz_comment_next (OGGZ * oggz, long serialno, const OggzComment * comment); + +/** + * Retrieve the first comment with a given name. + * \param oggz A OGGZ* handle + * \param serialno Identify a logical bitstream within \a oggz + * \param name the name of the comment to retrieve. + * \returns A read-only copy of the first comment matching the given \a name. + * \retval NULL No match was found, or \a serialno does not identify an + * existing logical bitstream in \a oggz. + * \note If \a name is NULL, the behaviour is the same as for + * oggz_comment_first() + */ +const OggzComment * +oggz_comment_first_byname (OGGZ * oggz, long serialno, char * name); + +/** + * Retrieve the next comment following and with the same name as a given + * comment. + * \param oggz A OGGZ* handle + * \param serialno Identify a logical bitstream within \a oggz + * \param comment A comment + * \returns A read-only copy of the next comment with the same name as + * \a comment. + * \retval NULL No further comments with the same name exist for this + * OGGZ* object, or \a serialno does not identify an existing + * logical bitstream in \a oggz. + */ +const OggzComment * +oggz_comment_next_byname (OGGZ * oggz, long serialno, + const OggzComment * comment); + +/** + * Add a comment + * \param oggz A OGGZ* handle (created with mode OGGZ_WRITE) + * \param serialno Identify a logical bitstream within \a oggz + * \param comment The comment to add + * \retval 0 Success + * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + */ +int +oggz_comment_add (OGGZ * oggz, long serialno, OggzComment * comment); + +/** + * Add a comment by name and value. + * \param oggz A OGGZ* handle (created with mode OGGZ_WRITE) + * \param serialno Identify a logical bitstream within \a oggz + * \param name The name of the comment to add + * \param value The contents of the comment to add + * \retval 0 Success + * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + */ +int +oggz_comment_add_byname (OGGZ * oggz, long serialno, + const char * name, const char * value); + +/** + * Remove a comment + * \param oggz A OGGZ* handle (created with OGGZ_WRITE) + * \param serialno Identify a logical bitstream within \a oggz + * \param comment The comment to remove. + * \retval 1 Success: comment removed + * \retval 0 No-op: comment not found, nothing to remove + * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + */ +int +oggz_comment_remove (OGGZ * oggz, long serialno, OggzComment * comment); + +/** + * Remove all comments with a given name. + * \param oggz A OGGZ* handle (created with OGGZ_WRITE) + * \param serialno Identify a logical bitstream within \a oggz + * \param name The name of the comments to remove + * \retval ">= 0" The number of comments removed + * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + */ +int +oggz_comment_remove_byname (OGGZ * oggz, long serialno, char * name); + +/** + * Output a comment packet for the specified stream + * \param oggz A OGGZ* handle (created with OGGZ_WRITE) + * \param serialno Identify a logical bitstream within \a oggz + * \param FLAC_final_metadata_block Set this to zero unless the packet_type is + * FLAC, and there are no further metadata blocks to follow. See note below + * for details. + * \returns A comment packet for the stream. When no longer needed it + * should be freed with oggz_packet_destroy(). + * \retval NULL content type does not support comments, not enough memory + * or comment was too long for FLAC + * \note FLAC streams may contain multiple metadata blocks of different types. + * When encapsulated in Ogg the first of these must be a Vorbis comment packet + * but PADDING, APPLICATION, SEEKTABLE, CUESHEET and PICTURE may follow. + * The last metadata block must have its first bit set to 1. Since liboggz does + * not know whether you will supply more metadata blocks you must tell it if + * this is the last (or only) metadata block by setting + * FLAC_final_metadata_block to 1. + * \n As FLAC metadata blocks are limited in size to 16MB minus 1 byte, this + * function will refuse to produce longer comment packets for FLAC. + * \n See http://flac.sourceforge.net/format.html for more details. + */ +ogg_packet * +oggz_comments_generate(OGGZ * oggz, long serialno, + int FLAC_final_metadata_block); + +/* + * Copy comments between two streams. + * \param src A OGGZ* handle + * \param src_serialno Identify a logical bitstream within \a src + * \param dest A OGGZ* handle (created with OGGZ_WRITE) + * \param dest_serialno Identify a logical bitstream within \a dest + * \retval OGGZ_ERR_BAD \a oggz is not a valid OGGZ* handle + * \retval OGGZ_ERR_INVALID Operation not suitable for \a dest + */ +int +oggz_comments_copy (OGGZ * src, long src_serialno, + OGGZ * dest, long dest_serialno); + +/** + * Free a packet and its payload. + * \param packet A packet previously returned from a function such + * as oggz_comment_generate(). User generated packets should not be passed. + */ +void oggz_packet_destroy (ogg_packet *packet); + +#ifdef __cplusplus +} +#endif + +#endif /* __OGGZ_COMMENTS_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_constants.h b/Frameworks/Oggz.framework/Headers/oggz_constants.h new file mode 100644 index 0000000..da553c6 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_constants.h @@ -0,0 +1,209 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_CONSTANTS_H__ +#define __OGGZ_CONSTANTS_H__ + +/** \file + * General constants used by liboggz. + */ + +/** + * Flags to oggz_new(), oggz_open(), and oggz_openfd(). + * Can be or'ed together in the following combinations: + * - OGGZ_READ | OGGZ_AUTO + * - OGGZ_WRITE | OGGZ_NONSTRICT | OGGZ_PREFIX | OGGZ_SUFFIX + */ +enum OggzFlags { + /** Read only */ + OGGZ_READ = 0x00, + + /** Write only */ + OGGZ_WRITE = 0x01, + + /** Disable strict adherence to mapping constraints, eg for + * handling an incomplete stream */ + OGGZ_NONSTRICT = 0x10, + + /** + * Scan for known headers while reading, and automatically set + * metrics appropriately. Opening a file for reading with + * \a flags = OGGZ_READ | OGGZ_AUTO will allow seeking on Speex, + * Vorbis, FLAC, Theora, CMML and all Annodex streams in units of + * milliseconds, once all bos pages have been delivered. */ + OGGZ_AUTO = 0x20, + + /** + * Write Prefix: Assume that we are only writing the prefix of an + * Ogg stream, ie. disable checking for conformance with end-of-stream + * constraints. + */ + OGGZ_PREFIX = 0x40, + + /** + * Write Suffix: Assume that we are only writing the suffix of an + * Ogg stream, ie. disable checking for conformance with + * beginning-of-stream constraints. + */ + OGGZ_SUFFIX = 0x80 + +}; + +enum OggzStopCtl { + /** Continue calling read callbacks */ + OGGZ_CONTINUE = 0, + + /** Stop calling callbacks, but retain buffered packet data */ + OGGZ_STOP_OK = 1, + + /** Stop calling callbacks, and purge buffered packet data */ + OGGZ_STOP_ERR = -1 +}; + +/** + * Flush options for oggz_write_feed; can be or'ed together + */ +enum OggzFlushOpts { + /** Flush all streams before beginning this packet */ + OGGZ_FLUSH_BEFORE = 0x01, + + /** Flush after this packet */ + OGGZ_FLUSH_AFTER = 0x02 +}; + +/** + * Definition of stream content types + */ +typedef enum OggzStreamContent { + OGGZ_CONTENT_THEORA = 0, + OGGZ_CONTENT_VORBIS, + OGGZ_CONTENT_SPEEX, + OGGZ_CONTENT_PCM, + OGGZ_CONTENT_CMML, + OGGZ_CONTENT_ANX2, + OGGZ_CONTENT_SKELETON, + OGGZ_CONTENT_FLAC0, + OGGZ_CONTENT_FLAC, + OGGZ_CONTENT_ANXDATA, + OGGZ_CONTENT_CELT, + OGGZ_CONTENT_KATE, + OGGZ_CONTENT_DIRAC, + OGGZ_CONTENT_UNKNOWN +} OggzStreamContent; + +/** + * Definitions of error return values + */ +enum OggzError { + /** No error */ + OGGZ_ERR_OK = 0, + + /** generic error */ + OGGZ_ERR_GENERIC = -1, + + /** oggz is not a valid OGGZ */ + OGGZ_ERR_BAD_OGGZ = -2, + + /** The requested operation is not suitable for this OGGZ */ + OGGZ_ERR_INVALID = -3, + + /** oggz contains no logical bitstreams */ + OGGZ_ERR_NO_STREAMS = -4, + + /** Operation is inappropriate for oggz in current bos state */ + OGGZ_ERR_BOS = -5, + + /** Operation is inappropriate for oggz in current eos state */ + OGGZ_ERR_EOS = -6, + + /** Operation requires a valid metric, but none has been set */ + OGGZ_ERR_BAD_METRIC = -7, + + /** System specific error; check errno for details */ + OGGZ_ERR_SYSTEM = -10, + + /** Functionality disabled at build time */ + OGGZ_ERR_DISABLED = -11, + + /** Seeking operation is not possible for this OGGZ */ + OGGZ_ERR_NOSEEK = -13, + + /** Reading was stopped by an OggzReadCallback returning OGGZ_STOP_OK + * or writing was stopped by an OggzWriteHungry callback returning + * OGGZ_STOP_OK */ + OGGZ_ERR_STOP_OK = -14, + + /** Reading was stopped by an OggzReadCallback returning OGGZ_STOP_ERR + * or writing was stopped by an OggzWriteHungry callback returning + * OGGZ_STOP_ERR */ + OGGZ_ERR_STOP_ERR = -15, + + /** no data available from IO, try again */ + OGGZ_ERR_IO_AGAIN = -16, + + /** Hole (sequence number gap) detected in input data */ + OGGZ_ERR_HOLE_IN_DATA = -17, + + /** Out of memory */ + OGGZ_ERR_OUT_OF_MEMORY = -18, + + /** The requested serialno does not exist in this OGGZ */ + OGGZ_ERR_BAD_SERIALNO = -20, + + /** Packet disallowed due to invalid byte length */ + OGGZ_ERR_BAD_BYTES = -21, + + /** Packet disallowed due to invalid b_o_s (beginning of stream) flag */ + OGGZ_ERR_BAD_B_O_S = -22, + + /** Packet disallowed due to invalid e_o_s (end of stream) flag */ + OGGZ_ERR_BAD_E_O_S = -23, + + /** Packet disallowed due to invalid granulepos */ + OGGZ_ERR_BAD_GRANULEPOS = -24, + + /** Packet disallowed due to invalid packetno */ + OGGZ_ERR_BAD_PACKETNO = -25, + + /** Comment violates VorbisComment restrictions */ + /* 129 == 0x81 is the frame marker for Theora's comments page ;-) */ + OGGZ_ERR_COMMENT_INVALID = -129, + + /** Guard provided by user has non-zero value */ + OGGZ_ERR_BAD_GUARD = -210, + + /** Attempt to call oggz_write() or oggz_write_output() from within + * a hungry() callback */ + OGGZ_ERR_RECURSIVE_WRITE = -266 +}; + +#endif /* __OGGZ_CONSTANTS_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_deprecated.h b/Frameworks/Oggz.framework/Headers/oggz_deprecated.h new file mode 100644 index 0000000..08434cb --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_deprecated.h @@ -0,0 +1,127 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_DEPRECATED_H__ +#define __OGGZ_DEPRECATED_H__ + +/** \file + * Deprecated interfaces + */ + +/** + * DEPRECATED CONSTANT. + * OGGZ_ERR_USER_STOPPED was introduced during development (post 0.8.3), + * and is similar in functionality to and numerically equal to (ie. ABI + * compatible with) OGGZ_ERR_STOP_OK in . + * It was badly named, as the preferred functionality distinguishes between + * a user's OggzReadCallback returning OGGZ_STOP_OK or OGGZ_STOP_ERR; your + * code should distinguish between these two too :-) Hence, don't use this + * (unreleased) name in new code. + */ +#define OGGZ_ERR_USER_STOPPED OGGZ_ERR_STOP_OK + +/** + * DEPRECATED CONSTANT. + * OGGZ_ERR_READ_STOP_OK, OGGZ_ERR_READ_STOP_ERR were introduced to allow + * the user to differentiate between a cancelled oggz_read_*() returning + * due to error or an ok condition. + * From 0.9.4 similar functionality was added for oggz_write_*(), hence this + * constant was renamed. + */ +#define OGGZ_ERR_READ_STOP_OK OGGZ_ERR_STOP_OK + +/** + * DEPRECATED CONSTANT. + * OGGZ_ERR_READ_STOP_OK, OGGZ_ERR_READ_STOP_ERR were introduced to allow + * the user to differentiate between a cancelled oggz_read_*() returning + * due to error or an ok condition. + * From 0.9.4 similar functionality was added for oggz_write_*(), hence this + * constant was renamed. + */ +#define OGGZ_ERR_READ_STOP_ERR OGGZ_ERR_STOP_ERR + +/** + * DEPRECATED FUNCTION + * This function has been replaced with the more clearly named + * oggz_set_granulerate(). + * Specify that a logical bitstream has a linear metric + * \param oggz An OGGZ handle + * \param serialno Identify the logical bitstream in \a oggz to attach + * this linear metric to. A value of -1 indicates that the metric should + * be attached to all unattached logical bitstreams in \a oggz. + * \param granule_rate_numerator The numerator of the granule rate + * \param granule_rate_denominator The denominator of the granule rate + * \returns 0 Success + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + */ +int oggz_set_metric_linear (OGGZ * oggz, long serialno, + ogg_int64_t granule_rate_numerator, + ogg_int64_t granule_rate_denominator); + +/** + * DEPRECATED FUNCTION + * This function has been replaced with oggz_comments_generate(), which + * does not require the packet_type argument. Instead, the packet type is + * determined by the content type of the stream, which was discovered when + * the bos packet was passed to oggz_write_feed. + * + * Output a comment packet for the specified stream. + * \param oggz A OGGZ* handle (created with OGGZ_WRITE) + * \param serialno Identify a logical bitstream within \a oggz + * \param packet_type Type of comment packet to generate, + * FLAC, OggPCM, Speex, Theora and Vorbis are supported + * \param FLAC_final_metadata_block Set this to zero unless the packet_type is + * FLAC, and there are no further metadata blocks to follow. See note below + * for details. + * \returns A comment packet for the stream. When no longer needed it + * should be freed with oggz_packet_destroy(). + * \retval NULL content type does not support comments, not enough memory + * or comment was too long for FLAC + * \note FLAC streams may contain multiple metadata blocks of different types. + * When encapsulated in Ogg the first of these must be a Vorbis comment packet + * but PADDING, APPLICATION, SEEKTABLE, CUESHEET and PICTURE may follow. + * The last metadata block must have its first bit set to 1. Since liboggz does + * not know whether you will supply more metadata blocks you must tell it if + * this is the last (or only) metadata block by setting + * FLAC_final_metadata_block to 1. + * \n As FLAC metadata blocks are limited in size to 16MB minus 1 byte, this + * function will refuse to produce longer comment packets for FLAC. + * \n See http://flac.sourceforge.net/format.html for more details. + */ +ogg_packet * +oggz_comment_generate(OGGZ * oggz, long serialno, + OggzStreamContent packet_type, + int FLAC_final_metadata_block); + +#endif /* __OGGZ_DEPRECATED_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_io.h b/Frameworks/Oggz.framework/Headers/oggz_io.h new file mode 100644 index 0000000..116fb49 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_io.h @@ -0,0 +1,236 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_IO_H__ +#define __OGGZ_IO_H__ + +/** \file + * Overriding the functions used for input and output of raw data. + * + * OggzIO provides a way of overriding the functions Oggz uses to access + * its raw input or output data. This is required in many situations where + * the raw stream cannot be accessed via stdio, but can be accessed by + * other means. This is typically useful within media frameworks, where + * accessing and moving around in the data is possible only using methods + * provided by the framework. + * + * The functions you provide for overriding IO will be used by Oggz + * whenever you call oggz_read() or oggz_write(). They will also be + * used repeatedly by Oggz when you call oggz_seek(). + * + * \note Opening a file with oggz_open() or oggz_open_stdio() is equivalent + * to calling oggz_new() and setting stdio based functions for data IO. + */ + +/** + * This is the signature of a function which you provide for Oggz + * to call when it needs to acquire raw input data. + * + * \param user_handle A generic pointer you have provided earlier + * \param n The length in bytes that Oggz wants to read + * \param buf The buffer that you read data into + * \retval "> 0" The number of bytes successfully read into the buffer + * \retval 0 to indicate that there is no more data to read (End of file) + * \retval "< 0" An error condition + */ +typedef size_t (*OggzIORead) (void * user_handle, void * buf, size_t n); + +/** + * This is the signature of a function which you provide for Oggz + * to call when it needs to output raw data. + * + * \param user_handle A generic pointer you have provided earlier + * \param n The length in bytes of the data + * \param buf A buffer containing data to write + * \retval ">= 0" The number of bytes successfully written (may be less than + * \a n if a write error has occurred) + * \retval "< 0" An error condition + */ +typedef size_t (*OggzIOWrite) (void * user_handle, void * buf, size_t n); + +/** + * This is the signature of a function which you provide for Oggz + * to call when it needs to seek on the raw input or output data. + * + * \param user_handle A generic pointer you have provided earlier + * \param offset The offset in bytes to seek to + * \param whence SEEK_SET, SEEK_CUR or SEEK_END (as for stdio.h) + * \retval ">= 0" The offset seeked to + * \retval "< 0" An error condition + * + * \note If you provide an OggzIOSeek function, you MUST also provide + * an OggzIOTell function, or else all your seeks will fail. + */ +typedef int (*OggzIOSeek) (void * user_handle, long offset, int whence); + +/** + * This is the signature of a function which you provide for Oggz + * to call when it needs to determine the current offset of the raw + * input or output data. + * + * \param user_handle A generic pointer you have provided earlier + * \retval ">= 0" The offset + * \retval "< 0" An error condition + */ +typedef long (*OggzIOTell) (void * user_handle); + +/** + * This is the signature of a function which you provide for Oggz + * to call when it needs to flush the output data. The behaviour + * of this function is similar to that of fflush() in stdio. + * + * \param user_handle A generic pointer you have provided earlier + * \retval 0 Success + * \retval "< 0" An error condition + */ +typedef int (*OggzIOFlush) (void * user_handle); + + +/** + * Set a function for Oggz to call when it needs to read input data. + * + * \param oggz An OGGZ handle + * \param read Your reading function + * \param user_handle Any arbitrary data you wish to pass to the function + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not + * open for reading. + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + */ +int oggz_io_set_read (OGGZ * oggz, OggzIORead read, void * user_handle); + +/** + * Retrieve the user_handle associated with the function you have provided + * for reading input data. + * + * \param oggz An OGGZ handle + * \returns the associated user_handle + */ +void * oggz_io_get_read_user_handle (OGGZ * oggz); + +/** + * Set a function for Oggz to call when it needs to write output data. + * + * \param oggz An OGGZ handle + * \param write Your writing function + * \param user_handle Any arbitrary data you wish to pass to the function + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not + * open for writing. + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + */ +int oggz_io_set_write (OGGZ * oggz, OggzIOWrite write, void * user_handle); + +/** + * Retrieve the user_handle associated with the function you have provided + * for writing output data. + * + * \param oggz An OGGZ handle + * \returns the associated user_handle + */ +void * oggz_io_get_write_user_handle (OGGZ * oggz); + +/** + * Set a function for Oggz to call when it needs to seek on its raw data. + * + * \param oggz An OGGZ handle + * \param seek Your seeking function + * \param user_handle Any arbitrary data you wish to pass to the function + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + * + * \note If you provide an OggzIOSeek function, you MUST also provide + * an OggzIOTell function, or else all your seeks will fail. + */ +int oggz_io_set_seek (OGGZ * oggz, OggzIOSeek seek, void * user_handle); + +/** + * Retrieve the user_handle associated with the function you have provided + * for seeking on input or output data. + * + * \param oggz An OGGZ handle + * \returns the associated user_handle + */ +void * oggz_io_get_seek_user_handle (OGGZ * oggz); + +/** + * Set a function for Oggz to call when it needs to determine the offset + * within its input data (if OGGZ_READ) or output data (if OGGZ_WRITE). + * + * \param oggz An OGGZ handle + * \param tell Your tell function + * \param user_handle Any arbitrary data you wish to pass to the function + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + */ +int oggz_io_set_tell (OGGZ * oggz, OggzIOTell tell, void * user_handle); + +/** + * Retrieve the user_handle associated with the function you have provided + * for determining the current offset in input or output data. + * + * \param oggz An OGGZ handle + * \returns the associated user_handle + */ +void * oggz_io_get_tell_user_handle (OGGZ * oggz); + +/** + * Set a function for Oggz to call when it needs to flush its output. The + * meaning of this is similar to that of fflush() in stdio. + * + * \param oggz An OGGZ handle + * \param flush Your flushing function + * \param user_handle Any arbitrary data you wish to pass to the function + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not + * open for writing. + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + */ +int oggz_io_set_flush (OGGZ * oggz, OggzIOFlush flush, void * user_handle); + +/** + * Retrieve the user_handle associated with the function you have provided + * for flushing output. + * + * \param oggz An OGGZ handle + * \returns the associated user_handle + */ +void * oggz_io_get_flush_user_handle (OGGZ * oggz); + +#endif /* __OGGZ_IO_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_off_t.h b/Frameworks/Oggz.framework/Headers/oggz_off_t.h new file mode 100644 index 0000000..0a89f83 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_off_t.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2007 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_OFF_T_H__ +#define __OGGZ_OFF_T_H__ + +/** \file + * Architecture-dependent type and printf format for file position. + * Allows Large File Sizes on systems supporting 64-bit off_t types. + */ + +#ifdef _WIN32 + /* MSVC/Borland & Cygwin */ + typedef off_t oggz_off_t; + +#define PRI_OGGZ_OFF_T "l" + +#else +#include +#endif + +#endif /* __OGGZ_OFF_T__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_off_t_generated.h b/Frameworks/Oggz.framework/Headers/oggz_off_t_generated.h new file mode 100644 index 0000000..45c74c4 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_off_t_generated.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2007 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_OFF_T_GENERATED_H__ +#define __OGGZ_OFF_T_GENERATED_H__ + +/** \file + * Architecture-dependent type for oggz_off_t. + * + * This file should never be included directly by user code. Please include + * either of or instead. + * + * This file was generated when liboggz was built. + * + * Note that this file is only generated when using GNU autoconf. + * This file is not used on Win32 systems. + */ + +/** + * This typedef was determined on the system on which the documentation + * was generated. + * + * To query this on your system, do eg. + * +
+   echo "gcc -E oggz.h | grep oggz_off_t
+ 
+ * + */ + +#include + +typedef off_t oggz_off_t; + +#define PRI_OGGZ_OFF_T "ll" + +#endif /* __OGGZ_OFF_T_GENERATED__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_packet.h b/Frameworks/Oggz.framework/Headers/oggz_packet.h new file mode 100644 index 0000000..1e2c330 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_packet.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 2009 Annodex Association + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Annodex Association nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ASSOCIATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_PACKET_H__ +#define __OGGZ_PACKET_H__ + +/** \file + * Packet positioning + * + * oggz_packet derives from ogg_packet, and includes position information. + */ + +/************************************************************ + * OggzPacket + */ + +/** + * The position of an oggz_packet. + */ +typedef struct { + /** + * Granulepos calculated by inspection of codec data. + * -1 if unknown + */ + ogg_int64_t calc_granulepos; + + /** + * Byte offset of the start of the page on which this + * packet begins. + */ + oggz_off_t begin_page_offset; + + /** + * Byte offset of the start of the page on which this + * packet ends. + */ + oggz_off_t end_page_offset; + + /** Number of pages this packet spans. */ + int pages; + + /** + * Index into begin_page's lacing values + * for the segment that begins this packet. + * NB. if begin_page is continued then the first + * of these packets will not be reported by + * ogg_sync_packetout() after a seek. + * -1 if unknown. + */ + int begin_segment_index; +} oggz_position; + +/** + * An ogg_packet and its position in the stream. + */ +typedef struct { + /** The ogg_packet structure, defined in */ + ogg_packet op; + + /** Its position */ + oggz_position pos; +} oggz_packet; + +#endif /* __OGGZ_PACKET_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_read.h b/Frameworks/Oggz.framework/Headers/oggz_read.h new file mode 100644 index 0000000..80416f5 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_read.h @@ -0,0 +1,238 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_READ_H__ +#define __OGGZ_READ_H__ + +/** \file + * Interfaces for reading Ogg files and streams + */ + +#include + +/** \defgroup read_api Oggz Read API + * + * Oggz parses Ogg bitstreams, forming ogg_packet structures, and calling + * your OggzReadPacket callback(s). + * + * You provide Ogg data to Oggz with oggz_read() or oggz_read_input(), and + * independently process it in OggzReadPacket callbacks. + * It is possible to set a different callback per \a serialno (ie. for each + * logical bitstream in the Ogg bitstream - see the \ref basics section for + * more detail). + * + * When using an OGGZ* opened with the OGGZ_AUTO flag set, Oggz will + * internally calculate the granulepos for each packet, even though these + * are not all recorded in the file: only the last packet ending on a page + * will have its granulepos recorded in the page header. + * Within a OggzReadPacket callback, calling oggz_tell_granulepos() will + * retrieve the calculated granulepos. + * + * See \ref seek_api for information on seeking on interleaved Ogg data, + * and for working with calculated granulepos values. + * + * \{ + */ + +/** + * This is the signature of a callback which you must provide for Oggz + * to call whenever it finds a new packet in the Ogg stream associated + * with \a oggz. + * + * \param oggz The OGGZ handle + * \param packet The packet, including its position in the stream. + * \param serialno Identify the logical bistream in \a oggz that contains + * \a packet + * \param user_data A generic pointer you have provided earlier + * \returns 0 to continue, non-zero to instruct Oggz to stop. + * + * \note It is possible to provide different callbacks per logical + * bitstream -- see oggz_set_read_callback() for more information. + */ +typedef int (*OggzReadPacket) (OGGZ * oggz, oggz_packet * packet, long serialno, + void * user_data); + +/** + * Set a callback for Oggz to call when a new Ogg packet is found in the + * stream. + * + * \param oggz An OGGZ handle previously opened for reading + * \param serialno Identify the logical bitstream in \a oggz to attach + * this callback to, or -1 to attach this callback to all unattached + * logical bitstreams in \a oggz. + * \param read_packet Your callback function + * \param user_data Arbitrary data you wish to pass to your callback + * \retval 0 Success + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + * + * \note Values of \a serialno other than -1 allows you to specify different + * callback functions for each logical bitstream. + * + * \note It is safe to call this callback from within an OggzReadPacket + * function, in order to specify that subsequent packets should be handled + * by a different OggzReadPacket function. + */ +int oggz_set_read_callback (OGGZ * oggz, long serialno, + OggzReadPacket read_packet, void * user_data); + +/** + * This is the signature of a callback which you must provide for Oggz + * to call whenever it finds a new page in the Ogg stream associated + * with \a oggz. + * + * \param oggz The OGGZ handle + * \param op The full ogg_page (see ) + * \param user_data A generic pointer you have provided earlier + * \returns 0 to continue, non-zero to instruct Oggz to stop. + */ +typedef int (*OggzReadPage) (OGGZ * oggz, const ogg_page * og, + long serialno, void * user_data); + +/** + * Set a callback for Oggz to call when a new Ogg page is found in the + * stream. + * + * \param oggz An OGGZ handle previously opened for reading + * \param serialno Identify the logical bitstream in \a oggz to attach + * this callback to, or -1 to attach this callback to all unattached + * logical bitstreams in \a oggz. + * \param read_page Your OggzReadPage callback function + * \param user_data Arbitrary data you wish to pass to your callback + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + * + * \note Values of \a serialno other than -1 allows you to specify different + * callback functions for each logical bitstream. + * + * \note It is safe to call this callback from within an OggzReadPage + * function, in order to specify that subsequent pages should be handled + * by a different OggzReadPage function. + */ +int oggz_set_read_page (OGGZ * oggz, long serialno, + OggzReadPage read_page, void * user_data); + + +/** + * Read n bytes into \a oggz, calling any read callbacks on the fly. + * \param oggz An OGGZ handle previously opened for reading + * \param n A count of bytes to ingest + * \retval "> 0" The number of bytes successfully ingested. + * \retval 0 End of file + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_SYSTEM System error; check errno for details + * \retval OGGZ_ERR_STOP_OK Reading was stopped by a user callback + * returning OGGZ_STOP_OK + * \retval OGGZ_ERR_STOP_ERR Reading was stopped by a user callback + * returning OGGZ_STOP_ERR + * \retval OGGZ_ERR_HOLE_IN_DATA Hole (sequence number gap) detected in input data + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + */ +long oggz_read (OGGZ * oggz, long n); + +/** + * Input data into \a oggz. + * \param oggz An OGGZ handle previously opened for reading + * \param buf A memory buffer + * \param n A count of bytes to input + * \retval "> 0" The number of bytes successfully ingested. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_STOP_OK Reading was stopped by a user callback + * returning OGGZ_STOP_OK + * \retval OGGZ_ERR_STOP_ERR Reading was stopped by a user callback + * returning OGGZ_STOP_ERR + * \retval OGGZ_ERR_HOLE_IN_DATA Hole (sequence number gap) detected in input data + * \retval OGGZ_ERR_OUT_OF_MEMORY Out of memory + */ +long oggz_read_input (OGGZ * oggz, unsigned char * buf, long n); + +/** \} + */ + +/** + * Erase any input buffered in Oggz. This discards any input read from the + * underlying IO system but not yet delivered as ogg_packets. + * + * \param oggz An OGGZ handle + * \retval 0 Success + * \retval OGGZ_ERR_SYSTEM Error seeking on underlying IO. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + */ +int oggz_purge (OGGZ * oggz); + +/** + * Determine the content type of the oggz stream referred to by \a serialno + * + * \param oggz An OGGZ handle + * \param serialno An ogg stream serialno + * \retval OGGZ_CONTENT_THEORA..OGGZ_CONTENT_UNKNOWN content successfully + * identified + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not refer to an existing + * stream + */ +OggzStreamContent oggz_stream_get_content (OGGZ * oggz, long serialno); + +/** + * Return human-readable string representation of content type of oggz stream + * referred to by \a serialno + * + * \param oggz An OGGZ handle + * \param serialno An ogg stream serialno + * \retval string the name of the content type + * \retval NULL \a oggz or \a serialno invalid + */ +const char * oggz_stream_get_content_type (OGGZ *oggz, long serialno); + +/** + * Determine the number of headers of the oggz stream referred to by + * \a serialno + * + * \param oggz An OGGZ handle + * \param serialno An ogg stream serialno + * \retval OGGZ_CONTENT_THEORA..OGGZ_CONTENT_UNKNOWN content successfully + * identified + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not refer to an existing + * stream + */ +int oggz_stream_get_numheaders (OGGZ * oggz, long serialno); + +#endif /* __OGGZ_READ_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_seek.h b/Frameworks/Oggz.framework/Headers/oggz_seek.h new file mode 100644 index 0000000..1801236 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_seek.h @@ -0,0 +1,497 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_SEEK_H__ +#define __OGGZ_SEEK_H__ + +/** \file + * Seeking within files + */ + +/** \defgroup seek_api Oggz Seek API + * + * Oggz can seek on multitrack, multicodec bitstreams. + * + * \section seek_time Time seeking + * + * Support is built-in for seeking to time positions in + * CELT, + * CMML. + * FLAC, + * OggPCM, + * Speex, + * Theora + * and Vorbis. + * Oggz is also compatible with + * Annodex streams, and supports seeking + * on all tracks described in an + * Ogg Skeleton track. + * + * You need to open the file with the OGGZ_AUTO flag set: + * + * - Create an OGGZ handle for reading with \a flags = OGGZ_READ | OGGZ_AUTO + * - Read data, ensuring that you have received all b_o_s pages before + * attempting to seek. + * + * Oggz will silently parse known codec headers and associate metrics + * appropriately; if you attempt to seek before you have received all + * b_o_s pages, Oggz will not have had a chance to parse the codec headers + * and associate metrics. + * It is safe to seek once you have received a packet with \a b_o_s == 0; + * see the \link basics Ogg basics \endlink section for more details. + * + * \note Oggz parses these codec headers internally, and so liboggz is \b not + * linked to libspeex, libvorbis, libflac, libtheora, libcmml or libannodex. + * + * For other data streams, you will need to provide a metric function; + * see the section on \link metric Using OggzMetrics \endlink for details + * of setting up and seeking with metrics. + * + * \section seek_bytes Byte seeking + * + * oggz_seek() provides low-level seeking to byte positions. + * + * \section seek_info More detail + * + * For a full description of the seeking methods possible in Ogg, see + * \link seek_semantics Semantics of seeking in Ogg bitstreams \endlink. + * + * \{ + */ + +/** + * Query the current offset in milliseconds, or custom units as + * specified by a Metric function you have provided. + * \param oggz An OGGZ handle + * \returns the offset in milliseconds, or custom units + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + */ +ogg_int64_t oggz_tell_units (OGGZ * oggz); + +/** + * Seek to an offset in milliseconds, or custom units as specified + * by a Metric function you have provided. + * \param oggz An OGGZ handle + * \param units A number of milliseconds, or custom units + * \param whence As defined in : SEEK_SET, SEEK_CUR or SEEK_END + * \returns the new file offset, or -1 on failure. + */ +ogg_int64_t oggz_seek_units (OGGZ * oggz, ogg_int64_t units, int whence); + +/** + * Provide the exact stored granulepos (from the page header) if relevant to + * the current packet, or a constructed granulepos if the stored granulepos + * does not belong to this packet, or -1 if this codec does not have support + * for granulepos interpolation + * \param oggz An OGGZ handle + * \returns the granulepos of the \a current packet (if available) + */ +ogg_int64_t +oggz_tell_granulepos (OGGZ * oggz); + +/** + * Query the file offset in bytes corresponding to the data read. + * \param oggz An OGGZ handle + * \returns The current offset of oggz. + * + * \note When reading, the value returned by oggz_tell() reflects the + * data offset of the start of the most recent packet processed, so that + * when called from an OggzReadPacket callback it reflects the byte + * offset of the start of the packet. As Oggz may have internally read + * ahead, this may differ from the current offset of the associated file + * descriptor. + */ +oggz_off_t oggz_tell (OGGZ * oggz); + +/** + * Seek to a specific byte offset + * \param oggz An OGGZ handle + * \param offset a byte offset + * \param whence As defined in : SEEK_SET, SEEK_CUR or SEEK_END + * \returns the new file offset, or -1 on failure. + */ +oggz_off_t oggz_seek (OGGZ * oggz, oggz_off_t offset, int whence); + +#ifdef _UNIMPLEMENTED +long oggz_seek_packets (OGGZ * oggz, long serialno, long packets, int whence); +#endif + +/** \} + */ + +/** \defgroup seek_semantics Semantics of seeking in Ogg bitstreams + * + * \section seek_semantics_intro Introduction + * + * [*** This line works around a bug in doxygen ***] + * + * [*** This line works around a bug in doxygen ***] + * + * The seeking semantics of the Ogg file format were outlined by Monty in + * a + * post to theora-dev in September 2002. Quoting from that post, we + * have the following assumptions: + * + * - Ogg is not a non-linear format. ... It is a media transport format + * designed to do nothing more than deliver content, in a stream, and + * have all the pieces arrive on time and in sync. + * - The Ogg layer does not know the specifics of the codec data it's + * multiplexing into a stream. It knows nothing beyond 'Oooo, packets!', + * that the packets belong to different buckets, that the packets go in + * order, and that packets have position markers. Ogg does not even have + * a concept of 'time'; it only knows about the sequentially increasing, + * unitless position markers. It is up to higher layers which have + * access to the codec APIs to assign and convert units of framing or + * time. + * + * (For more details on the structure of Ogg streams, see the + * \link basics Ogg Basics \endlink section). + * + * For data such as media, for which it is possible to provide a mapping + * such as 'time', Oggz can efficiently navigate through an Ogg stream + * by use of an OggzMetric callback, thus allowing automatic seeking to + * points in 'time'. + * + * For common codecs you can ask Oggz to set this for you automatically by + * instantiating the OGGZ handle with the OGGZ_AUTO flag set. For others + * you can specify a multiplier with oggz_set_metric_linear(), or a generic + * non-linear metric with oggz_set_metric(). + * + */ + +/** \defgroup metric Using OggzMetric + * + * \section metric_intro Introduction + * + * An OggzMetric is a helper function for Oggz's seeking mechanism. + * + * If every position in an Ogg stream can be described by a metric such as + * time, then it is possible to define a function that, given a serialno and + * granulepos, returns a measurement in units such as milliseconds. Oggz + * will use this function repeatedly while seeking in order to navigate + * through the Ogg stream. + * + * The meaning of the units is arbitrary, but must be consistent across all + * logical bitstreams. This allows Oggz to seek accurately through Ogg + * bitstreams containing multiple logical bitstreams such as tracks of media. + * + * \section setting How to set metrics + * + * You don't need to set metrics for Speex, Vorbis, FLAC, Theora, CMML or + * Annodex. + * These can be handled \link seek_api automatically \endlink by Oggz. + * + * For most others it is simply a matter of providing a "granulerate": + * a frame or sampling rate, if each packet's granulepos represents a + * sample number. + * + * - Set the \a granule_rate_numerator and \a granule_rate_denominator + * appropriately using oggz_set_granulerate() + * + * Some codecs use a "granuleshift" to divide a granulepos into two halves; + * the first describing a dependency on a previous packet, the second + * giving the offset since that packet. This is used to mark keyframes and + * intermediate frames. + * + * - Set the \a granuleshift appropriately using oggz_set_granuleshift() + * + * \subsection custom Custom Metrics + * + * For streams with non-linear granulepos, you need to set a custom metric: + * + * - Implement an OggzMetric callback + * - Set the OggzMetric callback using oggz_set_metric() + * + * \section using Seeking with OggzMetrics + * + * To seek, use oggz_seek_units(). Oggz will perform a ratio search + * through the Ogg bitstream, using the OggzMetric callback to determine + * its position relative to the desired unit. + * + * \note + * + * Many data streams begin with headers describing such things as codec + * setup parameters. One of the assumptions Monty makes is: + * + * - Given pre-cached decode headers, a player may seek into a stream at + * any point and begin decode. + * + * Thus, the first action taken by applications dealing with such data is + * to read in and cache the decode headers; thereafter the application can + * safely seek to arbitrary points in the data. + * + * This impacts seeking because the portion of the bitstream containing + * decode headers should not be considered part of the metric space. To + * inform Oggz not to seek earlier than the end of the decode headers, + * use oggz_set_data_start(). + * + * \{ + */ + +/** + * Retrieve the preroll of a logical bitstream. + * \param oggz An OGGZ handle + * \param serialno Identify the logical bitstream in \a oggz + * \returns The preroll of the specified logical bitstream. + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + */ +int oggz_get_preroll (OGGZ * oggz, long serialno); + +/** + * Specify the preroll of a logical bitstream. + * \param oggz An OGGZ handle + * \param serialno Identify the logical bitstream in \a oggz to attach + * this preroll to. + * \param preroll The preroll + * \returns 0 Success + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + */ +int oggz_set_preroll (OGGZ * oggz, long serialno, int preroll); + +/** + * Retrieve the granuleshift of a logical bitstream. + * \param oggz An OGGZ handle + * \param serialno Identify the logical bitstream in \a oggz + * \returns The granuleshift of the specified logical bitstream. + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + */ +int oggz_get_granuleshift (OGGZ * oggz, long serialno); + +/** + * Specify the granuleshift of a logical bitstream. + * \param oggz An OGGZ handle + * \param serialno Identify the logical bitstream in \a oggz to attach + * this granuleshift metric to. A value of -1 indicates that the metric should + * be attached to all unattached logical bitstreams in \a oggz. + * \param granuleshift The granuleshift + * \returns 0 Success + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + */ +int oggz_set_granuleshift (OGGZ * oggz, long serialno, int granuleshift); + +/** + * Retrieve the granulerate of a logical bitstream. + * \param oggz An OGGZ handle + * \param serialno Identify the logical bitstream in \a oggz + * \param granulerate_n Return location for the granulerate numerator + * \param granulerate_d Return location for the granulerate denominator + * \returns 0 Success + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * + */ +int oggz_get_granulerate (OGGZ * oggz, long serialno, + ogg_int64_t * granulerate_n, + ogg_int64_t * granulerate_d); + +/** + * Specify the granulerate of a logical bitstream. + * \param oggz An OGGZ handle + * \param serialno Identify the logical bitstream in \a oggz to attach + * this linear metric to. A value of -1 indicates that the metric should + * be attached to all unattached logical bitstreams in \a oggz. + * \param granule_rate_numerator The numerator of the granule rate + * \param granule_rate_denominator The denominator of the granule rate + * \returns 0 Success + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz. + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + */ +int oggz_set_granulerate (OGGZ * oggz, long serialno, + ogg_int64_t granule_rate_numerator, + ogg_int64_t granule_rate_denominator); + +/** + * This is the signature of a function to correlate Ogg streams. + * If every position in an Ogg stream can be described by a metric (eg. time) + * then define this function that returns some arbitrary unit value. + * This is the normal use of Oggz for media streams. The meaning of units is + * arbitrary, but must be consistent across all logical bitstreams; for + * example a conversion of the time offset of a given packet into nanoseconds + * or a similar stream-specific subdivision may be appropriate. + * + * \param oggz An OGGZ handle + * \param serialno Identifies a logical bitstream within \a oggz + * \param granulepos A granulepos within the logical bitstream identified + * by \a serialno + * \param user_data Arbitrary data you wish to pass to your callback + * \returns A conversion of the (serialno, granulepos) pair into a measure + * in units which is consistent across all logical bitstreams within \a oggz + */ +typedef ogg_int64_t (*OggzMetric) (OGGZ * oggz, long serialno, + ogg_int64_t granulepos, void * user_data); + +/** + * Set the OggzMetric to use for an OGGZ handle + * + * \param oggz An OGGZ handle + * \param serialno Identify the logical bitstream in \a oggz to attach + * this metric to. A value of -1 indicates that this metric + * should be attached to all unattached logical bitstreams + * in \a oggz. + * \param metric An OggzMetric callback + * \param user_data arbitrary data to pass to the metric callback + * + * \returns 0 Success + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz, and is not -1 + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * + * \note Specifying values of \a serialno other than -1 allows you to pass + * logical bitstream specific user_data to the same metric. + * \note Alternatively, you may use a different \a metric for each + * \a serialno, but all metrics used must return mutually consistent + * unit measurements. + */ +int oggz_set_metric (OGGZ * oggz, long serialno, OggzMetric metric, + void * user_data); + +#ifdef _UNIMPLEMENTED +/** \defgroup order OggzOrder + * + * - A mechanism to aid seeking across non-metric spaces for which a partial + * order exists (ie. data that is not synchronised by a measure such as time, + * but is nevertheless somehow seekably structured), is also planned. + * + * \subsection OggzOrder + * + * Suppose there is a partial order < and a corresponding equivalence + * relation = defined on the space of packets in the Ogg stream of 'OGGZ'. + * An OggzOrder simply provides a comparison in terms of '<' and '=' for + * ogg_packets against a target. + * + * To use OggzOrder: + * + * - Implement an OggzOrder callback + * - Set the OggzOrder callback for an OGGZ handle with oggz_set_order() + * - To seek, use oggz_seek_byorder(). Oggz will use a combination bisection + * search and scan of the Ogg bitstream, using the OggzOrder callback to + * match against the desired 'target'. + * + * Otherwise, for more general ogg streams for which a partial order can be + * defined, define a function matching this specification. + * + * Parameters: + * + * OGGZ: the OGGZ object + * op: an ogg packet in the stream + * target: a user defined object + * + * Return values: + * + * -1 , if 'op' would occur before the position represented by 'target' + * 0 , if the position of 'op' is equivalent to that of 'target' + * 1 , if 'op' would occur after the position represented by 'target' + * 2 , if the relationship between 'op' and 'target' is undefined. + * + * Symbolically: + * + * Suppose there is a partial order < and a corresponding equivalence + * relation = defined on the space of packets in the Ogg stream of 'OGGZ'. + * Let p represent the position of the packet 'op', and t be the position + * represented by 'target'. + * + * Then a function implementing OggzPacketOrder should return as follows: + * + * -1 , p < t + * 0 , p = t + * 1 , t < p + * 2 , otherwise + * + * Hacker's hint: if there are no circumstances in which you would return + * a value of 2, there is a linear order; it may be possible to define a + * Metric rather than an Order. + * + */ +typedef int (*OggzOrder) (OGGZ * oggz, ogg_packet * op, void * target, + void * user_data); +/** + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz, and is not -1 + */ +int oggz_set_order (OGGZ * oggz, long serialno, OggzOrder order, + void * user_data); + +long oggz_seek_byorder (OGGZ * oggz, void * target); + +#endif /* _UNIMPLEMENTED */ + +/** + * Tell Oggz to remember the given offset as the start of data. + * This informs the seeking mechanism that when seeking back to unit 0, + * go to the given offset, not to the start of the file, which is usually + * codec headers. + * The usual usage is: +
+    oggz_set_data_start (oggz, oggz_tell (oggz));
+
+ * \param oggz An OGGZ handle previously opened for reading + * \param offset The offset of the start of data + * \returns 0 on success, -1 on failure. + */ +int oggz_set_data_start (OGGZ * oggz, oggz_off_t offset); +/** \} + */ + +/** + * Seeks Oggz to time unit_target, but with the bounds of the offset range + * [offset_begin, offset_end]. This is useful when seeking in network streams + * where only parts of a media are buffered, and retrieving unbuffered + * parts is expensive. + * \param oggz An OGGZ handle previously opened for reading + * \param unit_target The seek target, in milliseconds, or custom units + * \param offset_begin Start of offset range to seek inside, in bytes + * \param offset_end End of offset range to seek inside, in bytes, + pass -1 for end of media + * \returns The new position, in milliseconds or custom units + * \retval -1 on failure (unit_target is not within range) + */ +ogg_int64_t +oggz_bounded_seek_set (OGGZ * oggz, + ogg_int64_t unit_target, + ogg_int64_t offset_begin, + ogg_int64_t offset_end); + +#endif /* __OGGZ_SEEK_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_stream.h b/Frameworks/Oggz.framework/Headers/oggz_stream.h new file mode 100644 index 0000000..778f0e3 --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_stream.h @@ -0,0 +1,77 @@ +/* + Copyright (C) 2007 Annodex Association + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Annodex Association nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ASSOCIATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_STREAM_H__ +#define __OGGZ_STREAM_H__ + +/** \file + * Interfaces for querying Ogg streams + */ + +/** + * Determine the content type of the oggz stream referred to by \a serialno + * + * \param oggz An OGGZ handle + * \param serialno An ogg stream serialno + * \retval OGGZ_CONTENT_THEORA..OGGZ_CONTENT_UNKNOWN content successfully + * identified + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not refer to an existing + * stream + */ +OggzStreamContent oggz_stream_get_content (OGGZ * oggz, long serialno); + +/** + * Return human-readable string representation of content type of oggz stream + * referred to by \a serialno + * + * \param oggz An OGGZ handle + * \param serialno An ogg stream serialno + * \retval string the name of the content type + * \retval NULL \a oggz or \a serialno invalid + */ +const char * oggz_stream_get_content_type (OGGZ *oggz, long serialno); + +/** + * Determine the number of headers of the oggz stream referred to by + * \a serialno + * + * \param oggz An OGGZ handle + * \param serialno An ogg stream serialno + * \retval OGGZ_CONTENT_THEORA..OGGZ_CONTENT_UNKNOWN content successfully + * identified + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not refer to an existing + * stream + */ +int oggz_stream_get_numheaders (OGGZ * oggz, long serialno); + +#endif /* __OGGZ_STREAM_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_table.h b/Frameworks/Oggz.framework/Headers/oggz_table.h new file mode 100644 index 0000000..1accd8c --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_table.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_TABLE_H__ +#define __OGGZ_TABLE_H__ + +/** \file + * A lookup table. + * + * OggzTable is provided for convenience to allow the storage of + * serialno-specific data. + */ + +/** + * A table of key-value pairs. + */ +typedef void OggzTable; + +/** + * Instantiate a new OggzTable + * \returns A new OggzTable + * \retval NULL Could not allocate memory for table + */ +OggzTable * +oggz_table_new (void); + +/** + * Delete an OggzTable + * \param table An OggzTable + */ +void +oggz_table_delete (OggzTable * table); + +/** + * Insert an element into a table. If a previous value existed for this key, + * it is overwritten with the new data element. + * \param table An OggzTable + * \param key Key to access this data element + * \param data The new element to add + * \retval data If the element was successfully added + * \retval NULL If adding the element failed due to a realloc() error + */ +void * +oggz_table_insert (OggzTable * table, long key, void * data); + +/** + * Remove the element of an OggzTable indexed by a given key + * \param table An OggzTable + * \param key a key + * \retval 0 Success + * \retval -1 Not found + */ +int +oggz_table_remove (OggzTable * table, long key); + +/** + * Retrieve the element of an OggzTable indexed by a given key + * \param table An OggzTable + * \param key a key + * \returns The element indexed by \a key + * \retval NULL \a table is undefined, or no element is indexed by \a key + */ +void * +oggz_table_lookup (OggzTable * table, long key); + +/** + * Query the number of elements in an OggzTable + * \param table An OggzTable + * \returns the number of elements in \a table + */ +int +oggz_table_size (OggzTable * table); + +/** + * Retrieve the nth element of an OggzTable, and optionally its key + * \param table An OggzTable + * \param n An index into the \a table + * \param key Return pointer for key corresponding to nth data element + * of \a table. Ignored if NULL. + * \returns The nth data element of \a table + * \retval NULL \a table is undefined, or \a n is out of range + */ +void * +oggz_table_nth (OggzTable * table, int n, long * key); + +#endif /* __OGGZ_TABLE_H__ */ diff --git a/Frameworks/Oggz.framework/Headers/oggz_write.h b/Frameworks/Oggz.framework/Headers/oggz_write.h new file mode 100644 index 0000000..13ac71e --- /dev/null +++ b/Frameworks/Oggz.framework/Headers/oggz_write.h @@ -0,0 +1,241 @@ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __OGGZ_WRITE_H__ +#define __OGGZ_WRITE_H__ + +/** \file + * Interfaces for writing Ogg files and streams + */ + +/** \defgroup force_feed Writing by force feeding Oggz + * + * Force feeding involves synchronously: + * - Creating an \a ogg_packet structure + * - Adding it to the packet queue with oggz_write_feed() + * - Calling oggz_write() or oggz_write_output(), repeatedly as necessary, + * to generate the Ogg bitstream. + * + * This process is illustrated in the following diagram: + * + * \image html forcefeed.png + * \image latex forcefeed.eps "Force Feeding Oggz" width=10cm + * + * The following example code generates a stream of ten packets, each + * containing a single byte ('A', 'B', ... , 'J'): + * + * \include write-feed.c + */ + +/** \defgroup hungry Writing with OggzHungry callbacks + * + * You can add packets to the Oggz packet queue only when it is "hungry" + * by providing an OggzHungry callback. + * + * An OggzHungry callback will: + * - Create an \a ogg_packet structure + * - Add it to the packet queue with oggz_write_feed() + * + * Once you have set such a callback with oggz_write_set_hungry_callback(), + * simply call oggz_write() or oggz_write_output() repeatedly, and Oggz + * will call your callback to provide packets when it is hungry. + * + * This process is illustrated in the following diagram: + * + * \image html hungry.png + * \image latex hungry.eps "Using OggzHungry" width=10cm + * + * The following example code generates a stream of ten packets, each + * containing a single byte ('A', 'B', ... , 'J'): + * + * \include write-hungry.c + */ + +/** \defgroup write_api Oggz Write API + * + * Oggz maintains a packet queue, such that you can independently add + * packets to the queue and write an Ogg bitstream. + * There are two complementary methods for adding packets to the + * packet queue. + * + * - by \link force_feed force feeding Oggz \endlink + * - by using \link hungry OggzHungry \endlink callbacks + * + * As each packet is enqueued, its validity is checked against the framing + * constraints outlined in the \link basics Ogg basics \endlink section. + * If it does not pass these constraints, oggz_write_feed() will fail with + * an appropriate error code. + * + * \note + * - When writing, you can ensure that a packet starts on a new page + * by setting the \a flush parameter of oggz_write_feed() to + * \a OGGZ_FLUSH_BEFORE when enqueuing it. + * Similarly you can ensure that the last page a packet is written into + * won't contain any following packets by setting the \a flush parameter + * of oggz_write_feed() to \a OGGZ_FLUSH_AFTER. + * - The \a OGGZ_FLUSH_BEFORE and \a OGGZ_FLUSH_AFTER flags can be bitwise + * OR'd together to ensure that the packet will not share any pages with + * any other packets, either before or after. + * + * \{ + */ + +/** + * This is the signature of a callback which Oggz will call when \a oggz + * is \link hungry hungry \endlink. + * + * \param oggz The OGGZ handle + * \param empty A value of 1 indicates that the packet queue is currently + * empty. A value of 0 indicates that the packet queue is not empty. + * \param user_data A generic pointer you have provided earlier + * \retval 0 Continue + * \retval non-zero Instruct Oggz to stop. + */ +typedef int (*OggzWriteHungry) (OGGZ * oggz, int empty, void * user_data); + +/** + * Set a callback for Oggz to call when \a oggz + * is \link hungry hungry \endlink. + * + * \param oggz An OGGZ handle previously opened for writing + * \param hungry Your callback function + * \param only_when_empty When to call: a value of 0 indicates that + * Oggz should call \a hungry() after each and every packet is written; + * a value of 1 indicates that Oggz should call \a hungry() only when + * its packet queue is empty + * \param user_data Arbitrary data you wish to pass to your callback + * \retval 0 Success + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \note Passing a value of 0 for \a only_when_empty allows you to feed + * new packets into \a oggz's packet queue on the fly. + */ +int oggz_write_set_hungry_callback (OGGZ * oggz, + OggzWriteHungry hungry, + int only_when_empty, + void * user_data); +/** + * Add a packet to \a oggz's packet queue. + * \param oggz An OGGZ handle previously opened for writing + * \param op An ogg_packet with all fields filled in + * \param serialno Identify the logical bitstream in \a oggz to add the + * packet to + * \param flush Bitmask of OGGZ_FLUSH_BEFORE, OGGZ_FLUSH_AFTER + * \param guard A guard for nocopy, NULL otherwise + * \retval 0 Success + * \retval OGGZ_ERR_BAD_GUARD \a guard specified has non-zero initialization + * \retval OGGZ_ERR_BOS Packet would be bos packet of a new logical bitstream, + * but oggz has already written one or more non-bos packets in + * other logical bitstreams, + * and \a oggz is not flagged OGGZ_NONSTRICT + * \retval OGGZ_ERR_EOS The logical bitstream identified by \a serialno is + * already at eos, + * and \a oggz is not flagged OGGZ_NONSTRICT + * \retval OGGZ_ERR_BAD_BYTES \a op->bytes is invalid, + * and \a oggz is not flagged OGGZ_NONSTRICT + * \retval OGGZ_ERR_BAD_B_O_S \a op->b_o_s is invalid, + * and \a oggz is not flagged OGGZ_NONSTRICT + * \retval OGGZ_ERR_BAD_GRANULEPOS \a op->granulepos is less than that of + * an earlier packet within this logical bitstream, + * and \a oggz is not flagged OGGZ_NONSTRICT + * \retval OGGZ_ERR_BAD_PACKETNO \a op->packetno is less than that of an + * earlier packet within this logical bitstream, + * and \a oggz is not flagged OGGZ_NONSTRICT + * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing + * logical bitstream in \a oggz, + * and \a oggz is not flagged OGGZ_NONSTRICT + * or \a serialno is equal to -1, or \a serialno does not fit in + * 32 bits, ie. within the range (-(2^31), (2^31)-1) + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_OUT_OF_MEMORY Unable to allocate memory to queue packet + * + * \note If \a op->b_o_s is initialized to \a -1 before calling + * oggz_write_feed(), Oggz will fill it in with the appropriate + * value; ie. 1 for the first packet of a new stream, and 0 otherwise. + */ +int oggz_write_feed (OGGZ * oggz, ogg_packet * op, long serialno, int flush, + int * guard); + +/** + * Output data from an OGGZ handle. Oggz will call your write callback + * as needed. + * + * \param oggz An OGGZ handle previously opened for writing + * \param buf A memory buffer + * \param n A count of bytes to output + * \retval "> 0" The number of bytes successfully output + * \retval 0 End of stream + * \retval OGGZ_ERR_RECURSIVE_WRITE Attempt to initiate writing from + * within an OggzHungry callback + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_STOP_OK Writing was stopped by an OggzHungry callback + * returning OGGZ_STOP_OK + * \retval OGGZ_ERR_STOP_ERR Reading was stopped by an OggzHungry callback + * returning OGGZ_STOP_ERR + */ +long oggz_write_output (OGGZ * oggz, unsigned char * buf, long n); + +/** + * Write n bytes from an OGGZ handle. Oggz will call your write callback + * as needed. + * + * \param oggz An OGGZ handle previously opened for writing + * \param n A count of bytes to be written + * \retval "> 0" The number of bytes successfully output + * \retval 0 End of stream + * \retval OGGZ_ERR_RECURSIVE_WRITE Attempt to initiate writing from + * within an OggzHungry callback + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + * \retval OGGZ_ERR_STOP_OK Writing was stopped by an OggzHungry callback + * returning OGGZ_STOP_OK + * \retval OGGZ_ERR_STOP_ERR Reading was stopped by an OggzHungry callback + * returning OGGZ_STOP_ERR + */ +long oggz_write (OGGZ * oggz, long n); + +/** + * Query the number of bytes in the next page to be written. + * + * \param oggz An OGGZ handle previously opened for writing + * \retval ">= 0" The number of bytes in the next page + * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ + * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ + */ +long oggz_write_get_next_page_size (OGGZ * oggz); + +/** \} + */ + +#endif /* __OGGZ_WRITE_H__ */ diff --git a/Frameworks/Oggz.framework/Oggz b/Frameworks/Oggz.framework/Oggz new file mode 100644 index 0000000..455291d Binary files /dev/null and b/Frameworks/Oggz.framework/Oggz differ diff --git a/Frameworks/Opus.framework/Headers/opus.h b/Frameworks/Opus.framework/Headers/opus.h new file mode 100644 index 0000000..ce86038 --- /dev/null +++ b/Frameworks/Opus.framework/Headers/opus.h @@ -0,0 +1,906 @@ +/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited + Written by Jean-Marc Valin and Koen Vos */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @file opus.h + * @brief Opus reference implementation API + */ + +#ifndef OPUS_H +#define OPUS_H + +#include "opus_types.h" +#include "opus_defines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @mainpage Opus + * + * The Opus codec is designed for interactive speech and audio transmission over the Internet. + * It is designed by the IETF Codec Working Group and incorporates technology from + * Skype's SILK codec and Xiph.Org's CELT codec. + * + * The Opus codec is designed to handle a wide range of interactive audio applications, + * including Voice over IP, videoconferencing, in-game chat, and even remote live music + * performances. It can scale from low bit-rate narrowband speech to very high quality + * stereo music. Its main features are: + + * @li Sampling rates from 8 to 48 kHz + * @li Bit-rates from 6 kb/s to 510 kb/s + * @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR) + * @li Audio bandwidth from narrowband to full-band + * @li Support for speech and music + * @li Support for mono and stereo + * @li Support for multichannel (up to 255 channels) + * @li Frame sizes from 2.5 ms to 60 ms + * @li Good loss robustness and packet loss concealment (PLC) + * @li Floating point and fixed-point implementation + * + * Documentation sections: + * @li @ref opus_encoder + * @li @ref opus_decoder + * @li @ref opus_repacketizer + * @li @ref opus_multistream + * @li @ref opus_libinfo + * @li @ref opus_custom + */ + +/** @defgroup opus_encoder Opus Encoder + * @{ + * + * @brief This page describes the process and functions used to encode Opus. + * + * Since Opus is a stateful codec, the encoding process starts with creating an encoder + * state. This can be done with: + * + * @code + * int error; + * OpusEncoder *enc; + * enc = opus_encoder_create(Fs, channels, application, &error); + * @endcode + * + * From this point, @c enc can be used for encoding an audio stream. An encoder state + * @b must @b not be used for more than one stream at the same time. Similarly, the encoder + * state @b must @b not be re-initialized for each frame. + * + * While opus_encoder_create() allocates memory for the state, it's also possible + * to initialize pre-allocated memory: + * + * @code + * int size; + * int error; + * OpusEncoder *enc; + * size = opus_encoder_get_size(channels); + * enc = malloc(size); + * error = opus_encoder_init(enc, Fs, channels, application); + * @endcode + * + * where opus_encoder_get_size() returns the required size for the encoder state. Note that + * future versions of this code may change the size, so no assuptions should be made about it. + * + * The encoder state is always continuous in memory and only a shallow copy is sufficient + * to copy it (e.g. memcpy()) + * + * It is possible to change some of the encoder's settings using the opus_encoder_ctl() + * interface. All these settings already default to the recommended value, so they should + * only be changed when necessary. The most common settings one may want to change are: + * + * @code + * opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate)); + * opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); + * opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type)); + * @endcode + * + * where + * + * @arg bitrate is in bits per second (b/s) + * @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest + * @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC + * + * See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream. + * + * To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data: + * @code + * len = opus_encode(enc, audio_frame, frame_size, packet, max_packet); + * @endcode + * + * where + *
    + *
  • audio_frame is the audio data in opus_int16 (or float for opus_encode_float())
  • + *
  • frame_size is the duration of the frame in samples (per channel)
  • + *
  • packet is the byte array to which the compressed data is written
  • + *
  • max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended). + * Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.
  • + *
+ * + * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet. + * The return value can be negative, which indicates that an error has occurred. If the return value + * is 1 byte, then the packet does not need to be transmitted (DTX). + * + * Once the encoder state if no longer needed, it can be destroyed with + * + * @code + * opus_encoder_destroy(enc); + * @endcode + * + * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(), + * then no action is required aside from potentially freeing the memory that was manually + * allocated for it (calling free(enc) for the example above) + * + */ + +/** Opus encoder state. + * This contains the complete state of an Opus encoder. + * It is position independent and can be freely copied. + * @see opus_encoder_create,opus_encoder_init + */ +typedef struct OpusEncoder OpusEncoder; + +/** Gets the size of an OpusEncoder structure. + * @param[in] channels int: Number of channels. + * This must be 1 or 2. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels); + +/** + */ + +/** Allocates and initializes an encoder state. + * There are three coding modes: + * + * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice + * signals. It enhances the input signal by high-pass filtering and + * emphasizing formants and harmonics. Optionally it includes in-band + * forward error correction to protect against packet loss. Use this + * mode for typical VoIP applications. Because of the enhancement, + * even at high bitrates the output may sound different from the input. + * + * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most + * non-voice signals like music. Use this mode for music and mixed + * (music/voice) content, broadcast, and applications requiring less + * than 15 ms of coding delay. + * + * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that + * disables the speech-optimized mode in exchange for slightly reduced delay. + * This mode can only be set on an newly initialized or freshly reset encoder + * because it changes the codec delay. + * + * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution). + * @param [in] Fs opus_int32: Sampling rate of input signal (Hz) + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) in input signal + * @param [in] application int: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY) + * @param [out] error int*: @ref opus_errorcodes + * @note Regardless of the sampling rate and number channels selected, the Opus encoder + * can switch to a lower audio bandwidth or number of channels if the bitrate + * selected is too low. This also means that it is safe to always use 48 kHz stereo input + * and let the encoder optimize the encoding. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create( + opus_int32 Fs, + int channels, + int application, + int *error +); + +/** Initializes a previously allocated encoder state + * The memory pointed to by st must be at least the size returned by opus_encoder_get_size(). + * This is intended for applications which use their own allocator instead of malloc. + * @see opus_encoder_create(),opus_encoder_get_size() + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] Fs opus_int32: Sampling rate of input signal (Hz) + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) in input signal + * @param [in] application int: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY) + * @retval #OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_EXPORT int opus_encoder_init( + OpusEncoder *st, + opus_int32 Fs, + int channels, + int application +) OPUS_ARG_NONNULL(1); + +/** Encodes an Opus frame. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] pcm opus_int16*: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16) + * @param [in] frame_size int: Number of samples per channel in the + * input signal. + * This must be an Opus frame size for + * the encoder's sampling rate. + * For example, at 48 kHz the permitted + * values are 120, 240, 480, 960, 1920, + * and 2880. + * Passing in a duration of less than + * 10 ms (480 samples at 48 kHz) will + * prevent the encoder from using the LPC + * or hybrid modes. + * @param [out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode( + OpusEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Encodes an Opus frame from floating point input. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] pcm float*: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0. + * Samples with a range beyond +/-1.0 are supported but will + * be clipped by decoders using the integer API and should + * only be used if it is known that the far end supports + * extended dynamic range. + * length is frame_size*channels*sizeof(float) + * @param [in] frame_size int: Number of samples per channel in the + * input signal. + * This must be an Opus frame size for + * the encoder's sampling rate. + * For example, at 48 kHz the permitted + * values are 120, 240, 480, 960, 1920, + * and 2880. + * Passing in a duration of less than + * 10 ms (480 samples at 48 kHz) will + * prevent the encoder from using the LPC + * or hybrid modes. + * @param [out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float( + OpusEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Frees an OpusEncoder allocated by opus_encoder_create(). + * @param[in] st OpusEncoder*: State to be freed. + */ +OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st); + +/** Perform a CTL function on an Opus encoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @param st OpusEncoder*: Encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls or + * @ref opus_encoderctls. + * @see opus_genericctls + * @see opus_encoderctls + */ +OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); +/**@}*/ + +/** @defgroup opus_decoder Opus Decoder + * @{ + * + * @brief This page describes the process and functions used to decode Opus. + * + * The decoding process also starts with creating a decoder + * state. This can be done with: + * @code + * int error; + * OpusDecoder *dec; + * dec = opus_decoder_create(Fs, channels, &error); + * @endcode + * where + * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000 + * @li channels is the number of channels (1 or 2) + * @li error will hold the error code in case of failure (or #OPUS_OK on success) + * @li the return value is a newly created decoder state to be used for decoding + * + * While opus_decoder_create() allocates memory for the state, it's also possible + * to initialize pre-allocated memory: + * @code + * int size; + * int error; + * OpusDecoder *dec; + * size = opus_decoder_get_size(channels); + * dec = malloc(size); + * error = opus_decoder_init(dec, Fs, channels); + * @endcode + * where opus_decoder_get_size() returns the required size for the decoder state. Note that + * future versions of this code may change the size, so no assuptions should be made about it. + * + * The decoder state is always continuous in memory and only a shallow copy is sufficient + * to copy it (e.g. memcpy()) + * + * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data: + * @code + * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0); + * @endcode + * where + * + * @li packet is the byte array containing the compressed data + * @li len is the exact number of bytes contained in the packet + * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float()) + * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array + * + * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet. + * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio + * buffer is too small to hold the decoded audio. + * + * Opus is a stateful codec with overlapping blocks and as a result Opus + * packets are not coded independently of each other. Packets must be + * passed into the decoder serially and in the correct order for a correct + * decode. Lost packets can be replaced with loss concealment by calling + * the decoder with a null pointer and zero length for the missing packet. + * + * A single codec state may only be accessed from a single thread at + * a time and any required locking must be performed by the caller. Separate + * streams must be decoded with separate decoder states and can be decoded + * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK + * defined. + * + */ + +/** Opus decoder state. + * This contains the complete state of an Opus decoder. + * It is position independent and can be freely copied. + * @see opus_decoder_create,opus_decoder_init + */ +typedef struct OpusDecoder OpusDecoder; + +/** Gets the size of an OpusDecoder structure. + * @param [in] channels int: Number of channels. + * This must be 1 or 2. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels); + +/** Allocates and initializes a decoder state. + * @param [in] Fs opus_int32: Sample rate to decode at (Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) to decode + * @param [out] error int*: #OPUS_OK Success or @ref opus_errorcodes + * + * Internally Opus stores data at 48000 Hz, so that should be the default + * value for Fs. However, the decoder can efficiently decode to buffers + * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use + * data at the full sample rate, or knows the compressed data doesn't + * use the full frequency range, it can request decoding at a reduced + * rate. Likewise, the decoder is capable of filling in either mono or + * interleaved stereo pcm buffers, at the caller's request. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create( + opus_int32 Fs, + int channels, + int *error +); + +/** Initializes a previously allocated decoder state. + * The state must be at least the size returned by opus_decoder_get_size(). + * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @param [in] st OpusDecoder*: Decoder state. + * @param [in] Fs opus_int32: Sampling rate to decode to (Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) to decode + * @retval #OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_EXPORT int opus_decoder_init( + OpusDecoder *st, + opus_int32 Fs, + int channels +) OPUS_ARG_NONNULL(1); + +/** Decode an Opus packet. + * @param [in] st OpusDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len opus_int32: Number of bytes in payload* + * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(opus_int16) + * @param [in] frame_size Number of samples per channel of available space in \a pcm. + * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will + * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), + * then frame_size needs to be exactly the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and + * FEC cases, frame_size must be a multiple of 2.5 ms. + * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be + * decoded. If no such data is available, the frame is decoded as if it were lost. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode( + OpusDecoder *st, + const unsigned char *data, + opus_int32 len, + opus_int16 *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Decode an Opus packet with floating point output. + * @param [in] st OpusDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len opus_int32: Number of bytes in payload + * @param [out] pcm float*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(float) + * @param [in] frame_size Number of samples per channel of available space in \a pcm. + * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will + * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), + * then frame_size needs to be exactly the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and + * FEC cases, frame_size must be a multiple of 2.5 ms. + * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be + * decoded. If no such data is available the frame is decoded as if it were lost. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float( + OpusDecoder *st, + const unsigned char *data, + opus_int32 len, + float *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on an Opus decoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @param st OpusDecoder*: Decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls or + * @ref opus_decoderctls. + * @see opus_genericctls + * @see opus_decoderctls + */ +OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/** Frees an OpusDecoder allocated by opus_decoder_create(). + * @param[in] st OpusDecoder*: State to be freed. + */ +OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st); + +/** Parse an opus packet into one or more frames. + * Opus_decode will perform this operation internally so most applications do + * not need to use this function. + * This function does not copy the frames, the returned pointers are pointers into + * the input packet. + * @param [in] data char*: Opus packet to be parsed + * @param [in] len opus_int32: size of data + * @param [out] out_toc char*: TOC pointer + * @param [out] frames char*[48] encapsulated frames + * @param [out] size opus_int16[48] sizes of the encapsulated frames + * @param [out] payload_offset int*: returns the position of the payload within the packet (in bytes) + * @returns number of frames + */ +OPUS_EXPORT int opus_packet_parse( + const unsigned char *data, + opus_int32 len, + unsigned char *out_toc, + const unsigned char *frames[48], + opus_int16 size[48], + int *payload_offset +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Gets the bandwidth of an Opus packet. + * @param [in] data char*: Opus packet + * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass) + * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass) + * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass) + * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass) + * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass) + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples per frame from an Opus packet. + * @param [in] data char*: Opus packet. + * This must contain at least one byte of + * data. + * @param [in] Fs opus_int32: Sampling rate in Hz. + * This must be a multiple of 400, or + * inaccurate results will be returned. + * @returns Number of samples per frame. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1); + +/** Gets the number of channels from an Opus packet. + * @param [in] data char*: Opus packet + * @returns Number of channels + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1); + +/** Gets the number of frames in an Opus packet. + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @returns Number of frames + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples of an Opus packet. + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @param [in] Fs opus_int32: Sampling rate in Hz. + * This must be a multiple of 400, or + * inaccurate results will be returned. + * @returns Number of samples + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples of an Opus packet. + * @param [in] dec OpusDecoder*: Decoder state + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @returns Number of samples + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); +/**@}*/ + +/** @defgroup opus_repacketizer Repacketizer + * @{ + * + * The repacketizer can be used to merge multiple Opus packets into a single + * packet or alternatively to split Opus packets that have previously been + * merged. Splitting valid Opus packets is always guaranteed to succeed, + * whereas merging valid packets only succeeds if all frames have the same + * mode, bandwidth, and frame size, and when the total duration of the merged + * packet is no more than 120 ms. + * The repacketizer currently only operates on elementary Opus + * streams. It will not manipualte multistream packets successfully, except in + * the degenerate case where they consist of data from a single stream. + * + * The repacketizing process starts with creating a repacketizer state, either + * by calling opus_repacketizer_create() or by allocating the memory yourself, + * e.g., + * @code + * OpusRepacketizer *rp; + * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size()); + * if (rp != NULL) + * opus_repacketizer_init(rp); + * @endcode + * + * Then the application should submit packets with opus_repacketizer_cat(), + * extract new packets with opus_repacketizer_out() or + * opus_repacketizer_out_range(), and then reset the state for the next set of + * input packets via opus_repacketizer_init(). + * + * For example, to split a sequence of packets into individual frames: + * @code + * unsigned char *data; + * int len; + * while (get_next_packet(&data, &len)) + * { + * unsigned char out[1276]; + * opus_int32 out_len; + * int nb_frames; + * int err; + * int i; + * err = opus_repacketizer_cat(rp, data, len); + * if (err != OPUS_OK) + * { + * release_packet(data); + * return err; + * } + * nb_frames = opus_repacketizer_get_nb_frames(rp); + * for (i = 0; i < nb_frames; i++) + * { + * out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out)); + * if (out_len < 0) + * { + * release_packet(data); + * return (int)out_len; + * } + * output_next_packet(out, out_len); + * } + * opus_repacketizer_init(rp); + * release_packet(data); + * } + * @endcode + * + * Alternatively, to combine a sequence of frames into packets that each + * contain up to TARGET_DURATION_MS milliseconds of data: + * @code + * // The maximum number of packets with duration TARGET_DURATION_MS occurs + * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5) + * // packets. + * unsigned char *data[(TARGET_DURATION_MS*2/5)+1]; + * opus_int32 len[(TARGET_DURATION_MS*2/5)+1]; + * int nb_packets; + * unsigned char out[1277*(TARGET_DURATION_MS*2/2)]; + * opus_int32 out_len; + * int prev_toc; + * nb_packets = 0; + * while (get_next_packet(data+nb_packets, len+nb_packets)) + * { + * int nb_frames; + * int err; + * nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]); + * if (nb_frames < 1) + * { + * release_packets(data, nb_packets+1); + * return nb_frames; + * } + * nb_frames += opus_repacketizer_get_nb_frames(rp); + * // If adding the next packet would exceed our target, or it has an + * // incompatible TOC sequence, output the packets we already have before + * // submitting it. + * // N.B., The nb_packets > 0 check ensures we've submitted at least one + * // packet since the last call to opus_repacketizer_init(). Otherwise a + * // single packet longer than TARGET_DURATION_MS would cause us to try to + * // output an (invalid) empty packet. It also ensures that prev_toc has + * // been set to a valid value. Additionally, len[nb_packets] > 0 is + * // guaranteed by the call to opus_packet_get_nb_frames() above, so the + * // reference to data[nb_packets][0] should be valid. + * if (nb_packets > 0 && ( + * ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) || + * opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames > + * TARGET_DURATION_MS*48)) + * { + * out_len = opus_repacketizer_out(rp, out, sizeof(out)); + * if (out_len < 0) + * { + * release_packets(data, nb_packets+1); + * return (int)out_len; + * } + * output_next_packet(out, out_len); + * opus_repacketizer_init(rp); + * release_packets(data, nb_packets); + * data[0] = data[nb_packets]; + * len[0] = len[nb_packets]; + * nb_packets = 0; + * } + * err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]); + * if (err != OPUS_OK) + * { + * release_packets(data, nb_packets+1); + * return err; + * } + * prev_toc = data[nb_packets][0]; + * nb_packets++; + * } + * // Output the final, partial packet. + * if (nb_packets > 0) + * { + * out_len = opus_repacketizer_out(rp, out, sizeof(out)); + * release_packets(data, nb_packets); + * if (out_len < 0) + * return (int)out_len; + * output_next_packet(out, out_len); + * } + * @endcode + * + * An alternate way of merging packets is to simply call opus_repacketizer_cat() + * unconditionally until it fails. At that point, the merged packet can be + * obtained with opus_repacketizer_out() and the input packet for which + * opus_repacketizer_cat() needs to be re-added to a newly reinitialized + * repacketizer state. + */ + +typedef struct OpusRepacketizer OpusRepacketizer; + +/** Gets the size of an OpusRepacketizer structure. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void); + +/** (Re)initializes a previously allocated repacketizer state. + * The state must be at least the size returned by opus_repacketizer_get_size(). + * This can be used for applications which use their own allocator instead of + * malloc(). + * It must also be called to reset the queue of packets waiting to be + * repacketized, which is necessary if the maximum packet duration of 120 ms + * is reached or if you wish to submit packets with a different Opus + * configuration (coding mode, audio bandwidth, frame size, or channel count). + * Failure to do so will prevent a new packet from being added with + * opus_repacketizer_cat(). + * @see opus_repacketizer_create + * @see opus_repacketizer_get_size + * @see opus_repacketizer_cat + * @param rp OpusRepacketizer*: The repacketizer state to + * (re)initialize. + * @returns A pointer to the same repacketizer state that was passed in. + */ +OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); + +/** Allocates memory and initializes the new repacketizer with + * opus_repacketizer_init(). + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void); + +/** Frees an OpusRepacketizer allocated by + * opus_repacketizer_create(). + * @param[in] rp OpusRepacketizer*: State to be freed. + */ +OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp); + +/** Add a packet to the current repacketizer state. + * This packet must match the configuration of any packets already submitted + * for repacketization since the last call to opus_repacketizer_init(). + * This means that it must have the same coding mode, audio bandwidth, frame + * size, and channel count. + * This can be checked in advance by examining the top 6 bits of the first + * byte of the packet, and ensuring they match the top 6 bits of the first + * byte of any previously submitted packet. + * The total duration of audio in the repacketizer state also must not exceed + * 120 ms, the maximum duration of a single packet, after adding this packet. + * + * The contents of the current repacketizer state can be extracted into new + * packets using opus_repacketizer_out() or opus_repacketizer_out_range(). + * + * In order to add a packet with a different configuration or to add more + * audio beyond 120 ms, you must clear the repacketizer state by calling + * opus_repacketizer_init(). + * If a packet is too large to add to the current repacketizer state, no part + * of it is added, even if it contains multiple frames, some of which might + * fit. + * If you wish to be able to add parts of such packets, you should first use + * another repacketizer to split the packet into pieces and add them + * individually. + * @see opus_repacketizer_out_range + * @see opus_repacketizer_out + * @see opus_repacketizer_init + * @param rp OpusRepacketizer*: The repacketizer state to which to + * add the packet. + * @param[in] data const unsigned char*: The packet data. + * The application must ensure + * this pointer remains valid + * until the next call to + * opus_repacketizer_init() or + * opus_repacketizer_destroy(). + * @param len opus_int32: The number of bytes in the packet data. + * @returns An error code indicating whether or not the operation succeeded. + * @retval #OPUS_OK The packet's contents have been added to the repacketizer + * state. + * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence, + * the packet's TOC sequence was not compatible + * with previously submitted packets (because + * the coding mode, audio bandwidth, frame size, + * or channel count did not match), or adding + * this packet would increase the total amount of + * audio stored in the repacketizer state to more + * than 120 ms. + */ +OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); + + +/** Construct a new packet from data previously submitted to the repacketizer + * state via opus_repacketizer_cat(). + * @param rp OpusRepacketizer*: The repacketizer state from which to + * construct the new packet. + * @param begin int: The index of the first frame in the current + * repacketizer state to include in the output. + * @param end int: One past the index of the last frame in the + * current repacketizer state to include in the + * output. + * @param[out] data const unsigned char*: The buffer in which to + * store the output packet. + * @param maxlen opus_int32: The maximum number of bytes to store in + * the output buffer. In order to guarantee + * success, this should be at least + * 1276 for a single frame, + * or for multiple frames, + * 1277*(end-begin). + * However, 1*(end-begin) plus + * the size of all packet data submitted to + * the repacketizer since the last call to + * opus_repacketizer_init() or + * opus_repacketizer_create() is also + * sufficient, and possibly much smaller. + * @returns The total size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BAD_ARG [begin,end) was an invalid range of + * frames (begin < 0, begin >= end, or end > + * opus_repacketizer_get_nb_frames()). + * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the + * complete output packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Return the total number of frames contained in packet data submitted to + * the repacketizer state so far via opus_repacketizer_cat() since the last + * call to opus_repacketizer_init() or opus_repacketizer_create(). + * This defines the valid range of packets that can be extracted with + * opus_repacketizer_out_range() or opus_repacketizer_out(). + * @param rp OpusRepacketizer*: The repacketizer state containing the + * frames. + * @returns The total number of frames contained in the packet data submitted + * to the repacketizer state. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); + +/** Construct a new packet from data previously submitted to the repacketizer + * state via opus_repacketizer_cat(). + * This is a convenience routine that returns all the data submitted so far + * in a single packet. + * It is equivalent to calling + * @code + * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp), + * data, maxlen) + * @endcode + * @param rp OpusRepacketizer*: The repacketizer state from which to + * construct the new packet. + * @param[out] data const unsigned char*: The buffer in which to + * store the output packet. + * @param maxlen opus_int32: The maximum number of bytes to store in + * the output buffer. In order to guarantee + * success, this should be at least + * 1277*opus_repacketizer_get_nb_frames(rp). + * However, + * 1*opus_repacketizer_get_nb_frames(rp) + * plus the size of all packet data + * submitted to the repacketizer since the + * last call to opus_repacketizer_init() or + * opus_repacketizer_create() is also + * sufficient, and possibly much smaller. + * @returns The total size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the + * complete output packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_H */ diff --git a/Frameworks/Opus.framework/Headers/opus_defines.h b/Frameworks/Opus.framework/Headers/opus_defines.h new file mode 100644 index 0000000..9fa3ccb --- /dev/null +++ b/Frameworks/Opus.framework/Headers/opus_defines.h @@ -0,0 +1,655 @@ +/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited + Written by Jean-Marc Valin and Koen Vos */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @file opus_defines.h + * @brief Opus reference implementation constants + */ + +#ifndef OPUS_DEFINES_H +#define OPUS_DEFINES_H + +#include "opus_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup opus_errorcodes Error codes + * @{ + */ +/** No error @hideinitializer*/ +#define OPUS_OK 0 +/** One or more invalid/out of range arguments @hideinitializer*/ +#define OPUS_BAD_ARG -1 +/** The mode struct passed is invalid @hideinitializer*/ +#define OPUS_BUFFER_TOO_SMALL -2 +/** An internal error was detected @hideinitializer*/ +#define OPUS_INTERNAL_ERROR -3 +/** The compressed data passed is corrupted @hideinitializer*/ +#define OPUS_INVALID_PACKET -4 +/** Invalid/unsupported request number @hideinitializer*/ +#define OPUS_UNIMPLEMENTED -5 +/** An encoder or decoder structure is invalid or already freed @hideinitializer*/ +#define OPUS_INVALID_STATE -6 +/** Memory allocation has failed @hideinitializer*/ +#define OPUS_ALLOC_FAIL -7 +/**@}*/ + +/** @cond OPUS_INTERNAL_DOC */ +/**Export control for opus functions */ + +#ifndef OPUS_EXPORT +# if defined(WIN32) +# ifdef OPUS_BUILD +# define OPUS_EXPORT __declspec(dllexport) +# else +# define OPUS_EXPORT +# endif +# elif defined(__GNUC__) && defined(OPUS_BUILD) +# define OPUS_EXPORT __attribute__ ((visibility ("default"))) +# else +# define OPUS_EXPORT +# endif +#endif + +# if !defined(OPUS_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define OPUS_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define OPUS_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if OPUS_GNUC_PREREQ(3,0) +# define OPUS_RESTRICT __restrict__ +# elif (defined(_MSC_VER) && _MSC_VER >= 1400) +# define OPUS_RESTRICT __restrict +# else +# define OPUS_RESTRICT +# endif +#else +# define OPUS_RESTRICT restrict +#endif + +/**Warning attributes for opus functions + * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out + * some paranoid null checks. */ +#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4) +# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) +#else +# define OPUS_WARN_UNUSED_RESULT +#endif +#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4) +# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) +#else +# define OPUS_ARG_NONNULL(_x) +#endif + +/** These are the actual Encoder CTL ID numbers. + * They should not be used directly by applications. + * In general, SETs should be even and GETs should be odd.*/ +#define OPUS_SET_APPLICATION_REQUEST 4000 +#define OPUS_GET_APPLICATION_REQUEST 4001 +#define OPUS_SET_BITRATE_REQUEST 4002 +#define OPUS_GET_BITRATE_REQUEST 4003 +#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004 +#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005 +#define OPUS_SET_VBR_REQUEST 4006 +#define OPUS_GET_VBR_REQUEST 4007 +#define OPUS_SET_BANDWIDTH_REQUEST 4008 +#define OPUS_GET_BANDWIDTH_REQUEST 4009 +#define OPUS_SET_COMPLEXITY_REQUEST 4010 +#define OPUS_GET_COMPLEXITY_REQUEST 4011 +#define OPUS_SET_INBAND_FEC_REQUEST 4012 +#define OPUS_GET_INBAND_FEC_REQUEST 4013 +#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014 +#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015 +#define OPUS_SET_DTX_REQUEST 4016 +#define OPUS_GET_DTX_REQUEST 4017 +#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020 +#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021 +#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022 +#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023 +#define OPUS_SET_SIGNAL_REQUEST 4024 +#define OPUS_GET_SIGNAL_REQUEST 4025 +#define OPUS_GET_LOOKAHEAD_REQUEST 4027 +/* #define OPUS_RESET_STATE 4028 */ +#define OPUS_GET_SAMPLE_RATE_REQUEST 4029 +#define OPUS_GET_FINAL_RANGE_REQUEST 4031 +#define OPUS_GET_PITCH_REQUEST 4033 +#define OPUS_SET_GAIN_REQUEST 4034 +#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */ +#define OPUS_SET_LSB_DEPTH_REQUEST 4036 +#define OPUS_GET_LSB_DEPTH_REQUEST 4037 + +#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039 + +/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */ + +/* Macros to trigger compilation errors when the wrong types are provided to a CTL */ +#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x)) +#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr))) +#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr))) +/** @endcond */ + +/** @defgroup opus_ctlvalues Pre-defined values for CTL interface + * @see opus_genericctls, opus_encoderctls + * @{ + */ +/* Values for the various encoder CTLs */ +#define OPUS_AUTO -1000 /**opus_int32: Allowed values: 0-10, inclusive. + * + * @hideinitializer */ +#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x) +/** Gets the encoder's complexity configuration. + * @see OPUS_SET_COMPLEXITY + * @param[out] x opus_int32 *: Returns a value in the range 0-10, + * inclusive. + * @hideinitializer */ +#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x) + +/** Configures the bitrate in the encoder. + * Rates from 500 to 512000 bits per second are meaningful, as well as the + * special values #OPUS_AUTO and #OPUS_BITRATE_MAX. + * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much + * rate as it can, which is useful for controlling the rate by adjusting the + * output buffer size. + * @see OPUS_GET_BITRATE + * @param[in] x opus_int32: Bitrate in bits per second. The default + * is determined based on the number of + * channels and the input sampling rate. + * @hideinitializer */ +#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x) +/** Gets the encoder's bitrate configuration. + * @see OPUS_SET_BITRATE + * @param[out] x opus_int32 *: Returns the bitrate in bits per second. + * The default is determined based on the + * number of channels and the input + * sampling rate. + * @hideinitializer */ +#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x) + +/** Enables or disables variable bitrate (VBR) in the encoder. + * The configured bitrate may not be met exactly because frames must + * be an integer number of bytes in length. + * @warning Only the MDCT mode of Opus can provide hard CBR behavior. + * @see OPUS_GET_VBR + * @see OPUS_SET_VBR_CONSTRAINT + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Hard CBR. For LPC/hybrid modes at very low bit-rate, this can + * cause noticeable quality degradation.
+ *
1
VBR (default). The exact type of VBR is controlled by + * #OPUS_SET_VBR_CONSTRAINT.
+ *
+ * @hideinitializer */ +#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x) +/** Determine if variable bitrate (VBR) is enabled in the encoder. + * @see OPUS_SET_VBR + * @see OPUS_GET_VBR_CONSTRAINT + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
Hard CBR.
+ *
1
VBR (default). The exact type of VBR may be retrieved via + * #OPUS_GET_VBR_CONSTRAINT.
+ *
+ * @hideinitializer */ +#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x) + +/** Enables or disables constrained VBR in the encoder. + * This setting is ignored when the encoder is in CBR mode. + * @warning Only the MDCT mode of Opus currently heeds the constraint. + * Speech mode ignores it completely, hybrid mode may fail to obey it + * if the LPC layer uses more bitrate than the constraint would have + * permitted. + * @see OPUS_GET_VBR_CONSTRAINT + * @see OPUS_SET_VBR + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Unconstrained VBR.
+ *
1
Constrained VBR (default). This creates a maximum of one + * frame of buffering delay assuming a transport with a + * serialization speed of the nominal bitrate.
+ *
+ * @hideinitializer */ +#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x) +/** Determine if constrained VBR is enabled in the encoder. + * @see OPUS_SET_VBR_CONSTRAINT + * @see OPUS_GET_VBR + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
Unconstrained VBR.
+ *
1
Constrained VBR (default).
+ *
+ * @hideinitializer */ +#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x) + +/** Configures mono/stereo forcing in the encoder. + * This can force the encoder to produce packets encoded as either mono or + * stereo, regardless of the format of the input audio. This is useful when + * the caller knows that the input signal is currently a mono source embedded + * in a stereo stream. + * @see OPUS_GET_FORCE_CHANNELS + * @param[in] x opus_int32: Allowed values: + *
+ *
#OPUS_AUTO
Not forced (default)
+ *
1
Forced mono
+ *
2
Forced stereo
+ *
+ * @hideinitializer */ +#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x) +/** Gets the encoder's forced channel configuration. + * @see OPUS_SET_FORCE_CHANNELS + * @param[out] x opus_int32 *: + *
+ *
#OPUS_AUTO
Not forced (default)
+ *
1
Forced mono
+ *
2
Forced stereo
+ *
+ * @hideinitializer */ +#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x) + +/** Configures the maximum bandpass that the encoder will select automatically. + * Applications should normally use this instead of #OPUS_SET_BANDWIDTH + * (leaving that set to the default, #OPUS_AUTO). This allows the + * application to set an upper bound based on the type of input it is + * providing, but still gives the encoder the freedom to reduce the bandpass + * when the bitrate becomes too low, for better overall quality. + * @see OPUS_GET_MAX_BANDWIDTH + * @param[in] x opus_int32: Allowed values: + *
+ *
OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
+ *
OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
+ *
OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
+ *
OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
+ *
OPUS_BANDWIDTH_FULLBAND
20 kHz passband (default)
+ *
+ * @hideinitializer */ +#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x) + +/** Gets the encoder's configured maximum allowed bandpass. + * @see OPUS_SET_MAX_BANDWIDTH + * @param[out] x opus_int32 *: Allowed values: + *
+ *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
+ *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
+ *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
+ *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
+ *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband (default)
+ *
+ * @hideinitializer */ +#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) + +/** Sets the encoder's bandpass to a specific value. + * This prevents the encoder from automatically selecting the bandpass based + * on the available bitrate. If an application knows the bandpass of the input + * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH + * instead, which still gives the encoder the freedom to reduce the bandpass + * when the bitrate becomes too low, for better overall quality. + * @see OPUS_GET_BANDWIDTH + * @param[in] x opus_int32: Allowed values: + *
+ *
#OPUS_AUTO
(default)
+ *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
+ *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
+ *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
+ *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
+ *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband
+ *
+ * @hideinitializer */ +#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x) + +/** Configures the type of signal being encoded. + * This is a hint which helps the encoder's mode selection. + * @see OPUS_GET_SIGNAL + * @param[in] x opus_int32: Allowed values: + *
+ *
#OPUS_AUTO
(default)
+ *
#OPUS_SIGNAL_VOICE
Bias thresholds towards choosing LPC or Hybrid modes.
+ *
#OPUS_SIGNAL_MUSIC
Bias thresholds towards choosing MDCT modes.
+ *
+ * @hideinitializer */ +#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured signal type. + * @see OPUS_SET_SIGNAL + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
#OPUS_AUTO
(default)
+ *
#OPUS_SIGNAL_VOICE
Bias thresholds towards choosing LPC or Hybrid modes.
+ *
#OPUS_SIGNAL_MUSIC
Bias thresholds towards choosing MDCT modes.
+ *
+ * @hideinitializer */ +#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x) + + +/** Configures the encoder's intended application. + * The initial value is a mandatory argument to the encoder_create function. + * @see OPUS_GET_APPLICATION + * @param[in] x opus_int32: Returns one of the following values: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @hideinitializer */ +#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured application. + * @see OPUS_SET_APPLICATION + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @hideinitializer */ +#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x) + +/** Gets the sampling rate the encoder or decoder was initialized with. + * This simply returns the Fs value passed to opus_encoder_init() + * or opus_decoder_init(). + * @param[out] x opus_int32 *: Sampling rate of encoder or decoder. + * @hideinitializer + */ +#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x) + +/** Gets the total samples of delay added by the entire codec. + * This can be queried by the encoder and then the provided number of samples can be + * skipped on from the start of the decoder's output to provide time aligned input + * and output. From the perspective of a decoding application the real data begins this many + * samples late. + * + * The decoder contribution to this delay is identical for all decoders, but the + * encoder portion of the delay may vary from implementation to implementation, + * version to version, or even depend on the encoder's initial configuration. + * Applications needing delay compensation should call this CTL rather than + * hard-coding a value. + * @param[out] x opus_int32 *: Number of lookahead samples + * @hideinitializer */ +#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's use of inband forward error correction (FEC). + * @note This is only applicable to the LPC layer + * @see OPUS_GET_INBAND_FEC + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Disable inband FEC (default).
+ *
1
Enable inband FEC.
+ *
+ * @hideinitializer */ +#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x) +/** Gets encoder's configured use of inband forward error correction. + * @see OPUS_SET_INBAND_FEC + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
Inband FEC disabled (default).
+ *
1
Inband FEC enabled.
+ *
+ * @hideinitializer */ +#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's expected packet loss percentage. + * Higher values with trigger progressively more loss resistant behavior in the encoder + * at the expense of quality at a given bitrate in the lossless case, but greater quality + * under loss. + * @see OPUS_GET_PACKET_LOSS_PERC + * @param[in] x opus_int32: Loss percentage in the range 0-100, inclusive (default: 0). + * @hideinitializer */ +#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured packet loss percentage. + * @see OPUS_SET_PACKET_LOSS_PERC + * @param[out] x opus_int32 *: Returns the configured loss percentage + * in the range 0-100, inclusive (default: 0). + * @hideinitializer */ +#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's use of discontinuous transmission (DTX). + * @note This is only applicable to the LPC layer + * @see OPUS_GET_DTX + * @param[in] x opus_int32: Allowed values: + *
+ *
0
Disable DTX (default).
+ *
1
Enabled DTX.
+ *
+ * @hideinitializer */ +#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x) +/** Gets encoder's configured use of discontinuous transmission. + * @see OPUS_SET_DTX + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
0
DTX disabled (default).
+ *
1
DTX enabled.
+ *
+ * @hideinitializer */ +#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x) +/** Configures the depth of signal being encoded. + * This is a hint which helps the encoder identify silence and near-silence. + * @see OPUS_GET_LSB_DEPTH + * @param[in] x opus_int32: Input precision in bits, between 8 and 24 + * (default: 24). + * @hideinitializer */ +#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured signal depth. + * @see OPUS_SET_LSB_DEPTH + * @param[out] x opus_int32 *: Input precision in bits, between 8 and + * 24 (default: 24). + * @hideinitializer */ +#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x) + +/** Gets the duration (in samples) of the last packet successfully decoded or concealed. + * @param[out] x opus_int32 *: Number of samples (at current sampling rate). + * @hideinitializer */ +#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x) +/**@}*/ + +/** @defgroup opus_genericctls Generic CTLs + * + * These macros are used with the \c opus_decoder_ctl and + * \c opus_encoder_ctl calls to generate a particular + * request. + * + * When called on an \c OpusDecoder they apply to that + * particular decoder instance. When called on an + * \c OpusEncoder they apply to the corresponding setting + * on that encoder instance, if present. + * + * Some usage examples: + * + * @code + * int ret; + * opus_int32 pitch; + * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch)); + * if (ret == OPUS_OK) return ret; + * + * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE); + * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE); + * + * opus_int32 enc_bw, dec_bw; + * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw)); + * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw)); + * if (enc_bw != dec_bw) { + * printf("packet bandwidth mismatch!\n"); + * } + * @endcode + * + * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls + * @{ + */ + +/** Resets the codec state to be equivalent to a freshly initialized state. + * This should be called when switching streams in order to prevent + * the back to back decoding from giving different results from + * one at a time decoding. + * @hideinitializer */ +#define OPUS_RESET_STATE 4028 + +/** Gets the final state of the codec's entropy coder. + * This is used for testing purposes, + * The encoder and decoder state should be identical after coding a payload + * (assuming no data corruption or software bugs) + * + * @param[out] x opus_uint32 *: Entropy coder state + * + * @hideinitializer */ +#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x) + +/** Gets the pitch of the last decoded frame, if available. + * This can be used for any post-processing algorithm requiring the use of pitch, + * e.g. time stretching/shortening. If the last frame was not voiced, or if the + * pitch was not coded in the frame, then zero is returned. + * + * This CTL is only implemented for decoder instances. + * + * @param[out] x opus_int32 *: pitch period at 48 kHz (or 0 if not available) + * + * @hideinitializer */ +#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x) + +/** Gets the encoder's configured bandpass or the decoder's last bandpass. + * @see OPUS_SET_BANDWIDTH + * @param[out] x opus_int32 *: Returns one of the following values: + *
+ *
#OPUS_AUTO
(default)
+ *
#OPUS_BANDWIDTH_NARROWBAND
4 kHz passband
+ *
#OPUS_BANDWIDTH_MEDIUMBAND
6 kHz passband
+ *
#OPUS_BANDWIDTH_WIDEBAND
8 kHz passband
+ *
#OPUS_BANDWIDTH_SUPERWIDEBAND
12 kHz passband
+ *
#OPUS_BANDWIDTH_FULLBAND
20 kHz passband
+ *
+ * @hideinitializer */ +#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) + +/**@}*/ + +/** @defgroup opus_decoderctls Decoder related CTLs + * @see opus_genericctls, opus_encoderctls, opus_decoder + * @{ + */ + +/** Configures decoder gain adjustment. + * Scales the decoded output by a factor specified in Q8 dB units. + * This has a maximum range of -32768 to 32767 inclusive, and returns + * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment. + * This setting survives decoder reset. + * + * gain = pow(10, x/(20.0*256)) + * + * @param[in] x opus_int32: Amount to scale PCM signal by in Q8 dB units. + * @hideinitializer */ +#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x) +/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN + * + * @param[out] x opus_int32 *: Amount to scale PCM signal by in Q8 dB units. + * @hideinitializer */ +#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x) + +/**@}*/ + +/** @defgroup opus_libinfo Opus library information functions + * @{ + */ + +/** Converts an opus error code into a human readable string. + * + * @param[in] error int: Error number + * @returns Error string + */ +OPUS_EXPORT const char *opus_strerror(int error); + +/** Gets the libopus version string. + * + * @returns Version string + */ +OPUS_EXPORT const char *opus_get_version_string(void); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_DEFINES_H */ diff --git a/Frameworks/Opus.framework/Headers/opus_multistream.h b/Frameworks/Opus.framework/Headers/opus_multistream.h new file mode 100644 index 0000000..ae59979 --- /dev/null +++ b/Frameworks/Opus.framework/Headers/opus_multistream.h @@ -0,0 +1,660 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @file opus_multistream.h + * @brief Opus reference implementation multistream API + */ + +#ifndef OPUS_MULTISTREAM_H +#define OPUS_MULTISTREAM_H + +#include "opus.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond OPUS_INTERNAL_DOC */ + +/** Macros to trigger compilation errors when the wrong types are provided to a + * CTL. */ +/**@{*/ +#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr))) +#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr))) +/**@}*/ + +/** These are the actual encoder and decoder CTL ID numbers. + * They should not be used directly by applications. + * In general, SETs should be even and GETs should be odd.*/ +/**@{*/ +#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120 +#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122 +/**@}*/ + +/** @endcond */ + +/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs + * + * These are convenience macros that are specific to the + * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl() + * interface. + * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and + * @ref opus_decoderctls may be applied to a multistream encoder or decoder as + * well. + * In addition, you may retrieve the encoder or decoder state for an specific + * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or + * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually. + */ +/**@{*/ + +/** Gets the encoder state for an individual stream of a multistream encoder. + * @param[in] x opus_int32: The index of the stream whose encoder you + * wish to retrieve. + * This must be non-negative and less than + * the streams parameter used + * to initialize the encoder. + * @param[out] y OpusEncoder**: Returns a pointer to the given + * encoder state. + * @retval OPUS_BAD_ARG The index of the requested stream was out of range. + * @hideinitializer + */ +#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y) + +/** Gets the decoder state for an individual stream of a multistream decoder. + * @param[in] x opus_int32: The index of the stream whose decoder you + * wish to retrieve. + * This must be non-negative and less than + * the streams parameter used + * to initialize the decoder. + * @param[out] y OpusDecoder**: Returns a pointer to the given + * decoder state. + * @retval OPUS_BAD_ARG The index of the requested stream was out of range. + * @hideinitializer + */ +#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y) + +/**@}*/ + +/** @defgroup opus_multistream Opus Multistream API + * @{ + * + * The multistream API allows individual Opus streams to be combined into a + * single packet, enabling support for up to 255 channels. Unlike an + * elementary Opus stream, the encoder and decoder must negotiate the channel + * configuration before the decoder can successfully interpret the data in the + * packets produced by the encoder. Some basic information, such as packet + * duration, can be computed without any special negotiation. + * + * The format for multistream Opus packets is defined in the + * Ogg + * encapsulation specification and is based on the self-delimited Opus + * framing described in Appendix B of RFC 6716. + * Normal Opus packets are just a degenerate case of multistream Opus packets, + * and can be encoded or decoded with the multistream API by setting + * streams to 1 when initializing the encoder or + * decoder. + * + * Multistream Opus streams can contain up to 255 elementary Opus streams. + * These may be either "uncoupled" or "coupled", indicating that the decoder + * is configured to decode them to either 1 or 2 channels, respectively. + * The streams are ordered so that all coupled streams appear at the + * beginning. + * + * A mapping table defines which decoded channel i + * should be used for each input/output (I/O) channel j. This table is + * typically provided as an unsigned char array. + * Let i = mapping[j] be the index for I/O channel j. + * If i < 2*coupled_streams, then I/O channel j is + * encoded as the left channel of stream (i/2) if i + * is even, or as the right channel of stream (i/2) if + * i is odd. Otherwise, I/O channel j is encoded as + * mono in stream (i - coupled_streams), unless it has the special + * value 255, in which case it is omitted from the encoding entirely (the + * decoder will reproduce it as silence). Each value i must either + * be the special value 255 or be less than streams + coupled_streams. + * + * The output channels specified by the encoder + * should use the + * Vorbis + * channel ordering. A decoder may wish to apply an additional permutation + * to the mapping the encoder used to achieve a different output channel + * order (e.g. for outputing in WAV order). + * + * Each multistream packet contains an Opus packet for each stream, and all of + * the Opus packets in a single multistream packet must have the same + * duration. Therefore the duration of a multistream packet can be extracted + * from the TOC sequence of the first stream, which is located at the + * beginning of the packet, just like an elementary Opus stream: + * + * @code + * int nb_samples; + * int nb_frames; + * nb_frames = opus_packet_get_nb_frames(data, len); + * if (nb_frames < 1) + * return nb_frames; + * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames; + * @endcode + * + * The general encoding and decoding process proceeds exactly the same as in + * the normal @ref opus_encoder and @ref opus_decoder APIs. + * See their documentation for an overview of how to use the corresponding + * multistream functions. + */ + +/** Opus multistream encoder state. + * This contains the complete state of a multistream Opus encoder. + * It is position independent and can be freely copied. + * @see opus_multistream_encoder_create + * @see opus_multistream_encoder_init + */ +typedef struct OpusMSEncoder OpusMSEncoder; + +/** Opus multistream decoder state. + * This contains the complete state of a multistream Opus decoder. + * It is position independent and can be freely copied. + * @see opus_multistream_decoder_create + * @see opus_multistream_decoder_init + */ +typedef struct OpusMSDecoder OpusMSDecoder; + +/**\name Multistream encoder functions */ +/**@{*/ + +/** Gets the size of an OpusMSEncoder structure. + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size( + int streams, + int coupled_streams +); + +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size( + int channels, + int mapping_family +); + + +/** Allocates and initializes a multistream encoder state. + * Call opus_multistream_encoder_destroy() to release + * this object when finished. + * @param Fs opus_int32: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (streams + + * coupled_streams). + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than the number of input channels. + * @param[in] mapping const unsigned char[channels]: Mapping from + * encoded channels to input channels, as described in + * @ref opus_multistream. As an extra constraint, the + * multistream encoder does not allow encoding coupled + * streams for which one channel is unused since this + * is never a good idea. + * @param application int: The target encoder application. + * This must be one of the following: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @param[out] error int *: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application, + int *error +) OPUS_ARG_NONNULL(5); + +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create( + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + unsigned char *mapping, + int application, + int *error +) OPUS_ARG_NONNULL(5); + +/** Initialize a previously allocated multistream encoder state. + * The memory pointed to by \a st must be at least the size returned by + * opus_multistream_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_multistream_encoder_create + * @see opus_multistream_encoder_get_size + * @param st OpusMSEncoder*: Multistream encoder state to initialize. + * @param Fs opus_int32: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (streams + + * coupled_streams). + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than the number of input channels. + * @param[in] mapping const unsigned char[channels]: Mapping from + * encoded channels to input channels, as described in + * @ref opus_multistream. As an extra constraint, the + * multistream encoder does not allow encoding coupled + * streams for which one channel is unused since this + * is never a good idea. + * @param application int: The target encoder application. + * This must be one of the following: + *
+ *
#OPUS_APPLICATION_VOIP
+ *
Process signal for improved speech intelligibility.
+ *
#OPUS_APPLICATION_AUDIO
+ *
Favor faithfulness to the original input.
+ *
#OPUS_APPLICATION_RESTRICTED_LOWDELAY
+ *
Configure the minimum possible coding delay by disabling certain modes + * of operation.
+ *
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ +OPUS_EXPORT int opus_multistream_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + +OPUS_EXPORT int opus_multistream_surround_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + unsigned char *mapping, + int application +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + +/** Encodes a multistream Opus frame. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param[in] pcm const opus_int16*: The input signal as interleaved + * samples. + * This must contain + * frame_size*channels + * samples. + * @param frame_size int: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode( + OpusMSEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Encodes a multistream Opus frame from floating point input. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param[in] pcm const float*: The input signal as interleaved + * samples with a normal range of + * +/-1.0. + * Samples with a range beyond +/-1.0 + * are supported but will be clipped by + * decoders using the integer API and + * should only be used if it is known + * that the far end supports extended + * dynamic range. + * This must contain + * frame_size*channels + * samples. + * @param frame_size int: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float( + OpusMSEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Frees an OpusMSEncoder allocated by + * opus_multistream_encoder_create(). + * @param st OpusMSEncoder*: Multistream encoder state to be freed. + */ +OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st); + +/** Perform a CTL function on a multistream Opus encoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_encoderctls, or @ref opus_multistream_ctls. + * @see opus_genericctls + * @see opus_encoderctls + * @see opus_multistream_ctls + */ +OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/**@}*/ + +/**\name Multistream decoder functions */ +/**@{*/ + +/** Gets the size of an OpusMSDecoder structure. + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size( + int streams, + int coupled_streams +); + +/** Allocates and initializes a multistream decoder state. + * Call opus_multistream_decoder_destroy() to release + * this object when finished. + * @param Fs opus_int32: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (streams + + * coupled_streams). + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @param[in] mapping const unsigned char[channels]: Mapping from + * coded channels to output channels, as described in + * @ref opus_multistream. + * @param[out] error int *: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int *error +) OPUS_ARG_NONNULL(5); + +/** Intialize a previously allocated decoder state object. + * The memory pointed to by \a st must be at least the size returned by + * opus_multistream_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_multistream_decoder_create + * @see opus_multistream_deocder_get_size + * @param st OpusMSEncoder*: Multistream encoder state to initialize. + * @param Fs opus_int32: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (streams + + * coupled_streams). + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @param[in] mapping const unsigned char[channels]: Mapping from + * coded channels to output channels, as described in + * @ref opus_multistream. + * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ +OPUS_EXPORT int opus_multistream_decoder_init( + OpusMSDecoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + +/** Decode a multistream Opus packet. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param[in] data const unsigned char*: Input payload. + * Use a NULL + * pointer to indicate packet + * loss. + * @param len opus_int32: Number of bytes in payload. + * @param[out] pcm opus_int16*: Output signal, with interleaved + * samples. + * This must contain room for + * frame_size*channels + * samples. + * @param frame_size int: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * must be a multiple of 2.5 ms. + * @param decode_fec int: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode( + OpusMSDecoder *st, + const unsigned char *data, + opus_int32 len, + opus_int16 *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Decode a multistream Opus packet with floating point output. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param[in] data const unsigned char*: Input payload. + * Use a NULL + * pointer to indicate packet + * loss. + * @param len opus_int32: Number of bytes in payload. + * @param[out] pcm opus_int16*: Output signal, with interleaved + * samples. + * This must contain room for + * frame_size*channels + * samples. + * @param frame_size int: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * must be a multiple of 2.5 ms. + * @param decode_fec int: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float( + OpusMSDecoder *st, + const unsigned char *data, + opus_int32 len, + float *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on a multistream Opus decoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_decoderctls, or @ref opus_multistream_ctls. + * @see opus_genericctls + * @see opus_decoderctls + * @see opus_multistream_ctls + */ +OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/** Frees an OpusMSDecoder allocated by + * opus_multistream_decoder_create(). + * @param st OpusMSDecoder: Multistream decoder state to be freed. + */ +OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st); + +/**@}*/ + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_MULTISTREAM_H */ diff --git a/Frameworks/Opus.framework/Headers/opus_types.h b/Frameworks/Opus.framework/Headers/opus_types.h new file mode 100644 index 0000000..b28e03a --- /dev/null +++ b/Frameworks/Opus.framework/Headers/opus_types.h @@ -0,0 +1,159 @@ +/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */ +/* Modified by Jean-Marc Valin */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* opus_types.h based on ogg_types.h from libogg */ + +/** + @file opus_types.h + @brief Opus reference implementation types +*/ +#ifndef OPUS_TYPES_H +#define OPUS_TYPES_H + +/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */ +#if (defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H)) +#include + + typedef int16_t opus_int16; + typedef uint16_t opus_uint16; + typedef int32_t opus_int32; + typedef uint32_t opus_uint32; +#elif defined(_WIN32) + +# if defined(__CYGWIN__) +# include <_G_config.h> + typedef _G_int32_t opus_int32; + typedef _G_uint32_t opus_uint32; + typedef _G_int16 opus_int16; + typedef _G_uint16 opus_uint16; +# elif defined(__MINGW32__) + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; +# elif defined(__MWERKS__) + typedef int opus_int32; + typedef unsigned int opus_uint32; + typedef short opus_int16; + typedef unsigned short opus_uint16; +# else + /* MSVC/Borland */ + typedef __int32 opus_int32; + typedef unsigned __int32 opus_uint32; + typedef __int16 opus_int16; + typedef unsigned __int16 opus_uint16; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 opus_int16; + typedef UInt16 opus_uint16; + typedef SInt32 opus_int32; + typedef UInt32 opus_uint32; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t opus_int16; + typedef u_int16_t opus_uint16; + typedef int32_t opus_int32; + typedef u_int32_t opus_uint32; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16 opus_int16; + typedef u_int16 opus_uint16; + typedef int32_t opus_int32; + typedef u_int32_t opus_uint32; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined(R5900) + + /* PS2 EE */ + typedef int opus_int32; + typedef unsigned opus_uint32; + typedef short opus_int16; + typedef unsigned short opus_uint16; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short opus_int16; + typedef unsigned short opus_uint16; + typedef signed int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef long opus_int32; + typedef unsigned long opus_uint32; + +#elif defined(CONFIG_TI_C6X) + + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#else + + /* Give up, take a reasonable guess */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#endif + +#define opus_int int /* used for counters etc; at least 16 bits */ +#define opus_int64 long long +#define opus_int8 signed char + +#define opus_uint unsigned int /* used for counters etc; at least 16 bits */ +#define opus_uint64 unsigned long long +#define opus_uint8 unsigned char + +#endif /* OPUS_TYPES_H */ diff --git a/Frameworks/Opus.framework/Headers/opusfile.h b/Frameworks/Opus.framework/Headers/opusfile.h new file mode 100644 index 0000000..fd7317e --- /dev/null +++ b/Frameworks/Opus.framework/Headers/opusfile.h @@ -0,0 +1,2089 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.h 17182 2010-04-29 03:48:32Z xiphmont $ + + ********************************************************************/ +#if !defined(_opusfile_h) +# define _opusfile_h (1) + +/**\mainpage + \section Introduction + + This is the documentation for the libopusfile C API. + + The libopusfile package provides a convenient high-level API for + decoding and basic manipulation of all Ogg Opus audio streams. + libopusfile is implemented as a layer on top of Xiph.Org's + reference + libogg + and + libopus + libraries. + + libopusfile provides several sets of built-in routines for + file/stream access, and may also use custom stream I/O routines provided by + the embedded environment. + There are built-in I/O routines provided for ANSI-compliant + stdio (FILE *), memory buffers, and URLs + (including URLs, plus optionally and URLs). + + \section Organization + + The main API is divided into several sections: + - \ref stream_open_close + - \ref stream_info + - \ref stream_decoding + - \ref stream_seeking + + Several additional sections are not tied to the main API. + - \ref stream_callbacks + - \ref header_info + - \ref error_codes + + \section Overview + + The libopusfile API always decodes files to 48 kHz. + The original sample rate is not preserved by the lossy compression, though + it is stored in the header to allow you to resample to it after decoding + (the libopusfile API does not currently provide a resampler, + but the + the + Speex resampler is a good choice if you need one). + In general, if you are playing back the audio, you should leave it at + 48 kHz, provided your audio hardware supports it. + When decoding to a file, it may be worth resampling back to the original + sample rate, so as not to surprise users who might not expect the sample + rate to change after encoding to Opus and decoding. + + Opus files can contain anywhere from 1 to 255 channels of audio. + The channel mappings for up to 8 channels are the same as the + Vorbis + mappings. + A special stereo API can convert everything to 2 channels, making it simple + to support multichannel files in an application which only has stereo + output. + Although the libopusfile ABI provides support for the theoretical + maximum number of channels, the current implementation does not support + files with more than 8 channels, as they do not have well-defined channel + mappings. + + Like all Ogg files, Opus files may be "chained". + That is, multiple Opus files may be combined into a single, longer file just + by concatenating the original files. + This is commonly done in internet radio streaming, as it allows the title + and artist to be updated each time the song changes, since each link in the + chain includes its own set of metadata. + + libopusfile fully supports chained files. + It will decode the first Opus stream found in each link of a chained file + (ignoring any other streams that might be concurrently multiplexed with it, + such as a video stream). + + The channel count can also change between links. + If your application is not prepared to deal with this, it can use the stereo + API to ensure the audio from all links will always get decoded into a + common format. + Since libopusfile always decodes to 48 kHz, you do not have to + worry about the sample rate changing between links (as was possible with + Vorbis). + This makes application support for chained files with libopusfile + very easy.*/ + +# if defined(__cplusplus) +extern "C" { +# endif + +# include +# include +# include +# include + +/**@cond PRIVATE*/ + +/*Enable special features for gcc and gcc-compatible compilers.*/ +# if !defined(OP_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define OP_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define OP_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +# if OP_GNUC_PREREQ(4,0) +# pragma GCC visibility push(default) +# endif + +typedef struct OpusHead OpusHead; +typedef struct OpusTags OpusTags; +typedef struct OpusPictureTag OpusPictureTag; +typedef struct OpusServerInfo OpusServerInfo; +typedef struct OpusFileCallbacks OpusFileCallbacks; +typedef struct OggOpusFile OggOpusFile; + +/*Warning attributes for libopusfile functions.*/ +# if OP_GNUC_PREREQ(3,4) +# define OP_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +# else +# define OP_WARN_UNUSED_RESULT +# endif +# if OP_GNUC_PREREQ(3,4) +# define OP_ARG_NONNULL(_x) __attribute__((__nonnull__(_x))) +# else +# define OP_ARG_NONNULL(_x) +# endif + +/**@endcond*/ + +/**\defgroup error_codes Error Codes*/ +/*@{*/ +/**\name List of possible error codes + Many of the functions in this library return a negative error code when a + function fails. + This list provides a brief explanation of the common errors. + See each individual function for more details on what a specific error code + means in that context.*/ +/*@{*/ + +/**A request did not succeed.*/ +#define OP_FALSE (-1) +/*Currently not used externally.*/ +#define OP_EOF (-2) +/**There was a hole in the page sequence numbers (e.g., a page was corrupt or + missing).*/ +#define OP_HOLE (-3) +/**An underlying read, seek, or tell operation failed when it should have + succeeded.*/ +#define OP_EREAD (-128) +/**A NULL pointer was passed where one was unexpected, or an + internal memory allocation failed, or an internal library error was + encountered.*/ +#define OP_EFAULT (-129) +/**The stream used a feature that is not implemented, such as an unsupported + channel family.*/ +#define OP_EIMPL (-130) +/**One or more parameters to a function were invalid.*/ +#define OP_EINVAL (-131) +/**A purported Ogg Opus stream did not begin with an Ogg page, a purported + header packet did not start with one of the required strings, "OpusHead" or + "OpusTags", or a link in a chained file was encountered that did not + contain any logical Opus streams.*/ +#define OP_ENOTFORMAT (-132) +/**A required header packet was not properly formatted, contained illegal + values, or was missing altogether.*/ +#define OP_EBADHEADER (-133) +/**The ID header contained an unrecognized version number.*/ +#define OP_EVERSION (-134) +/*Currently not used at all.*/ +#define OP_ENOTAUDIO (-135) +/**An audio packet failed to decode properly. + This is usually caused by a multistream Ogg packet where the durations of + the individual Opus packets contained in it are not all the same.*/ +#define OP_EBADPACKET (-136) +/**We failed to find data we had seen before, or the bitstream structure was + sufficiently malformed that seeking to the target destination was + impossible.*/ +#define OP_EBADLINK (-137) +/**An operation that requires seeking was requested on an unseekable stream.*/ +#define OP_ENOSEEK (-138) +/**The first or last granule position of a link failed basic validity checks.*/ +#define OP_EBADTIMESTAMP (-139) + +/*@}*/ +/*@}*/ + +/**\defgroup header_info Header Information*/ +/*@{*/ + +/**The maximum number of channels in an Ogg Opus stream.*/ +#define OPUS_CHANNEL_COUNT_MAX (255) + +/**Ogg Opus bitstream information. + This contains the basic playback parameters for a stream, and corresponds to + the initial ID header packet of an Ogg Opus stream.*/ +struct OpusHead{ + /**The Ogg Opus format version, in the range 0...255. + The top 4 bits represent a "major" version, and the bottom four bits + represent backwards-compatible "minor" revisions. + The current specification describes version 1. + This library will recognize versions up through 15 as backwards compatible + with the current specification. + An earlier draft of the specification described a version 0, but the only + difference between version 1 and version 0 is that version 0 did + not specify the semantics for handling the version field.*/ + int version; + /**The number of channels, in the range 1...255.*/ + int channel_count; + /**The number of samples that should be discarded from the beginning of the + stream.*/ + unsigned pre_skip; + /**The sampling rate of the original input. + All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz + for playback (unless the target hardware does not support this sampling + rate). + However, this field may be used to resample the audio back to the original + sampling rate, for example, when saving the output to a file.*/ + opus_uint32 input_sample_rate; + /**The gain to apply to the decoded output, in dB, as a Q8 value in the range + -32768...32767. + The libopusfile API will automatically apply this gain to the + decoded output before returning it, scaling it by + pow(10,output_gain/(20.0*256)).*/ + int output_gain; + /**The channel mapping family, in the range 0...255. + Channel mapping family 0 covers mono or stereo in a single stream. + Channel mapping family 1 covers 1 to 8 channels in one or more streams, + using the Vorbis speaker assignments. + Channel mapping family 255 covers 1 to 255 channels in one or more + streams, but without any defined speaker assignment.*/ + int mapping_family; + /**The number of Opus streams in each Ogg packet, in the range 1...255.*/ + int stream_count; + /**The number of coupled Opus streams in each Ogg packet, in the range + 0...127. + This must satisfy 0 <= coupled_count <= stream_count and + coupled_count + stream_count <= 255. + The coupled streams appear first, before all uncoupled streams, in an Ogg + Opus packet.*/ + int coupled_count; + /**The mapping from coded stream channels to output channels. + Let index=mapping[k] be the value for channel k. + If index<2*coupled_count, then it refers to the left channel + from stream (index/2) if even, and the right channel from + stream (index/2) if odd. + Otherwise, it refers to the output of the uncoupled stream + (index-coupled_count).*/ + unsigned char mapping[OPUS_CHANNEL_COUNT_MAX]; +}; + +/**The metadata from an Ogg Opus stream. + + This structure holds the in-stream metadata corresponding to the 'comment' + header packet of an Ogg Opus stream. + The comment header is meant to be used much like someone jotting a quick + note on the label of a CD. + It should be a short, to the point text note that can be more than a couple + words, but not more than a short paragraph. + + The metadata is stored as a series of (tag, value) pairs, in length-encoded + string vectors, using the same format as Vorbis (without the final "framing + bit"), Theora, and Speex, except for the packet header. + The first occurrence of the '=' character delimits the tag and value. + A particular tag may occur more than once, and order is significant. + The character set encoding for the strings is always UTF-8, but the tag + names are limited to ASCII, and treated as case-insensitive. + See the Vorbis + comment header specification for details. + + In filling in this structure, libopusfile will null-terminate the + #user_comments strings for safety. + However, the bitstream format itself treats them as 8-bit clean vectors, + possibly containing NUL characters, so the #comment_lengths array should be + treated as their authoritative length. + + This structure is binary and source-compatible with a + vorbis_comment, and pointers to it may be freely cast to + vorbis_comment pointers, and vice versa. + It is provided as a separate type to avoid introducing a compile-time + dependency on the libvorbis headers.*/ +struct OpusTags{ + /**The array of comment string vectors.*/ + char **user_comments; + /**An array of the corresponding length of each vector, in bytes.*/ + int *comment_lengths; + /**The total number of comment streams.*/ + int comments; + /**The null-terminated vendor string. + This identifies the software used to encode the stream.*/ + char *vendor; +}; + +/**\name Picture tag image formats*/ +/*@{*/ + +/**The MIME type was not recognized, or the image data did not match the + declared MIME type.*/ +#define OP_PIC_FORMAT_UNKNOWN (-1) +/**The MIME type indicates the image data is really a URL.*/ +#define OP_PIC_FORMAT_URL (0) +/**The image is a JPEG.*/ +#define OP_PIC_FORMAT_JPEG (1) +/**The image is a PNG.*/ +#define OP_PIC_FORMAT_PNG (2) +/**The image is a GIF.*/ +#define OP_PIC_FORMAT_GIF (3) + +/*@}*/ + +/**The contents of a METADATA_BLOCK_PICTURE tag.*/ +struct OpusPictureTag{ + /**The picture type according to the ID3v2 APIC frame: +
    +
  1. Other
  2. +
  3. 32x32 pixels 'file icon' (PNG only)
  4. +
  5. Other file icon
  6. +
  7. Cover (front)
  8. +
  9. Cover (back)
  10. +
  11. Leaflet page
  12. +
  13. Media (e.g. label side of CD)
  14. +
  15. Lead artist/lead performer/soloist
  16. +
  17. Artist/performer
  18. +
  19. Conductor
  20. +
  21. Band/Orchestra
  22. +
  23. Composer
  24. +
  25. Lyricist/text writer
  26. +
  27. Recording Location
  28. +
  29. During recording
  30. +
  31. During performance
  32. +
  33. Movie/video screen capture
  34. +
  35. A bright colored fish
  36. +
  37. Illustration
  38. +
  39. Band/artist logotype
  40. +
  41. Publisher/Studio logotype
  42. +
+ Others are reserved and should not be used. + There may only be one each of picture type 1 and 2 in a file.*/ + opus_int32 type; + /**The MIME type of the picture, in printable ASCII characters 0x20-0x7E. + The MIME type may also be "-->" to signify that the data part + is a URL pointing to the picture instead of the picture data itself. + In this case, a terminating NUL is appended to the URL string in #data, + but #data_length is set to the length of the string excluding that + terminating NUL.*/ + char *mime_type; + /**The description of the picture, in UTF-8.*/ + char *description; + /**The width of the picture in pixels.*/ + opus_uint32 width; + /**The height of the picture in pixels.*/ + opus_uint32 height; + /**The color depth of the picture in bits-per-pixel (not + bits-per-channel).*/ + opus_uint32 depth; + /**For indexed-color pictures (e.g., GIF), the number of colors used, or 0 + for non-indexed pictures.*/ + opus_uint32 colors; + /**The length of the picture data in bytes.*/ + opus_uint32 data_length; + /**The binary picture data.*/ + unsigned char *data; + /**The format of the picture data, if known. + One of +
    +
  • #OP_PIC_FORMAT_UNKNOWN,
  • +
  • #OP_PIC_FORMAT_URL,
  • +
  • #OP_PIC_FORMAT_JPEG,
  • +
  • #OP_PIC_FORMAT_PNG, or
  • +
  • #OP_PIC_FORMAT_GIF.
  • +
*/ + int format; +}; + +/**\name Functions for manipulating header data + + These functions manipulate the #OpusHead and #OpusTags structures, + which describe the audio parameters and tag-value metadata, respectively. + These can be used to query the headers returned by libopusfile, or + to parse Opus headers from sources other than an Ogg Opus stream, provided + they use the same format.*/ +/*@{*/ + +/**Parses the contents of the ID header packet of an Ogg Opus stream. + \param[out] _head Returns the contents of the parsed packet. + The contents of this structure are untouched on error. + This may be NULL to merely test the header + for validity. + \param[in] _data The contents of the ID header packet. + \param _len The number of bytes of data in the ID header packet. + \return 0 on success or a negative value on error. + \retval #OP_ENOTFORMAT If the data does not start with the "OpusHead" + string. + \retval #OP_EVERSION If the version field signaled a version this library + does not know how to parse. + \retval #OP_EIMPL If the channel mapping family was 255, which general + purpose players should not attempt to play. + \retval #OP_EBADHEADER If the contents of the packet otherwise violate the + Ogg Opus specification: +
    +
  • Insufficient data,
  • +
  • Too much data for the known minor versions,
  • +
  • An unrecognized channel mapping family,
  • +
  • Zero channels or too many channels,
  • +
  • Zero coded streams,
  • +
  • Too many coupled streams, or
  • +
  • An invalid channel mapping index.
  • +
*/ +OP_WARN_UNUSED_RESULT int opus_head_parse(OpusHead *_head, + const unsigned char *_data,size_t _len) OP_ARG_NONNULL(2); + +/**Converts a granule position to a sample offset for a given Ogg Opus stream. + The sample offset is simply _gp-_head->pre_skip. + Granule position values smaller than OpusHead#pre_skip correspond to audio + that should never be played, and thus have no associated sample offset. + This function returns -1 for such values. + This function also correctly handles extremely large granule positions, + which may have wrapped around to a negative number when stored in a signed + ogg_int64_t value. + \param _head The #OpusHead information from the ID header of the stream. + \param _gp The granule position to convert. + \return The sample offset associated with the given granule position + (counting at a 48 kHz sampling rate), or the special value -1 on + error (i.e., the granule position was smaller than the pre-skip + amount).*/ +ogg_int64_t opus_granule_sample(const OpusHead *_head,ogg_int64_t _gp) + OP_ARG_NONNULL(1); + +/**Parses the contents of the 'comment' header packet of an Ogg Opus stream. + \param[out] _tags An uninitialized #OpusTags structure. + This returns the contents of the parsed packet. + The contents of this structure are untouched on error. + This may be NULL to merely test the header + for validity. + \param[in] _data The contents of the 'comment' header packet. + \param _len The number of bytes of data in the 'info' header packet. + \retval 0 Success. + \retval #OP_ENOTFORMAT If the data does not start with the "OpusTags" + string. + \retval #OP_EBADHEADER If the contents of the packet otherwise violate the + Ogg Opus specification. + \retval #OP_EFAULT If there wasn't enough memory to store the tags.*/ +OP_WARN_UNUSED_RESULT int opus_tags_parse(OpusTags *_tags, + const unsigned char *_data,size_t _len) OP_ARG_NONNULL(2); + +/**Performs a deep copy of an #OpusTags structure. + \param _dst The #OpusTags structure to copy into. + If this function fails, the contents of this structure remain + untouched. + \param _src The #OpusTags structure to copy from. + \retval 0 Success. + \retval #OP_EFAULT If there wasn't enough memory to copy the tags.*/ +int opus_tags_copy(OpusTags *_dst,const OpusTags *_src) OP_ARG_NONNULL(1); + +/**Initializes an #OpusTags structure. + This should be called on a freshly allocated #OpusTags structure before + attempting to use it. + \param _tags The #OpusTags structure to initialize.*/ +void opus_tags_init(OpusTags *_tags) OP_ARG_NONNULL(1); + +/**Add a (tag, value) pair to an initialized #OpusTags structure. + \note Neither opus_tags_add() nor opus_tags_add_comment() support values + containing embedded NULs, although the bitstream format does support them. + To add such tags, you will need to manipulate the #OpusTags structure + directly. + \param _tags The #OpusTags structure to add the (tag, value) pair to. + \param _tag A NUL-terminated, case-insensitive, ASCII string containing + the tag to add (without an '=' character). + \param _value A NUL-terminated UTF-8 containing the corresponding value. + \return 0 on success, or a negative value on failure. + \retval #OP_EFAULT An internal memory allocation failed.*/ +int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2) OP_ARG_NONNULL(3); + +/**Add a comment to an initialized #OpusTags structure. + \note Neither opus_tags_add_comment() nor opus_tags_add() support comments + containing embedded NULs, although the bitstream format does support them. + To add such tags, you will need to manipulate the #OpusTags structure + directly. + \param _tags The #OpusTags structure to add the comment to. + \param _comment A NUL-terminated UTF-8 string containing the comment in + "TAG=value" form. + \return 0 on success, or a negative value on failure. + \retval #OP_EFAULT An internal memory allocation failed.*/ +int opus_tags_add_comment(OpusTags *_tags,const char *_comment) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Look up a comment value by its tag. + \param _tags An initialized #OpusTags structure. + \param _tag The tag to look up. + \param _count The instance of the tag. + The same tag can appear multiple times, each with a distinct + value, so an index is required to retrieve them all. + The order in which these values appear is significant and + should be preserved. + Use opus_tags_query_count() to get the legal range for the + \a _count parameter. + \return A pointer to the queried tag's value. + This points directly to data in the #OpusTags structure. + It should not be modified or freed by the application, and + modifications to the structure may invalidate the pointer. + \retval NULL If no matching tag is found.*/ +const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Look up the number of instances of a tag. + Call this first when querying for a specific tag and then iterate over the + number of instances with separate calls to opus_tags_query() to retrieve + all the values for that tag in order. + \param _tags An initialized #OpusTags structure. + \param _tag The tag to look up. + \return The number of instances of this particular tag.*/ +int opus_tags_query_count(const OpusTags *_tags,const char *_tag) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Get the track gain from an R128_TRACK_GAIN tag, if one was specified. + This searches for the first R128_TRACK_GAIN tag with a valid signed, + 16-bit decimal integer value and returns the value. + This routine is exposed merely for convenience for applications which wish + to do something special with the track gain (i.e., display it). + If you simply wish to apply the track gain instead of the header gain, you + can use op_set_gain_offset() with an #OP_TRACK_GAIN type and no offset. + \param _tags An initialized #OpusTags structure. + \param[out] _gain_q8 The track gain, in 1/256ths of a dB. + This will lie in the range [-32768,32767], and should + be applied in addition to the header gain. + On error, no value is returned, and the previous + contents remain unchanged. + \return 0 on success, or a negative value on error. + \retval #OP_FALSE There was no track gain available in the given tags.*/ +int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Clears the #OpusTags structure. + This should be called on an #OpusTags structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _tags The #OpusTags structure to clear.*/ +void opus_tags_clear(OpusTags *_tags) OP_ARG_NONNULL(1); + +/**Check if \a _comment is an instance of a \a _tag_name tag. + \see opus_tagncompare + \param _tag_name A NUL-terminated, case-insensitive, ASCII string containing + the name of the tag to check for (without the terminating + '=' character). + \param _comment The comment string to check. + \return An integer less than, equal to, or greater than zero if \a _comment + is found respectively, to be less than, to match, or be greater + than a "tag=value" string whose tag matches \a _tag_name.*/ +int opus_tagcompare(const char *_tag_name,const char *_comment); + +/**Check if \a _comment is an instance of a \a _tag_name tag. + This version is slightly more efficient than opus_tagcompare() if the length + of the tag name is already known (e.g., because it is a constant). + \see opus_tagcompare + \param _tag_name A case-insensitive ASCII string containing the name of the + tag to check for (without the terminating '=' character). + \param _tag_len The number of characters in the tag name. + This must be non-negative. + \param _comment The comment string to check. + \return An integer less than, equal to, or greater than zero if \a _comment + is found respectively, to be less than, to match, or be greater + than a "tag=value" string whose tag matches the first \a _tag_len + characters of \a _tag_name.*/ +int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment); + +/**Parse a single METADATA_BLOCK_PICTURE tag. + This decodes the BASE64-encoded content of the tag and returns a structure + with the MIME type, description, image parameters (if known), and the + compressed image data. + If the MIME type indicates the presence of an image format we recognize + (JPEG, PNG, or GIF) and the actual image data contains the magic signature + associated with that format, then the OpusPictureTag::format field will be + set to the corresponding format. + This is provided as a convenience to avoid requiring applications to parse + the MIME type and/or do their own format detection for the commonly used + formats. + In this case, we also attempt to extract the image parameters directly from + the image data (overriding any that were present in the tag, which the + specification says applications are not meant to rely on). + The application must still provide its own support for actually decoding the + image data and, if applicable, retrieving that data from URLs. + \param[out] _pic Returns the parsed picture data. + No sanitation is done on the type, MIME type, or + description fields, so these might return invalid values. + The contents of this structure are left unmodified on + failure. + \param _tag The METADATA_BLOCK_PICTURE tag contents. + The leading "METADATA_BLOCK_PICTURE=" portion is optional, + to allow the function to be used on either directly on the + values in OpusTags::user_comments or on the return value + of opus_tags_query(). + \return 0 on success or a negative value on error. + \retval #OP_ENOTFORMAT The METADATA_BLOCK_PICTURE contents were not valid. + \retval #OP_EFAULT There was not enough memory to store the picture tag + contents.*/ +OP_WARN_UNUSED_RESULT int opus_picture_tag_parse(OpusPictureTag *_pic, + const char *_tag) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Initializes an #OpusPictureTag structure. + This should be called on a freshly allocated #OpusPictureTag structure + before attempting to use it. + \param _pic The #OpusPictureTag structure to initialize.*/ +void opus_picture_tag_init(OpusPictureTag *_pic) OP_ARG_NONNULL(1); + +/**Clears the #OpusPictureTag structure. + This should be called on an #OpusPictureTag structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _pic The #OpusPictureTag structure to clear.*/ +void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1); + +/*@}*/ + +/*@}*/ + +/**\defgroup url_options URL Reading Options*/ +/*@{*/ +/**\name URL reading options + Options for op_url_stream_create() and associated functions. + These allow you to provide proxy configuration parameters, skip SSL + certificate checks, etc. + Options are processed in order, and if the same option is passed multiple + times, only the value specified by the last occurrence has an effect + (unless otherwise specified). + They may be expanded in the future.*/ +/*@{*/ + +/**@cond PRIVATE*/ + +/*These are the raw numbers used to define the request codes. + They should not be used directly.*/ +#define OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST (6464) +#define OP_HTTP_PROXY_HOST_REQUEST (6528) +#define OP_HTTP_PROXY_PORT_REQUEST (6592) +#define OP_HTTP_PROXY_USER_REQUEST (6656) +#define OP_HTTP_PROXY_PASS_REQUEST (6720) +#define OP_GET_SERVER_INFO_REQUEST (6784) + +#define OP_URL_OPT(_request) ((_request)+(char *)0) + +/*These macros trigger compilation errors or warnings if the wrong types are + provided to one of the URL options.*/ +#define OP_CHECK_INT(_x) ((void)((_x)==(opus_int32)0),(opus_int32)(_x)) +#define OP_CHECK_CONST_CHAR_PTR(_x) ((_x)+((_x)-(const char *)(_x))) +#define OP_CHECK_SERVER_INFO_PTR(_x) ((_x)+((_x)-(OpusServerInfo *)(_x))) + +/**@endcond*/ + +/**HTTP/Shoutcast/Icecast server information associated with a URL.*/ +struct OpusServerInfo{ + /**The name of the server (icy-name/ice-name). + This is NULL if there was no icy-name or + ice-name header.*/ + char *name; + /**A short description of the server (icy-description/ice-description). + This is NULL if there was no icy-description or + ice-description header.*/ + char *description; + /**The genre the server falls under (icy-genre/ice-genre). + This is NULL if there was no icy-genre or + ice-genre header.*/ + char *genre; + /**The homepage for the server (icy-url/ice-url). + This is NULL if there was no icy-url or + ice-url header.*/ + char *url; + /**The software used by the origin server (Server). + This is NULL if there was no Server header.*/ + char *server; + /**The media type of the entity sent to the recepient (Content-Type). + This is NULL if there was no Content-Type + header.*/ + char *content_type; + /**The nominal stream bitrate in kbps (icy-br/ice-bitrate). + This is -1 if there was no icy-br or + ice-bitrate header.*/ + opus_int32 bitrate_kbps; + /**Flag indicating whether the server is public (1) or not + (0) (icy-pub/ice-public). + This is -1 if there was no icy-pub or + ice-public header.*/ + int is_public; + /**Flag indicating whether the server is using HTTPS instead of HTTP. + This is 0 unless HTTPS is being used. + This may not match the protocol used in the original URL if there were + redirections.*/ + int is_ssl; +}; + +/**Initializes an #OpusServerInfo structure. + All fields are set as if the corresponding header was not available. + \param _info The #OpusServerInfo structure to initialize. + \note If you use this function, you must link against libopusurl.*/ +void opus_server_info_init(OpusServerInfo *_info) OP_ARG_NONNULL(1); + +/**Clears the #OpusServerInfo structure. + This should be called on an #OpusServerInfo structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _info The #OpusServerInfo structure to clear. + \note If you use this function, you must link against libopusurl.*/ +void opus_server_info_clear(OpusServerInfo *_info) OP_ARG_NONNULL(1); + +/**Skip the certificate check when connecting via TLS/SSL (https). + \param _b opus_int32: Whether or not to skip the certificate + check. + The check will be skipped if \a _b is non-zero, and will not be + skipped if \a _b is zero. + \hideinitializer*/ +#define OP_SSL_SKIP_CERTIFICATE_CHECK(_b) \ + OP_URL_OPT(OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST),OP_CHECK_INT(_b) + +/**Proxy connections through the given host. + If no port is specified via #OP_HTTP_PROXY_PORT, the port number defaults + to 8080 (http-alt). + All proxy parameters are ignored for non-http and non-https URLs. + \param _host const char *: The proxy server hostname. + This may be NULL to disable the use of a proxy + server. + \hideinitializer*/ +#define OP_HTTP_PROXY_HOST(_host) \ + OP_URL_OPT(OP_HTTP_PROXY_HOST_REQUEST),OP_CHECK_CONST_CHAR_PTR(_host) + +/**Use the given port when proxying connections. + This option only has an effect if #OP_HTTP_PROXY_HOST is specified with a + non-NULL \a _host. + If this option is not provided, the proxy port number defaults to 8080 + (http-alt). + All proxy parameters are ignored for non-http and non-https URLs. + \param _port opus_int32: The proxy server port. + This must be in the range 0...65535 (inclusive), or the + URL function this is passed to will fail. + \hideinitializer*/ +#define OP_HTTP_PROXY_PORT(_port) \ + OP_URL_OPT(OP_HTTP_PROXY_PORT_REQUEST),OP_CHECK_INT(_port) + +/**Use the given user name for authentication when proxying connections. + All proxy parameters are ignored for non-http and non-https URLs. + \param _user const char *: The proxy server user name. + This may be NULL to disable proxy + authentication. + A non-NULL value only has an effect + if #OP_HTTP_PROXY_HOST and #OP_HTTP_PROXY_PASS + are also specified with non-NULL + arguments. + \hideinitializer*/ +#define OP_HTTP_PROXY_USER(_user) \ + OP_URL_OPT(OP_HTTP_PROXY_USER_REQUEST),OP_CHECK_CONST_CHAR_PTR(_user) + +/**Use the given password for authentication when proxying connections. + All proxy parameters are ignored for non-http and non-https URLs. + \param _pass const char *: The proxy server password. + This may be NULL to disable proxy + authentication. + A non-NULL value only has an effect + if #OP_HTTP_PROXY_HOST and #OP_HTTP_PROXY_USER + are also specified with non-NULL + arguments. + \hideinitializer*/ +#define OP_HTTP_PROXY_PASS(_pass) \ + OP_URL_OPT(OP_HTTP_PROXY_PASS_REQUEST),OP_CHECK_CONST_CHAR_PTR(_pass) + +/**Parse information about the streaming server (if any) and return it. + Very little validation is done. + In particular, OpusServerInfo::url may not be a valid URL, + OpusServerInfo::bitrate_kbps may not really be in kbps, and + OpusServerInfo::content_type may not be a valid MIME type. + The character set of the string fields is not specified anywhere, and should + not be assumed to be valid UTF-8. + \param _info OpusServerInfo *: Returns information about the server. + If there is any error opening the stream, the + contents of this structure remain + unmodified. + On success, fills in the structure with the + server information that was available, if + any. + After a successful return, the contents of + this structure should be freed by calling + opus_server_info_clear(). + \hideinitializer*/ +#define OP_GET_SERVER_INFO(_info) \ + OP_URL_OPT(OP_GET_SERVER_INFO_REQUEST),OP_CHECK_SERVER_INFO_PTR(_info) + +/*@}*/ +/*@}*/ + +/**\defgroup stream_callbacks Abstract Stream Reading Interface*/ +/*@{*/ +/**\name Functions for reading from streams + These functions define the interface used to read from and seek in a stream + of data. + A stream does not need to implement seeking, but the decoder will not be + able to seek if it does not do so. + These functions also include some convenience routines for working with + standard FILE pointers, complete streams stored in a single + block of memory, or URLs.*/ +/*@{*/ + +/**Reads up to \a _nbytes bytes of data from \a _stream. + \param _stream The stream to read from. + \param[out] _ptr The buffer to store the data in. + \param _nbytes The maximum number of bytes to read. + This function may return fewer, though it will not + return zero unless it reaches end-of-file. + \return The number of bytes successfully read, or a negative value on + error.*/ +typedef int (*op_read_func)(void *_stream,unsigned char *_ptr,int _nbytes); + +/**Sets the position indicator for \a _stream. + The new position, measured in bytes, is obtained by adding \a _offset + bytes to the position specified by \a _whence. + If \a _whence is set to SEEK_SET, SEEK_CUR, or + SEEK_END, the offset is relative to the start of the stream, + the current position indicator, or end-of-file, respectively. + \retval 0 Success. + \retval -1 Seeking is not supported or an error occurred. + errno need not be set.*/ +typedef int (*op_seek_func)(void *_stream,opus_int64 _offset,int _whence); + +/**Obtains the current value of the position indicator for \a _stream. + \return The current position indicator.*/ +typedef opus_int64 (*op_tell_func)(void *_stream); + +/**Closes the underlying stream. + \retval 0 Success. + \retval EOF An error occurred. + errno need not be set.*/ +typedef int (*op_close_func)(void *_stream); + +/**The callbacks used to access non-FILE stream resources. + The function prototypes are basically the same as for the stdio functions + fread(), fseek(), ftell(), and + fclose(). + The differences are that the FILE * arguments have been + replaced with a void *, which is to be used as a pointer to + whatever internal data these functions might need, that #seek and #tell + take and return 64-bit offsets, and that #seek must return -1 if + the stream is unseekable.*/ +struct OpusFileCallbacks{ + /**Used to read data from the stream. + This must not be NULL.*/ + op_read_func read; + /**Used to seek in the stream. + This may be NULL if seeking is not implemented.*/ + op_seek_func seek; + /**Used to return the current read position in the stream. + This may be NULL if seeking is not implemented.*/ + op_tell_func tell; + /**Used to close the stream when the decoder is freed. + This may be NULL to leave the stream open.*/ + op_close_func close; +}; + +/**Opens a stream with fopen() and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + FILE * must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _path The path to the file to open. + On Windows, this string must be UTF-8 (to allow access to + files whose names cannot be represented in the current + MBCS code page). + All other systems use the native character encoding. + \param _mode The mode to open the file in. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_fopen(OpusFileCallbacks *_cb, + const char *_path,const char *_mode) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2) + OP_ARG_NONNULL(3); + +/**Opens a stream with fdopen() and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + FILE * must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _fd The file descriptor to open. + \param _mode The mode to open the file in. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_fdopen(OpusFileCallbacks *_cb, + int _fd,const char *_mode) OP_ARG_NONNULL(1) OP_ARG_NONNULL(3); + +/**Opens a stream with freopen() and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + FILE * must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _path The path to the file to open. + On Windows, this string must be UTF-8 (to allow access + to files whose names cannot be represented in the + current MBCS code page). + All other systems use the native character encoding. + \param _mode The mode to open the file in. + \param _stream A stream previously returned by op_fopen(), op_fdopen(), + or op_freopen(). + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_freopen(OpusFileCallbacks *_cb, + const char *_path,const char *_mode,void *_stream) OP_ARG_NONNULL(1) + OP_ARG_NONNULL(2) OP_ARG_NONNULL(3) OP_ARG_NONNULL(4); + +/**Creates a stream that reads from the given block of memory. + This block of memory must contain the complete stream to decode. + This is useful for caching small streams (e.g., sound effects) in RAM. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will be + filled in here. + \param _data The block of memory to read from. + \param _size The size of the block of memory. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_mem_stream_create(OpusFileCallbacks *_cb, + const unsigned char *_data,size_t _size) OP_ARG_NONNULL(1); + +/**Creates a stream that reads from the given URL. + This function behaves identically to op_url_stream_create(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the va_end macro, and because it invokes the + va_arg macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against libopusurl. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will + be filled in here. + \param _url The URL to read from. + Currently only the , , and + schemes are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[in,out] _ap A list of the \ref url_options "optional flags" to use. + This is a variable-length list of options terminated + with NULL. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_url_stream_vcreate(OpusFileCallbacks *_cb, + const char *_url,va_list _ap) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Creates a stream that reads from the given URL. + \note If you use this function, you must link against libopusurl. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will be + filled in here. + \param _url The URL to read from. + Currently only the , , and schemes + are supported. + Both and may be disabled at compile time, + in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, before + passing them to this function. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated with + NULL. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_url_stream_create(OpusFileCallbacks *_cb, + const char *_url,...) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_open_close Opening and Closing*/ +/*@{*/ +/**\name Functions for opening and closing streams + + These functions allow you to test a stream to see if it is Opus, open it, + and close it. + Several flavors are provided for each of the built-in stream types, plus a + more general version which takes a set of application-provided callbacks.*/ +/*@{*/ + +/**Test to see if this is an Opus stream. + For good results, you will need at least 57 bytes (for a pure Opus-only + stream). + Something like 512 bytes will give more reliable results for multiplexed + streams. + This function is meant to be a quick-rejection filter. + Its purpose is not to guarantee that a stream is a valid Opus stream, but to + ensure that it looks enough like Opus that it isn't going to be recognized + as some other format (except possibly an Opus stream that is also + multiplexed with other codecs, such as video). + \param[out] _head The parsed ID header contents. + You may pass NULL if you do not need + this information. + If the function fails, the contents of this structure + remain untouched. + \param _initial_data An initial buffer of data from the start of the + stream. + \param _initial_bytes The number of bytes in \a _initial_data. + \return 0 if the data appears to be Opus, or a negative value on error. + \retval #OP_FALSE There was not enough data to tell if this was an Opus + stream or not. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL The stream used a feature that is not implemented, + such as an unsupported channel family. + \retval #OP_ENOTFORMAT If the data did not contain a recognizable ID + header for an Opus stream. + \retval #OP_EVERSION If the version field signaled a version this library + does not know how to parse. + \retval #OP_EBADHEADER The ID header was not properly formatted or contained + illegal values.*/ +int op_test(OpusHead *_head, + const unsigned char *_initial_data,size_t _initial_bytes); + +/**Open a stream from the given file path. + \param _path The path to the file to open. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + The failure code will be #OP_EFAULT if the file could not + be opened, or one of the other failure codes from + op_open_callbacks() otherwise. + \return A freshly opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_file(const char *_path,int *_error) + OP_ARG_NONNULL(1); + +/**Open a stream from a memory buffer. + \param _data The memory buffer to open. + \param _size The number of bytes in the buffer. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \return A freshly opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_memory(const unsigned char *_data, + size_t _size,int *_error); + +/**Open a stream from a URL. + This function behaves identically to op_open_url(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the va_end macro, and because it invokes the + va_arg macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against libopusurl. + \param _url The URL to open. + Currently only the , , and + schemes are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always + fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, + with internationalized domain names encoded in + punycode, before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \param[in,out] _ap A list of the \ref url_options "optional flags" to + use. + This is a variable-length list of options terminated + with NULL. + \return A freshly opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_vopen_url(const char *_url, + int *_error,va_list _ap) OP_ARG_NONNULL(1); + +/**Open a stream from a URL. + \note If you use this function, you must link against libopusurl. + \param _url The URL to open. + Currently only the , , and schemes + are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated with + NULL. + \return A freshly opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url, + int *_error,...) OP_ARG_NONNULL(1); + +/**Open a stream using the given set of callbacks to access it. + \param _source The stream to read from (e.g., a FILE *). + \param _cb The callbacks with which to access the stream. + read() must + be implemented. + seek() and + tell() may + be NULL, or may always return -1 to + indicate a source is unseekable, but if + seek() is + implemented and succeeds on a particular source, then + tell() must + also. + close() may + be NULL, but if it is not, it will be + called when the \c OggOpusFile is destroyed by + op_free(). + It will not be called if op_open_callbacks() fails + with an error. + \param _initial_data An initial buffer of data from the start of the + stream. + Applications can read some number of bytes from the + start of the stream to help identify this as an Opus + stream, and then provide them here to allow the + stream to be opened, even if it is unseekable. + \param _initial_bytes The number of bytes in \a _initial_data. + If the stream is seekable, its current position (as + reported by + tell() + at the start of this function) must be equal to + \a _initial_bytes. + Otherwise, seeking to absolute positions will + generate inconsistent results. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want + the failure code. + The failure code will be one of +
+
#OP_EREAD
+
An underlying read, seek, or tell operation + failed when it should have succeeded, or we failed + to find data in the stream we had seen before.
+
#OP_EFAULT
+
There was a memory allocation failure, or an + internal library error.
+
#OP_EIMPL
+
The stream used a feature that is not + implemented, such as an unsupported channel + family.
+
#OP_EINVAL
+
seek() + was implemented and succeeded on this source, but + tell() + did not, or the starting position indicator was + not equal to \a _initial_bytes.
+
#OP_ENOTFORMAT
+
The stream contained a link that did not have + any logical Opus streams in it.
+
#OP_EBADHEADER
+
A required header packet was not properly + formatted, contained illegal values, or was missing + altogether.
+
#OP_EVERSION
+
An ID header contained an unrecognized version + number.
+
#OP_EBADLINK
+
We failed to find data we had seen before after + seeking.
+
#OP_EBADTIMESTAMP
+
The first or last timestamp in a link failed + basic validity checks.
+
+ \return A freshly opened \c OggOpusFile, or NULL on error. + libopusfile does not take ownership of the source + if the call fails. + The calling application is responsible for closing the source if + this call returns an error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_callbacks(void *_source, + const OpusFileCallbacks *_cb,const unsigned char *_initial_data, + size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2); + +/**Partially open a stream from the given file path. + \see op_test_callbacks + \param _path The path to the file to open. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + The failure code will be #OP_EFAULT if the file could not + be opened, or one of the other failure codes from + op_open_callbacks() otherwise. + \return A partially opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_file(const char *_path,int *_error) + OP_ARG_NONNULL(1); + +/**Partially open a stream from a memory buffer. + \see op_test_callbacks + \param _data The memory buffer to open. + \param _size The number of bytes in the buffer. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \return A partially opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_memory(const unsigned char *_data, + size_t _size,int *_error); + +/**Partially open a stream from a URL. + This function behaves identically to op_test_url(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the va_end macro, and because it invokes the + va_arg macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against libopusurl. + \see op_test_url + \see op_test_callbacks + \param _url The URL to open. + Currently only the , , and + schemes are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always + fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, + with internationalized domain names encoded in + punycode, before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \param[in,out] _ap A list of the \ref url_options "optional flags" to + use. + This is a variable-length list of options terminated + with NULL. + \return A partially opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_vtest_url(const char *_url, + int *_error,va_list _ap) OP_ARG_NONNULL(1); + +/**Partially open a stream from a URL. + \note If you use this function, you must link against libopusurl. + \see op_test_callbacks + \param _url The URL to open. + Currently only the , , and + schemes are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + See op_open_callbacks() for a full list of failure + codes. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated + with NULL. + \return A partially opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url, + int *_error,...) OP_ARG_NONNULL(1); + +/**Partially open a stream using the given set of callbacks to access it. + This tests for Opusness and loads the headers for the first link. + It does not seek (although it tests for seekability). + You can query a partially open stream for the few pieces of basic + information returned by op_serialno(), op_channel_count(), op_head(), and + op_tags() (but only for the first link). + You may also determine if it is seekable via a call to op_seekable(). + You cannot read audio from the stream, seek, get the size or duration, + get information from links other than the first one, or even get the total + number of links until you finish opening the stream with op_test_open(). + If you do not need to do any of these things, you can dispose of it with + op_free() instead. + + This function is provided mostly to simplify porting existing code that used + libvorbisfile. + For new code, you are likely better off using op_test() instead, which + is less resource-intensive, requires less data to succeed, and imposes a + hard limit on the amount of data it examines (important for unseekable + sources, where all such data must be buffered until you are sure of the + stream type). + \param _source The stream to read from (e.g., a FILE *). + \param _cb The callbacks with which to access the stream. + read() must + be implemented. + seek() and + tell() may + be NULL, or may always return -1 to + indicate a source is unseekable, but if + seek() is + implemented and succeeds on a particular source, then + tell() must + also. + close() may + be NULL, but if it is not, it will be + called when the \c OggOpusFile is destroyed by + op_free(). + It will not be called if op_open_callbacks() fails + with an error. + \param _initial_data An initial buffer of data from the start of the + stream. + Applications can read some number of bytes from the + start of the stream to help identify this as an Opus + stream, and then provide them here to allow the + stream to be tested more thoroughly, even if it is + unseekable. + \param _initial_bytes The number of bytes in \a _initial_data. + If the stream is seekable, its current position (as + reported by + tell() + at the start of this function) must be equal to + \a _initial_bytes. + Otherwise, seeking to absolute positions will + generate inconsistent results. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \return A partially opened \c OggOpusFile, or NULL on error. + libopusfile does not take ownership of the source + if the call fails. + The calling application is responsible for closing the source if + this call returns an error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_callbacks(void *_source, + const OpusFileCallbacks *_cb,const unsigned char *_initial_data, + size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2); + +/**Finish opening a stream partially opened with op_test_callbacks() or one of + the associated convenience functions. + If this function fails, you are still responsible for freeing the + \c OggOpusFile with op_free(). + \param _of The \c OggOpusFile to finish opening. + \return 0 on success, or a negative value on error. + \retval #OP_EREAD An underlying read, seek, or tell operation failed + when it should have succeeded. + \retval #OP_EFAULT There was a memory allocation failure, or an + internal library error. + \retval #OP_EIMPL The stream used a feature that is not implemented, + such as an unsupported channel family. + \retval #OP_EINVAL The stream was not partially opened with + op_test_callbacks() or one of the associated + convenience functions. + \retval #OP_ENOTFORMAT The stream contained a link that did not have any + logical Opus streams in it. + \retval #OP_EBADHEADER A required header packet was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An ID header contained an unrecognized version + number. + \retval #OP_EBADLINK We failed to find data we had seen before after + seeking. + \retval #OP_EBADTIMESTAMP The first or last timestamp in a link failed basic + validity checks.*/ +int op_test_open(OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Release all memory used by an \c OggOpusFile. + \param _of The \c OggOpusFile to free.*/ +void op_free(OggOpusFile *_of); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_info Stream Information*/ +/*@{*/ +/**\name Functions for obtaining information about streams + + These functions allow you to get basic information about a stream, including + seekability, the number of links (for chained streams), plus the size, + duration, bitrate, header parameters, and meta information for each link + (or, where available, the stream as a whole). + Some of these (size, duration) are only available for seekable streams. + You can also query the current stream position, link, and playback time, + and instantaneous bitrate during playback. + + Some of these functions may be used successfully on the partially open + streams returned by op_test_callbacks() or one of the associated + convenience functions. + Their documention will indicate so explicitly.*/ +/*@{*/ + +/**Returns whether or not the data source being read is seekable. + This is true if +
    +
  1. The seek() and + tell() callbacks are both + non-NULL,
  2. +
  3. The seek() callback was + successfully executed at least once, and
  4. +
  5. The tell() callback was + successfully able to report the position indicator afterwards.
  6. +
+ This function may be called on partially-opened streams. + \param _of The \c OggOpusFile whose seekable status is to be returned. + \return A non-zero value if seekable, and 0 if unseekable.*/ +int op_seekable(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Returns the number of links in this chained stream. + This function may be called on partially-opened streams, but it will always + return 1. + The actual number of links is not known until the stream is fully opened. + \param _of The \c OggOpusFile from which to retrieve the link count. + \return For fully-open seekable sources, this returns the total number of + links in the whole stream, which will be at least 1. + For partially-open or unseekable sources, this always returns 1.*/ +int op_link_count(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Get the serial number of the given link in a (possibly-chained) Ogg Opus + stream. + This function may be called on partially-opened streams, but it will always + return the serial number of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the serial number. + \param _li The index of the link whose serial number should be retrieved. + Use a negative number to get the serial number of the current + link. + \return The serial number of the given link. + If \a _li is greater than the total number of links, this returns + the serial number of the last link. + If the source is not seekable, this always returns the serial number + of the current link.*/ +opus_uint32 op_serialno(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the channel count of the given link in a (possibly-chained) Ogg Opus + stream. + This is equivalent to op_head(_of,_li)->channel_count, but + is provided for convenience. + This function may be called on partially-opened streams, but it will always + return the channel count of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the channel count. + \param _li The index of the link whose channel count should be retrieved. + Use a negative number to get the channel count of the current + link. + \return The channel count of the given link. + If \a _li is greater than the total number of links, this returns + the channel count of the last link. + If the source is not seekable, this always returns the channel count + of the current link.*/ +int op_channel_count(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the total (compressed) size of the stream, or of an individual link in + a (possibly-chained) Ogg Opus stream, including all headers and Ogg muxing + overhead. + \param _of The \c OggOpusFile from which to retrieve the compressed size. + \param _li The index of the link whose compressed size should be computed. + Use a negative number to get the compressed size of the entire + stream. + \return The compressed size of the entire stream if \a _li is negative, the + compressed size of link \a _li if it is non-negative, or a negative + value on error. + The compressed size of the entire stream may be smaller than that + of the underlying source if trailing garbage was detected in the + file. + \retval #OP_EINVAL The source is not seekable (so we can't know the length), + \a _li wasn't less than the total number of links in + the stream, or the stream was only partially open.*/ +opus_int64 op_raw_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the total PCM length (number of samples at 48 kHz) of the stream, or of + an individual link in a (possibly-chained) Ogg Opus stream. + Users looking for op_time_total() should use op_pcm_total() + instead. + Because timestamps in Opus are fixed at 48 kHz, there is no need for a + separate function to convert this to seconds (and leaving it out avoids + introducing floating point to the API, for those that wish to avoid it). + \param _of The \c OggOpusFile from which to retrieve the PCM offset. + \param _li The index of the link whose PCM length should be computed. + Use a negative number to get the PCM length of the entire stream. + \return The PCM length of the entire stream if \a _li is negative, the PCM + length of link \a _li if it is non-negative, or a negative value on + error. + \retval #OP_EINVAL The source is not seekable (so we can't know the length), + \a _li wasn't less than the total number of links in + the stream, or the stream was only partially open.*/ +ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the ID header information for the given link in a (possibly chained) Ogg + Opus stream. + This function may be called on partially-opened streams, but it will always + return the ID header information of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the ID header + information. + \param _li The index of the link whose ID header information should be + retrieved. + Use a negative number to get the ID header information of the + current link. + For an unseekable stream, \a _li is ignored, and the ID header + information for the current link is always returned, if + available. + \return The contents of the ID header for the given link.*/ +const OpusHead *op_head(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the comment header information for the given link in a (possibly + chained) Ogg Opus stream. + This function may be called on partially-opened streams, but it will always + return the tags from the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the comment header + information. + \param _li The index of the link whose comment header information should be + retrieved. + Use a negative number to get the comment header information of + the current link. + For an unseekable stream, \a _li is ignored, and the comment + header information for the current link is always returned, if + available. + \return The contents of the comment header for the given link, or + NULL if this is an unseekable stream that encountered + an invalid link.*/ +const OpusTags *op_tags(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Retrieve the index of the current link. + This is the link that produced the data most recently read by + op_read_float() or its associated functions, or, after a seek, the link + that the seek target landed in. + Reading more data may advance the link index (even on the first read after a + seek). + \param _of The \c OggOpusFile from which to retrieve the current link index. + \return The index of the current link on success, or a negative value on + failure. + For seekable streams, this is a number between 0 and the value + returned by op_link_count(). + For unseekable streams, this value starts at 0 and increments by one + each time a new link is encountered (even though op_link_count() + always returns 1). + \retval #OP_EINVAL The stream was only partially open.*/ +int op_current_link(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Computes the bitrate for a given link in a (possibly chained) Ogg Opus + stream. + The stream must be seekable to compute the bitrate. + For unseekable streams, use op_bitrate_instant() to get periodic estimates. + \param _of The \c OggOpusFile from which to retrieve the bitrate. + \param _li The index of the link whose bitrate should be computed. + USe a negative number to get the bitrate of the whole stream. + \return The bitrate on success, or a negative value on error. + \retval #OP_EINVAL The stream was only partially open, the stream was not + seekable, or \a _li was larger than the number of + links.*/ +opus_int32 op_bitrate(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Compute the instantaneous bitrate, measured as the ratio of bits to playable + samples decoded since a) the last call to op_bitrate_instant(), b) the last + seek, or c) the start of playback, whichever was most recent. + This will spike somewhat after a seek or at the start/end of a chain + boundary, as pre-skip, pre-roll, and end-trimming causes samples to be + decoded but not played. + \param _of The \c OggOpusFile from which to retrieve the bitrate. + \return The bitrate, in bits per second, or a negative value on error. + \retval #OP_FALSE No data has been decoded since any of the events + described above. + \retval #OP_EINVAL The stream was only partially open.*/ +opus_int32 op_bitrate_instant(OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Obtain the current value of the position indicator for \a _of. + \param _of The \c OggOpusFile from which to retrieve the position indicator. + \return The byte position that is currently being read from. + \retval #OP_EINVAL The stream was only partially open.*/ +opus_int64 op_raw_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Obtain the PCM offset of the next sample to be read. + If the stream is not properly timestamped, this might not increment by the + proper amount between reads, or even return monotonically increasing + values. + \param _of The \c OggOpusFile from which to retrieve the PCM offset. + \return The PCM offset of the next sample to be read. + \retval #OP_EINVAL The stream was only partially open.*/ +ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_seeking Seeking*/ +/*@{*/ +/**\name Functions for seeking in Opus streams + + These functions let you seek in Opus streams, if the underlying source + support it. + Seeking is implemented for all built-in stream I/O routines, though some + individual sources may not be seekable (pipes, live HTTP streams, or HTTP + streams from a server that does not support Range requests). + + op_raw_seek() is the fastest: it is guaranteed to perform at most one + physical seek, but, since the target is a byte position, makes no guarantee + how close to a given time it will come. + op_pcm_seek() provides sample-accurate seeking. + The number of physical seeks it requires is still quite small (often 1 or + 2, even in highly variable bitrate streams). + + Seeking in Opus requires decoding some pre-roll amount before playback to + allow the internal state to converge (as if recovering from packet loss). + This is handled internally by libopusfile, but means there is + little extra overhead for decoding up to the exact position requested + (since it must decode some amount of audio anyway). + It also means that decoding after seeking may not return exactly the same + values as would be obtained by decoding the stream straight through. + However, such differences are expected to be smaller than the loss + introduced by Opus's lossy compression.*/ +/*@{*/ + +/**Seek to a byte offset relative to the compressed data. + This also scans packets to update the PCM cursor. + It will cross a logical bitstream boundary, but only if it can't get any + packets out of the tail of the link to which it seeks. + \param _of The \c OggOpusFile in which to seek. + \param _byte_offset The byte position to seek to. + \return 0 on success, or a negative error code on failure. + \retval #OP_EREAD The underlying seek operation failed. + \retval #OP_EINVAL The stream was only partially open, or the target was + outside the valid range for the stream. + \retval #OP_ENOSEEK This stream is not seekable. + \retval #OP_EBADLINK Failed to initialize a decoder for a stream for an + unknown reason.*/ +int op_raw_seek(OggOpusFile *_of,opus_int64 _byte_offset) OP_ARG_NONNULL(1); + +/**Seek to the specified PCM offset, such that decoding will begin at exactly + the requested position. + \param _of The \c OggOpusFile in which to seek. + \param _pcm_offset The PCM offset to seek to. + This is in samples at 48 kHz relative to the start of the + stream. + \return 0 on success, or a negative value on error. + \retval #OP_EREAD An underlying read or seek operation failed. + \retval #OP_EINVAL The stream was only partially open, or the target was + outside the valid range for the stream. + \retval #OP_ENOSEEK This stream is not seekable. + \retval #OP_EBADLINK We failed to find data we had seen before, or the + bitstream structure was sufficiently malformed that + seeking to the target destination was impossible.*/ +int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_decoding Decoding*/ +/*@{*/ +/**\name Functions for decoding audio data + + These functions retrieve actual decoded audio data from the stream. + The general functions, op_read() and op_read_float() return 16-bit or + floating-point output, both using native endian ordering. + The number of channels returned can change from link to link in a chained + stream. + There are special functions, op_read_stereo() and op_read_float_stereo(), + which always output two channels, to simplify applications which do not + wish to handle multichannel audio. + These downmix multichannel files to two channels, so they can always return + samples in the same format for every link in a chained file. + + If the rest of your audio processing chain can handle floating point, those + routines should be preferred, as floating point output avoids introducing + clipping and other issues which might be avoided entirely if, e.g., you + scale down the volume at some other stage. + However, if you intend to direct consume 16-bit samples, the conversion in + libopusfile provides noise-shaping dithering and, if compiled + against libopus 1.1 or later, soft-clipping prevention. + + libopusfile can also be configured at compile time to use the + fixed-point libopus API. + If so, libopusfile's floating-point API may also be disabled. + In that configuration, nothing in libopusfile will use any + floating-point operations, to simplify support on devices without an + adequate FPU. + + \warning HTTPS streams may be be vulnerable to truncation attacks if you do + not check the error return code from op_read_float() or its associated + functions. + If the remote peer does not close the connection gracefully (with a TLS + "close notify" message), these functions will return #OP_EREAD instead of 0 + when they reach the end of the file. + If you are reading from an URL (particularly if seeking is not + supported), you should make sure to check for this error and warn the user + appropriately.*/ +/*@{*/ + +/**Indicates that the decoding callback should produce signed 16-bit + native-endian output samples.*/ +#define OP_DEC_FORMAT_SHORT (7008) +/**Indicates that the decoding callback should produce 32-bit native-endian + float samples.*/ +#define OP_DEC_FORMAT_FLOAT (7040) + +/**Indicates that the decoding callback did not decode anything, and that + libopusfile should decode normally instead.*/ +#define OP_DEC_USE_DEFAULT (6720) + +/**Called to decode an Opus packet. + This should invoke the functional equivalent of opus_multistream_decode() or + opus_multistream_decode_float(), except that it returns 0 on success + instead of the number of decoded samples (which is known a priori). + \param _ctx The application-provided callback context. + \param _decoder The decoder to use to decode the packet. + \param[out] _pcm The buffer to decode into. + This will always have enough room for \a _nchannels of + \a _nsamples samples, which should be placed into this + buffer interleaved. + \param _op The packet to decode. + This will always have its granule position set to a valid + value. + \param _nsamples The number of samples expected from the packet. + \param _nchannels The number of channels expected from the packet. + \param _format The desired sample output format. + This is either #OP_DEC_FORMAT_SHORT or + #OP_DEC_FORMAT_FLOAT. + \param _li The index of the link from which this packet was decoded. + \return A non-negative value on success, or a negative value on error. + The error codes should be the same as those returned by + opus_multistream_decode() or opus_multistream_decode_float(). + \retval 0 Decoding was successful. + The application has filled the buffer with + exactly \a _nsamples*\a + _nchannels samples in the requested + format. + \retval #OP_DEC_USE_DEFAULT No decoding was done. + libopusfile should decode normally + instead.*/ +typedef int (*op_decode_cb_func)(void *_ctx,OpusMSDecoder *_decoder,void *_pcm, + const ogg_packet *_op,int _nsamples,int _nchannels,int _format,int _li); + +/**Sets the packet decode callback function. + This is called once for each packet that needs to be decoded. + A call to this function is no guarantee that the audio will eventually be + delivered to the application. + Some or all of the data from the packet may be discarded (i.e., at the + beginning or end of a link, or after a seek), however the callback is + required to provide all of it. + \param _of The \c OggOpusFile on which to set the decode callback. + \param _decode_cb The callback function to call. + This may be NULL to disable calling the + callback. + \param _ctx The application-provided context pointer to pass to the + callback on each call.*/ +void op_set_decode_callback(OggOpusFile *_of, + op_decode_cb_func _decode_cb,void *_ctx) OP_ARG_NONNULL(1); + +/**Gain offset type that indicates that the provided offset is relative to the + header gain. + This is the default.*/ +#define OP_HEADER_GAIN (0) + +/**Gain offset type that indicates that the provided offset is relative to the + R128_TRACK_GAIN value (if any), in addition to the header gain.*/ +#define OP_TRACK_GAIN (3008) + +/**Gain offset type that indicates that the provided offset should be used as + the gain directly, without applying any the header or track gains.*/ +#define OP_ABSOLUTE_GAIN (3009) + +/**Sets the gain to be used for decoded output. + By default, the gain in the header is applied with no additional offset. + The total gain (including header gain and/or track gain, if applicable, and + this offset), will be clamped to [-32768,32767]/256 dB. + This is more than enough to saturate or underflow 16-bit PCM. + \note The new gain will not be applied to any already buffered, decoded + output. + This means you cannot change it sample-by-sample, as at best it will be + updated packet-by-packet. + It is meant for setting a target volume level, rather than applying smooth + fades, etc. + \param _of The \c OggOpusFile on which to set the gain offset. + \param _gain_type One of #OP_HEADER_GAIN, #OP_TRACK_GAIN, or + #OP_ABSOLUTE_GAIN. + \param _gain_offset_q8 The gain offset to apply, in 1/256ths of a dB. + \return 0 on success or a negative value on error. + \retval #OP_EINVAL The \a _gain_type was unrecognized.*/ +int op_set_gain_offset(OggOpusFile *_of, + int _gain_type,opus_int32 _gain_offset_q8) OP_ARG_NONNULL(1); + +/**Sets whether or not dithering is enabled for 16-bit decoding. + By default, when libopusfile is compiled to use floating-point + internally, calling op_read() or op_read_stereo() will first decode to + float, and then convert to fixed-point using noise-shaping dithering. + This flag can be used to disable that dithering. + When the application uses op_read_float() or op_read_float_stereo(), or when + the library has been compiled to decode directly to fixed point, this flag + has no effect. + \param _of The \c OggOpusFile on which to enable or disable dithering. + \param _enabled A non-zero value to enable dithering, or 0 to disable it.*/ +void op_set_dither_enabled(OggOpusFile *_of,int _enabled) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream. + \note Although \a _buf_size must indicate the total number of values that + can be stored in \a _pcm, the return value is the number of samples + per channel. + This is done because +
    +
  1. The channel count cannot be known a priori (reading more samples might + advance us into the next link, with a different channel count), so + \a _buf_size cannot also be in units of samples per channel,
  2. +
  3. Returning the samples per channel matches the libopus API + as closely as we're able,
  4. +
  5. Returning the total number of values instead of samples per channel + would mean the caller would need a division to compute the samples per + channel, and might worry about the possibility of getting back samples + for some channels and not others, and
  6. +
  7. This approach is relatively fool-proof: if an application passes too + small a value to \a _buf_size, they will simply get fewer samples back, + and if they assume the return value is the total number of values, then + they will simply read too few (rather than reading too many and going + off the end of the buffer).
  8. +
+ \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed native-endian 16-bit values at 48 kHz + with a nominal range of [-32768,32767). + Multiple channels are interleaved using the + Vorbis + channel ordering. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (5760 + values per channel). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + libopusfile may return less data than + requested. + If so, there is no guarantee that the remaining data + in \a _pcm will be unmodified. + \param[out] _li The index of the link this data was decoded from. + You may pass NULL if you do not need this + information. + If this function fails (returning a negative value), + this parameter is left unset. + \return The number of samples read per channel on success, or a negative + value on failure. + The channel count can be retrieved on success by calling + op_head(_of,*_li). + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for all channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read(OggOpusFile *_of, + opus_int16 *_pcm,int _buf_size,int *_li) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream. + \note Although \a _buf_size must indicate the total number of values that + can be stored in \a _pcm, the return value is the number of samples + per channel. +
    +
  1. The channel count cannot be known a priori (reading more samples might + advance us into the next link, with a different channel count), so + \a _buf_size cannot also be in units of samples per channel,
  2. +
  3. Returning the samples per channel matches the libopus API + as closely as we're able,
  4. +
  5. Returning the total number of values instead of samples per channel + would mean the caller would need a division to compute the samples per + channel, and might worry about the possibility of getting back samples + for some channels and not others, and
  6. +
  7. This approach is relatively fool-proof: if an application passes too + small a value to \a _buf_size, they will simply get fewer samples back, + and if they assume the return value is the total number of values, then + they will simply read too few (rather than reading too many and going + off the end of the buffer).
  8. +
+ \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples as + signed floats at 48 kHz with a nominal range of + [-1.0,1.0]. + Multiple channels are interleaved using the + Vorbis + channel ordering. + This must have room for at least \a _buf_size floats. + \param _buf_size The number of floats that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (5760 + samples per channel). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + libopusfile makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \param[out] _li The index of the link this data was decoded from. + You may pass NULL if you do not need this + information. + If this function fails (returning a negative value), + this parameter is left unset. + \return The number of samples read per channel on success, or a negative + value on failure. + The channel count can be retrieved on success by calling + op_head(_of,*_li). + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for all channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_float(OggOpusFile *_of, + float *_pcm,int _buf_size,int *_li) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream and downmixes to stereo, if necessary. + This function is intended for simple players that want a uniform output + format, even if the channel count changes between links in a chained + stream. + \note \a _buf_size indicates the total number of values that can be stored + in \a _pcm, while the return value is the number of samples per + channel, even though the channel count is known, for consistency with + op_read(). + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed native-endian 16-bit values at 48 kHz + with a nominal range of [-32768,32767). + The left and right channels are interleaved in the + buffer. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (11520 + values total). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + libopusfile makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \return The number of samples read per channel on success, or a negative + value on failure. + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for both channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_stereo(OggOpusFile *_of, + opus_int16 *_pcm,int _buf_size) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream and downmixes to stereo, if necessary. + This function is intended for simple players that want a uniform output + format, even if the channel count changes between links in a chained + stream. + \note \a _buf_size indicates the total number of values that can be stored + in \a _pcm, while the return value is the number of samples per + channel, even though the channel count is known, for consistency with + op_read_float(). + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed floats at 48 kHz with a nominal range of + [-1.0,1.0]. + The left and right channels are interleaved in the + buffer. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (11520 + values total). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + libopusfile makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \return The number of samples read per channel on success, or a negative + value on failure. + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for both channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + that did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_float_stereo(OggOpusFile *_of, + float *_pcm,int _buf_size) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +# if OP_GNUC_PREREQ(4,0) +# pragma GCC visibility pop +# endif + +# if defined(__cplusplus) +} +# endif + +#endif diff --git a/Frameworks/Opus.framework/Opus b/Frameworks/Opus.framework/Opus new file mode 100644 index 0000000..13cc866 Binary files /dev/null and b/Frameworks/Opus.framework/Opus differ diff --git a/Frameworks/Vorbis.framework/Headers/codec.h b/Frameworks/Vorbis.framework/Headers/codec.h new file mode 100644 index 0000000..999aa33 --- /dev/null +++ b/Frameworks/Vorbis.framework/Headers/codec.h @@ -0,0 +1,243 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + + ******************************************************************** + + function: libvorbis codec headers + last mod: $Id: codec.h 17021 2010-03-24 09:29:41Z xiphmont $ + + ********************************************************************/ + +#ifndef _vorbis_codec_h_ +#define _vorbis_codec_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include + +typedef struct vorbis_info{ + int version; + int channels; + long rate; + + /* The below bitrate declarations are *hints*. + Combinations of the three values carry the following implications: + + all three set to the same value: + implies a fixed rate bitstream + only nominal set: + implies a VBR stream that averages the nominal bitrate. No hard + upper/lower limit + upper and or lower set: + implies a VBR bitstream that obeys the bitrate limits. nominal + may also be set to give a nominal rate. + none set: + the coder does not care to speculate. + */ + + long bitrate_upper; + long bitrate_nominal; + long bitrate_lower; + long bitrate_window; + + void *codec_setup; +} vorbis_info; + +/* vorbis_dsp_state buffers the current vorbis audio + analysis/synthesis state. The DSP state belongs to a specific + logical bitstream ****************************************************/ +typedef struct vorbis_dsp_state{ + int analysisp; + vorbis_info *vi; + + float **pcm; + float **pcmret; + int pcm_storage; + int pcm_current; + int pcm_returned; + + int preextrapolate; + int eofflag; + + long lW; + long W; + long nW; + long centerW; + + ogg_int64_t granulepos; + ogg_int64_t sequence; + + ogg_int64_t glue_bits; + ogg_int64_t time_bits; + ogg_int64_t floor_bits; + ogg_int64_t res_bits; + + void *backend_state; +} vorbis_dsp_state; + +typedef struct vorbis_block{ + /* necessary stream state for linking to the framing abstraction */ + float **pcm; /* this is a pointer into local storage */ + oggpack_buffer opb; + + long lW; + long W; + long nW; + int pcmend; + int mode; + + int eofflag; + ogg_int64_t granulepos; + ogg_int64_t sequence; + vorbis_dsp_state *vd; /* For read-only access of configuration */ + + /* local storage to avoid remallocing; it's up to the mapping to + structure it */ + void *localstore; + long localtop; + long localalloc; + long totaluse; + struct alloc_chain *reap; + + /* bitmetrics for the frame */ + long glue_bits; + long time_bits; + long floor_bits; + long res_bits; + + void *internal; + +} vorbis_block; + +/* vorbis_block is a single block of data to be processed as part of +the analysis/synthesis stream; it belongs to a specific logical +bitstream, but is independent from other vorbis_blocks belonging to +that logical bitstream. *************************************************/ + +struct alloc_chain{ + void *ptr; + struct alloc_chain *next; +}; + +/* vorbis_info contains all the setup information specific to the + specific compression/decompression mode in progress (eg, + psychoacoustic settings, channel setup, options, codebook + etc). vorbis_info and substructures are in backends.h. +*********************************************************************/ + +/* the comments are not part of vorbis_info so that vorbis_info can be + static storage */ +typedef struct vorbis_comment{ + /* unlimited user comment fields. libvorbis writes 'libvorbis' + whatever vendor is set to in encode */ + char **user_comments; + int *comment_lengths; + int comments; + char *vendor; + +} vorbis_comment; + + +/* libvorbis encodes in two abstraction layers; first we perform DSP + and produce a packet (see docs/analysis.txt). The packet is then + coded into a framed OggSquish bitstream by the second layer (see + docs/framing.txt). Decode is the reverse process; we sync/frame + the bitstream and extract individual packets, then decode the + packet back into PCM audio. + + The extra framing/packetizing is used in streaming formats, such as + files. Over the net (such as with UDP), the framing and + packetization aren't necessary as they're provided by the transport + and the streaming layer is not used */ + +/* Vorbis PRIMITIVES: general ***************************************/ + +extern void vorbis_info_init(vorbis_info *vi); +extern void vorbis_info_clear(vorbis_info *vi); +extern int vorbis_info_blocksize(vorbis_info *vi,int zo); +extern void vorbis_comment_init(vorbis_comment *vc); +extern void vorbis_comment_add(vorbis_comment *vc, const char *comment); +extern void vorbis_comment_add_tag(vorbis_comment *vc, + const char *tag, const char *contents); +extern char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count); +extern int vorbis_comment_query_count(vorbis_comment *vc, const char *tag); +extern void vorbis_comment_clear(vorbis_comment *vc); + +extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); +extern int vorbis_block_clear(vorbis_block *vb); +extern void vorbis_dsp_clear(vorbis_dsp_state *v); +extern double vorbis_granule_time(vorbis_dsp_state *v, + ogg_int64_t granulepos); + +extern const char *vorbis_version_string(void); + +/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/ + +extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op); +extern int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code); +extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); + +extern int vorbis_bitrate_addblock(vorbis_block *vb); +extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, + ogg_packet *op); + +/* Vorbis PRIMITIVES: synthesis layer *******************************/ +extern int vorbis_synthesis_idheader(ogg_packet *op); +extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, + ogg_packet *op); + +extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_synthesis_restart(vorbis_dsp_state *v); +extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); +extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); + +extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag); +extern int vorbis_synthesis_halfrate_p(vorbis_info *v); + +/* Vorbis ERRORS and return codes ***********************************/ + +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 + +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 +#define OV_ENOTVORBIS -132 +#define OV_EBADHEADER -133 +#define OV_EVERSION -134 +#define OV_ENOTAUDIO -135 +#define OV_EBADPACKET -136 +#define OV_EBADLINK -137 +#define OV_ENOSEEK -138 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/Frameworks/Vorbis.framework/Headers/vorbisenc.h b/Frameworks/Vorbis.framework/Headers/vorbisenc.h new file mode 100644 index 0000000..02332b5 --- /dev/null +++ b/Frameworks/Vorbis.framework/Headers/vorbisenc.h @@ -0,0 +1,436 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: vorbis encode-engine setup + last mod: $Id: vorbisenc.h 17021 2010-03-24 09:29:41Z xiphmont $ + + ********************************************************************/ + +/** \file + * Libvorbisenc is a convenient API for setting up an encoding + * environment using libvorbis. Libvorbisenc encapsulates the + * actions needed to set up the encoder properly. + */ + +#ifndef _OV_ENC_H_ +#define _OV_ENC_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "codec.h" + +/** + * This is the primary function within libvorbisenc for setting up managed + * bitrate modes. + * + * Before this function is called, the \ref vorbis_info + * struct should be initialized by using vorbis_info_init() from the libvorbis + * API. After encoding, vorbis_info_clear() should be called. + * + * The max_bitrate, nominal_bitrate, and min_bitrate settings are used to set + * constraints for the encoded file. This function uses these settings to + * select the appropriate encoding mode and set it up. + * + * \param vi Pointer to an initialized \ref vorbis_info struct. + * \param channels The number of channels to be encoded. + * \param rate The sampling rate of the source audio. + * \param max_bitrate Desired maximum bitrate (limit). -1 indicates unset. + * \param nominal_bitrate Desired average, or central, bitrate. -1 indicates unset. + * \param min_bitrate Desired minimum bitrate. -1 indicates unset. + * + * \return Zero for success, and negative values for failure. + * + * \retval 0 Success. + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * \retval OV_EINVAL Invalid setup request, eg, out of range argument. + * \retval OV_EIMPL Unimplemented mode; unable to comply with bitrate request. + */ +extern int vorbis_encode_init(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate); + +/** + * This function performs step-one of a three-step bitrate-managed encode + * setup. It functions similarly to the one-step setup performed by \ref + * vorbis_encode_init but allows an application to make further encode setup + * tweaks using \ref vorbis_encode_ctl before finally calling \ref + * vorbis_encode_setup_init to complete the setup process. + * + * Before this function is called, the \ref vorbis_info struct should be + * initialized by using vorbis_info_init() from the libvorbis API. After + * encoding, vorbis_info_clear() should be called. + * + * The max_bitrate, nominal_bitrate, and min_bitrate settings are used to set + * constraints for the encoded file. This function uses these settings to + * select the appropriate encoding mode and set it up. + * + * \param vi Pointer to an initialized vorbis_info struct. + * \param channels The number of channels to be encoded. + * \param rate The sampling rate of the source audio. + * \param max_bitrate Desired maximum bitrate (limit). -1 indicates unset. + * \param nominal_bitrate Desired average, or central, bitrate. -1 indicates unset. + * \param min_bitrate Desired minimum bitrate. -1 indicates unset. + * + * \return Zero for success, and negative for failure. + * + * \retval 0 Success + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * \retval OV_EINVAL Invalid setup request, eg, out of range argument. + * \retval OV_EIMPL Unimplemented mode; unable to comply with bitrate request. + */ +extern int vorbis_encode_setup_managed(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate); + +/** + * This function performs step-one of a three-step variable bitrate + * (quality-based) encode setup. It functions similarly to the one-step setup + * performed by \ref vorbis_encode_init_vbr() but allows an application to + * make further encode setup tweaks using \ref vorbis_encode_ctl() before + * finally calling \ref vorbis_encode_setup_init to complete the setup + * process. + * + * Before this function is called, the \ref vorbis_info struct should be + * initialized by using \ref vorbis_info_init() from the libvorbis API. After + * encoding, vorbis_info_clear() should be called. + * + * \param vi Pointer to an initialized vorbis_info struct. + * \param channels The number of channels to be encoded. + * \param rate The sampling rate of the source audio. + * \param quality Desired quality level, currently from -0.1 to 1.0 (lo to hi). + * + * \return Zero for success, and negative values for failure. + * + * \retval 0 Success + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * \retval OV_EINVAL Invalid setup request, eg, out of range argument. + * \retval OV_EIMPL Unimplemented mode; unable to comply with quality level request. + */ +extern int vorbis_encode_setup_vbr(vorbis_info *vi, + long channels, + long rate, + + float quality + ); + +/** + * This is the primary function within libvorbisenc for setting up variable + * bitrate ("quality" based) modes. + * + * + * Before this function is called, the vorbis_info struct should be + * initialized by using vorbis_info_init() from the libvorbis API. After + * encoding, vorbis_info_clear() should be called. + * + * \param vi Pointer to an initialized vorbis_info struct. + * \param channels The number of channels to be encoded. + * \param rate The sampling rate of the source audio. + * \param base_quality Desired quality level, currently from -0.1 to 1.0 (lo to hi). + * + * + * \return Zero for success, or a negative number for failure. + * + * \retval 0 Success + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * \retval OV_EINVAL Invalid setup request, eg, out of range argument. + * \retval OV_EIMPL Unimplemented mode; unable to comply with quality level request. + */ +extern int vorbis_encode_init_vbr(vorbis_info *vi, + long channels, + long rate, + + float base_quality + ); + +/** + * This function performs the last stage of three-step encoding setup, as + * described in the API overview under managed bitrate modes. + * + * Before this function is called, the \ref vorbis_info struct should be + * initialized by using vorbis_info_init() from the libvorbis API, one of + * \ref vorbis_encode_setup_managed() or \ref vorbis_encode_setup_vbr() called to + * initialize the high-level encoding setup, and \ref vorbis_encode_ctl() + * called if necessary to make encoding setup changes. + * vorbis_encode_setup_init() finalizes the highlevel encoding structure into + * a complete encoding setup after which the application may make no further + * setup changes. + * + * After encoding, vorbis_info_clear() should be called. + * + * \param vi Pointer to an initialized \ref vorbis_info struct. + * + * \return Zero for success, and negative values for failure. + * + * \retval 0 Success. + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * + * \retval OV_EINVAL Attempt to use vorbis_encode_setup_init() without first + * calling one of vorbis_encode_setup_managed() or vorbis_encode_setup_vbr() to + * initialize the high-level encoding setup + * + */ +extern int vorbis_encode_setup_init(vorbis_info *vi); + +/** + * This function implements a generic interface to miscellaneous encoder + * settings similar to the classic UNIX 'ioctl()' system call. Applications + * may use vorbis_encode_ctl() to query or set bitrate management or quality + * mode details by using one of several \e request arguments detailed below. + * vorbis_encode_ctl() must be called after one of + * vorbis_encode_setup_managed() or vorbis_encode_setup_vbr(). When used + * to modify settings, \ref vorbis_encode_ctl() must be called before \ref + * vorbis_encode_setup_init(). + * + * \param vi Pointer to an initialized vorbis_info struct. + * + * \param number Specifies the desired action; See \ref encctlcodes "the list + * of available requests". + * + * \param arg void * pointing to a data structure matching the request + * argument. + * + * \retval 0 Success. Any further return information (such as the result of a + * query) is placed into the storage pointed to by *arg. + * + * \retval OV_EINVAL Invalid argument, or an attempt to modify a setting after + * calling vorbis_encode_setup_init(). + * + * \retval OV_EIMPL Unimplemented or unknown request + */ +extern int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg); + +/** + * \deprecated This is a deprecated interface. Please use vorbis_encode_ctl() + * with the \ref ovectl_ratemanage2_arg struct and \ref + * OV_ECTL_RATEMANAGE2_GET and \ref OV_ECTL_RATEMANAGE2_SET calls in new code. + * + * The \ref ovectl_ratemanage_arg structure is used with vorbis_encode_ctl() + * and the \ref OV_ECTL_RATEMANAGE_GET, \ref OV_ECTL_RATEMANAGE_SET, \ref + * OV_ECTL_RATEMANAGE_AVG, \ref OV_ECTL_RATEMANAGE_HARD calls in order to + * query and modify specifics of the encoder's bitrate management + * configuration. +*/ +struct ovectl_ratemanage_arg { + int management_active; /**< nonzero if bitrate management is active*/ +/** hard lower limit (in kilobits per second) below which the stream bitrate + will never be allowed for any given bitrate_hard_window seconds of time.*/ + long bitrate_hard_min; +/** hard upper limit (in kilobits per second) above which the stream bitrate + will never be allowed for any given bitrate_hard_window seconds of time.*/ + long bitrate_hard_max; +/** the window period (in seconds) used to regulate the hard bitrate minimum + and maximum*/ + double bitrate_hard_window; +/** soft lower limit (in kilobits per second) below which the average bitrate + tracker will start nudging the bitrate higher.*/ + long bitrate_av_lo; +/** soft upper limit (in kilobits per second) above which the average bitrate + tracker will start nudging the bitrate lower.*/ + long bitrate_av_hi; +/** the window period (in seconds) used to regulate the average bitrate + minimum and maximum.*/ + double bitrate_av_window; +/** Regulates the relative centering of the average and hard windows; in + libvorbis 1.0 and 1.0.1, the hard window regulation overlapped but + followed the average window regulation. In libvorbis 1.1 a bit-reservoir + interface replaces the old windowing interface; the older windowing + interface is simulated and this field has no effect.*/ + double bitrate_av_window_center; +}; + +/** + * \name struct ovectl_ratemanage2_arg + * + * The ovectl_ratemanage2_arg structure is used with vorbis_encode_ctl() and + * the OV_ECTL_RATEMANAGE2_GET and OV_ECTL_RATEMANAGE2_SET calls in order to + * query and modify specifics of the encoder's bitrate management + * configuration. + * +*/ +struct ovectl_ratemanage2_arg { + int management_active; /**< nonzero if bitrate management is active */ +/** Lower allowed bitrate limit in kilobits per second */ + long bitrate_limit_min_kbps; +/** Upper allowed bitrate limit in kilobits per second */ + long bitrate_limit_max_kbps; + long bitrate_limit_reservoir_bits; /**struct ovectl_ratemanage2_arg * + * + * Used to query the current encoder bitrate management setting. Also used to + * initialize fields of an ovectl_ratemanage2_arg structure for use with + * \ref OV_ECTL_RATEMANAGE2_SET. + */ +#define OV_ECTL_RATEMANAGE2_GET 0x14 + +/** + * Set the current encoder bitrate management settings. + * + * Argument: struct ovectl_ratemanage2_arg * + * + * Used to set the current encoder bitrate management settings to the values + * listed in the ovectl_ratemanage2_arg. Passing a NULL pointer will disable + * bitrate management. +*/ +#define OV_ECTL_RATEMANAGE2_SET 0x15 + +/** + * Returns the current encoder hard-lowpass setting (kHz) in the double + * pointed to by arg. + * + * Argument: double * +*/ +#define OV_ECTL_LOWPASS_GET 0x20 + +/** + * Sets the encoder hard-lowpass to the value (kHz) pointed to by arg. Valid + * lowpass settings range from 2 to 99. + * + * Argument: double * +*/ +#define OV_ECTL_LOWPASS_SET 0x21 + +/** + * Returns the current encoder impulse block setting in the double pointed + * to by arg. + * + * Argument: double * +*/ +#define OV_ECTL_IBLOCK_GET 0x30 + +/** + * Sets the impulse block bias to the the value pointed to by arg. + * + * Argument: double * + * + * Valid range is -15.0 to 0.0 [default]. A negative impulse block bias will + * direct to encoder to use more bits when incoding short blocks that contain + * strong impulses, thus improving the accuracy of impulse encoding. + */ +#define OV_ECTL_IBLOCK_SET 0x31 + +/** + * Returns the current encoder coupling setting in the int pointed + * to by arg. + * + * Argument: int * +*/ +#define OV_ECTL_COUPLING_GET 0x40 + +/** + * Enables/disables channel coupling in multichannel encoding according to arg. + * + * Argument: int * + * + * Zero disables channel coupling for multichannel inputs, nonzer enables + * channel coupling. Setting has no effect on monophonic encoding or + * multichannel counts that do not offer coupling. At present, coupling is + * available for stereo and 5.1 encoding. + */ +#define OV_ECTL_COUPLING_SET 0x41 + + /* deprecated rate management supported only for compatibility */ + +/** + * Old interface to querying bitrate management settings. + * + * Deprecated after move to bit-reservoir style management in 1.1 rendered + * this interface partially obsolete. + + * \deprecated Please use \ref OV_ECTL_RATEMANAGE2_GET instead. + * + * Argument: struct ovectl_ratemanage_arg * + */ +#define OV_ECTL_RATEMANAGE_GET 0x10 +/** + * Old interface to modifying bitrate management settings. + * + * deprecated after move to bit-reservoir style management in 1.1 rendered + * this interface partially obsolete. + * + * \deprecated Please use \ref OV_ECTL_RATEMANAGE2_SET instead. + * + * Argument: struct ovectl_ratemanage_arg * + */ +#define OV_ECTL_RATEMANAGE_SET 0x11 +/** + * Old interface to setting average-bitrate encoding mode. + * + * Deprecated after move to bit-reservoir style management in 1.1 rendered + * this interface partially obsolete. + * + * \deprecated Please use \ref OV_ECTL_RATEMANAGE2_SET instead. + * + * Argument: struct ovectl_ratemanage_arg * + */ +#define OV_ECTL_RATEMANAGE_AVG 0x12 +/** + * Old interface to setting bounded-bitrate encoding modes. + * + * deprecated after move to bit-reservoir style management in 1.1 rendered + * this interface partially obsolete. + * + * \deprecated Please use \ref OV_ECTL_RATEMANAGE2_SET instead. + * + * Argument: struct ovectl_ratemanage_arg * + */ +#define OV_ECTL_RATEMANAGE_HARD 0x13 + +/*@}*/ + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/Frameworks/Vorbis.framework/Headers/vorbisfile.h b/Frameworks/Vorbis.framework/Headers/vorbisfile.h new file mode 100644 index 0000000..9271331 --- /dev/null +++ b/Frameworks/Vorbis.framework/Headers/vorbisfile.h @@ -0,0 +1,206 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.h 17182 2010-04-29 03:48:32Z xiphmont $ + + ********************************************************************/ + +#ifndef _OV_FILE_H_ +#define _OV_FILE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include +#include "codec.h" + +/* The function prototypes for the callbacks are basically the same as for + * the stdio functions fread, fseek, fclose, ftell. + * The one difference is that the FILE * arguments have been replaced with + * a void * - this is to be used as a pointer to whatever internal data these + * functions might need. In the stdio case, it's just a FILE * cast to a void * + * + * If you use other functions, check the docs for these functions and return + * the right values. For seek_func(), you *MUST* return -1 if the stream is + * unseekable + */ +typedef struct { + size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); + int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); + int (*close_func) (void *datasource); + long (*tell_func) (void *datasource); +} ov_callbacks; + +#ifndef OV_EXCLUDE_STATIC_CALLBACKS + +/* a few sets of convenient callbacks, especially for use under + * Windows where ov_open_callbacks() should always be used instead of + * ov_open() to avoid problems with incompatible crt.o version linking + * issues. */ + +static int _ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){ + if(f==NULL)return(-1); + +#ifdef __MINGW32__ + return fseeko64(f,off,whence); +#elif defined (_WIN32) + return _fseeki64(f,off,whence); +#else + return fseek(f,off,whence); +#endif +} + +/* These structs below (OV_CALLBACKS_DEFAULT etc) are defined here as + * static data. That means that every file which includes this header + * will get its own copy of these structs whether it uses them or + * not unless it #defines OV_EXCLUDE_STATIC_CALLBACKS. + * These static symbols are essential on platforms such as Windows on + * which several different versions of stdio support may be linked to + * by different DLLs, and we need to be certain we know which one + * we're using (the same one as the main application). + */ + +static ov_callbacks OV_CALLBACKS_DEFAULT = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, + (int (*)(void *)) fclose, + (long (*)(void *)) ftell +}; + +static ov_callbacks OV_CALLBACKS_NOCLOSE = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, + (int (*)(void *)) NULL, + (long (*)(void *)) ftell +}; + +static ov_callbacks OV_CALLBACKS_STREAMONLY = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) NULL, + (int (*)(void *)) fclose, + (long (*)(void *)) NULL +}; + +static ov_callbacks OV_CALLBACKS_STREAMONLY_NOCLOSE = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) NULL, + (int (*)(void *)) NULL, + (long (*)(void *)) NULL +}; + +#endif + +#define NOTOPEN 0 +#define PARTOPEN 1 +#define OPENED 2 +#define STREAMSET 3 +#define INITSET 4 + +typedef struct OggVorbis_File { + void *datasource; /* Pointer to a FILE *, etc. */ + int seekable; + ogg_int64_t offset; + ogg_int64_t end; + ogg_sync_state oy; + + /* If the FILE handle isn't seekable (eg, a pipe), only the current + stream appears */ + int links; + ogg_int64_t *offsets; + ogg_int64_t *dataoffsets; + long *serialnos; + ogg_int64_t *pcmlengths; /* overloaded to maintain binary + compatibility; x2 size, stores both + beginning and end values */ + vorbis_info *vi; + vorbis_comment *vc; + + /* Decoding working state local storage */ + ogg_int64_t pcm_offset; + int ready_state; + long current_serialno; + int current_link; + + double bittrack; + double samptrack; + + ogg_stream_state os; /* take physical pages, weld into a logical + stream of packets */ + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + vorbis_block vb; /* local working space for packet->PCM decode */ + + ov_callbacks callbacks; + +} OggVorbis_File; + + +extern int ov_clear(OggVorbis_File *vf); +extern int ov_fopen(const char *path,OggVorbis_File *vf); +extern int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); +extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, + const char *initial, long ibytes, ov_callbacks callbacks); + +extern int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); +extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, + const char *initial, long ibytes, ov_callbacks callbacks); +extern int ov_test_open(OggVorbis_File *vf); + +extern long ov_bitrate(OggVorbis_File *vf,int i); +extern long ov_bitrate_instant(OggVorbis_File *vf); +extern long ov_streams(OggVorbis_File *vf); +extern long ov_seekable(OggVorbis_File *vf); +extern long ov_serialnumber(OggVorbis_File *vf,int i); + +extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i); +extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i); +extern double ov_time_total(OggVorbis_File *vf,int i); + +extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek(OggVorbis_File *vf,double pos); +extern int ov_time_seek_page(OggVorbis_File *vf,double pos); + +extern int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek_lap(OggVorbis_File *vf,double pos); +extern int ov_time_seek_page_lap(OggVorbis_File *vf,double pos); + +extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf); +extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf); +extern double ov_time_tell(OggVorbis_File *vf); + +extern vorbis_info *ov_info(OggVorbis_File *vf,int link); +extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link); + +extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples, + int *bitstream); +extern long ov_read_filter(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream, + void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param); +extern long ov_read(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream); +extern int ov_crosslap(OggVorbis_File *vf1,OggVorbis_File *vf2); + +extern int ov_halfrate(OggVorbis_File *vf,int flag); +extern int ov_halfrate_p(OggVorbis_File *vf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/Frameworks/Vorbis.framework/Vorbis b/Frameworks/Vorbis.framework/Vorbis new file mode 100644 index 0000000..06199c6 Binary files /dev/null and b/Frameworks/Vorbis.framework/Vorbis differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..cbd2eeb --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +AudioStreamer +============= + +A streaming audio player class (based on Matt's AudioStreamer) for iOS +*with Ogg Opus and Vorbis* audio codecs. diff --git a/iPhone Resources/iPhoneStreamingPlayerViewController.xib b/iPhone Resources/iPhoneStreamingPlayerViewController.xib index 6cd02a5..4bc22bf 100644 --- a/iPhone Resources/iPhoneStreamingPlayerViewController.xib +++ b/iPhone Resources/iPhoneStreamingPlayerViewController.xib @@ -1,536 +1,88 @@ - - - - 528 - 10J869 - 1864 - 1038.35 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 865 - - - YES - IBUILabel - IBUISlider - IBUIButton - IBUIView - IBUITextField - IBProxyObject - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - YES - - - 292 - {{20, 49}, {280, 31}} - - - NO - NO - IBCocoaTouchFramework - 0 - http://shoutmedia.abc.net.au:10326 - 3 - - 3 - MAA - - 2 - - - YES - 17 - - 1 - 3 - IBCocoaTouchFramework - - - 1 - 4 - - - Helvetica - 14 - 16 - - - - - 292 - {{20, 20}, {280, 21}} - - - NO - YES - NO - IBCocoaTouchFramework - Download URL: - - 1 - MCAwIDAAA - - - 1 - 10 - - - - - - 292 - {{124, 88}, {72, 73}} - - - NO - NO - IBCocoaTouchFramework - 0 - 0 - - 3 - MQA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - 3 - MC41AA - - - NSImage - playbutton.png - - - Helvetica-Bold - Helvetica - 2 - 15 - - - Helvetica-Bold - 15 - 16 - - - - - 292 - {{20, 169}, {280, 21}} - - - NO - YES - NO - IBCocoaTouchFramework - Time Played: - - - 1 - 10 - - - - - - 292 - {{20, 356}, {280, 21}} - - - NO - YES - NO - IBCocoaTouchFramework - Volume: - - - 1 - 10 - - - - - - 292 - {{20, 385}, {280, 55}} - - - - 3 - MSAwAA - - NO - IBCocoaTouchFramework - - - - 292 - {{18, 198}, {284, 23}} - - - NO - IBCocoaTouchFramework - NO - 0 - 0 - 50 - 100 - NO - - - {{0, 20}, {320, 460}} - - - - 1 - MC44NTIwNDA4MyAwLjg1MjA0MDgzIDAuODUyMDQwODMAA - - NO - - IBCocoaTouchFramework - - - - - YES - - - view - - - - 7 - - - - button - - - - 28 - - - - buttonPressed: - - - 7 - - 29 - - - - volumeSlider - - - - 36 - - - - downloadSourceField - - - - 38 - - - - positionLabel - - - - 41 - - - - delegate - - - - 44 - - - - progressSlider - - - - 47 - - - - sliderMoved: - - - 13 - - 48 - - - - - YES - - 0 - - YES - - - - - - -1 - - - File's Owner - - - -2 - - - - - 6 - - - YES - - - - - - - - - - - - 16 - - - - - 21 - - - - - 23 - - - - - 26 - - - - - 35 - - - YES - - - - - 25 - - - - - 46 - - - - - - - YES - - YES - -1.CustomClassName - -1.IBPluginDependency - -2.CustomClassName - -2.IBPluginDependency - 16.IBPluginDependency - 21.IBPluginDependency - 23.IBPluginDependency - 25.IBPluginDependency - 26.IBPluginDependency - 35.IBPluginDependency - 46.IBPluginDependency - 6.IBPluginDependency - - - YES - iPhoneStreamingPlayerViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - - - - YES - - - - - 48 - - - - YES - - iPhoneStreamingPlayerViewController - UIViewController - - YES - - YES - buttonPressed: - sliderMoved: - - - YES - id - UISlider - - - - YES - - YES - buttonPressed: - sliderMoved: - - - YES - - buttonPressed: - id - - - sliderMoved: - UISlider - - - - - YES - - YES - button - downloadSourceField - positionLabel - progressSlider - volumeSlider - - - YES - UIButton - UITextField - UILabel - UISlider - UIView - - - - YES - - YES - button - downloadSourceField - positionLabel - progressSlider - volumeSlider - - - YES - - button - UIButton - - - downloadSourceField - UITextField - - - positionLabel - UILabel - - - progressSlider - UISlider - - - volumeSlider - UIView - - - - - IBProjectSource - ./Classes/iPhoneStreamingPlayerViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - - playbutton.png - {64, 64} - - 865 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/iPhoneInfo.plist b/iPhoneInfo.plist index 71715a2..6cb36c9 100644 --- a/iPhoneInfo.plist +++ b/iPhoneInfo.plist @@ -2,6 +2,10 @@ + UIBackgroundModes + + audio + CFBundleDevelopmentRegion en CFBundleDisplayName @@ -11,7 +15,7 @@ CFBundleIconFile CFBundleIdentifier - com.mattgallagher.${PRODUCT_NAME:identifier} + com.bennykhoo.${PRODUCT_NAME:identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/iPhoneStreamingPlayer.xcodeproj/project.pbxproj b/iPhoneStreamingPlayer.xcodeproj/project.pbxproj index 3b82522..4751d31 100755 --- a/iPhoneStreamingPlayer.xcodeproj/project.pbxproj +++ b/iPhoneStreamingPlayer.xcodeproj/project.pbxproj @@ -7,6 +7,14 @@ objects = { /* Begin PBXBuildFile section */ + 191AFDE817F6A30000E7F483 /* OggOpusStreamParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 191AFDE717F6A30000E7F483 /* OggOpusStreamParser.mm */; }; + 1940DE4117F86BA5002A6432 /* Ogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1940DE4017F86BA5002A6432 /* Ogg.framework */; }; + 1940DE4417F86BB6002A6432 /* Opus.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1940DE4217F86BB6002A6432 /* Opus.framework */; }; + 1940DE4517F86BB6002A6432 /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1940DE4317F86BB6002A6432 /* Vorbis.framework */; }; + 19A0141C17E6FD4000C7D69C /* AppleAudioFileStreamParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 19A0141B17E6FD4000C7D69C /* AppleAudioFileStreamParser.m */; }; + 19A70D9A17F1C08600F5A2C6 /* cputime.c in Sources */ = {isa = PBXBuildFile; fileRef = 19A70D9917F1C08600F5A2C6 /* cputime.c */; }; + 19A8DEA917EED03A00ED8C86 /* OggVorbisStreamParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 19A8DEA817EED03A00ED8C86 /* OggVorbisStreamParser.mm */; }; + 19B273BF180A3EFF0072C2A5 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 19B273BE180A3EFF0072C2A5 /* AVFoundation.framework */; }; 1D3623260D0F684500981E51 /* iPhoneStreamingPlayerAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* iPhoneStreamingPlayerAppDelegate.m */; }; 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; @@ -28,6 +36,19 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 191AFDE617F6A30000E7F483 /* OggOpusStreamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OggOpusStreamParser.h; sourceTree = ""; }; + 191AFDE717F6A30000E7F483 /* OggOpusStreamParser.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OggOpusStreamParser.mm; sourceTree = ""; }; + 1940DE4017F86BA5002A6432 /* Ogg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Ogg.framework; path = Frameworks/Ogg.framework; sourceTree = ""; }; + 1940DE4217F86BB6002A6432 /* Opus.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Opus.framework; path = Frameworks/Opus.framework; sourceTree = ""; }; + 1940DE4317F86BB6002A6432 /* Vorbis.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Vorbis.framework; path = Frameworks/Vorbis.framework; sourceTree = ""; }; + 199175D917E70C6600D69392 /* BKAudioFileStreamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKAudioFileStreamParser.h; sourceTree = ""; }; + 19A0141A17E6FD4000C7D69C /* AppleAudioFileStreamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleAudioFileStreamParser.h; sourceTree = ""; }; + 19A0141B17E6FD4000C7D69C /* AppleAudioFileStreamParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppleAudioFileStreamParser.m; sourceTree = ""; }; + 19A70D9917F1C08600F5A2C6 /* cputime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cputime.c; sourceTree = ""; }; + 19A70D9B17F1C0C400F5A2C6 /* cputime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cputime.h; sourceTree = ""; }; + 19A8DEA717EED03A00ED8C86 /* OggVorbisStreamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OggVorbisStreamParser.h; sourceTree = ""; }; + 19A8DEA817EED03A00ED8C86 /* OggVorbisStreamParser.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OggVorbisStreamParser.mm; sourceTree = ""; }; + 19B273BE180A3EFF0072C2A5 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D3623240D0F684500981E51 /* iPhoneStreamingPlayerAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iPhoneStreamingPlayerAppDelegate.h; sourceTree = ""; }; 1D3623250D0F684500981E51 /* iPhoneStreamingPlayerAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iPhoneStreamingPlayerAppDelegate.m; sourceTree = ""; }; @@ -59,6 +80,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 19B273BF180A3EFF0072C2A5 /* AVFoundation.framework in Frameworks */, + 1940DE4417F86BB6002A6432 /* Opus.framework in Frameworks */, + 1940DE4517F86BB6002A6432 /* Vorbis.framework in Frameworks */, + 1940DE4117F86BA5002A6432 /* Ogg.framework in Frameworks */, 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, @@ -81,6 +106,15 @@ 1D3623250D0F684500981E51 /* iPhoneStreamingPlayerAppDelegate.m */, 28D7ACF60DDB3853001CB0EB /* iPhoneStreamingPlayerViewController.h */, 28D7ACF70DDB3853001CB0EB /* iPhoneStreamingPlayerViewController.m */, + 19A0141A17E6FD4000C7D69C /* AppleAudioFileStreamParser.h */, + 19A0141B17E6FD4000C7D69C /* AppleAudioFileStreamParser.m */, + 199175D917E70C6600D69392 /* BKAudioFileStreamParser.h */, + 19A8DEA717EED03A00ED8C86 /* OggVorbisStreamParser.h */, + 19A8DEA817EED03A00ED8C86 /* OggVorbisStreamParser.mm */, + 19A70D9917F1C08600F5A2C6 /* cputime.c */, + 19A70D9B17F1C0C400F5A2C6 /* cputime.h */, + 191AFDE617F6A30000E7F483 /* OggOpusStreamParser.h */, + 191AFDE717F6A30000E7F483 /* OggOpusStreamParser.mm */, ); path = Classes; sourceTree = ""; @@ -132,6 +166,10 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 19B273BE180A3EFF0072C2A5 /* AVFoundation.framework */, + 1940DE4217F86BB6002A6432 /* Opus.framework */, + 1940DE4317F86BB6002A6432 /* Vorbis.framework */, + 1940DE4017F86BA5002A6432 /* Ogg.framework */, C9AB93F20FCF81790047C0FA /* MediaPlayer.framework */, C9AB93E10FCF816F0047C0FA /* AudioToolbox.framework */, C9423DF00EF8AA6B003B785B /* CFNetwork.framework */, @@ -169,7 +207,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0460; + LastUpgradeCheck = 0500; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "iPhoneStreamingPlayer" */; compatibilityVersion = "Xcode 3.2"; @@ -213,8 +251,12 @@ buildActionMask = 2147483647; files = ( 1D60589B0D05DD56006BFB54 /* main.m in Sources */, + 19A8DEA917EED03A00ED8C86 /* OggVorbisStreamParser.mm in Sources */, 1D3623260D0F684500981E51 /* iPhoneStreamingPlayerAppDelegate.m in Sources */, + 19A70D9A17F1C08600F5A2C6 /* cputime.c in Sources */, 28D7ACF80DDB3853001CB0EB /* iPhoneStreamingPlayerViewController.m in Sources */, + 191AFDE817F6A30000E7F483 /* OggOpusStreamParser.mm in Sources */, + 19A0141C17E6FD4000C7D69C /* AppleAudioFileStreamParser.m in Sources */, C9C2D87A0EB6E09C00A3D071 /* AudioStreamer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -226,13 +268,21 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = "iPhone Distribution: BENNY KHOO (39HKGMK865)"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + /Users/bennykhoo/Sources/Barcast/src/AudioStreamer/Frameworks, + ); GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = iPhoneStreamingPlayer_Prefix.pch; INFOPLIST_FILE = iPhoneInfo.plist; PRODUCT_NAME = iPhoneStreamingPlayer; + PROVISIONING_PROFILE = "B3C8F2A1-322E-4186-A395-9C158693CAE3"; + "VALID_ARCHS[sdk=*]" = "arm64 armv7 armv7s"; }; name = Debug; }; @@ -240,24 +290,30 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = "iPhone Distribution: BENNY KHOO (39HKGMK865)"; COPY_PHASE_STRIP = YES; + DEAD_CODE_STRIPPING = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + /Users/bennykhoo/Sources/Barcast/src/AudioStreamer/Frameworks, + ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = iPhoneStreamingPlayer_Prefix.pch; INFOPLIST_FILE = iPhoneInfo.plist; PRODUCT_NAME = iPhoneStreamingPlayer; + PROVISIONING_PROFILE = "B3C8F2A1-322E-4186-A395-9C158693CAE3"; }; name = Release; }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Distribution: BENNY KHOO (39HKGMK865)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; - PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE = "B3C8F2A1-322E-4186-A395-9C158693CAE3"; SDKROOT = iphoneos; }; name = Debug; @@ -265,12 +321,12 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Distribution: BENNY KHOO (39HKGMK865)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - PROVISIONING_PROFILE = ""; + ONLY_ACTIVE_ARCH = YES; + PROVISIONING_PROFILE = "B3C8F2A1-322E-4186-A395-9C158693CAE3"; SDKROOT = iphoneos; }; name = Release;