Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

supporting Ogg Opus #88

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Classes/AppleAudioFileStreamParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// AppleAudioFileStreamParser.h
// iPhoneStreamingPlayer
//
// Created by Benny Khoo on 9/16/13.
//
//

#import <Foundation/Foundation.h>

#include <AudioToolbox/AudioToolbox.h>

#include "BKAudioFileStreamParser.h"

@interface AppleAudioFileStreamParser : NSObject<BKAudioFileStreamParser>

- (id) initWithHint:(AudioFileTypeID)fileTypeHint;

@end
216 changes: 216 additions & 0 deletions Classes/AppleAudioFileStreamParser.m
Original file line number Diff line number Diff line change
@@ -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
33 changes: 31 additions & 2 deletions Classes/AudioStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include <pthread.h>
#include <AudioToolbox/AudioToolbox.h>
#include "BKAudioFileStreamParser.h"

#define LOG_QUEUED_BUFFERS 0

Expand Down Expand Up @@ -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<BKAudioFileStreamDelegate>
{
NSURL *url;

Expand All @@ -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<BKAudioFileStreamParser> audioFileStreamParser;
AudioStreamBasicDescription asbd; // description of the audio
NSThread *internalThread; // the thread where the download and
// audio file stream parsing occurs
Expand Down
Loading