Updated Quicktime code so settings can be stored in the blendfile.
[blender.git] / source / blender / quicktime / apple / quicktime_export.c
1 /**
2  * $Id$
3  *
4  * quicktime_export.c
5  *
6  * Code to create QuickTime Movies with Blender
7  *
8  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  *
27  * The Original Code is written by Rob Haarsma (phase)
28  *
29  * Contributor(s): Stefan Gartner (sgefant)
30  *
31  * ***** END GPL/BL DUAL LICENSE BLOCK *****
32  */
33 /*      
34 DONE:
35
36 *  structurize file & compression data
37
38 *  fix 23.98, 29.97, 59.94 framerates
39 *  fix framerate button
40 *  fix mac compatibility
41
42 *  fix fallthrough to codecselector  // buttons.c
43 *  fix playback qt movie             // playanim.c
44 *  fix setting fps thru blenderbutton as well as codec dialog
45 *  fix saving of compressionsettings
46
47 */
48
49 #ifdef WITH_QUICKTIME
50
51 #if defined(_WIN32) || defined(__APPLE__)
52
53 /************************************************************
54 *                                                           *
55 *    INCLUDE FILES                                          *
56 *                                                           *
57 *************************************************************/
58
59 #include "BKE_global.h"
60 #include "BKE_scene.h"
61 #include "BLI_blenlib.h"
62 #include "BLO_sys_types.h"
63 #include "IMB_imbuf.h"
64 #include "IMB_imbuf_types.h"
65 #include "MEM_guardedalloc.h"
66 #include "render.h"
67
68 #include "quicktime_export.h"
69
70 #ifdef _WIN32
71 #include <FixMath.h>
72 #include <QTML.h>
73 #include <TextUtils.h> 
74 #include <Movies.h>
75 #include <QuicktimeComponents.h>
76 #include <MoviesFormat.h>
77 #endif /* _WIN32 */
78
79 #ifdef __APPLE__
80 #undef NDEBUG
81 #include <QuickTime/Movies.h>
82 #include <QuickTime/QuicktimeComponents.h>
83 #include <fcntl.h> /* open() */
84 #include <unistd.h> /* close() */
85 #include <sys/stat.h> /* file permissions */
86 #endif /* __APPLE__ */
87
88
89 /************************************************************
90 *                                                           *
91 *    FUNCTION PROTOTYPES                                    *
92 *                                                           *
93 *************************************************************/
94
95 static void QT_StartAddVideoSamplesToMedia (const Rect *trackFrame);
96 static void QT_DoAddVideoSamplesToMedia (int frame);
97 static void QT_EndAddVideoSamplesToMedia (void);
98 static void QT_CreateMyVideoTrack (void);
99 static void QT_EndCreateMyVideoTrack (void);
100
101 static void check_renderbutton_framerate(void);
102
103 /************************************************************
104 *                                                           *
105 *    STRUCTS                                                *
106 *                                                           *
107 *************************************************************/
108
109 typedef struct _QuicktimeExport {
110
111         FSSpec          theSpec;
112         short           resRefNum;
113         short           resId;
114         short           movieResId;
115         Str255          qtfilename;
116
117         Media           theMedia;
118         Movie           theMovie;
119         Track           theTrack;
120
121         GWorldPtr       theGWorld;
122         PixMapHandle    thePixMap;
123
124         ImageDescription        **anImageDescription;
125         ImageSequence           anImageSequence;
126
127         ImBuf           *ibuf;  //for Qtime's Gworld
128         ImBuf           *ibuf2; //copy of renderdata, to be Y-flipped
129
130 } QuicktimeExport;
131
132 typedef struct _QuicktimeCodecDataExt {
133
134         ComponentInstance       theComponent;
135         SCTemporalSettings  gTemporalSettings;
136         SCSpatialSettings   gSpatialSettings;
137         SCDataRateSettings  aDataRateSetting;
138         TimeValue                       duration;
139         long                            kVideoTimeScale;
140
141 } QuicktimeCodecDataExt;        //qtopts
142
143
144 struct _QuicktimeExport *qte;
145 struct _QuicktimeCodecDataExt *qcdx;
146
147 /************************************************************
148 *                                                           *
149 *    VARIABLES                                              *
150 *                                                           *
151 *************************************************************/
152
153 #define kMyCreatorType  FOUR_CHAR_CODE('TVOD')
154 #define kPixelDepth     32      /* use 32-bit depth */
155 #define kTrackStart             0
156 #define kMediaStart             0
157
158 static int      sframe;
159 static char     qtcdname[128];
160
161
162 /************************************************************
163 *                                                           *
164 *    SaveExporterSettingsToMem                              *
165 *                                                           *
166 *************************************************************/
167
168 OSErr SaveExporterSettingsToMem (QuicktimeCodecData *qcd)
169 {       
170         QTAtomContainer         myContainer = NULL;
171         ComponentResult         myErr = noErr;
172         Ptr                                     myPtr;
173         Handle                          myHandle;
174         long                            mySize = 0;
175
176         // check if current scene already has qtcodec settings, and erase them
177         if (qcd) {
178                 free_qtcodecdata(qcd);
179         } else {
180                 qcd = G.scene->r.qtcodecdata = MEM_callocN(sizeof(QuicktimeCodecData), "QuicktimeCodecData");
181         }
182
183         // obtain all current codec settings
184         SCSetInfo(qcdx->theComponent, scTemporalSettingsType,   &qcdx->gTemporalSettings);
185         SCSetInfo(qcdx->theComponent, scSpatialSettingsType,    &qcdx->gSpatialSettings);
186         SCSetInfo(qcdx->theComponent, scDataRateSettingsType,   &qcdx->aDataRateSetting);
187
188         // retreive codecdata from quicktime in a atomcontainer
189         myErr = SCGetSettingsAsAtomContainer(qcdx->theComponent,  &myContainer);
190         if (myErr != noErr) {
191                 printf("Quicktime: SCGetSettingsAsAtomContainer failed\n"); 
192                 goto bail;
193         }
194
195         // get the size of the atomcontainer
196         mySize = GetHandleSize((Handle)myContainer);
197
198         // lock and convert the atomcontainer to a *valid* pointer
199         QTLockContainer(myContainer);
200         myHandle = (Handle) myContainer;
201         HLockHi(myHandle);
202         myPtr = *myHandle;
203
204         // copy the Quicktime data into the blender qtcodecdata struct
205         if (myPtr) {
206                 qcd->cdParms = MEM_mallocN(mySize, "qt.cdParms");
207                 memcpy(qcd->cdParms, myPtr, mySize);
208                 qcd->cdSize = mySize;
209                 sprintf(qcd->qtcodecname, qtcdname);
210         } else {
211                 printf("Quicktime: SaveExporterSettingsToMem failed\n"); 
212         }
213
214         QTUnlockContainer(myContainer);
215
216 bail:
217         if (myHandle != NULL)
218                 DisposeHandle(myHandle);
219         if (myContainer != NULL)
220                 QTDisposeAtomContainer(myContainer);
221                 
222         return((OSErr)myErr);
223 }
224
225 /************************************************************
226 *                                                           *
227 *    GetExporterSettingsFromMem                             *
228 *                                                           *
229 *************************************************************/
230
231 OSErr GetExporterSettingsFromMem (QuicktimeCodecData *qcd)
232 {       
233         Handle                          myHandle = NULL;
234         ComponentResult         myErr = noErr;
235 //      CodecInfo ci;
236 //      char str[255];
237
238         // if there is codecdata in the blendfile, convert it to a Quicktime handle 
239         if (qcd) {
240                 myHandle = NewHandle(qcd->cdSize);
241                 PtrToHand( qcd->cdParms, &myHandle, qcd->cdSize);
242         }
243                 
244         // restore codecsettings to the quicktime component
245         if(qcd->cdParms && qcd->cdSize) {
246                 myErr = SCSetSettingsFromAtomContainer((GraphicsExportComponent)qcdx->theComponent, (QTAtomContainer)myHandle);
247                 if (myErr != noErr) {
248                         printf("Quicktime: SCSetSettingsFromAtomContainer failed\n"); 
249                         goto bail;
250                 }
251
252                 // update runtime codecsettings for use with the codec dialog
253                 SCGetInfo(qcdx->theComponent, scDataRateSettingsType,   &qcdx->aDataRateSetting);
254                 SCGetInfo(qcdx->theComponent, scSpatialSettingsType,    &qcdx->gSpatialSettings);
255                 SCGetInfo(qcdx->theComponent, scTemporalSettingsType,   &qcdx->gTemporalSettings);
256
257 //              GetCodecInfo (&ci, qcdx->gSpatialSettings.codecType, 0);
258 //              CopyPascalStringToC(ci.typeName, str);
259 //              printf("restored Codec: %s\n", str);
260         } else {
261                 printf("Quicktime: GetExporterSettingsFromMem failed\n"); 
262         }
263 bail:
264         if (myHandle != NULL)
265                 DisposeHandle(myHandle);
266                 
267         return((OSErr)myErr);
268 }
269
270
271 /************************************************************
272 *                                                           *
273 *    CheckError(OSErr err, char *msg)                       *
274 *                                                           *
275 *    prints errors in console, doesnt interrupt Blender     *
276 *                                                           *
277 *************************************************************/
278
279 void CheckError(OSErr err, char *msg)
280 {
281         if(err != noErr) printf("%s: %d\n", msg, err);
282 }
283
284
285 /************************************************************
286 *                                                           *
287 *    QT_CreateMyVideoTrack()                                *
288 *    QT_EndCreateMyVideoTrack()                             *
289 *                                                           *
290 *    Creates/finishes a video track for the QuickTime movie *
291 *                                                           *
292 *************************************************************/
293
294 static void QT_CreateMyVideoTrack(void)
295 {
296         OSErr err = noErr;
297         Rect trackFrame;
298
299         trackFrame.top = 0;
300         trackFrame.left = 0;
301         trackFrame.bottom = R.recty;
302         trackFrame.right = R.rectx;
303         
304         qte->theTrack = NewMovieTrack (qte->theMovie, 
305                                                         FixRatio(trackFrame.right,1),
306                                                         FixRatio(trackFrame.bottom,1), 
307                                                         kNoVolume);
308         CheckError( GetMoviesError(), "NewMovieTrack error" );
309
310         qte->theMedia = NewTrackMedia (qte->theTrack,
311                                                         VideoMediaType,
312                                                         qcdx->kVideoTimeScale,
313                                                         nil,
314                                                         0);
315         CheckError( GetMoviesError(), "NewTrackMedia error" );
316
317         err = BeginMediaEdits (qte->theMedia);
318         CheckError( err, "BeginMediaEdits error" );
319
320         QT_StartAddVideoSamplesToMedia (&trackFrame);
321
322
323
324 static void QT_EndCreateMyVideoTrack(void)
325 {
326         OSErr err = noErr;
327
328         QT_EndAddVideoSamplesToMedia ();
329
330         err = EndMediaEdits (qte->theMedia);
331         CheckError( err, "EndMediaEdits error" );
332
333         err = InsertMediaIntoTrack (qte->theTrack,
334                                                                 kTrackStart,/* track start time */
335                                                                 kMediaStart,/* media start time */
336                                                                 GetMediaDuration (qte->theMedia),
337                                                                 fixed1);
338         CheckError( err, "InsertMediaIntoTrack error" );
339
340
341
342 /************************************************************
343 *                                                           *
344 *    QT_StartAddVideoSamplesToMedia()                       *
345 *    QT_DoAddVideoSamplesToMedia()                          *
346 *    QT_EndAddVideoSamplesToMedia()                         *
347 *                                                           *
348 *    Creates video samples for the media in a track         *
349 *                                                           *
350 *************************************************************/
351
352 static void QT_StartAddVideoSamplesToMedia (const Rect *trackFrame)
353 {
354         OSErr err = noErr;
355
356         qte->ibuf = IMB_allocImBuf (R.rectx, R.recty, 32, IB_rect, 0);
357         qte->ibuf2 = IMB_allocImBuf (R.rectx, R.recty, 32, IB_rect, 0);
358
359         err = NewGWorldFromPtr( &qte->theGWorld,
360                                                         k32ARGBPixelFormat,
361                                                         trackFrame,
362                                                         NULL, NULL, 0,
363                                                         (unsigned char *)qte->ibuf->rect,
364                                                         R.rectx * 4 );
365         CheckError (err, "NewGWorldFromPtr error");
366
367         qte->thePixMap = GetGWorldPixMap(qte->theGWorld);
368         LockPixels(qte->thePixMap);
369
370         SCDefaultPixMapSettings (qcdx->theComponent, qte->thePixMap, true);
371
372         SCSetInfo(qcdx->theComponent, scTemporalSettingsType,   &qcdx->gTemporalSettings);
373         SCSetInfo(qcdx->theComponent, scSpatialSettingsType,    &qcdx->gSpatialSettings);
374         SCSetInfo(qcdx->theComponent, scDataRateSettingsType,   &qcdx->aDataRateSetting);
375
376         err = SCCompressSequenceBegin(qcdx->theComponent, qte->thePixMap, NULL, &qte->anImageDescription); 
377         CheckError (err, "SCCompressSequenceBegin error" );
378 }
379
380
381 static void QT_DoAddVideoSamplesToMedia (int frame)
382 {
383         OSErr   err = noErr;
384         Rect    imageRect;
385
386         register int            index;
387         register int            boxsize;
388         register uint32_t       *readPos;
389         register uint32_t       *changePos;
390         Ptr                                     myPtr;
391
392         short   syncFlag;
393         long    dataSize;
394         Handle  compressedData;
395
396 // copy and flip the renderdata
397         if(qte->ibuf2) {
398                 memcpy(qte->ibuf2->rect, R.rectot, 4*R.rectx*R.recty);
399                 IMB_flipy(qte->ibuf2);
400         }
401
402 //get pointers to parse bitmapdata
403         myPtr = GetPixBaseAddr(qte->thePixMap);
404         imageRect = (**qte->thePixMap).bounds;
405
406         boxsize = R.rectx * R.recty;
407         readPos = (uint32_t *) qte->ibuf2->rect;
408         changePos = (uint32_t *) myPtr;
409
410 #ifdef __APPLE__
411 // Swap alpha byte to the end, so ARGB become RGBA; note this is big endian-centric.
412         for( index = 0; index < boxsize; index++, changePos++, readPos++ )
413                 *( changePos ) = ( ( *readPos & 0xFFFFFFFF ) >> 8 ) |
414                          ( ( *readPos << 24 ) & 0xFF );
415 #endif
416
417 #ifdef _WIN32
418 // poked around a little... this seems to work for windows, dunno if it's legal
419         for( index = 0; index < boxsize; index++, changePos++, readPos++ )
420                 *( changePos ) = ( ( *readPos & 0xFFFFFFFF ) << 8 ) |
421                                                  ( ( *readPos >> 24 ) & 0xFF ); // & ( ( *readPos << 8 ) & 0xFF );
422 #endif
423
424         err = SCCompressSequenceFrame(qcdx->theComponent,
425                 qte->thePixMap,
426                 &imageRect,
427                 &compressedData,
428                 &dataSize,
429                 &syncFlag);
430         CheckError(err, "SCCompressSequenceFrame error");
431
432         err = AddMediaSample(qte->theMedia,
433                 compressedData,
434                 0,
435                 dataSize,
436                 qcdx->duration,
437                 (SampleDescriptionHandle)qte->anImageDescription,
438                 1,
439                 syncFlag,
440                 NULL);
441         CheckError(err, "AddMediaSample error");
442
443         printf ("added frame %3d (frame %3d in movie): ", frame, frame-sframe);
444 }
445
446
447 static void QT_EndAddVideoSamplesToMedia (void)
448 {
449         SCCompressSequenceEnd(qcdx->theComponent);
450
451         UnlockPixels(qte->thePixMap);
452         if (qte->theGWorld)     DisposeGWorld (qte->theGWorld);
453         if (qte->ibuf)          IMB_freeImBuf(qte->ibuf);
454         if (qte->ibuf2)         IMB_freeImBuf(qte->ibuf2);
455
456
457
458 /************************************************************
459 *                                                           *
460 *    makeqtstring (char *string)                            *
461 *                                                           *
462 *    Function to generate output filename                   *
463 *                                                           *
464 *************************************************************/
465
466 void makeqtstring (char *string) {
467         char txt[64];
468
469         if (string==0) return;
470
471         strcpy(string, G.scene->r.pic);
472         BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
473
474         RE_make_existing_file(string);
475
476         if (strcasecmp(string + strlen(string) - 4, ".mov")) {
477                 sprintf(txt, "%04d_%04d.mov", (G.scene->r.sfra) , (G.scene->r.efra) );
478                 strcat(string, txt);
479         }
480 }
481
482
483 /************************************************************
484 *                                                           *
485 *    start_qt(void)                                         *
486 *    append_qt(int frame)                                   *
487 *    end_qt(int frame)                                      *
488 *                                                           *
489 *    Quicktime Export functions for Blender's initrender.c  *
490 *                                                           *
491 ************************************************************/
492
493 void start_qt(void) {
494         OSErr err = noErr;
495
496         char name[2048];
497         char theFullPath[255];
498
499 #ifdef __APPLE__
500         int             myFile;
501         FSRef   myRef;
502 #endif
503
504         if(qte == NULL) qte = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport");
505
506         if(qcdx) {
507                 if(qcdx->theComponent) CloseComponent(qcdx->theComponent);
508                 free_qtcodecdataExt();
509         }
510
511         qcdx = MEM_callocN(sizeof(QuicktimeCodecDataExt), "QuicktimeCodecDataExt");
512
513         if(G.scene->r.qtcodecdata == NULL && G.scene->r.qtcodecdata->cdParms == NULL) {
514                 get_qtcodec_settings();
515         } else {
516                 qcdx->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
517
518 //              printf("getting from blend\n");
519                 GetExporterSettingsFromMem (G.scene->r.qtcodecdata);
520                 check_renderbutton_framerate();
521         }
522         
523         if (G.afbreek != 1) {
524                 sframe = (G.scene->r.sfra);
525
526                 makeqtstring(name);
527                 sprintf(theFullPath, "%s", name);
528
529 #ifdef __APPLE__
530                 /* hack: create an empty file to make FSPathMakeRef() happy */
531                 myFile = open(theFullPath, O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRUSR|S_IWUSR);
532                 if (myFile < 0) {
533                         printf("error while creating file!\n");
534                         /* do something? */
535                 }
536                 close(myFile);
537                 err = FSPathMakeRef(theFullPath, &myRef, 0);
538                 CheckError(err, "FsPathMakeRef error");
539                 err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &qte->theSpec, NULL);
540                 CheckError(err, "FsGetCatalogInfoRef error");
541 #else
542                 CopyCStringToPascal(theFullPath, qte->qtfilename);
543                 err = FSMakeFSSpec(0, 0L, qte->qtfilename, &qte->theSpec);
544 #endif
545
546                 err = CreateMovieFile (&qte->theSpec, 
547                                                         kMyCreatorType,
548                                                         smCurrentScript, 
549                                                         createMovieFileDeleteCurFile | createMovieFileDontCreateResFile,
550                                                         &qte->resRefNum, 
551                                                         &qte->theMovie );
552                 CheckError(err, "CreateMovieFile error");
553
554                 printf("Created QuickTime movie: %s\n", name);
555
556                 QT_CreateMyVideoTrack();
557         }
558 }
559
560
561 void append_qt(int frame) {
562         QT_DoAddVideoSamplesToMedia(frame);
563 }
564
565 void end_qt(void) {
566         OSErr err = noErr;
567
568         if(qte->theMovie) {
569                 QT_EndCreateMyVideoTrack ();
570
571                 qte->resId = movieInDataForkResID;
572                 err = AddMovieResource (qte->theMovie, qte->resRefNum, &qte->resId, qte->qtfilename);
573                 CheckError(err, "AddMovieResource error");
574
575                 if (qte->resRefNum)     CloseMovieFile (qte->resRefNum);
576
577                 DisposeMovie (qte->theMovie);
578         }
579
580         if(qte) {
581                 MEM_freeN(qte);
582                 qte = NULL;
583         }
584 };
585
586
587 /************************************************************
588 *                                                           *
589 *    free_qtcodecdataExt(void)                              *
590 *                                                           *
591 *    Function to release codec memory, since it remains     *
592 *    resident after allocation.                             *
593 *                                                           *
594 *************************************************************/
595
596 void free_qtcodecdataExt(void) {
597         if(qcdx) {
598                 if(qcdx->theComponent) CloseComponent(qcdx->theComponent);
599                 MEM_freeN(qcdx);
600                 qcdx = NULL;
601         }
602 }
603
604
605 /************************************************************
606 *                                                           *
607 *    check_renderbutton_framerate ( void )                  *
608 *                                                           *
609 *    To keep float framerates consistent between the codec  *
610 *    dialog and frs/sec button.                             *
611 *                                                           *
612 *************************************************************/
613
614 static void check_renderbutton_framerate(void) {
615         OSErr   err;    
616
617         err = SCGetInfo(qcdx->theComponent, scTemporalSettingsType,     &qcdx->gTemporalSettings);
618         CheckError(err, "SCGetInfo fr error");
619
620         if( (G.scene->r.frs_sec == 24 || G.scene->r.frs_sec == 30 || G.scene->r.frs_sec == 60) &&
621                 (qcdx->gTemporalSettings.frameRate == 1571553 ||
622                  qcdx->gTemporalSettings.frameRate == 1964113 ||
623                  qcdx->gTemporalSettings.frameRate == 3928227)) {;} else
624         qcdx->gTemporalSettings.frameRate = G.scene->r.frs_sec << 16;
625
626         err = SCSetInfo(qcdx->theComponent, scTemporalSettingsType,     &qcdx->gTemporalSettings);
627         CheckError( err, "SCSetInfo error" );
628
629         if(qcdx->gTemporalSettings.frameRate == 1571553) {                      // 23.98 fps
630                 qcdx->kVideoTimeScale = 2398;
631                 qcdx->duration = 100;
632         } else if (qcdx->gTemporalSettings.frameRate == 1964113) {      // 29.97 fps
633                 qcdx->kVideoTimeScale = 2997;
634                 qcdx->duration = 100;
635         } else if (qcdx->gTemporalSettings.frameRate == 3928227) {      // 59.94 fps
636                 qcdx->kVideoTimeScale = 5994;
637                 qcdx->duration = 100;
638         } else {
639                 qcdx->kVideoTimeScale = (qcdx->gTemporalSettings.frameRate >> 16) * 100;
640                 qcdx->duration = 100;
641         }
642 }
643
644 /********************************************************************
645 *                                                                   *
646 *    get_qtcodec_settings()                                         *
647 *                                                                   *
648 *    Displays Codec Dialog and retrieves Quicktime Codec settings.  *
649 *                                                                   *
650 ********************************************************************/
651
652 int get_qtcodec_settings(void) 
653 {
654         OSErr   err = noErr;
655         CodecInfo ci;
656         char str[255];
657
658         // erase any existing codecsetting
659         if(qcdx) {
660                 if(qcdx->theComponent) CloseComponent(qcdx->theComponent);
661                 free_qtcodecdataExt();
662         }
663
664         // allocate new
665         qcdx = MEM_callocN(sizeof(QuicktimeCodecDataExt), "QuicktimeCodecDataExt");
666         qcdx->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
667
668         // get previous selected codecsetting, if any 
669         if(G.scene->r.qtcodecdata && G.scene->r.qtcodecdata->cdParms) {
670 //              printf("getting from MEM\n");
671                 GetExporterSettingsFromMem (G.scene->r.qtcodecdata);
672                 check_renderbutton_framerate();
673         } else {
674
675         // configure the standard image compression dialog box
676         // set some default settings
677 //              qcdx->gSpatialSettings.codecType = nil;     
678                 qcdx->gSpatialSettings.codec = anyCodec;         
679 //              qcdx->gSpatialSettings.depth;         
680                 qcdx->gSpatialSettings.spatialQuality = codecMaxQuality;
681
682                 qcdx->gTemporalSettings.temporalQuality = codecMaxQuality;
683 //              qcdx->gTemporalSettings.frameRate;      
684                 qcdx->gTemporalSettings.keyFrameRate = 25;   
685
686                 qcdx->aDataRateSetting.dataRate = 90 * 1024;          
687 //              qcdx->aDataRateSetting.frameDuration;     
688 //              qcdx->aDataRateSetting.minSpatialQuality; 
689 //              qcdx->aDataRateSetting.minTemporalQuality;
690
691                 err = SCSetInfo(qcdx->theComponent, scTemporalSettingsType,     &qcdx->gTemporalSettings);
692                 CheckError(err, "SCSetInfo1 error");
693                 err = SCSetInfo(qcdx->theComponent, scSpatialSettingsType,      &qcdx->gSpatialSettings);
694                 CheckError(err, "SCSetInfo2 error");
695                 err = SCSetInfo(qcdx->theComponent, scDataRateSettingsType,     &qcdx->aDataRateSetting);
696                 CheckError(err, "SCSetInfo3 error");
697         }
698         // put up the dialog box
699         err = SCRequestSequenceSettings(qcdx->theComponent);
700  
701         if (err == scUserCancelled) {
702                 G.afbreek = 1;
703                 return 0;
704         }
705
706         // get user selected data
707         SCGetInfo(qcdx->theComponent, scTemporalSettingsType,   &qcdx->gTemporalSettings);
708         SCGetInfo(qcdx->theComponent, scSpatialSettingsType,    &qcdx->gSpatialSettings);
709         SCGetInfo(qcdx->theComponent, scDataRateSettingsType,   &qcdx->aDataRateSetting);
710
711         GetCodecInfo (&ci, qcdx->gSpatialSettings.codecType, 0);
712         CopyPascalStringToC(ci.typeName, str);
713         sprintf(qtcdname,"Codec: %s", str);
714
715         SaveExporterSettingsToMem(G.scene->r.qtcodecdata);
716
717         // framerate jugglin'
718         if(qcdx->gTemporalSettings.frameRate == 1571553) {                      // 23.98 fps
719                 qcdx->kVideoTimeScale = 2398;
720                 qcdx->duration = 100;
721
722                 G.scene->r.frs_sec = 24;
723         } else if (qcdx->gTemporalSettings.frameRate == 1964113) {      // 29.97 fps
724                 qcdx->kVideoTimeScale = 2997;
725                 qcdx->duration = 100;
726
727                 G.scene->r.frs_sec = 30;
728         } else if (qcdx->gTemporalSettings.frameRate == 3928227) {      // 59.94 fps
729                 qcdx->kVideoTimeScale = 5994;
730                 qcdx->duration = 100;
731
732                 G.scene->r.frs_sec = 60;
733         } else {
734                 qcdx->kVideoTimeScale = 600;
735                 qcdx->duration = qcdx->kVideoTimeScale / (qcdx->gTemporalSettings.frameRate / 65536);
736
737                 G.scene->r.frs_sec = (qcdx->gTemporalSettings.frameRate / 65536);
738         }
739
740         return 1;
741 }
742
743 #endif /* _WIN32 || __APPLE__ */
744
745 #endif /* WITH_QUICKTIME */
746