void openMovSettingsPopup(TPropertyGroup *props, bool macBringToFront) { #ifdef _WIN32 if (InitializeQTML(0) != noErr) return; #endif ComponentInstance ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); QTAtomContainer atoms; QTNewAtomContainer(&atoms); fromPropertiesToAtoms(*props, atoms); ComponentResult err; if ((err = SCSetSettingsFromAtomContainer(ci, atoms)) != noErr) { CloseComponent(ci); ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); assert(false); } QTDisposeAtomContainer(atoms); #ifdef MACOSX // Install an external procedure to use a callback filter on the request // settings dialog // On MACOSX we need to change the dialog appearance in order to pop-up in front // of the // toonz main window. /* gProcStruct.filterProc = NewSCModalFilterUPP(QTCmpr_FilterProc); // I don't install any hook gProcStruct.hookProc = NULL; gProcStruct.customName[0] = 0; // I don't use refcon gProcStruct.refcon = 0; // set the current extended procs SCSetInfo(ci, scExtendedProcsType, &gProcStruct); */ #endif err = SCRequestSequenceSettings(ci); // assert(err==noErr); QTAtomContainer atomsOut; if (SCGetSettingsAsAtomContainer(ci, &atomsOut) != noErr) assert(false); fromAtomsToProperties(atomsOut, *props); QTDisposeAtomContainer(atomsOut); CloseComponent(ci); // int dataSize=0, numChildren = 0, numLevels=0; // retrieveData(settings, kParentAtomIsContainer, dataSize, numChildren, // numLevels); }
HNoPurge((Handle) pict); rct.left = (width - scTestImageWidth) >> 1; rct.top = (height - scTestImageHeight) >> 1; rct.right = rct.left + scTestImageWidth; rct.bottom = rct.top + scTestImageHeight; err = SCSetTestImagePictHandle(ci, pict, &rct, scPreferCropping); } #endif SCWindowSettings ws; ws.size = sizeof(SCWindowSettings); ws.windowRefKind = scWindowRefKindCarbon; ws.parentWindow = parent; err = SCSetInfo(ci, scWindowOptionsType, &ws); err = SCRequestSequenceSettings(ci); if (err == noErr) { CFDataRef data; Handle hdl; err = SCGetInfo(ci, scSettingsStateType, &hdl); if (err == noErr) { HLock(hdl); data = CFDataCreate(kCFAllocatorDefault, (unsigned char *) *hdl, GetHandleSize(hdl)); if (data) { CFPreferencesSetAppValue(CFSTR("QTVideoSetting"), data, kCFPreferencesCurrentApplication); CFRelease(data); }
static int request_qtcodec_settings(bContext *C, wmOperator *op) { OSErr err = noErr; Scene *scene = CTX_data_scene(C); RenderData *rd = &scene->r; // erase any existing codecsetting if(qtdata) { if(qtdata->theComponent) CloseComponent(qtdata->theComponent); free_qtcomponentdata(); } // allocate new qtdata = MEM_callocN(sizeof(QuicktimeComponentData), "QuicktimeComponentData"); qtdata->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); // get previous selected codecsetting, from qtatom or detailed settings if(rd->qtcodecdata && rd->qtcodecdata->cdParms) { QT_GetCodecSettingsFromScene(rd, op->reports); } else { SCGetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); SCGetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); qtdata->gSpatialSettings.codecType = rd->qtcodecsettings.codecType; qtdata->gSpatialSettings.codec = (CodecComponent)rd->qtcodecsettings.codec; qtdata->gSpatialSettings.spatialQuality = (rd->qtcodecsettings.codecSpatialQuality * codecLosslessQuality) /100; qtdata->gTemporalSettings.temporalQuality = (rd->qtcodecsettings.codecTemporalQuality * codecLosslessQuality) /100; qtdata->gTemporalSettings.keyFrameRate = rd->qtcodecsettings.keyFrameRate; qtdata->gTemporalSettings.frameRate = ((float)(rd->frs_sec << 16) / rd->frs_sec_base); qtdata->aDataRateSetting.dataRate = rd->qtcodecsettings.bitRate; qtdata->gSpatialSettings.depth = rd->qtcodecsettings.colorDepth; qtdata->aDataRateSetting.minSpatialQuality = (rd->qtcodecsettings.minSpatialQuality * codecLosslessQuality) / 100; qtdata->aDataRateSetting.minTemporalQuality = (rd->qtcodecsettings.minTemporalQuality * codecLosslessQuality) / 100; qtdata->aDataRateSetting.frameDuration = rd->frs_sec; err = SCSetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); CheckError(err, "SCSetInfo1 error", op->reports); err = SCSetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); CheckError(err, "SCSetInfo2 error", op->reports); err = SCSetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); CheckError(err, "SCSetInfo3 error", op->reports); } // put up the dialog box - it needs to be called from the main thread err = SCRequestSequenceSettings(qtdata->theComponent); if (err == scUserCancelled) { return OPERATOR_FINISHED; } // update runtime codecsettings for use with the codec dialog SCGetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); SCGetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); //Fill the render QuicktimeCodecSettings struct rd->qtcodecsettings.codecTemporalQuality = (qtdata->gTemporalSettings.temporalQuality * 100) / codecLosslessQuality; //Do not override scene frame rate (qtdata->gTemporalSettings.framerate) rd->qtcodecsettings.keyFrameRate = qtdata->gTemporalSettings.keyFrameRate; rd->qtcodecsettings.codecType = qtdata->gSpatialSettings.codecType; rd->qtcodecsettings.codec = (int)qtdata->gSpatialSettings.codec; rd->qtcodecsettings.colorDepth = qtdata->gSpatialSettings.depth; rd->qtcodecsettings.codecSpatialQuality = (qtdata->gSpatialSettings.spatialQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.bitRate = qtdata->aDataRateSetting.dataRate; rd->qtcodecsettings.minSpatialQuality = (qtdata->aDataRateSetting.minSpatialQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.minTemporalQuality = (qtdata->aDataRateSetting.minTemporalQuality * 100) / codecLosslessQuality; //Frame duration is already known (qtdata->aDataRateSetting.frameDuration) QT_SaveCodecSettingsToScene(rd, op->reports); // framerate jugglin' if(qtdata->gTemporalSettings.frameRate == 1571553) { // 23.98 fps qtdata->kVideoTimeScale = 24000; qtdata->duration = 1001; rd->frs_sec = 24; rd->frs_sec_base = 1.001; } else if (qtdata->gTemporalSettings.frameRate == 1964113) { // 29.97 fps qtdata->kVideoTimeScale = 30000; qtdata->duration = 1001; rd->frs_sec = 30; rd->frs_sec_base = 1.001; } else if (qtdata->gTemporalSettings.frameRate == 3928227) { // 59.94 fps qtdata->kVideoTimeScale = 60000; qtdata->duration = 1001; rd->frs_sec = 60; rd->frs_sec_base = 1.001; } else { double fps = qtdata->gTemporalSettings.frameRate; qtdata->kVideoTimeScale = 60000; qtdata->duration = qtdata->kVideoTimeScale / (qtdata->gTemporalSettings.frameRate / 65536); if ((qtdata->gTemporalSettings.frameRate & 0xffff) == 0) { rd->frs_sec = fps / 65536; rd->frs_sec_base = 1.0; } else { /* we do our very best... */ rd->frs_sec = fps / 65536; rd->frs_sec_base = 1.0; } } return OPERATOR_FINISHED; }
OSStatus MovieMaker::setupMovie() { OSStatus error = noErr; FSRef fileRef; FSSpec fileSpec; rowBytes = width * 4; bufferSize = height * rowBytes; buffer = (char*)malloc(bufferSize); invertedBuffer = (char*)malloc(bufferSize); rect.left = 0; rect.top = 0; rect.right = width; rect.bottom = height; error = NewGWorldFromPtr(&gworld, k32ARGBPixelFormat, &rect, 0, 0, 0, buffer, rowBytes); if (error == noErr) { LockPixels(GetGWorldPixMap(gworld)); } // MBW -- I think this needs to happen after all the dialogs, etc. // if (error == noErr) // { // Microseconds(&lastFrameTime); // error = grabFrame(); // } if (error == noErr) { error = EnterMovies(); } if (error == noErr) { ci = OpenDefaultComponent(StandardCompressionType,StandardCompressionSubType); if(ci == NULL) error = paramErr; } if (error == noErr) { long flags; SCGetInfo(ci,scPreferenceFlagsType,&flags); flags &= ~scShowBestDepth; flags |= scAllowZeroFrameRate; SCSetInfo(ci,scPreferenceFlagsType,&flags); } if (error == noErr) { send_agent_pause(); gViewerWindow->mWindow->beforeDialog(); error = SCRequestSequenceSettings(ci); gViewerWindow->mWindow->afterDialog(); send_agent_resume(); if (error == scUserCancelled) { // deal with user cancelling. EndCapture(); } } if (error == noErr) { // This is stoopid. I have to take the passed full path, create the file so I can get an FSRef, and Get Info to get the FSSpec for QuickTime. Could Apple make this any more difficult... FILE* file = LLFile::fopen(fname, "w"); /* Flawfinder: ignore */ if (file) { fclose(file); error = FSPathMakeRef((UInt8*)fname, &fileRef, NULL); if (error == noErr) error = FSGetCatalogInfo(&fileRef, 0, NULL, NULL, &fileSpec, NULL); } else { error = paramErr; } } if (error == noErr) { error = CreateMovieFile(&fileSpec, 'TVOD', smCurrentScript, createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, &movieResRef, &movie); } if (error == noErr) { track = NewMovieTrack(movie, FixRatio(width, 1), FixRatio(height, 1), kNoVolume); error = GetMoviesError(); } if (error == noErr) { media = NewTrackMedia(track, VideoMediaType, 600, NULL, 0); error = GetMoviesError(); } if (error == noErr) { Microseconds(&lastFrameTime); error = grabFrame(); } if (error == noErr) { error = SCCompressSequenceBegin(ci,GetPortPixMap(gworld),nil,&idh); } if (error == noErr) { error = BeginMediaEdits(media); } if (error != noErr) { media = NULL; } return error; }
void qtCanvas::Impl::showSettingsDialog() { SCRequestSequenceSettings(mSCComponent); }
void MacQTVideoConfig(WindowRef parent) { OSStatus err; ComponentInstance ci; if (running) return; MacQTOpenVideoComponent(&ci); long flag; flag = scListEveryCodec | scAllowZeroKeyFrameRate | scDisableFrameRateItem; err = SCSetInfo(ci, scPreferenceFlagsType, &flag); PicHandle pict; Rect rct; int width, height; width = IPPU.RenderedScreenWidth; height = IPPU.RenderedScreenHeight; pict = GetScreenAsPicHandle(width, height, width, height); HNoPurge((Handle) pict); rct.left = (width - scTestImageWidth) >> 1; rct.top = (height - scTestImageHeight) >> 1; rct.right = rct.left + scTestImageWidth; rct.bottom = rct.top + scTestImageHeight; err = SCSetTestImagePictHandle(ci, pict, &rct, scPreferCropping); SCWindowSettings ws; ws.size = sizeof(SCWindowSettings); ws.windowRefKind = scWindowRefKindCarbon; ws.parentWindow = parent; err = SCSetInfo(ci, scWindowOptionsType, &ws); err = SCRequestSequenceSettings(ci); if (err == noErr) { CFDataRef data; Handle hdl; err = SCGetInfo(ci, scSettingsStateType, &hdl); if (err == noErr) { HLock(hdl); data = CFDataCreate(kCFAllocatorDefault, (unsigned char *) *hdl, GetHandleSize(hdl)); if (data) { CFPreferencesSetAppValue(CFSTR("QTVideoSetting"), data, kCFPreferencesCurrentApplication); CFRelease(data); } DisposeHandle(hdl); } } MacQTCloseVideoComponent(ci); KillPicture(pict); }
void QTCmpr_CompressSequence (WindowObject theWindowObject) { ComponentInstance myComponent = NULL; GWorldPtr myImageWorld = NULL; // the graphics world we draw the images in PixMapHandle myPixMap = NULL; Movie mySrcMovie = NULL; Track mySrcTrack = NULL; Movie myDstMovie = NULL; Track myDstTrack = NULL; Media myDstMedia = NULL; Rect myRect; PicHandle myPicture = NULL; CGrafPtr mySavedPort = NULL; GDHandle mySavedDevice = NULL; SCTemporalSettings myTimeSettings; SCDataRateSettings myRateSettings; FSSpec myFile; Boolean myIsSelected = false; Boolean myIsReplacing = false; short myRefNum = -1; StringPtr myMoviePrompt = QTUtils_ConvertCToPascalString(kQTCSaveMoviePrompt); StringPtr myMovieFileName = QTUtils_ConvertCToPascalString(kQTCSaveMovieFileName); MatrixRecord myMatrix; ImageDescriptionHandle myImageDesc = NULL; TimeValue myCurMovieTime = 0L; TimeValue myOrigMovieTime = 0L; // current movie time, when compression is begun short myFrameNum; long myFlags = 0L; long myNumFrames = 0L; long mySrcMovieDuration = 0L; // duration of source movie OSErr myErr = noErr; #if USE_ASYNC_COMPRESSION ICMCompletionProcRecord myICMComplProcRec; ICMCompletionProcRecordPtr myICMComplProcPtr = NULL; OSErr myICMComplProcErr = noErr; myICMComplProcRec.completionProc = NULL; myICMComplProcRec.completionRefCon = 0L; #endif if (theWindowObject == NULL) goto bail; ////////// // // get the movie and the first video track in the movie // ////////// mySrcMovie = (**theWindowObject).fMovie; if (mySrcMovie == NULL) goto bail; mySrcTrack = GetMovieIndTrackType(mySrcMovie, 1, VideoMediaType, movieTrackMediaType); if (mySrcTrack == NULL) goto bail; // stop the movie; we don't want it to be playing while we're (re)compressing it SetMovieRate(mySrcMovie, (Fixed)0L); // get the current movie time, when compression is begun; we'll restore this later myOrigMovieTime = GetMovieTime(mySrcMovie, NULL); ////////// // // configure and display the Standard Image Compression dialog box // ////////// // open an instance of the Standard Image Compression dialog component myComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); if (myComponent == NULL) goto bail; // turn off "best depth" option in the compression dialog, because all of our // buffering is done at 32-bits (regardless of the depth of the source data) // // a more ambitious approach would be to loop through each of the video sample // descriptions in each of the video tracks looking for the deepest depth, and // using that for the best depth; better yet, we could find out which compressors // were used and set one of those as the default in the compression dialog SCGetInfo(myComponent, scPreferenceFlagsType, &myFlags); myFlags &= ~scShowBestDepth; SCSetInfo(myComponent, scPreferenceFlagsType, &myFlags); // because we are recompressing a movie that may have a variable frame rate, // we want to allow the user to leave the frame rate text field blank (in which // case we can preserve the frame durations of the source movie); if the user // enters a number, we will resample the movie at a new frame rate; if we don't // clear this flag, the compression dialog will not allow zero in the frame rate field // // NOTE: we could have set this flag above when we cleared the scShowBestDepth flag; // it is done here for clarity. SCGetInfo(myComponent, scPreferenceFlagsType, &myFlags); myFlags |= scAllowZeroFrameRate; SCSetInfo(myComponent, scPreferenceFlagsType, &myFlags); // get the number of video frames in the movie myNumFrames = QTUtils_GetFrameCount(mySrcTrack); // get the bounding rectangle of the movie, create a 32-bit GWorld with those // dimensions, and draw the movie poster picture into it; this GWorld will be // used for the test image in the compression dialog box and for rendering movie // frames myPicture = GetMoviePosterPict(mySrcMovie); if (myPicture == NULL) goto bail; GetMovieBox(mySrcMovie, &myRect); myErr = NewGWorld(&myImageWorld, 32, &myRect, NULL, NULL, 0L); if (myErr != noErr) goto bail; // get the pixmap of the GWorld; we'll lock the pixmap, just to be safe myPixMap = GetGWorldPixMap(myImageWorld); if (!LockPixels(myPixMap)) goto bail; // draw the movie poster image into the GWorld GetGWorld(&mySavedPort, &mySavedDevice); SetGWorld(myImageWorld, NULL); EraseRect(&myRect); DrawPicture(myPicture, &myRect); KillPicture(myPicture); SetGWorld(mySavedPort, mySavedDevice); // set the picture to be displayed in the dialog box; passing NULL for the rect // means use the entire image; passing 0 for the flags means to use the default // system method of displaying the test image, which is currently a combination // of cropping and scaling; personally, I prefer scaling (your mileage may vary) SCSetTestImagePixMap(myComponent, myPixMap, NULL, scPreferScaling); // install the custom procs, if requested // we can install two kinds of custom procedures for use in connection with // the standard dialog box: (1) a modal-dialog filter function, and (2) a hook // function to handle the custom button in the dialog box if (gUseExtendedProcs) QTCmpr_InstallExtendedProcs(myComponent, (long)myPixMap); // set up some default settings for the compression dialog SCDefaultPixMapSettings(myComponent, myPixMap, true); // clear out the default frame rate chosen by Standard Compression (a frame rate // of 0 means to use the rate of the source movie) myErr = SCGetInfo(myComponent, scTemporalSettingsType, &myTimeSettings); if (myErr != noErr) goto bail; myTimeSettings.frameRate = 0; SCSetInfo(myComponent, scTemporalSettingsType, &myTimeSettings); // request image compression settings from the user; in other words, put up the dialog box myErr = SCRequestSequenceSettings(myComponent); if (myErr == scUserCancelled) goto bail; // get a copy of the temporal settings the user entered; we'll need them for some // of our calculations (in a simpler application, we'd never have to look at them) SCGetInfo(myComponent, scTemporalSettingsType, &myTimeSettings); ////////// // // adjust the data rate [to be supplied][relevant only for movies that have sound tracks] // ////////// ////////// // // adjust the sample count // // if the user wants to resample the frame rate of the movie (as indicated a non-zero // value in the frame rate field) calculate the number of frames and duration for the new movie // ////////// if (myTimeSettings.frameRate != 0) { long myDuration = GetMovieDuration(mySrcMovie); long myTimeScale = GetMovieTimeScale(mySrcMovie); float myFloat = (float)myDuration * myTimeSettings.frameRate; myNumFrames = myFloat / myTimeScale / 65536; if (myNumFrames == 0) myNumFrames = 1; } ////////// // // get the name and location of the new movie file // ////////// // prompt the user for a file to put the compressed image into; in theory, the name // should have a file extension appropriate to the type of compressed data selected by the user; // this is left as an exercise for the reader QTFrame_PutFile(myMoviePrompt, myMovieFileName, &myFile, &myIsSelected, &myIsReplacing); if (!myIsSelected) goto bail; // delete any existing file of that name if (myIsReplacing) { myErr = DeleteMovieFile(&myFile); if (myErr != noErr) goto bail; } ////////// // // create the target movie // ////////// myErr = CreateMovieFile(&myFile, sigMoviePlayer, smSystemScript, createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, &myRefNum, &myDstMovie); if (myErr != noErr) goto bail; // create a new video movie track with the same dimensions as the entire source movie myDstTrack = NewMovieTrack(myDstMovie, (long)(myRect.right - myRect.left) << 16, (long)(myRect.bottom - myRect.top) << 16, kNoVolume); if (myDstTrack == NULL) goto bail; // create a media for the new track with the same time scale as the source movie; // because the time scales are the same, we don't have to do any time scale conversions. myDstMedia = NewTrackMedia(myDstTrack, VIDEO_TYPE, GetMovieTimeScale(mySrcMovie), 0, 0); if (myDstMedia == NULL) goto bail; // copy the user data and settings from the source to the dest movie CopyMovieSettings(mySrcMovie, myDstMovie); // set movie matrix to identity and clear the movie clip region (because the conversion // process transforms and composites all video tracks into one untransformed video track) SetIdentityMatrix(&myMatrix); SetMovieMatrix(myDstMovie, &myMatrix); SetMovieClipRgn(myDstMovie, NULL); // set the movie to highest quality imaging SetMoviePlayHints(mySrcMovie, hintsHighQuality, hintsHighQuality); myImageDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription)); if (myImageDesc == NULL) goto bail; // prepare for adding frames to the movie myErr = BeginMediaEdits(myDstMedia); if (myErr != noErr) goto bail; ////////// // // compress the image sequence // // we are going to step through the source movie, compress each frame, and then add // the compressed frame to the destination movie // ////////// myErr = SCCompressSequenceBegin(myComponent, myPixMap, NULL, &myImageDesc); if (myErr != noErr) goto bail; #if USE_ASYNC_COMPRESSION myFlags = codecFlagUpdatePrevious + codecFlagUpdatePreviousComp + codecFlagLiveGrab; SCSetInfo(myComponent, scCodecFlagsType, &myFlags); #endif // clear out our image GWorld and set movie to draw into it SetGWorld(myImageWorld, NULL); EraseRect(&myRect); SetMovieGWorld(mySrcMovie, myImageWorld, GetGWorldDevice(myImageWorld)); // set current time value to beginning of the source movie myCurMovieTime = 0; // get a value we'll need inside the loop mySrcMovieDuration = GetMovieDuration(mySrcMovie); // loop through all of the interesting times we counted above for (myFrameNum = 0; myFrameNum < myNumFrames; myFrameNum++) { short mySyncFlag; TimeValue myDuration; long myDataSize; Handle myCompressedData; ////////// // // get the next frame of the source movie // ////////// // if we are resampling the movie, step to the next frame if (myTimeSettings.frameRate) { myCurMovieTime = myFrameNum * mySrcMovieDuration / (myNumFrames - 1); myDuration = mySrcMovieDuration / myNumFrames; } else { OSType myMediaType = VIDEO_TYPE; myFlags = nextTimeMediaSample; // if this is the first frame, include the frame we are currently on if (myFrameNum == 0) myFlags |= nextTimeEdgeOK; // if we are maintaining the frame durations of the source movie, // skip to the next interesting time and get the duration for that frame GetMovieNextInterestingTime(mySrcMovie, myFlags, 1, &myMediaType, myCurMovieTime, 0, &myCurMovieTime, &myDuration); } SetMovieTimeValue(mySrcMovie, myCurMovieTime); MoviesTask(mySrcMovie, 0); MoviesTask(mySrcMovie, 0); MoviesTask(mySrcMovie, 0); // if data rate constraining is being done, tell Standard Compression the // duration of the current frame in milliseconds; we only need to do this // if the frames have variable durations if (!SCGetInfo(myComponent, scDataRateSettingsType, &myRateSettings)) { myRateSettings.frameDuration = myDuration * 1000 / GetMovieTimeScale(mySrcMovie); SCSetInfo(myComponent, scDataRateSettingsType, &myRateSettings); } ////////// // // compress the current frame of the source movie and add it to the destination movie // ////////// // if SCCompressSequenceFrame completes successfully, myCompressedData will hold // a handle to the newly-compressed image data and myDataSize will be the size of // the compressed data (which will usually be different from the size of the handle); // also mySyncFlag will be a value that that indicates whether or not the frame is a // key frame (and which we pass directly to AddMediaSample); note that we do not need // to dispose of myCompressedData, since SCCompressSequenceEnd will do that for us #if !USE_ASYNC_COMPRESSION myErr = SCCompressSequenceFrame(myComponent, myPixMap, &myRect, &myCompressedData, &myDataSize, &mySyncFlag); if (myErr != noErr) goto bail; #else if (myICMComplProcPtr == NULL) { myICMComplProcRec.completionProc = NewICMCompletionProc(QTCmpr_CompletionProc); myICMComplProcRec.completionRefCon = (long)&myICMComplProcErr; myICMComplProcPtr = &myICMComplProcRec; } myICMComplProcErr = kAsyncDefaultValue; myErr = SCCompressSequenceFrameAsync(myComponent, myPixMap, &myRect, &myCompressedData, &myDataSize, &mySyncFlag, myICMComplProcPtr); if (myErr != noErr) goto bail; // spin our wheels while we're waiting for the compress call to complete while (myICMComplProcErr == kAsyncDefaultValue) { EventRecord myEvent; WaitNextEvent(0, &myEvent, 60, NULL); SCAsyncIdle(myComponent); } myErr = myICMComplProcErr; #endif myErr = AddMediaSample(myDstMedia, myCompressedData, 0, myDataSize, myDuration, (SampleDescriptionHandle)myImageDesc, 1, mySyncFlag, NULL); if (myErr != noErr) goto bail; } // close the compression sequence; this will dispose of the image description // and compressed data handles allocated by SCCompressSequenceBegin SCCompressSequenceEnd(myComponent); ////////// // // add the media data to the destination movie // ////////// myErr = EndMediaEdits(myDstMedia); if (myErr != noErr) goto bail; InsertMediaIntoTrack(myDstTrack, 0, 0, GetMediaDuration(myDstMedia), fixed1); // add the movie resource to the dst movie file. myErr = AddMovieResource(myDstMovie, myRefNum, NULL, NULL); if (myErr != noErr) goto bail; // flatten the movie data [to be supplied] // close the movie file CloseMovieFile(myRefNum); bail: // close the Standard Compression component if (myComponent != NULL) CloseComponent(myComponent); if (mySrcMovie != NULL) { // restore the source movie's original graphics port and device SetMovieGWorld(mySrcMovie, mySavedPort, mySavedDevice); // restore the source movie's original movie time SetMovieTimeValue(mySrcMovie, myOrigMovieTime); } // restore the original graphics port and device SetGWorld(mySavedPort, mySavedDevice); // delete the GWorld we were drawing frames into if (myImageWorld != NULL) DisposeGWorld(myImageWorld); #if USE_ASYNC_COMPRESSION if (myICMComplProcRec.completionProc != NULL) DisposeICMCompletionUPP(myICMComplProcRec.completionProc); #endif free(myMoviePrompt); free(myMovieFileName); }