Index: test/test.c =================================================================== --- test/test.c (revision 2440) +++ test/test.c (working copy) @@ -2747,6 +2747,12 @@ { return HB_ACODEC_VORBIS; } +#ifdef __APPLE__ + else if( !strcasecmp( codec, "ca_aac") ) + { + return HB_ACODEC_CA_AAC; + } +#endif else { return -1; Index: test/module.defs =================================================================== --- test/module.defs (revision 2440) +++ test/module.defs (working copy) @@ -36,7 +36,7 @@ TEST.GCC.I += $(LIBHB.GCC.I) ifeq ($(BUILD.system),darwin) - TEST.GCC.f += IOKit CoreServices + TEST.GCC.f += IOKit CoreServices AudioToolbox TEST.GCC.l += bz2 z else ifeq ($(BUILD.system),linux) TEST.GCC.l += bz2 z pthread dl m Index: libhb/platform/macosx/encca_aac.c =================================================================== --- libhb/platform/macosx/encca_aac.c (revision 0) +++ libhb/platform/macosx/encca_aac.c (revision 0) @@ -0,0 +1,279 @@ +/* This file is part of the HandBrake source code. + Homepage: . + It may be used under the terms of the GNU General Public License. */ + +#include "hb.h" +#include +#include + +int encCoreAudioInit( hb_work_object_t *, hb_job_t * ); +int encCoreAudioWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** ); +void encCoreAudioClose( hb_work_object_t * ); + +hb_work_object_t hb_encca_aac = +{ + WORK_ENC_CA_AAC, + "AAC encoder (Apple)", + encCoreAudioInit, + encCoreAudioWork, + encCoreAudioClose +}; + +struct hb_work_private_s +{ + hb_job_t *job; + + AudioConverterRef converter; + uint8_t *obuf; + uint8_t *buf; + hb_list_t *list; + unsigned long isamples, isamplesiz, omaxpacket, nchannels; + uint64_t pts, ibytes; +}; + +/*********************************************************************** + * hb_work_encCoreAudio_init + *********************************************************************** + * + **********************************************************************/ +int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job ) +{ + hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) ); + hb_audio_t * audio = w->audio; + AudioStreamBasicDescription input, output; + UInt32 tmp, tmpsiz = sizeof( tmp ); + OSStatus err; + + w->private_data = pv; + pv->job = job; + + // pass the number of channels used into the private work data + pv->nchannels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT( audio->config.out.mixdown ); + + bzero( &input, sizeof( AudioStreamBasicDescription ) ); + input.mSampleRate = ( Float64 ) audio->config.out.samplerate; + input.mFormatID = kAudioFormatLinearPCM; + input.mFormatFlags = kLinearPCMFormatFlagIsFloat | kAudioFormatFlagsNativeEndian; + input.mBytesPerPacket = 4 * pv->nchannels; + input.mFramesPerPacket = 1; + input.mBytesPerFrame = input.mBytesPerPacket * input.mFramesPerPacket; + input.mChannelsPerFrame = pv->nchannels; + input.mBitsPerChannel = 32; + + bzero( &output, sizeof( AudioStreamBasicDescription ) ); + output.mSampleRate = ( Float64 ) audio->config.out.samplerate; + output.mFormatID = kAudioFormatMPEG4AAC; + output.mChannelsPerFrame = pv->nchannels; + // let CoreAudio decide the rest... + + // initialise encoder + err = AudioConverterNew( &input, &output, &pv->converter ); + if( err != noErr) + { + hb_log( "Error creating an AudioConverter %x %d", err, output.mBytesPerFrame ); + *job->die = 1; + return 0; + } + + if( audio->config.out.mixdown == HB_AMIXDOWN_6CH && audio->config.in.codec == HB_ACODEC_AC3 ) + { + SInt32 channelMap[6] = { 2, 1, 3, 4, 5, 0 }; + AudioConverterSetProperty( pv->converter, kAudioConverterChannelMap, + sizeof( channelMap ), channelMap ); + } + + // set encoder quality to maximum + tmp = kAudioConverterQuality_Max; + AudioConverterSetProperty( pv->converter, kAudioConverterCodecQuality, + sizeof( tmp ), &tmp ); + + // set encoder bitrate control mode to constrained variable + tmp = kAudioCodecBitRateControlMode_VariableConstrained; + AudioConverterSetProperty( pv->converter, kAudioCodecPropertyBitRateControlMode, + sizeof( tmp ), &tmp ); + + // get available bitrates + AudioValueRange *bitrates; + ssize_t bitrateCounts, n; + err = AudioConverterGetPropertyInfo( pv->converter, kAudioConverterApplicableEncodeBitRates, + &tmpsiz, NULL); + bitrates = malloc( tmpsiz ); + err = AudioConverterGetProperty( pv->converter, kAudioConverterApplicableEncodeBitRates, + &tmpsiz, bitrates); + bitrateCounts = tmpsiz / sizeof( AudioValueRange ); + + // set bitrate + tmp = audio->config.out.bitrate * 1000; + if( tmp < bitrates[0].mMinimum ) + tmp = bitrates[0].mMinimum; + if( tmp > bitrates[bitrateCounts-1].mMinimum ) + tmp = bitrates[bitrateCounts-1].mMinimum; + free( bitrates ); + AudioConverterSetProperty( pv->converter, kAudioConverterEncodeBitRate, + sizeof( tmp ), &tmp ); + + // get real input + tmpsiz = sizeof( input ); + AudioConverterGetProperty( pv->converter, + kAudioConverterCurrentInputStreamDescription, + &tmpsiz, &input ); + // get real output + tmpsiz = sizeof( output ); + AudioConverterGetProperty( pv->converter, + kAudioConverterCurrentOutputStreamDescription, + &tmpsiz, &output ); + + // set sizes + pv->isamplesiz = input.mBytesPerPacket; + pv->isamples = output.mFramesPerPacket; + + // get maximum output size + AudioConverterGetProperty( pv->converter, + kAudioConverterPropertyMaximumOutputPacketSize, + &tmpsiz, &tmp ); + pv->omaxpacket = tmp; + + // get magic cookie (elementary stream descriptor) + tmp = HB_CONFIG_MAX_SIZE; + AudioConverterGetProperty( pv->converter, + kAudioConverterCompressionMagicCookie, + &tmp, w->config->aac.bytes ); + // CoreAudio returns a complete ESDS, but we only need + // the DecoderSpecific info. + w->config->aac.length = 2; + memmove( w->config->aac.bytes, w->config->aac.bytes + 31, + w->config->aac.length ); + + pv->list = hb_list_init(); + pv->buf = NULL; + + return 0; +} + +/*********************************************************************** + * Close + *********************************************************************** + * + **********************************************************************/ +void encCoreAudioClose( hb_work_object_t * w ) +{ + hb_work_private_t * pv = w->private_data; + + if( pv->converter ) + { + AudioConverterDispose( pv->converter ); + hb_list_empty( &pv->list ); + free( pv->obuf ); + free( pv->buf ); + free( pv ); + w->private_data = NULL; + } +} + +/* Called whenever necessary by AudioConverterFillComplexBuffer */ +static OSStatus inInputDataProc( AudioConverterRef converter, UInt32 *npackets, + AudioBufferList *buffers, + AudioStreamPacketDescription** ignored, + void *userdata ) +{ + hb_work_private_t *pv = userdata; + pv->ibytes = hb_list_bytes( pv->list ); + + if( pv->ibytes == 0 ) { + *npackets = 0; + return noErr; + } + + if( pv->buf != NULL ) + free( pv->buf ); + + uint64_t pts, pos; + pv->ibytes = buffers->mBuffers[0].mDataByteSize = MIN( *npackets * pv->isamplesiz, pv->ibytes ); + buffers->mBuffers[0].mData = pv->buf = malloc( buffers->mBuffers[0].mDataByteSize ); + + hb_list_getbytes( pv->list, buffers->mBuffers[0].mData, + buffers->mBuffers[0].mDataByteSize, &pts, &pos ); + + *npackets = buffers->mBuffers[0].mDataByteSize / pv->isamplesiz; + + /* transform data from [-32768,32767] to [-1.0,1.0] */ + float *fdata = buffers->mBuffers[0].mData; + int i; + + for( i = 0; i < *npackets * pv->nchannels; i++ ) + fdata[i] = fdata[i] / 32768.f; + + return noErr; +} + +/*********************************************************************** + * Encode + *********************************************************************** + * + **********************************************************************/ +static hb_buffer_t * Encode( hb_work_object_t * w ) +{ + hb_work_private_t * pv = w->private_data; + UInt32 npackets = 1; + + /* check if we need more data */ + if( hb_list_bytes( pv->list ) < pv->isamples * pv->isamplesiz ) + return NULL; + + hb_buffer_t * obuf; + AudioStreamPacketDescription odesc = { 0 }; + AudioBufferList obuflist = { .mNumberBuffers = 1, + .mBuffers = { { .mNumberChannels = pv->nchannels } }, + }; + + obuf = hb_buffer_init( pv->omaxpacket ); + obuflist.mBuffers[0].mDataByteSize = obuf->size; + obuflist.mBuffers[0].mData = obuf->data; + + AudioConverterFillComplexBuffer( pv->converter, inInputDataProc, pv, + &npackets, &obuflist, &odesc ); + + if( odesc.mDataByteSize == 0 ) + return NULL; + + obuf->start = pv->pts; + pv->pts += 90000LL * pv->isamples / w->audio->config.out.samplerate; + obuf->stop = pv->pts; + obuf->size = odesc.mDataByteSize; + obuf->frametype = HB_FRAME_AUDIO; + + return obuf; +} + +/*********************************************************************** + * Work + *********************************************************************** + * + **********************************************************************/ +int encCoreAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out ) +{ + hb_work_private_t * pv = w->private_data; + hb_buffer_t * buf; + + if( (*buf_in)->size <= 0 ) + { + // EOF on input - send it downstream & say we're done + *buf_out = *buf_in; + *buf_in = NULL; + return HB_WORK_DONE; + } + + hb_list_add( pv->list, *buf_in ); + *buf_in = NULL; + + *buf_out = buf = Encode( w ); + + while( buf ) + { + buf->next = Encode( w ); + buf = buf->next; + } + + return HB_WORK_OK; +} Index: libhb/hb.c =================================================================== --- libhb/hb.c (revision 2440) +++ libhb/hb.c (working copy) @@ -86,7 +86,7 @@ * @param update_check signals libhb to check for updated version from HandBrake website. * @return Handle to hb_handle_t for use on all subsequent calls to libhb. */ -hb_handle_t * hb_init_real( int verbose, int update_check ) +hb_handle_t * hb_init( int verbose, int update_check ) { hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 ); uint64_t date; @@ -150,11 +150,29 @@ h->die = 0; h->main_thread = hb_thread_init( "libhb", thread_func, h, HB_NORMAL_PRIORITY ); + hb_register( &hb_sync ); + hb_register( &hb_decmpeg2 ); + hb_register( &hb_decvobsub ); + hb_register( &hb_render ); + hb_register( &hb_encavcodec ); + hb_register( &hb_encxvid ); + hb_register( &hb_encx264 ); + hb_register( &hb_enctheora ); + hb_register( &hb_deca52 ); + hb_register( &hb_decdca ); + hb_register( &hb_decavcodec ); + hb_register( &hb_decavcodecv ); + hb_register( &hb_decavcodecvi ); + hb_register( &hb_decavcodecai ); + hb_register( &hb_declpcm ); + hb_register( &hb_encfaac ); + hb_register( &hb_enclame ); + hb_register( &hb_encvorbis ); +#ifdef __APPLE__ + hb_register( &hb_encca_aac ); +#endif return h; - - /* Set the scan count to start at 0 */ - //scan_count = 0; } /** @@ -1301,7 +1319,7 @@ } /** - * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init_real. + * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init. * @param _h Pointer to handle to hb_handle_t. */ void hb_close( hb_handle_t ** _h ) Index: libhb/hb.h =================================================================== --- libhb/hb.h (revision 2440) +++ libhb/hb.h (working copy) @@ -14,51 +14,9 @@ #define HB_DEBUG_NONE 0 #define HB_DEBUG_ALL 1 void hb_register( hb_work_object_t * ); -hb_handle_t * hb_init_real( int verbose, int update_check ); +hb_handle_t * hb_init( int verbose, int update_check ); hb_handle_t * hb_init_dl ( int verbose, int update_check ); // hb_init for use with dylib -#define hb_init(v,u) \ -hb_init_real( v, u ); \ -hb_register( &hb_sync ); \ -hb_register( &hb_decmpeg2 ); \ -hb_register( &hb_decvobsub ); \ -hb_register( &hb_encvobsub ); \ -hb_register( &hb_deccc608 ); \ -hb_register( &hb_render ); \ -hb_register( &hb_encavcodec ); \ -hb_register( &hb_encxvid ); \ -hb_register( &hb_encx264 ); \ -hb_register( &hb_enctheora ); \ -hb_register( &hb_deca52 ); \ -hb_register( &hb_decdca ); \ -hb_register( &hb_decavcodec ); \ -hb_register( &hb_decavcodecv ); \ -hb_register( &hb_decavcodecvi ); \ -hb_register( &hb_decavcodecai ); \ -hb_register( &hb_declpcm ); \ -hb_register( &hb_encfaac ); \ -hb_register( &hb_enclame ); \ -hb_register( &hb_encvorbis ); \ - -#define hb_init_express(v,u) \ -hb_init_real( v, u ); \ -hb_register( &hb_sync ); \ -hb_register( &hb_decmpeg2 ); \ -hb_register( &hb_decvobsub ); \ -hb_register( &hb_encvobsub ); \ -hb_register( &hb_deccc608 ); \ -hb_register( &hb_render ); \ -hb_register( &hb_encavcodec ); \ -hb_register( &hb_encx264 ); \ -hb_register( &hb_deca52 ); \ -hb_register( &hb_decdca ); \ -hb_register( &hb_decavcodec ); \ -hb_register( &hb_decavcodecv ); \ -hb_register( &hb_decavcodecvi ); \ -hb_register( &hb_decavcodecai ); \ -hb_register( &hb_declpcm ); \ -hb_register( &hb_encfaac ); \ - /* hb_get_version() */ char * hb_get_version( hb_handle_t * ); int hb_get_build( hb_handle_t * ); Index: libhb/internal.h =================================================================== --- libhb/internal.h (revision 2440) +++ libhb/internal.h (working copy) @@ -271,7 +271,8 @@ WORK_DECLPCM, WORK_ENCFAAC, WORK_ENCLAME, - WORK_ENCVORBIS + WORK_ENCVORBIS, + WORK_ENC_CA_AAC }; enum Index: libhb/work.c =================================================================== --- libhb/work.c (revision 2440) +++ libhb/work.c (working copy) @@ -106,6 +106,7 @@ case HB_ACODEC_FAAC: return hb_get_work( WORK_ENCFAAC ); case HB_ACODEC_LAME: return hb_get_work( WORK_ENCLAME ); case HB_ACODEC_VORBIS: return hb_get_work( WORK_ENCVORBIS ); + case HB_ACODEC_CA_AAC: return hb_get_work( WORK_ENC_CA_AAC ); } return NULL; } @@ -329,8 +330,9 @@ else { hb_log( " + encoder: %s", ( audio->config.out.codec == HB_ACODEC_FAAC ) ? - "faac" : ( ( audio->config.out.codec == HB_ACODEC_LAME ) ? "lame" : - "vorbis" ) ); + "faac" : ( ( audio->config.out.codec == HB_ACODEC_LAME ) ? + "lame" : ( ( audio->config.out.codec == HB_ACODEC_CA_AAC ) ? + "ca_aac" : "vorbis" ) ) ); hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate ); } } Index: libhb/module.defs =================================================================== --- libhb/module.defs (revision 2440) +++ libhb/module.defs (working copy) @@ -41,6 +41,7 @@ LIBHB.GCC.D += SYS_CYGWIN else ifeq ($(BUILD.system),darwin) LIBHB.GCC.D += SYS_DARWIN + LIBHB.c += $(wildcard $(LIBHB.src/)platform/macosx/*.c) else ifeq ($(BUILD.system),linux) LIBHB.GCC.D += SYS_LINUX _LARGEFILE_SOURCE _FILE_OFFSET_BITS=64 else ifeq ($(BUILD.system),mingw) Index: libhb/muxmkv.c =================================================================== --- libhb/muxmkv.c (revision 2440) +++ libhb/muxmkv.c (working copy) @@ -226,6 +226,7 @@ } break; case HB_ACODEC_FAAC: + case HB_ACODEC_CA_AAC: track->codecPrivate = audio->priv.config.aac.bytes; track->codecPrivateSize = audio->priv.config.aac.length; track->codecID = MK_ACODEC_AAC; Index: libhb/common.c =================================================================== --- libhb/common.c (revision 2440) +++ libhb/common.c (working copy) @@ -31,7 +31,7 @@ { { "32", 32 }, { "40", 40 }, { "48", 48 }, { "56", 56 }, { "64", 64 }, { "80", 80 }, { "96", 96 }, { "112", 112 }, { "128", 128 }, { "160", 160 }, { "192", 192 }, { "224", 224 }, - { "256", 256 }, { "320", 320 }, { "384", 384 } }; + { "256", 256 }, { "320", 320 }, { "384", 384 }, { "448", 448 } }; int hb_audio_bitrates_count = sizeof( hb_audio_bitrates ) / sizeof( hb_rate_t ); int hb_audio_bitrates_default = 8; /* 128 kbps */ @@ -227,6 +227,7 @@ switch( audio->config.out.codec ) { case HB_ACODEC_FAAC: + case HB_ACODEC_CA_AAC: case HB_ACODEC_VORBIS: samples_per_frame = 1024; break; Index: libhb/common.h =================================================================== --- libhb/common.h (revision 2440) +++ libhb/common.h (working copy) @@ -286,6 +286,7 @@ #define HB_ACODEC_LPCM 0x002000 #define HB_ACODEC_DCA 0x004000 #define HB_ACODEC_FFMPEG 0x008000 +#define HB_ACODEC_CA_AAC 0x010000 /* Audio Mixdown */ /* define some masks, used to extract the various information from the HB_AMIXDOWN_XXXX values */ @@ -675,6 +676,7 @@ extern hb_work_object_t hb_encfaac; extern hb_work_object_t hb_enclame; extern hb_work_object_t hb_encvorbis; +extern hb_work_object_t hb_encca_aac; #define FILTER_OK 0 #define FILTER_DELAY 1 Index: macosx/Controller.mm =================================================================== --- macosx/Controller.mm (revision 2440) +++ macosx/Controller.mm (working copy) @@ -4787,10 +4787,14 @@ { case 0: /* MP4 */ - // AAC + // FAAC menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (faac)" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_ACODEC_FAAC]; + // CA_AAC + menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (CoreAudio)" action: NULL keyEquivalent: @""]; + [menuItem setTag: HB_ACODEC_CA_AAC]; + // AC3 Passthru menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AC3 Passthru" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_ACODEC_AC3]; @@ -5230,6 +5234,21 @@ break; } + case HB_ACODEC_CA_AAC: + /* check if we have a 6ch discrete conversion in either audio track */ + if ([[mixdownPopUp selectedItem] tag] == HB_AMIXDOWN_6CH) + { + minbitrate = 128; + maxbitrate = 768; + break; + } + else + { + minbitrate = 64; + maxbitrate = 320; + break; + } + case HB_ACODEC_LAME: /* Lame is happy using our min bitrate of 32 kbps */ minbitrate = 32; Index: macosx/HandBrake.xcodeproj/project.pbxproj =================================================================== --- macosx/HandBrake.xcodeproj/project.pbxproj (revision 2440) +++ macosx/HandBrake.xcodeproj/project.pbxproj (working copy) @@ -57,6 +57,8 @@ A2D7AD6D0C998AD30082CA33 /* pref-picture.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A2D7AD640C998AD30082CA33 /* pref-picture.tiff */; }; A2D7AD6E0C998AD30082CA33 /* Queue.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A2D7AD650C998AD30082CA33 /* Queue.tiff */; }; A2D7AD6F0C998AD30082CA33 /* Source.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A2D7AD660C998AD30082CA33 /* Source.tiff */; }; + A906A0510F7A7B210007A827 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A906A0500F7A7B210007A827 /* AudioToolbox.framework */; }; + A906A0520F7A7B210007A827 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A906A0500F7A7B210007A827 /* AudioToolbox.framework */; }; A9AC41DF0C918DB500DDF9B8 /* HBAdvancedController.m in Sources */ = {isa = PBXBuildFile; fileRef = A9AC41DD0C918DB500DDF9B8 /* HBAdvancedController.m */; }; A9AC41E00C918DB500DDF9B8 /* HBAdvancedController.h in Headers */ = {isa = PBXBuildFile; fileRef = A9AC41DE0C918DB500DDF9B8 /* HBAdvancedController.h */; }; D289A9F30DBBE7AC00CE614B /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D289A9F20DBBE7AC00CE614B /* CoreServices.framework */; }; @@ -177,6 +179,7 @@ A2D7AD640C998AD30082CA33 /* pref-picture.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "pref-picture.tiff"; sourceTree = ""; }; A2D7AD650C998AD30082CA33 /* Queue.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Queue.tiff; sourceTree = ""; }; A2D7AD660C998AD30082CA33 /* Source.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Source.tiff; sourceTree = ""; }; + A906A0500F7A7B210007A827 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; A9AC41DD0C918DB500DDF9B8 /* HBAdvancedController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = HBAdvancedController.m; sourceTree = ""; }; A9AC41DE0C918DB500DDF9B8 /* HBAdvancedController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HBAdvancedController.h; sourceTree = ""; }; D289A9F20DBBE7AC00CE614B /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; @@ -224,6 +227,7 @@ 2713E6300F676510002E0A01 /* libhb.a in Frameworks */, 2774BE900F66F47100B65FC6 /* libbz2.dylib in Frameworks */, 2774BE920F66F48200B65FC6 /* libz.dylib in Frameworks */, + A906A0520F7A7B210007A827 /* AudioToolbox.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -241,6 +245,7 @@ 2713E6420F676526002E0A01 /* libhb.a in Frameworks */, 2774BEC70F66F61A00B65FC6 /* libbz2.dylib in Frameworks */, 2774BEC80F66F61A00B65FC6 /* libz.dylib in Frameworks */, + A906A0510F7A7B210007A827 /* AudioToolbox.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -288,6 +293,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + A906A0500F7A7B210007A827 /* AudioToolbox.framework */, A25962E00F15077500B3BF4E /* Quartz.framework */, A20F47000EBB5EC2005B861B /* QTKit.framework */, A20F46DB0EBB5E7A005B861B /* QuickTime.framework */,