QTKit (OSX 64bit): Add audio export to Quicktime
authorDamien Plisson <damien.plisson@yahoo.fr>
Sat, 10 Apr 2010 09:31:41 +0000 (09:31 +0000)
committerDamien Plisson <damien.plisson@yahoo.fr>
Sat, 10 Apr 2010 09:31:41 +0000 (09:31 +0000)
Supports default OSX codecs : Linear PCM, Apple Lossless and AAC

Note that AAC codec doesn't support sample rates above 48kHz. If a python/rna guru knows how to easily enforce this limit, he is welcome!

Enjoy making Quicktime movies now with audio!

13 files changed:
release/scripts/ui/properties_render.py
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/SConscript
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/Makefile
source/blender/makesrna/intern/SConscript
source/blender/makesrna/intern/rna_scene.c
source/blender/quicktime/CMakeLists.txt
source/blender/quicktime/SConscript
source/blender/quicktime/apple/Makefile
source/blender/quicktime/apple/qtkit_export.m
source/blender/quicktime/apple/quicktime_export.c
source/blender/quicktime/quicktime_export.h

index 2d20a94..57cd23e 100644 (file)
@@ -362,13 +362,37 @@ class RENDER_PT_output(RenderButtonsPanel):
 
         elif rd.file_format == 'QUICKTIME_CARBON':
             split = layout.split()
-            split.operator("scene.render_set_quicktime_codec")
+            split.operator("scene.render_data_set_quicktime_codec")
 
         elif rd.file_format == 'QUICKTIME_QTKIT':
             split = layout.split()
             col = split.column()
-            col.prop(rd, "quicktime_codec_type")
+            col.prop(rd, "quicktime_codec_type", text="Video Codec")
             col.prop(rd, "quicktime_codec_spatial_quality", text="Quality")
+            
+            #Audio
+            col.prop(rd,"quicktime_audiocodec_type", text="Audio Codec")
+            if rd.quicktime_audiocodec_type != 'No audio':
+                split = layout.split()
+                col = split.column()
+                if rd.quicktime_audiocodec_type == 'LPCM':
+                    col.prop(rd,"quicktime_audio_bitdepth", text="")
+                if wide_ui:
+                    col = split.column()
+                col.prop(rd,"quicktime_audio_samplerate", text="")
+
+                split = layout.split()
+                col = split.column()
+                if rd.quicktime_audiocodec_type == 'AAC':
+                    col.prop(rd,"quicktime_audio_bitrate")
+                if wide_ui:
+                    subsplit = split.split()
+                    col = subsplit.column()
+                if rd.quicktime_audiocodec_type == 'AAC':
+                    col.prop(rd,"quicktime_audio_codec_isvbr")
+                if wide_ui:
+                    col = subsplit.column()
+                col.prop(rd,"quicktime_audio_resampling_hq")
 
 
 class RENDER_PT_encoding(RenderButtonsPanel):
index f9deebb..7d7af0d 100644 (file)
@@ -104,6 +104,15 @@ typedef struct QuicktimeCodecSettings {
        int     minTemporalQuality; /* in 0-100 scale, to be translated in 0-1024 for qt use */
        int     keyFrameRate;
        int     bitRate;        /* bitrate in bps */
+       
+       /* Audio Codec settings */
+       int audiocodecType;
+       int audioSampleRate;
+       short audioBitDepth;
+       short audioChannels;
+       int audioCodecFlags;
+       int audioBitRate;
+       int pad1;
 } QuicktimeCodecSettings;
 
 typedef struct FFMpegCodecData {
index cf31fb8..71cfc3c 100644 (file)
@@ -6,7 +6,7 @@ objs = []
 o = SConscript('intern/SConscript')
 objs += o
 
-incs = '#/intern/guardedalloc ../blenkernel ../blenlib ../makesdna intern .'
+incs = '#/intern/guardedalloc #/intern/audaspace/intern ../blenkernel ../blenlib ../makesdna intern .'
 incs += ' ../windowmanager ../editors/include ../gpu ../imbuf ../ikplugin'
 incs += ' ../render/extern/include'
 
index 5893116..0e25160 100644 (file)
@@ -39,7 +39,7 @@ SET(SRC
                ../../../../intern/guardedalloc/intern/mallocn.c
                ../../../../intern/guardedalloc/intern/mmap_win.c)
 
-INCLUDE_DIRECTORIES(../../../../intern/guardedalloc .. ../../makesdna ../../blenkernel ../../blenlib ../../ikplugin ../../windowmanager ../../editors/include ../../gpu ../../imbuf ../../render/extern/include .)
+INCLUDE_DIRECTORIES(../../../../intern/audaspace/intern ../../../../intern/guardedalloc .. ../../makesdna ../../blenkernel ../../blenlib ../../ikplugin ../../windowmanager ../../editors/include ../../gpu ../../imbuf ../../render/extern/include .)
 FILE(GLOB INC_FILES ../*.h ../../makesdna/*.h)
 
 IF(NOT WITH_PYTHON)
index 5afe55b..c265931 100644 (file)
@@ -46,6 +46,7 @@ endif
 CFLAGS += $(LEVEL_1_C_WARNINGS)
 
 CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../../../intern/audaspace/intern
 CPPFLAGS += -I../../blenlib
 CPPFLAGS += -I../../blenkernel
 CPPFLAGS += -I../../imbuf
index b63a816..d22a654 100644 (file)
@@ -33,6 +33,7 @@ incs = '#/intern/guardedalloc ../../blenlib ../../blenkernel'
 incs += ' ../../imbuf ../../makesdna ../../makesrna ../../ikplugin'
 incs += ' ../../windowmanager ../../editors/include'
 incs += ' ../../render/extern/include'
+incs += ' #/intern/audaspace/intern'
 
 if env['WITH_BF_OPENEXR']:
        defs.append('WITH_OPENEXR')
index dd06d2d..40027b1 100644 (file)
@@ -39,6 +39,7 @@
 
 #ifdef WITH_QUICKTIME
 #include "quicktime_export.h"
+#include "AUD_C-API.h"
 #endif
 
 #ifdef WITH_FFMPEG
@@ -523,14 +524,14 @@ static int rna_RenderSettings_qtcodecsettings_codecType_get(PointerRNA *ptr)
 {
        RenderData *rd= (RenderData*)ptr->data;
        
-       return quicktime_rnatmpvalue_from_codectype(rd->qtcodecsettings.codecType);
+       return quicktime_rnatmpvalue_from_videocodectype(rd->qtcodecsettings.codecType);
 }
 
 static void rna_RenderSettings_qtcodecsettings_codecType_set(PointerRNA *ptr, int value)
 {
        RenderData *rd= (RenderData*)ptr->data;
 
-       rd->qtcodecsettings.codecType = quicktime_codecType_from_rnatmpvalue(value);
+       rd->qtcodecsettings.codecType = quicktime_videocodecType_from_rnatmpvalue(value);
 }
 
 static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bContext *C, PointerRNA *ptr, int *free)
@@ -541,8 +542,8 @@ static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bCon
        int i=1, totitem= 0;
        char id[5];
        
-       for(i=0;i<quicktime_get_num_codecs();i++) {
-               codecTypeDesc = quicktime_get_codecType_desc(i);
+       for(i=0;i<quicktime_get_num_videocodecs();i++) {
+               codecTypeDesc = quicktime_get_videocodecType_desc(i);
                if (!codecTypeDesc) break;
                
                tmp.value= codecTypeDesc->rnatmpvalue;
@@ -556,9 +557,48 @@ static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bCon
        RNA_enum_item_end(&item, &totitem);
        *free= 1;
        
+       return item;    
+}
+
+#ifdef USE_QTKIT
+static int rna_RenderSettings_qtcodecsettings_audiocodecType_get(PointerRNA *ptr)
+{
+       RenderData *rd= (RenderData*)ptr->data;
+       
+       return quicktime_rnatmpvalue_from_audiocodectype(rd->qtcodecsettings.audiocodecType);
+}
+
+static void rna_RenderSettings_qtcodecsettings_audiocodecType_set(PointerRNA *ptr, int value)
+{
+       RenderData *rd= (RenderData*)ptr->data;
+       
+       rd->qtcodecsettings.audiocodecType = quicktime_audiocodecType_from_rnatmpvalue(value);
+}
+
+static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+       EnumPropertyItem *item= NULL;
+       EnumPropertyItem tmp = {0, "", 0, "", ""};
+       QuicktimeCodecTypeDesc *codecTypeDesc;
+       int i=1, totitem= 0;
+       
+       for(i=0;i<quicktime_get_num_audiocodecs();i++) {
+               codecTypeDesc = quicktime_get_audiocodecType_desc(i);
+               if (!codecTypeDesc) break;
+               
+               tmp.value= codecTypeDesc->rnatmpvalue;
+               tmp.identifier= codecTypeDesc->codecName; 
+               tmp.name= codecTypeDesc->codecName;
+               RNA_enum_item_add(&item, &totitem, &tmp);
+       }
+       
+       RNA_enum_item_end(&item, &totitem);
+       *free= 1;
+       
        return item;    
 }      
 #endif
+#endif
 
 static int rna_RenderSettings_active_layer_index_get(PointerRNA *ptr)
 {
@@ -1824,6 +1864,35 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
        static EnumPropertyItem quicktime_codec_type_items[] = {
                {0, "codec", 0, "codec", ""},
                {0, NULL, 0, NULL, NULL}};
+       
+#ifdef USE_QTKIT
+       static EnumPropertyItem quicktime_audio_samplerate_items[] = {
+               {22050, "22050", 0, "22kHz", ""},
+               {44100, "44100", 0, "44.1kHz", ""},
+               {48000, "48000", 0, "48kHz", ""},
+               {88200, "88200", 0, "88.2kHz", ""},
+               {96000, "96000", 0, "96kHz", ""},
+               {192000, "192000", 0, "192kHz", ""},
+               {0, NULL, 0, NULL, NULL}};
+       
+       static EnumPropertyItem quicktime_audio_bitdepth_items[] = {
+               {AUD_FORMAT_U8, "8BIT", 0, "8bit", ""},
+               {AUD_FORMAT_S16, "16BIT", 0, "16bit", ""},
+               {AUD_FORMAT_S24, "24BIT", 0, "24bit", ""},
+               {AUD_FORMAT_S32, "32BIT", 0, "32bit", ""},
+               {AUD_FORMAT_FLOAT32, "FLOAT32", 0, "float32", ""},
+               {AUD_FORMAT_FLOAT64, "FLOAT64", 0, "float64", ""},
+               {0, NULL, 0, NULL, NULL}};
+       
+       static EnumPropertyItem quicktime_audio_bitrate_items[] = {
+               {64000, "64000", 0, "64kbps", ""},
+               {112000, "112000", 0, "112kpbs", ""},
+               {128000, "128000", 0, "128kbps", ""},
+               {192000, "192000", 0, "192kbps", ""},
+               {256000, "256000", 0, "256kbps", ""},
+               {320000, "320000", 0, "320kbps", ""},
+               {0, NULL, 0, NULL, NULL}};
+#endif
 #endif
 
 #ifdef WITH_FFMPEG
@@ -2031,8 +2100,47 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
        RNA_def_property_int_sdna(prop, NULL, "qtcodecsettings.codecSpatialQuality");
        RNA_def_property_range(prop, 0, 100);
        RNA_def_property_ui_text(prop, "Spatial quality", "Intra-frame spatial quality level");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+
+#ifdef USE_QTKIT
+       prop= RNA_def_property(srna, "quicktime_audiocodec_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "qtcodecsettings.audiocodecType");
+       RNA_def_property_enum_items(prop, quicktime_codec_type_items);
+       RNA_def_property_enum_funcs(prop, "rna_RenderSettings_qtcodecsettings_audiocodecType_get",
+                                                               "rna_RenderSettings_qtcodecsettings_audiocodecType_set",
+                                                               "rna_RenderSettings_qtcodecsettings_audiocodecType_itemf");
+       RNA_def_property_ui_text(prop, "Audio Codec", "QuickTime audio codec type");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       
+       prop= RNA_def_property(srna, "quicktime_audio_samplerate", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "qtcodecsettings.audioSampleRate");
+       RNA_def_property_enum_items(prop, quicktime_audio_samplerate_items);
+       RNA_def_property_ui_text(prop, "Smp Rate", "Sample Rate");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       
+       prop= RNA_def_property(srna, "quicktime_audio_bitdepth", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "qtcodecsettings.audioBitDepth");
+       RNA_def_property_enum_items(prop, quicktime_audio_bitdepth_items);
+       RNA_def_property_ui_text(prop, "Bit Depth", "Bit Depth");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       
+       prop= RNA_def_property(srna, "quicktime_audio_resampling_hq", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_negative_sdna(prop, NULL, "qtcodecsettings.audioCodecFlags", QTAUDIO_FLAG_RESAMPLE_NOHQ);
+       RNA_def_property_ui_text(prop, "HQ", "Use High Quality resampling algorithm");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       
+       prop= RNA_def_property(srna, "quicktime_audio_codec_isvbr", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_negative_sdna(prop, NULL, "qtcodecsettings.audioCodecFlags", QTAUDIO_FLAG_CODEC_ISCBR);
+       RNA_def_property_ui_text(prop, "VBR", "Use Variable Bit Rate compression (improves quality at same bitrate)");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+
+       prop= RNA_def_property(srna, "quicktime_audio_bitrate", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "qtcodecsettings.audioBitRate");
+       RNA_def_property_enum_items(prop, quicktime_audio_bitrate_items);
+       RNA_def_property_ui_text(prop, "Bitrate", "Compressed audio bitrate");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);        
 #endif
+#endif
        
 #ifdef WITH_FFMPEG
        /* FFMPEG Video*/
index f1b2a12..2b5c8a5 100644 (file)
@@ -45,6 +45,7 @@ SET(INC
        ../render/extern/include
        ../include
        ../windowmanager
+       ../../../intern/audaspace/intern
 )
 
 SET(INC ${INC} ${QUICKTIME_INC})
index c8cd795..c8aeb70 100644 (file)
@@ -23,7 +23,8 @@ incs  = ['.',
                 '../imbuf/intern',
                 '../blenloader',
                 '../render/extern/include',
-                '../editors/include']
+                '../editors/include',
+                '#/intern/audaspace/intern']
 
 incs.append(env['BF_QUICKTIME_INC'])
 
index 70f3f05..70757f0 100644 (file)
@@ -59,4 +59,5 @@ CPPFLAGS += -I..
 CPPFLAGS += -I../../blenloader -I../../imbuf/intern -I../../imbuf 
 CPPFLAGS += -I../../blenlib -I../../makesdna -I../../editors/include -I../../avi 
 CPPFLAGS += -I../../blenkernel -I../../render/extern/include -I../../windowmanager -I../../makesrna
+CPPFLAGS += -I../../../intern/audaspace/intern
 
index 0608283..cfe8601 100644 (file)
@@ -36,6 +36,9 @@
 #include <string.h>
 
 #include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "AUD_C-API.h"
 
 #include "BKE_global.h"
 #include "BKE_scene.h"
@@ -57,6 +60,7 @@
 #endif
 #import <Cocoa/Cocoa.h>
 #import <QTKit/QTKit.h>
+#include <AudioToolbox/AudioToolbox.h>
 
 #if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4) || !__LP64__
 #error 64 bit build & OSX 10.5 minimum are needed for QTKit
@@ -74,14 +78,34 @@ typedef struct QuicktimeExport {
 
        QTTime frameDuration;
        NSDictionary *frameAttributes;
+       
+       NSString *videoTempFileName;
+       /* Audio section */
+       AUD_Device *audioInputDevice;
+       AudioFileID audioFile;
+       NSString *audioFileName;
+       AudioConverterRef audioConverter;
+       AudioBufferList audioBufferList;
+       AudioStreamBasicDescription audioInputFormat, audioOutputFormat;
+       AudioStreamPacketDescription *audioOutputPktDesc;
+       SInt64 audioFilePos;
+       char* audioInputBuffer;
+       char* audioOutputBuffer;
+       UInt32 audioCodecMaxOutputPacketSize;
+       UInt64 audioTotalExportedFrames, audioTotalSavedFrames;
+       UInt64 audioLastFrame;
+       SInt64 audioOutputPktPos;
+       
 } QuicktimeExport;
 
 static struct QuicktimeExport *qtexport;
 
-#pragma mark rna helper functions
+#define AUDIOOUTPUTBUFFERSIZE 65536
 
+#pragma mark rna helper functions
 
-static QuicktimeCodecTypeDesc qtCodecList[] = {
+/* Video codec */
+static QuicktimeCodecTypeDesc qtVideoCodecList[] = {
        {kRawCodecType, 1, "Uncompressed"},
        {kJPEGCodecType, 2, "JPEG"},
        {kMotionJPEGACodecType, 3, "M-JPEG A"},
@@ -96,34 +120,75 @@ static QuicktimeCodecTypeDesc qtCodecList[] = {
        {kH264CodecType, 12, "H.264"},
        {0,0,NULL}};
 
-static int qtCodecCount = 12;
+static int qtVideoCodecCount = 12;
 
-int quicktime_get_num_codecs() {
-       return qtCodecCount;
+int quicktime_get_num_videocodecs() {
+       return qtVideoCodecCount;
 }
 
-QuicktimeCodecTypeDesc* quicktime_get_codecType_desc(int indexValue) {
-       if ((indexValue>=0) && (indexValue < qtCodecCount))
-               return &qtCodecList[indexValue];
+QuicktimeCodecTypeDesc* quicktime_get_videocodecType_desc(int indexValue) {
+       if ((indexValue>=0) && (indexValue < qtVideoCodecCount))
+               return &qtVideoCodecList[indexValue];
        else
                return NULL;
 }
 
-int quicktime_rnatmpvalue_from_codectype(int codecType) {
+int quicktime_rnatmpvalue_from_videocodectype(int codecType) {
        int i;
-       for (i=0;i<qtCodecCount;i++) {
-               if (qtCodecList[i].codecType == codecType)
-                       return qtCodecList[i].rnatmpvalue;
+       for (i=0;i<qtVideoCodecCount;i++) {
+               if (qtVideoCodecList[i].codecType == codecType)
+                       return qtVideoCodecList[i].rnatmpvalue;
        }
 
        return 0;
 }
 
-int quicktime_codecType_from_rnatmpvalue(int rnatmpvalue) {
+int quicktime_videocodecType_from_rnatmpvalue(int rnatmpvalue) {
        int i;
-       for (i=0;i<qtCodecCount;i++) {
-               if (qtCodecList[i].rnatmpvalue == rnatmpvalue)
-                       return qtCodecList[i].codecType;
+       for (i=0;i<qtVideoCodecCount;i++) {
+               if (qtVideoCodecList[i].rnatmpvalue == rnatmpvalue)
+                       return qtVideoCodecList[i].codecType;
+       }
+       
+       return 0;       
+}
+
+/* Audio codec */
+static QuicktimeCodecTypeDesc qtAudioCodecList[] = {
+       {0, 0, "No audio"},
+       {kAudioFormatLinearPCM, 1, "LPCM"},
+       {kAudioFormatAppleLossless, 2, "Apple Lossless"},
+       {kAudioFormatMPEG4AAC, 3, "AAC"},
+       {0,0,NULL}};
+
+static int qtAudioCodecCount = 4;
+
+int quicktime_get_num_audiocodecs() {
+       return qtAudioCodecCount;
+}
+
+QuicktimeCodecTypeDesc* quicktime_get_audiocodecType_desc(int indexValue) {
+       if ((indexValue>=0) && (indexValue < qtAudioCodecCount))
+               return &qtAudioCodecList[indexValue];
+       else
+               return NULL;
+}
+
+int quicktime_rnatmpvalue_from_audiocodectype(int codecType) {
+       int i;
+       for (i=0;i<qtAudioCodecCount;i++) {
+               if (qtAudioCodecList[i].codecType == codecType)
+                       return qtAudioCodecList[i].rnatmpvalue;
+       }
+       
+       return 0;
+}
+
+int quicktime_audiocodecType_from_rnatmpvalue(int rnatmpvalue) {
+       int i;
+       for (i=0;i<qtAudioCodecCount;i++) {
+               if (qtAudioCodecList[i].rnatmpvalue == rnatmpvalue)
+                       return qtAudioCodecList[i].codecType;
        }
        
        return 0;       
@@ -172,14 +237,68 @@ void filepath_qt(char *string, RenderData *rd) {
 }
 
 
+#pragma mark audio export functions
+
+static OSStatus        write_cookie(AudioConverterRef converter, AudioFileID outfile)
+{
+       // grab the cookie from the converter and write it to the file
+       UInt32 cookieSize = 0;
+       OSStatus err = AudioConverterGetPropertyInfo(converter, kAudioConverterCompressionMagicCookie, &cookieSize, NULL);
+       // if there is an error here, then the format doesn't have a cookie, so on we go
+       if (!err && cookieSize) {
+               char* cookie = malloc(cookieSize);
+               
+               err = AudioConverterGetProperty(converter, kAudioConverterCompressionMagicCookie, &cookieSize, cookie);
+               
+               if (!err)
+                       err = AudioFileSetProperty (outfile, kAudioFilePropertyMagicCookieData, cookieSize, cookie);
+                       // even though some formats have cookies, some files don't take them
+               
+               free(cookie);
+       }
+       return err;
+}
+
+/* AudioConverter input stream callback */
+static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter, 
+                                                UInt32* ioNumberDataPackets,
+                                                AudioBufferList* ioData,
+                                                AudioStreamPacketDescription** outDataPacketDescription,
+                                                void* inUserData)
+{      
+       if (qtexport->audioTotalExportedFrames >= qtexport->audioLastFrame) { /* EOF */
+               *ioNumberDataPackets = 0;
+               return noErr;
+       }
+
+       if (qtexport->audioInputFormat.mBytesPerPacket * *ioNumberDataPackets > AUDIOOUTPUTBUFFERSIZE)
+               *ioNumberDataPackets = AUDIOOUTPUTBUFFERSIZE / qtexport->audioInputFormat.mBytesPerPacket;
+       
+       if ((qtexport->audioTotalExportedFrames + *ioNumberDataPackets) > qtexport->audioLastFrame)
+               *ioNumberDataPackets += qtexport->audioLastFrame - qtexport->audioTotalExportedFrames;
+       
+       qtexport->audioTotalExportedFrames += *ioNumberDataPackets;
+       
+       AUD_readDevice(qtexport->audioInputDevice, (UInt8*)qtexport->audioInputBuffer, 
+                                  qtexport->audioInputFormat.mFramesPerPacket * *ioNumberDataPackets);
+       
+       ioData->mBuffers[0].mDataByteSize = qtexport->audioInputFormat.mBytesPerPacket * *ioNumberDataPackets;
+       ioData->mBuffers[0].mData = qtexport->audioInputBuffer;
+       ioData->mBuffers[0].mNumberChannels = qtexport->audioInputFormat.mChannelsPerFrame;
+       
+       return noErr;
+}      
+
+
 #pragma mark export functions
 
 int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports)
 {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSError *error;
-       char name[2048];
+       char name[1024];
        int success= 1;
+       OSStatus err=noErr;
 
        if(qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport");
        
@@ -192,14 +311,223 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
        }
        else {
                makeqtstring(rd, name);
-               qtexport->filename = [NSString stringWithCString:name
+               qtexport->filename = [[NSString alloc] initWithCString:name
                                                                  encoding:[NSString defaultCStringEncoding]];
-               qtexport->movie = [[QTMovie alloc] initToWritableFile:qtexport->filename error:&error];
+               qtexport->movie = nil;
+               qtexport->audioFile = NULL;
+
+               if (rd->qtcodecsettings.audiocodecType) {
+                       // generate a name for our video & audio files
+                       /* Init audio file */
+                       CFURLRef outputFileURL;
+                       char extension[32];
+                       AudioFileTypeID audioFileType;
+                       
+                       switch (rd->qtcodecsettings.audiocodecType) {
+                               case kAudioFormatLinearPCM:
+                                       audioFileType = kAudioFileWAVEType;
+                                       strcpy(extension,".wav");
+                                       break;
+                               case kAudioFormatMPEG4AAC:
+                               case kAudioFormatAppleLossless:
+                                       audioFileType = kAudioFileM4AType;
+                                       strcpy(extension, ".m4a");
+                                       break;
+                               default:
+                                       audioFileType = kAudioFileAIFFType;
+                                       strcpy(extension,".aiff");
+                                       break;
+                       }
+                                       
+                       tmpnam(name);
+                       strcat(name, extension);
+                       outputFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,(UInt8*) name, strlen(name), false);
+                       
+                       if (outputFileURL) {
+                               
+                               qtexport->audioFileName = [[NSString alloc] initWithCString:name
+                                                                                                                        encoding:[NSString defaultCStringEncoding]];
+                               
+                               qtexport->audioInputFormat.mSampleRate = U.audiorate;
+                               qtexport->audioInputFormat.mFormatID = kAudioFormatLinearPCM;
+                               qtexport->audioInputFormat.mChannelsPerFrame = U.audiochannels;
+                               switch (U.audioformat) {
+                                       case AUD_FORMAT_U8:
+                                               qtexport->audioInputFormat.mBitsPerChannel = 8;
+                                               qtexport->audioInputFormat.mFormatFlags = 0;
+                                               break;
+                                       case AUD_FORMAT_S24:
+                                               qtexport->audioInputFormat.mBitsPerChannel = 24;
+                                               qtexport->audioInputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
+                                               break;
+                                       case AUD_FORMAT_S32:
+                                               qtexport->audioInputFormat.mBitsPerChannel = 32;
+                                               qtexport->audioInputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
+                                               break;
+                                       case AUD_FORMAT_FLOAT32:
+                                               qtexport->audioInputFormat.mBitsPerChannel = 32;
+                                               qtexport->audioInputFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat;
+                                               break;
+                                       case AUD_FORMAT_FLOAT64:
+                                               qtexport->audioInputFormat.mBitsPerChannel = 64;
+                                               qtexport->audioInputFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat;
+                                               break;
+                                       case AUD_FORMAT_S16:
+                                       default:
+                                               qtexport->audioInputFormat.mBitsPerChannel = 16;
+                                               qtexport->audioInputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
+                                               break;
+                               }
+                               qtexport->audioInputFormat.mBytesPerFrame = qtexport->audioInputFormat.mChannelsPerFrame * qtexport->audioInputFormat.mBitsPerChannel / 8;
+                               qtexport->audioInputFormat.mFramesPerPacket = 1;
+                               qtexport->audioInputFormat.mBytesPerPacket = qtexport->audioInputFormat.mBytesPerFrame;
+                               qtexport->audioInputFormat.mFormatFlags |= kLinearPCMFormatFlagIsPacked;
+                               
+                               
+                               /*Ouput format*/
+                               qtexport->audioOutputFormat.mFormatID = rd->qtcodecsettings.audiocodecType;
+                               //TODO: set audio channels
+                               qtexport->audioOutputFormat.mChannelsPerFrame = 2;
+                               qtexport->audioOutputFormat.mSampleRate = rd->qtcodecsettings.audioSampleRate;
+                               
+                               /* Default value for compressed formats, overriden after if not the case */
+                               qtexport->audioOutputFormat.mFramesPerPacket = 0;
+                               qtexport->audioOutputFormat.mBytesPerFrame = 0;
+                               qtexport->audioOutputFormat.mBytesPerPacket = 0;
+                               qtexport->audioOutputFormat.mBitsPerChannel = 0;
+
+                               switch (rd->qtcodecsettings.audiocodecType) {
+                                       case kAudioFormatMPEG4AAC:
+                                               qtexport->audioOutputFormat.mFormatFlags = kMPEG4Object_AAC_Main;
+                                       case kAudioFormatAppleLossless:
+                                               switch (U.audioformat) {
+                                                       case AUD_FORMAT_S16:
+                                                               qtexport->audioOutputFormat.mFormatFlags = kAppleLosslessFormatFlag_16BitSourceData;
+                                                               break;
+                                                       case AUD_FORMAT_S24:
+                                                               qtexport->audioOutputFormat.mFormatFlags = kAppleLosslessFormatFlag_24BitSourceData;
+                                                               break;
+                                                       case AUD_FORMAT_S32:
+                                                               qtexport->audioOutputFormat.mFormatFlags = kAppleLosslessFormatFlag_32BitSourceData;
+                                                               break;
+                                                       case AUD_FORMAT_U8:
+                                                       case AUD_FORMAT_FLOAT32:
+                                                       case AUD_FORMAT_FLOAT64:
+                                                       default:
+                                                               break;
+                                               }
+                                               break;
+                                       case kAudioFormatLinearPCM:
+                                       default:
+                                               switch (rd->qtcodecsettings.audioBitDepth) {
+                                                       case AUD_FORMAT_U8:
+                                                               qtexport->audioOutputFormat.mBitsPerChannel = 8;
+                                                               qtexport->audioOutputFormat.mFormatFlags = 0;
+                                                               break;
+                                                       case AUD_FORMAT_S24:
+                                                               qtexport->audioOutputFormat.mBitsPerChannel = 24;
+                                                               qtexport->audioOutputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
+                                                               break;
+                                                       case AUD_FORMAT_S32:
+                                                               qtexport->audioOutputFormat.mBitsPerChannel = 32;
+                                                               qtexport->audioOutputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
+                                                               break;
+                                                       case AUD_FORMAT_FLOAT32:
+                                                               qtexport->audioOutputFormat.mBitsPerChannel = 32;
+                                                               qtexport->audioOutputFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat;
+                                                               break;
+                                                       case AUD_FORMAT_FLOAT64:
+                                                               qtexport->audioOutputFormat.mBitsPerChannel = 64;
+                                                               qtexport->audioOutputFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat;
+                                                               break;
+                                                       case AUD_FORMAT_S16:
+                                                       default:
+                                                               qtexport->audioOutputFormat.mBitsPerChannel = 16;
+                                                               qtexport->audioOutputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
+                                                               break;
+                                               }
+                                               qtexport->audioOutputFormat.mFormatFlags |= kLinearPCMFormatFlagIsPacked;
+                                               qtexport->audioOutputFormat.mBytesPerPacket = qtexport->audioOutputFormat.mChannelsPerFrame * (qtexport->audioOutputFormat.mBitsPerChannel / 8);
+                                               qtexport->audioOutputFormat.mFramesPerPacket = 1;
+                                               qtexport->audioOutputFormat.mBytesPerFrame = qtexport->audioOutputFormat.mBytesPerPacket;
+                                               break;
+                               }
+                                                                                               
+                               err = AudioFileCreateWithURL(outputFileURL, audioFileType, &qtexport->audioOutputFormat, kAudioFileFlags_EraseFile, &qtexport->audioFile);
+                               CFRelease(outputFileURL);
+                               
+                               if(err)
+                                       BKE_report(reports, RPT_ERROR, "\nQuicktime: unable to create temporary audio file. Format error ?");
+                               else {
+                                       err = AudioConverterNew(&qtexport->audioInputFormat, &qtexport->audioOutputFormat, &qtexport->audioConverter);
+                                       if (err) {
+                                               BKE_report(reports, RPT_ERROR, "\nQuicktime: unable to initialize audio codec converter. Format error ?");
+                                               AudioFileClose(qtexport->audioFile);
+                                               qtexport->audioFile = NULL;
+                                               [qtexport->audioFileName release];
+                                               qtexport->audioFileName = nil;
+                                       } else {
+                                               UInt32 prop,propSize;
+                                               /* Set up codec properties */
+                                               if (rd->qtcodecsettings.audiocodecType == kAudioFormatMPEG4AAC) { /*Lossy compressed format*/
+                                                       prop = rd->qtcodecsettings.audioBitRate;
+                                                       AudioConverterSetProperty(qtexport->audioConverter, kAudioConverterEncodeBitRate,
+                                                                                                         sizeof(prop), &prop);
+                                                       
+                                                       if (rd->qtcodecsettings.audioCodecFlags & QTAUDIO_FLAG_CODEC_ISCBR)
+                                                               prop = kAudioCodecBitRateControlMode_Constant;
+                                                       else
+                                                               prop = kAudioCodecBitRateControlMode_LongTermAverage;
+                                                       AudioConverterSetProperty(qtexport->audioConverter, kAudioCodecPropertyBitRateControlMode,
+                                                                                                                       sizeof(prop), &prop);
+                                               }
+                                               /* Conversion quality : if performance impact then offer degraded option */
+                                               if ((rd->qtcodecsettings.audioCodecFlags & QTAUDIO_FLAG_RESAMPLE_NOHQ) == 0) {                                                  
+                                                       prop = kAudioConverterSampleRateConverterComplexity_Mastering;
+                                                       AudioConverterSetProperty(qtexport->audioConverter, kAudioConverterSampleRateConverterComplexity,
+                                                                                                         sizeof(prop), &prop);
+                                                       
+                                                       prop = kAudioConverterQuality_Max;
+                                                       AudioConverterSetProperty(qtexport->audioConverter, kAudioConverterSampleRateConverterQuality,
+                                                                                                         sizeof(prop), &prop);
+                                               }
+                                               
+                                               write_cookie(qtexport->audioConverter, qtexport->audioFile);
+                                               
+                                               /* Allocate output buffer */
+                                               if (qtexport->audioOutputFormat.mBytesPerPacket ==0) /* VBR */
+                                                       AudioConverterGetProperty(qtexport->audioConverter, kAudioConverterPropertyMaximumOutputPacketSize,
+                                                                                                 &propSize, &qtexport->audioCodecMaxOutputPacketSize);
+                                               else
+                                                       qtexport->audioCodecMaxOutputPacketSize = qtexport->audioOutputFormat.mBytesPerPacket;
+                                               
+                                               qtexport->audioInputBuffer = MEM_mallocN(AUDIOOUTPUTBUFFERSIZE, "qt_audio_inputPacket");
+                                               qtexport->audioOutputBuffer = MEM_mallocN(AUDIOOUTPUTBUFFERSIZE, "qt_audio_outputPacket");
+                                               qtexport->audioOutputPktDesc = MEM_mallocN(sizeof(AudioStreamPacketDescription)*AUDIOOUTPUTBUFFERSIZE/qtexport->audioCodecMaxOutputPacketSize,
+                                                                                                                                  "qt_audio_pktdesc");
+                                       }
+                               }
+                       }
+                       
+                       if (err == noErr) {
+                               qtexport->videoTempFileName = [[NSString alloc] initWithCString:tmpnam(nil) 
+                                                                                                                        encoding:[NSString defaultCStringEncoding]];                   
+                               if (qtexport->videoTempFileName)
+                                       qtexport->movie = [[QTMovie alloc] initToWritableFile:qtexport->videoTempFileName error:&error];
+
+                       }
+               } else
+                       qtexport->movie = [[QTMovie alloc] initToWritableFile:qtexport->filename error:&error];
                        
                if(qtexport->movie == nil) {
                        BKE_report(reports, RPT_ERROR, "Unable to create quicktime movie.");
                        success= 0;
-                       NSLog(@"Unable to create quicktime movie : %@",[error localizedDescription]);
+                       if (qtexport->filename) [qtexport->filename release];
+                       qtexport->filename = nil;
+                       if (qtexport->audioFileName) [qtexport->audioFileName release];
+                       qtexport->audioFileName = nil;
+                       if (qtexport->videoTempFileName) [qtexport->videoTempFileName release];
+                       qtexport->videoTempFileName = nil;
                        [QTMovie exitQTKitOnThread];
                } else {
                        [qtexport->movie retain];
@@ -226,6 +554,23 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
                                                                                         nil];
                        }
                        [qtexport->frameAttributes retain];
+                       
+                       if (qtexport->audioFile) {
+                               /* Init audio input stream */
+                               AUD_DeviceSpecs specs;
+
+                               specs.channels = U.audiochannels;
+                               specs.format = U.audioformat;
+                               specs.rate = U.audiorate;
+                               qtexport->audioInputDevice = AUD_openReadDevice(specs);
+                               AUD_playDevice(qtexport->audioInputDevice, scene->sound_scene, rd->sfra * rd->frs_sec_base / rd->frs_sec);
+                                                               
+                               qtexport->audioOutputPktPos = 0;
+                               qtexport->audioTotalExportedFrames = 0;
+                               qtexport->audioTotalSavedFrames = 0;
+                               
+                               qtexport->audioLastFrame = (rd->efra - rd->sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
+                       }
                }
        }
        
@@ -276,6 +621,41 @@ int append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int rect
 
        [blBitmapFormatImage release];
        [frameImage release];
+       
+       
+       if (qtexport->audioFile) {
+               UInt32 audioPacketsConverted;
+               /* Append audio */
+               while (((double)qtexport->audioTotalExportedFrames / (double) qtexport->audioInputFormat.mSampleRate)
+                          < ((double)(frame - rd->sfra)) / (((double)rd->frs_sec) / rd->frs_sec_base)) {       
+
+                       qtexport->audioBufferList.mNumberBuffers = 1;
+                       qtexport->audioBufferList.mBuffers[0].mNumberChannels = qtexport->audioOutputFormat.mChannelsPerFrame;
+                       qtexport->audioBufferList.mBuffers[0].mDataByteSize = AUDIOOUTPUTBUFFERSIZE;
+                       qtexport->audioBufferList.mBuffers[0].mData = qtexport->audioOutputBuffer;
+                       audioPacketsConverted = AUDIOOUTPUTBUFFERSIZE / qtexport->audioCodecMaxOutputPacketSize;
+                       
+                       AudioConverterFillComplexBuffer(qtexport->audioConverter, AudioConverterInputCallback,
+                                                                                       NULL, &audioPacketsConverted, &qtexport->audioBufferList, qtexport->audioOutputPktDesc);
+                       if (audioPacketsConverted) {
+                               AudioFileWritePackets(qtexport->audioFile, false, qtexport->audioBufferList.mBuffers[0].mDataByteSize,
+                                                                         qtexport->audioOutputPktDesc, qtexport->audioOutputPktPos, &audioPacketsConverted, qtexport->audioOutputBuffer);
+                               qtexport->audioOutputPktPos += audioPacketsConverted;
+                               
+                               if (qtexport->audioOutputFormat.mFramesPerPacket) { 
+                                       // this is the common case: format has constant frames per packet
+                                       qtexport->audioTotalSavedFrames += (audioPacketsConverted * qtexport->audioOutputFormat.mFramesPerPacket);
+                               } else {
+                                       unsigned int i;
+                                       // if there are variable frames per packet, then we have to do this for each packeet
+                                       for (i = 0; i < audioPacketsConverted; ++i)
+                                               qtexport->audioTotalSavedFrames += qtexport->audioOutputPktDesc[i].mVariableFramesInPacket;
+                               }
+                               
+                               
+                       }
+               }
+       }
        [pool drain];   
 
        return 1;
@@ -284,17 +664,96 @@ int append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int rect
 
 void end_qt(void)
 {
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        if (qtexport->movie) {
-               /* Flush update of the movie file */
-               [qtexport->movie updateMovieFile];
                
-               [qtexport->movie invalidate];
+               if (qtexport->audioFile)
+               {
+                       NSDictionary *dict = nil;
+                       QTMovie *audioTmpMovie = nil;
+                       NSError *error;
+                       NSFileManager *fileManager;
+                       
+                       /* Mux video and audio then save file */
+                       
+                       /* Write last frames for VBR files */
+                       if (qtexport->audioOutputFormat.mBitsPerChannel == 0) {
+                               OSStatus err = noErr;
+                               AudioConverterPrimeInfo primeInfo;
+                               UInt32 primeSize = sizeof(primeInfo);
+                               
+                               err = AudioConverterGetProperty(qtexport->audioConverter, kAudioConverterPrimeInfo, &primeSize, &primeInfo);
+                               if (err == noErr) {
+                                       // there's priming to write out to the file
+                                       AudioFilePacketTableInfo pti;
+                                       pti.mPrimingFrames = primeInfo.leadingFrames;
+                                       pti.mRemainderFrames = primeInfo.trailingFrames;
+                                       pti.mNumberValidFrames = qtexport->audioTotalSavedFrames - pti.mPrimingFrames - pti.mRemainderFrames;
+                                       AudioFileSetProperty(qtexport->audioFile, kAudioFilePropertyPacketTableInfo, sizeof(pti), &pti);
+                               }
+                               
+                       }
+                       
+                       write_cookie(qtexport->audioConverter, qtexport->audioFile);
+                       AudioConverterDispose(qtexport->audioConverter);
+                       AudioFileClose(qtexport->audioFile);
+                       AUD_closeReadDevice(qtexport->audioInputDevice);
+                       qtexport->audioFile = NULL;
+                       qtexport->audioInputDevice = NULL;
+                       MEM_freeN(qtexport->audioInputBuffer);
+                       MEM_freeN(qtexport->audioOutputBuffer);
+                       MEM_freeN(qtexport->audioOutputPktDesc);
+                       
+                       /* Reopen audio file and merge it */
+                       audioTmpMovie = [QTMovie movieWithFile:qtexport->audioFileName error:&error];
+                       if (audioTmpMovie) {
+                               NSArray *audioTracks = [audioTmpMovie tracksOfMediaType:QTMediaTypeSound];
+                               QTTrack *audioTrack = nil;
+                               if( [audioTracks count] > 0 )
+                               {
+                                       audioTrack = [audioTracks objectAtIndex:0];
+                               }
+                       
+                               if( audioTrack )
+                               {
+                                       QTTimeRange totalRange;
+                                       totalRange.time = QTZeroTime;
+                                       totalRange.duration = [[audioTmpMovie attributeForKey:QTMovieDurationAttribute] QTTimeValue];
+                                       
+                                       [qtexport->movie insertSegmentOfTrack:audioTrack timeRange:totalRange atTime:QTZeroTime];
+                               }
+                       }
+                       
+                       /* Save file */
+                       dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] 
+                                                                                          forKey:QTMovieFlatten];
+
+                       if (dict) {
+                               [qtexport->movie writeToFile:qtexport->filename withAttributes:dict];
+                       }
+                       
+                       /* Delete temp files */
+                       fileManager = [[NSFileManager alloc] init];
+                       [fileManager removeItemAtPath:qtexport->audioFileName error:&error];
+                       [fileManager removeItemAtPath:qtexport->videoTempFileName error:&error];
+               }
+               else {
+                       /* Flush update of the movie file */
+                       [qtexport->movie updateMovieFile];
+                       
+                       [qtexport->movie invalidate];
+               }
                
                /* Clean up movie structure */
-               [qtexport->filename release];
+               if (qtexport->filename) [qtexport->filename release];
+               qtexport->filename = nil;
+               if (qtexport->audioFileName) [qtexport->audioFileName release];
+               qtexport->audioFileName = nil;
+               if (qtexport->videoTempFileName) [qtexport->videoTempFileName release];
+               qtexport->videoTempFileName = nil;
                [qtexport->frameAttributes release];
                [qtexport->movie release];
-               }
+       }
        
        [QTMovie exitQTKitOnThread];
 
@@ -302,6 +761,7 @@ void end_qt(void)
                MEM_freeN(qtexport);
                qtexport = NULL;
        }
+       [pool drain];
 }
 
 
@@ -318,6 +778,15 @@ void quicktime_verify_image_type(RenderData *rd)
                        rd->qtcodecsettings.codecType = kJPEGCodecType;
                        rd->qtcodecsettings.codecSpatialQuality = (codecHighQuality*100)/codecLosslessQuality;
                }
+               if ((rd->qtcodecsettings.audioSampleRate < 21000) ||
+                       (rd->qtcodecsettings.audioSampleRate > 193000)) 
+                       rd->qtcodecsettings.audioSampleRate = 48000;
+               
+               if (rd->qtcodecsettings.audioBitDepth == 0)
+                       rd->qtcodecsettings.audioBitDepth = AUD_FORMAT_S16;
+               
+               if (rd->qtcodecsettings.audioBitRate == 0)
+                       rd->qtcodecsettings.audioBitRate = 256000;
        }
 }
 
index aaf2634..c1291fc 100644 (file)
@@ -123,7 +123,7 @@ static int  sframe;
 
 /* RNA functions */
 
-static QuicktimeCodecTypeDesc qtCodecList[] = {
+static QuicktimeCodecTypeDesc qtVideoCodecList[] = {
        {kRawCodecType, 1, "Uncompressed"},
        {kJPEGCodecType, 2, "JPEG"},
        {kMotionJPEGACodecType, 3, "M-JPEG A"},
@@ -138,34 +138,34 @@ static QuicktimeCodecTypeDesc qtCodecList[] = {
        {kH264CodecType, 12, "H.264"},
        {0,0,NULL}};
 
-static int qtCodecCount = 12;
+static int qtVideoCodecCount = 12;
 
-int quicktime_get_num_codecs() {
-       return qtCodecCount;
+int quicktime_get_num_videocodecs() {
+       return qtVideoCodecCount;
 }
 
-QuicktimeCodecTypeDesc* quicktime_get_codecType_desc(int indexValue) {
-       if ((indexValue>=0) && (indexValue < qtCodecCount))
-               return &qtCodecList[indexValue];
+QuicktimeCodecTypeDesc* quicktime_get_videocodecType_desc(int indexValue) {
+       if ((indexValue>=0) && (indexValue < qtVideoCodecCount))
+               return &qtVideoCodecList[indexValue];
        else
                return NULL;
 }
 
-int quicktime_rnatmpvalue_from_codectype(int codecType) {
+int quicktime_rnatmpvalue_from_videocodectype(int codecType) {
        int i;
-       for (i=0;i<qtCodecCount;i++) {
-               if (qtCodecList[i].codecType == codecType)
-                       return qtCodecList[i].rnatmpvalue;
+       for (i=0;i<qtVideoCodecCount;i++) {
+               if (qtVideoCodecList[i].codecType == codecType)
+                       return qtVideoCodecList[i].rnatmpvalue;
        }
        
        return 0;
 }
 
-int quicktime_codecType_from_rnatmpvalue(int rnatmpvalue) {
+int quicktime_videocodecType_from_rnatmpvalue(int rnatmpvalue) {
        int i;
-       for (i=0;i<qtCodecCount;i++) {
-               if (qtCodecList[i].rnatmpvalue == rnatmpvalue)
-                       return qtCodecList[i].codecType;
+       for (i=0;i<qtVideoCodecCount;i++) {
+               if (qtVideoCodecList[i].rnatmpvalue == rnatmpvalue)
+                       return qtVideoCodecList[i].codecType;
        }
        
        return 0;       
index 71faeeb..1ca52b1 100644 (file)
 #define __AIFF__
 
 
+#define QTAUDIO_FLAG_RESAMPLE_NOHQ 1
+#define QTAUDIO_FLAG_CODEC_ISCBR 2
+
+
 /*Codec list*/
 typedef struct QuicktimeCodecTypeDesc {
        int codecType;
@@ -54,10 +58,19 @@ void filepath_qt(char *string, struct RenderData *rd);
 
 /*RNA helper functions */
 void quicktime_verify_image_type(struct RenderData *rd); //used by RNA for defaults values init, if needed
-int quicktime_get_num_codecs();
-QuicktimeCodecTypeDesc* quicktime_get_codecType_desc(int indexValue);
-int quicktime_rnatmpvalue_from_codectype(int codecType);
-int quicktime_codecType_from_rnatmpvalue(int rnatmpvalue);
+/*Video codec type*/
+int quicktime_get_num_videocodecs();
+QuicktimeCodecTypeDesc* quicktime_get_videocodecType_desc(int indexValue);
+int quicktime_rnatmpvalue_from_videocodectype(int codecType);
+int quicktime_videocodecType_from_rnatmpvalue(int rnatmpvalue);
+
+#ifdef USE_QTKIT
+/*Audio codec type*/
+int quicktime_get_num_audiocodecs();
+QuicktimeCodecTypeDesc* quicktime_get_audiocodecType_desc(int indexValue);
+int quicktime_rnatmpvalue_from_audiocodectype(int codecType);
+int quicktime_audiocodecType_from_rnatmpvalue(int rnatmpvalue);
+#endif
 
 #ifndef USE_QTKIT
 void SCENE_OT_render_data_set_quicktime_codec(struct wmOperatorType *ot); //Operator to raise quicktime standard dialog to request codec settings