diff options
author | Aaron Carlisle <carlisle.b3d@gmail.com> | 2017-09-22 23:11:24 +0300 |
---|---|---|
committer | Aaron Carlisle <carlisle.b3d@gmail.com> | 2017-09-22 23:40:05 +0300 |
commit | efd5e3c25401b43cbd7f909418835bb570db1ab3 (patch) | |
tree | a649efbeef40fdae734545d2b4f65f6cca023832 /source/blender/quicktime/apple/qtkit_export.m | |
parent | 0e802fabb406e334a8cb1dad428e6fdac72ff7e5 (diff) |
Remove quicktime support
It has been deprecated since at least macOS 10.9 and fully removed in 10.12.
I am unsure if we should remove it only in 2.8. But you cannot build blender with it supported when using a modern xcode version anyway so I would tend towards just removing it also for 2.79 if that ever happens.
Reviewers: mont29, dfelinto, juicyfruit, brecht
Reviewed By: mont29, brecht
Subscribers: Blendify, brecht
Maniphest Tasks: T52807
Differential Revision: https://developer.blender.org/D2333
Diffstat (limited to 'source/blender/quicktime/apple/qtkit_export.m')
-rw-r--r-- | source/blender/quicktime/apple/qtkit_export.m | 884 |
1 files changed, 0 insertions, 884 deletions
diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m deleted file mode 100644 index 1ac3c58f888..00000000000 --- a/source/blender/quicktime/apple/qtkit_export.m +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Code to create QuickTime Movies with Blender - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * - * The Original Code is written by Rob Haarsma (phase) - * - * Contributor(s): Stefan Gartner (sgefant) - * Damien Plisson 11/2009 - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef WITH_QUICKTIME -#if defined(_WIN32) || defined(__APPLE__) - -#include <stdio.h> -#include <string.h> - -#include "DNA_scene_types.h" -#include "DNA_userdef_types.h" - -#ifdef WITH_AUDASPACE -# include AUD_DEVICE_H -#endif - -#include "BLI_utildefines.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_scene.h" -#include "BKE_report.h" - -#include "BLI_blenlib.h" - -#include "BLI_sys_types.h" - -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" - -#include "MEM_guardedalloc.h" - -#ifdef __APPLE__ -/* evil */ -#ifndef __AIFF__ -#define __AIFF__ -#endif -#import <Cocoa/Cocoa.h> -#import <QTKit/QTKit.h> -#include <AudioToolbox/AudioToolbox.h> - -#include "quicktime_import.h" -#include "quicktime_export.h" - -#endif /* __APPLE__ */ - -typedef struct QuicktimeExport { - QTMovie *movie; - - NSString *filename; - - 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; - -#define AUDIOOUTPUTBUFFERSIZE 65536 - -#pragma mark rna helper functions - -/* Video codec */ -static QuicktimeCodecTypeDesc qtVideoCodecList[] = { - {kRawCodecType, 1, "Uncompressed"}, - {k422YpCbCr8CodecType, 2, "Uncompressed 8-bit 4:2:2"}, - {k422YpCbCr10CodecType, 3, "Uncompressed 10-bit 4:2:2"}, - {kComponentVideoCodecType, 4, "Component Video"}, - {kPixletCodecType, 5, "Pixlet"}, - {kPNGCodecType, 6, "PNG"}, - {kJPEGCodecType, 7, "JPEG"}, - {kMotionJPEGACodecType, 8, "M-JPEG A"}, - {kMotionJPEGBCodecType, 9, "M-JPEG B"}, - {kDVCPALCodecType, 10, "DV PAL"}, - {kDVCNTSCCodecType, 11, "DV/DVCPRO NTSC"}, - {kDVCPROHD720pCodecType, 12, "DVCPRO HD 720p"}, - {kDVCPROHD1080i50CodecType, 13, "DVCPRO HD 1080i50"}, - {kDVCPROHD1080i60CodecType, 14, "DVCPRO HD 1080i60"}, - {kMPEG4VisualCodecType, 15, "MPEG4"}, - {kH263CodecType, 16, "H.263"}, - {kH264CodecType, 17, "H.264"}, - {kAnimationCodecType, 18, "Animation"}, - {0,0,NULL}}; - -static int qtVideoCodecCount = 18; - -int quicktime_get_num_videocodecs() -{ - return qtVideoCodecCount; -} - -QuicktimeCodecTypeDesc* quicktime_get_videocodecType_desc(int indexValue) -{ - if ((indexValue>=0) && (indexValue < qtVideoCodecCount)) - return &qtVideoCodecList[indexValue]; - else - return NULL; -} - -int quicktime_rnatmpvalue_from_videocodectype(int codecType) -{ - int i; - for (i = 0; i < qtVideoCodecCount; i++) { - if (qtVideoCodecList[i].codecType == codecType) - return qtVideoCodecList[i].rnatmpvalue; - } - - return 0; -} - -int quicktime_videocodecType_from_rnatmpvalue(int rnatmpvalue) -{ - int i; - 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; -} - - -static NSString *stringWithCodecType(int codecType) -{ - char str[5]; - - *((int *)str) = EndianU32_NtoB(codecType); - str[4] = 0; - - return [NSString stringWithCString:str encoding:NSASCIIStringEncoding]; -} - -void makeqtstring(RenderData *rd, char *string, bool preview) -{ - int sfra, efra; - - char txt[64]; - - if (preview) { - sfra = rd->psfra; - efra = rd->pefra; - } - else { - sfra = rd->sfra; - efra = rd->efra; - } - - strcpy(string, rd->pic); - BLI_path_abs(string, G.main->name); - - BLI_make_existing_file(string); - - if (BLI_strcasecmp(string + strlen(string) - 4, ".mov")) { - sprintf(txt, "%04d-%04d.mov", (rd->sfra) , (rd->efra) ); - strcat(string, txt); - } -} - -void filepath_qt(char *string, RenderData *rd, bool preview, const char *suffix) -{ - int sfra, efra; - - if (string == NULL) return; - - if (preview) { - sfra = rd->psfra; - efra = rd->pefra; - } - else { - sfra = rd->sfra; - efra = rd->efra; - } - - strcpy(string, rd->pic); - BLI_path_abs(string, G.main->name); - - BLI_make_existing_file(string); - - if (rd->scemode & R_EXTENSION) { - if (!BLI_testextensie(string, ".mov")) { - BLI_path_frame_range(string, sfra, efra, 4); - strcat(string, ".mov"); - } - } - else { - if (BLI_path_frame_check_chars(string)) { - BLI_path_frame_range(string, sfra, efra, 4); - } - } - - BLI_path_suffix(string, FILE_MAX, suffix, ""); -} - -void *context_create_qt(void) -{ - QuicktimeExport *qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); - return qtexport; -} - -void context_free_qt(void *context_v) -{ - QuicktimeExport *qtexport = context_v; - if (qtexport) { - MEM_freeN(qtexport); - } -} - -#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) -{ - QuicktimeExport *qtexport = 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->audioInputFormat.mFramesPerPacket; - - qtexport->audioTotalExportedFrames += *ioNumberDataPackets; - - AUD_Device_read(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( - void *context_v, struct Scene *scene, struct RenderData *rd, int UNUSED(rectx), int UNUSED(recty), - ReportList *reports, bool preview, const char *UNUSED(suffix)) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSError *error; - char name[1024]; - int success = 1; - OSStatus err = noErr; - int sfra, efra; - QuicktimeExport *qtexport = context_v; - - if (preview) { - sfra = rd->psfra; - efra = rd->pefra; - } - else { - sfra = rd->sfra; - efra = rd->efra; - } - - [QTMovie enterQTKitOnThread]; - - /* Check first if the QuickTime 7.2.1 initToWritableFile: method is available */ - if ([[[[QTMovie alloc] init] autorelease] respondsToSelector:@selector(initToWritableFile:error:)] != YES) { - BKE_report(reports, RPT_ERROR, "\nUnable to create quicktime movie, need Quicktime rev 7.2.1 or later"); - success = 0; - } - else { - makeqtstring(rd, name, preview); - qtexport->filename = [[NSString alloc] initWithUTF8String:name]; - 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; /*If not ==1, then need to check input callback for "rounding" issues"*/ - qtexport->audioInputFormat.mBytesPerPacket = qtexport->audioInputFormat.mBytesPerFrame; - qtexport->audioInputFormat.mFormatFlags |= kLinearPCMFormatFlagIsPacked; - - - /*Output 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, overridden 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; - /* AAC codec does not handle sample rates above 48kHz, force this limit instead of getting an error afterwards */ - if (qtexport->audioOutputFormat.mSampleRate > 48000) qtexport->audioOutputFormat.mSampleRate = 48000; - break; - 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; - 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]; - [qtexport->movie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute]; - [qtexport->movie setAttribute:@"Made with Blender" forKey:QTMovieCopyrightAttribute]; - - qtexport->frameDuration = QTMakeTime(rd->frs_sec_base * 1000, rd->frs_sec * 1000); - - /* specifying the codec attributes : try to retrieve them from render data first*/ - if (rd->qtcodecsettings.codecType) { - qtexport->frameAttributes = [ - NSDictionary dictionaryWithObjectsAndKeys: - stringWithCodecType(rd->qtcodecsettings.codecType), - QTAddImageCodecType, - [NSNumber numberWithLong:((rd->qtcodecsettings.codecSpatialQuality)*codecLosslessQuality)/100], - QTAddImageCodecQuality, - nil]; - } - else { - qtexport->frameAttributes = [ - NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", - QTAddImageCodecType, - [NSNumber numberWithLong:codecHighQuality], - QTAddImageCodecQuality, - 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, sfra * rd->frs_sec_base / rd->frs_sec); - - qtexport->audioOutputPktPos = 0; - qtexport->audioTotalExportedFrames = 0; - qtexport->audioTotalSavedFrames = 0; - - qtexport->audioLastFrame = (efra - sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec; - } - } - } - - [pool drain]; - - return success; -} - -int append_qt( - void *context_v, struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, - const char *UNUSED(suffix), ReportList *reports) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSBitmapImageRep *blBitmapFormatImage; - NSImage *frameImage; - OSStatus err = noErr; - unsigned char *from_Ptr,*to_Ptr; - int y,from_i,to_i; - QuicktimeExport *qtexport = context_v; - - /* Create bitmap image rep in blender format (32bit RGBA) */ - blBitmapFormatImage = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:rectx - pixelsHigh:recty - bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bitmapFormat:NSAlphaNonpremultipliedBitmapFormat - bytesPerRow:rectx*4 - bitsPerPixel:32]; - if (!blBitmapFormatImage) { - [pool drain]; - return 0; - } - - from_Ptr = (unsigned char *)pixels; - to_Ptr = (unsigned char *)[blBitmapFormatImage bitmapData]; - for (y = 0; y < recty; y++) { - to_i = (recty-y-1)*rectx; - from_i = y*rectx; - memcpy(to_Ptr+4*to_i, from_Ptr+4*from_i, 4*rectx); - } - - frameImage = [[NSImage alloc] initWithSize:NSMakeSize(rectx, recty)]; - [frameImage addRepresentation:blBitmapFormatImage]; - - /* Add the image to the movie clip */ - [qtexport->movie addImage:frameImage - forDuration:qtexport->frameDuration - withAttributes:qtexport->frameAttributes]; - - [blBitmapFormatImage release]; - [frameImage release]; - - - if (qtexport->audioFile) { - UInt32 audioPacketsConverted; - - // Upper limit on total exported audio frames for this particular video frame - const UInt64 exportedAudioFrameLimit = (frame - start_frame) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec; - - /* Append audio */ - while (qtexport->audioTotalExportedFrames < exportedAudioFrameLimit) { - - 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; - - // Convert one audio packet at a time so that enclosing while loop can - // keep audio processing in sync with video frames. - // Previously, this was set to (AUDIOOUTPUTBUFFERSIZE / qtexport->audioCodecMaxOutputPacketSize), - // however this may cause AudioConverterFillComplexBuffer to convert audio spanning multiple - // video frames, which breaks animation of audio parameters such as volume for fade-in/out. - audioPacketsConverted = 1; - - err = AudioConverterFillComplexBuffer(qtexport->audioConverter, AudioConverterInputCallback, - qtexport, &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; - } - - - } - else { - //Error getting audio packets - BKE_reportf(reports, RPT_ERROR, "Unable to get further audio packets from frame %i, error = 0x%x",(int)qtexport->audioTotalExportedFrames,err); - break; - } - - } - } - [pool drain]; - - return 1; -} - - -void end_qt(void *context_v) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - QuicktimeExport *qtexport = context_v; - - if (qtexport->movie) { - - 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_Device_free(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]; - [fileManager release]; - } - else { - /* Flush update of the movie file */ - [qtexport->movie updateMovieFile]; - - [qtexport->movie invalidate]; - } - - /* Clean up movie structure */ - 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]; - [pool drain]; -} - - -void free_qtcomponentdata(void) -{ -} - -void quicktime_verify_image_type(RenderData *rd, ImageFormatData *imf) -{ - if (imf->imtype == R_IMF_IMTYPE_QUICKTIME) { - if ((rd->qtcodecsettings.codecType <= 0) || - (rd->qtcodecsettings.codecSpatialQuality < 0) || - (rd->qtcodecsettings.codecSpatialQuality > 100)) - { - 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; - } - } -} - -#endif /* _WIN32 || __APPLE__ */ -#endif /* WITH_QUICKTIME */ - |