Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorDamien Plisson <damien.plisson@yahoo.fr>2010-04-10 13:31:41 +0400
committerDamien Plisson <damien.plisson@yahoo.fr>2010-04-10 13:31:41 +0400
commitc939331a6ccacc571c893646e209e99680a81aa5 (patch)
treeb375e40e228b5419bd16250d3b6a9b4f395a9aa7 /source
parentc3ab6bc509b4a322e66b59fd9c12b9954f851b66 (diff)
QTKit (OSX 64bit): Add audio export to Quicktime
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!
Diffstat (limited to 'source')
-rw-r--r--source/blender/makesdna/DNA_scene_types.h9
-rw-r--r--source/blender/makesrna/SConscript2
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/Makefile1
-rw-r--r--source/blender/makesrna/intern/SConscript1
-rw-r--r--source/blender/makesrna/intern/rna_scene.c116
-rw-r--r--source/blender/quicktime/CMakeLists.txt1
-rw-r--r--source/blender/quicktime/SConscript3
-rw-r--r--source/blender/quicktime/apple/Makefile1
-rw-r--r--source/blender/quicktime/apple/qtkit_export.m519
-rw-r--r--source/blender/quicktime/apple/quicktime_export.c30
-rw-r--r--source/blender/quicktime/quicktime_export.h21
12 files changed, 655 insertions, 51 deletions
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index f9deebb0026..7d7af0ddf82 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -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 {
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index cf31fb8e0e5..71cfc3c7da4 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -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'
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 58931165638..0e25160cdff 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -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)
diff --git a/source/blender/makesrna/intern/Makefile b/source/blender/makesrna/intern/Makefile
index 5afe55bb319..c26593100f8 100644
--- a/source/blender/makesrna/intern/Makefile
+++ b/source/blender/makesrna/intern/Makefile
@@ -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
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index b63a816edfb..d22a654db02 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -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')
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index dd06d2df8e0..40027b16950 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -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;
@@ -557,8 +558,47 @@ static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bCon
*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*/
diff --git a/source/blender/quicktime/CMakeLists.txt b/source/blender/quicktime/CMakeLists.txt
index f1b2a121b50..2b5c8a53e9b 100644
--- a/source/blender/quicktime/CMakeLists.txt
+++ b/source/blender/quicktime/CMakeLists.txt
@@ -45,6 +45,7 @@ SET(INC
../render/extern/include
../include
../windowmanager
+ ../../../intern/audaspace/intern
)
SET(INC ${INC} ${QUICKTIME_INC})
diff --git a/source/blender/quicktime/SConscript b/source/blender/quicktime/SConscript
index c8cd795decb..c8aeb70aa57 100644
--- a/source/blender/quicktime/SConscript
+++ b/source/blender/quicktime/SConscript
@@ -23,7 +23,8 @@ incs = ['.',
'../imbuf/intern',
'../blenloader',
'../render/extern/include',
- '../editors/include']
+ '../editors/include',
+ '#/intern/audaspace/intern']
incs.append(env['BF_QUICKTIME_INC'])
diff --git a/source/blender/quicktime/apple/Makefile b/source/blender/quicktime/apple/Makefile
index 70f3f05c5f0..70757f02055 100644
--- a/source/blender/quicktime/apple/Makefile
+++ b/source/blender/quicktime/apple/Makefile
@@ -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
diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m
index 06082832b1e..cfe86017e3a 100644
--- a/source/blender/quicktime/apple/qtkit_export.m
+++ b/source/blender/quicktime/apple/qtkit_export.m
@@ -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;
}
}
diff --git a/source/blender/quicktime/apple/quicktime_export.c b/source/blender/quicktime/apple/quicktime_export.c
index aaf2634bbf6..c1291fc6949 100644
--- a/source/blender/quicktime/apple/quicktime_export.c
+++ b/source/blender/quicktime/apple/quicktime_export.c
@@ -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;
diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h
index 71faeeb0ce0..1ca52b1bd10 100644
--- a/source/blender/quicktime/quicktime_export.h
+++ b/source/blender/quicktime/quicktime_export.h
@@ -34,6 +34,10 @@
#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