Beispiel #1
0
ComponentResult create_placeholder_track(Movie movie, Track *placeholderTrack, TimeValue duration, Handle dataRef, OSType dataRefType) {
    SampleDescriptionHandle sdH = NULL;
    Media placeholderMedia;
    TimeScale movieTimeScale;
    ComponentResult result = noErr;

    movieTimeScale = GetMovieTimeScale(movie);

    sdH = (SampleDescriptionHandle)NewHandleClear(sizeof(SampleDescription));
    (*sdH)->descSize = sizeof(SampleDescription);

    *placeholderTrack = NewMovieTrack(movie, 0, 0, kNoVolume);
    placeholderMedia = NewTrackMedia(*placeholderTrack, BaseMediaType, movieTimeScale, dataRef, dataRefType);

    result = AddMediaSampleReference(placeholderMedia, 0, 1, duration, sdH, 1, 0, NULL);
    if(result != noErr)
        goto bail;

    result = InsertMediaIntoTrack(*placeholderTrack, -1, 0, duration, fixed1);

bail:
    if (sdH)
        DisposeHandle((Handle) sdH);
    return(result);
}
bool
qtCanvas::Impl::setupTrack()
{
    mTrack = NewMovieTrack(mMovie,
				FixRatio(mWidth,1), FixRatio(mHeight,1),
				(short)kNoVolume);
	if (!CheckMoviesError("NewMovieTrack")) return false;


	SCTemporalSettings	temporal;
	SCGetInfo(mSCComponent, scTemporalSettingsType, &temporal);

    mMedia = NewTrackMedia(mTrack,
				VideoMediaType, (TimeScale)temporal.frameRate,
				nil, 0);
    if (!CheckMoviesError("NewTrackMedia" )) return false;
    
    MediaHandler mh = GetMediaHandler(mMedia);
    if (!CheckMoviesError("GetMediaHandler")) return false;
    
    ComponentResult err;
    err = MediaSetGraphicsMode(mh, graphicsModePreMulColorAlpha, NULL);
    if (!CheckError(err, "MediaSetGraphicsMode")) return false;

    BeginMediaEdits(mMedia);
    if (!CheckMoviesError("BeginMediaEdits" )) return false;
    return true;
}
Beispiel #3
0
void QTVideo_CreateMyVideoTrack(Movie theMovie)
{
	Track theTrack;
	Media theMedia;
	OSErr err = noErr;
	Rect trackFrame = {0,0,100,320};

		theTrack = NewMovieTrack (theMovie, 
								FixRatio(trackFrame.right,1),
								FixRatio(trackFrame.bottom,1), 
								kNoVolume);
		CheckError( GetMoviesError(), "NewMovieTrack error" );

		theMedia = NewTrackMedia (theTrack, VideoMediaType,
								kVideoTimeScale, /* Video Time Scale */
								nil, 0);
		CheckError( GetMoviesError(), "NewTrackMedia error" );

		err = BeginMediaEdits (theMedia);
		CheckError( err, "BeginMediaEdits error" );

		QTVideo_AddVideoSamplesToMedia (theMedia, &trackFrame);

		err = EndMediaEdits (theMedia);
		CheckError( err, "EndMediaEdits error" );

		err = InsertMediaIntoTrack (theTrack, kTrackStart,/* track start time */
									kMediaStart, /* media start time */
									GetMediaDuration (theMedia),
									fixed1);
		CheckError( err, "InsertMediaIntoTrack error" );
} 
Beispiel #4
0
static void QT_CreateMyVideoTrack(int rectx, int recty, ReportList *reports)
{
	OSErr err = noErr;
	Rect trackFrame;
//	MatrixRecord myMatrix;

	trackFrame.top = 0;
	trackFrame.left = 0;
	trackFrame.bottom = recty;
	trackFrame.right = rectx;
	
	qtexport->theTrack = NewMovieTrack (qtexport->theMovie, 
							FixRatio(trackFrame.right,1),
							FixRatio(trackFrame.bottom,1), 
							0);
	CheckError( GetMoviesError(), "NewMovieTrack error", reports );

//	SetIdentityMatrix(&myMatrix);
//	ScaleMatrix(&myMatrix, fixed1, Long2Fix(-1), 0, 0);
//	TranslateMatrix(&myMatrix, 0, Long2Fix(trackFrame.bottom));
//	SetMovieMatrix(qtexport->theMovie, &myMatrix);

	qtexport->theMedia = NewTrackMedia (qtexport->theTrack,
							VideoMediaType,
							qtdata->kVideoTimeScale,
							nil,
							0);
	CheckError( GetMoviesError(), "NewTrackMedia error", reports );

	err = BeginMediaEdits (qtexport->theMedia);
	CheckError( err, "BeginMediaEdits error", reports );

	QT_StartAddVideoSamplesToMedia (&trackFrame, rectx, recty, reports);
} 
OSErr QTDR_CreateTrackInRAM (Movie theMovie)
{
	Track					myTrack = NULL;
	Media					myMedia = NULL;
	Handle					myDataRef = NULL;
	unsigned long			myAtomHeader[2];
	OSErr					myErr = noErr;

	if (theMovie == NULL)
		return(paramErr);
	
	myDataRef = NewHandleClear(sizeof(Handle) + sizeof(char));
	if (myDataRef == NULL)
		return(MemError());
	
	myAtomHeader[0] = EndianU32_NtoB(sizeof(myAtomHeader));
	myAtomHeader[1] = EndianU32_NtoB(kDataRefExtensionInitializationData);

	myErr = PtrAndHand(myAtomHeader, myDataRef, sizeof(myAtomHeader));
	if (myErr != noErr)
		goto bail;
		
	// create the movie track and media
	myTrack = NewMovieTrack(theMovie, FixRatio(kVideoTrackWidth, 1), FixRatio(kVideoTrackHeight, 1), kNoVolume);
	myErr = GetMoviesError();
	if (myErr != noErr)
		goto bail;
		
	myMedia = NewTrackMedia(myTrack, VideoMediaType, kVideoTimeScale, myDataRef, HandleDataHandlerSubType);
	myErr = GetMoviesError();
	if (myErr != noErr)
		goto bail;

	// create the media samples
	myErr = BeginMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;

	myErr = QTDR_AddVideoSamplesToMedia(myMedia, kVideoTrackWidth, kVideoTrackHeight);
	if (myErr != noErr)
		goto bail;

	myErr = EndMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;
	
	// add the media to the track
	myErr = InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
	
bail:
	if (myDataRef != NULL)
		DisposeHandle(myDataRef);

	return(myErr);
}
void ofQtVideoSaver::addAudioTrack(string audioPath)
{
	if(audioPath == "")
        return;
    OSErr err;
    Handle dataRef = NULL;

    FSSpec    fileSpec;
    short audioMovieRefNum = 0;
    short audioMovieResId = 0;

    Movie audioMovie = NULL;
    Track audioCopyTrack = NULL;
    Media audioCopyMedia = NULL;

    Track destTrack = NULL;
    Media destMedia = NULL;

    destTrack =    NewMovieTrack (movie, 0, 0, kFullVolume);

    destMedia = NewTrackMedia (destTrack, SoundMediaType,
                            30. * 100, /* Video Time Scale */
                            nil, 0);

    err = BeginMediaEdits (destMedia);
   
 
    char * p = new char[audioPath.length()+1];
    strcpy(p, audioPath.c_str());

    NativePathNameToFSSpec(p, &fileSpec, 0L);
    err = OpenMovieFile(&fileSpec, &audioMovieRefNum, fsRdPerm);

    err = NewMovieFromFile(&audioMovie, audioMovieRefNum, &audioMovieResId, NULL, newMovieActive, NULL);

    err = CloseMovieFile(audioMovieRefNum);

    SetMovieTimeScale(audioMovie, 30.*100);

    audioCopyTrack = GetMovieTrack(audioMovie, 1);

    audioCopyMedia = GetTrackMedia(audioCopyTrack);

    long duration = GetMovieDuration(audioMovie);

    err = AddEmptyTrackToMovie (audioCopyTrack, movie, nil, nil, &destTrack);

    err = InsertTrackSegment(audioCopyTrack, destTrack, 0, duration, 0);

	err = EndMediaEdits(destMedia);

}
Beispiel #7
0
static OSStatus setup_video(void)
{
    //Add video track
    videoTrack = NewMovieTrack(movie, video_width << 16, video_height << 16, 0);
    OSStatus theError = GetMoviesError();
    if (theError) {
        log_debug("quicktime_video: error creating movie track");
        return theError;
    }

    //Create video track media
    videoMedia = NewTrackMedia(videoTrack, VideoMediaType, timeScale, 0, 0);
    theError = GetMoviesError();
    if (theError) {
        log_debug("quicktime_video: error creating track media!");
        return theError;
    }

    //Prepare media for editing
    theError = BeginMediaEdits(videoMedia);
    if (theError) {
        log_debug("quicktime_video: error beginning media edits!");
        return theError;
    }

    // ----- Setup Codec -----
    CodecType codec = (CodecType)video_codec;

    // Create compression session
    ICMEncodedFrameOutputRecord record = {
        FrameOutputCallback, NULL, NULL
    };
    theError = ICMCompressionSessionCreate(kCFAllocatorDefault,
                                           video_width, video_height, codec, timeScale, NULL /*options*/, NULL,
                                           &record, &videoCompressionSession);
    if (theError) {
        log_debug("quicktime_video: error creating compression session!");
        return theError;
    }

    // ----- PixelBuffer -----
    theError = CVPixelBufferCreate(NULL, video_width, video_height,
                                   kCVPixelFormatType_24RGB, NULL, &pixelBuffer);
    if (theError) {
        log_debug("quicktime_video: error creating pixel buffer!");
        return theError;
    }
    CVPixelBufferRetain(pixelBuffer);

    video_ready = 1;
    return noErr;
}
void ofxQtVideoSaver::addAudioTrack(string audioPath)
{
	OSErr err;
	Handle dataRef = NULL;
	FSSpec    fileSpec;
	short audioMovieRefNum = 0;
	short audioMovieResId = 0;
	Movie audioMovie = NULL;
	Track audioCopyTrack = NULL;
	Media audioCopyMedia = NULL;
	Track destTrack = NULL;
	Media destMedia = NULL;

	destTrack = NewMovieTrack (movie, 0, 0, kFullVolume);
	destMedia = NewTrackMedia (destTrack, SoundMediaType,
							   (TimeScale) (30.f * 100), /* Video Time Scale */
							   nil, 0);

	err = BeginMediaEdits (destMedia);

	char * p = new char[audioPath.length()+1];
    strcpy(p, audioPath.c_str());
#ifdef TARGET_WIN32
    NativePathNameToFSSpec(p, &fileSpec, 0L);
#endif
#ifdef TARGET_OSX
	Boolean isdir;
	FSPathMakeRef((const UInt8*)p, &fsref, &isdir);
	FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL);
#endif

	err = OpenMovieFile(&fileSpec, &audioMovieRefNum, fsRdPerm);
	err = NewMovieFromFile(&audioMovie, audioMovieRefNum, &audioMovieResId, NULL, newMovieActive, NULL);
	err = CloseMovieFile(audioMovieRefNum);

	SetMovieTimeScale(audioMovie, (TimeScale) (30.*100));

	audioCopyTrack = GetMovieTrack(audioMovie, 1);
	audioCopyMedia = GetTrackMedia(audioCopyTrack);

	long duration = GetMovieDuration(audioMovie);

	err = AddEmptyTrackToMovie (audioCopyTrack, movie, 0, 0, &destTrack);
	err = InsertTrackSegment(audioCopyTrack, destTrack, 0, duration, 0);
	err = EndMediaEdits(destMedia);
}
void ofxQtAudioRecorder::prepareAudioRecording(int sampleRate, int numChannels_){
	
	OSErr err = noErr;
	
	// create audio description and set format ID along with format flags, mBitsPerChannel and mBytesPerPacket
	AudioStreamBasicDescription asbd;
	
	numChannels = numChannels_;
	
	asbd.mSampleRate           = sampleRate;
    asbd.mFormatID             = kAudioFormatLinearPCM;
    asbd.mFormatFlags          = kAudioFormatFlagsNativeFloatPacked;
    // if multi-channel, the data format must be interleaved (non-interleaved is not allowed), 
    // and you should set up the asbd accordingly
    asbd.mChannelsPerFrame     = numChannels; // 2 (Stereo)
    // mBitsPerChannel = number of bits of sample data for each channel in a frame of data
    asbd.mBitsPerChannel       = sizeof (Float32) * 8; // was 8 // 32-bit floating point PCM
    // mBytesPerFrame = number of bytes in a single sample frame of data
    // (bytes per channel) * (channels per frame) = 4 * 2 = 8
    asbd.mBytesPerFrame        = (asbd.mBitsPerChannel>>3) * asbd.mChannelsPerFrame; // // number of *bytes* per channel * channels per frame
    asbd.mFramesPerPacket      = 1; // For PCM, frames per packet is always 1
    // mBytesPerPacket = (bytes per frame) * (frames per packet) = 8 * 1 = 8
    asbd.mBytesPerPacket       = asbd.mBytesPerFrame * asbd.mFramesPerPacket;
	
	//printf("bits per channel %i\n", asbd.mBitsPerChannel);
	//printf("bytes per frame %i - %i %i\n", asbd.mBytesPerFrame, (asbd.mBitsPerChannel>>3), asbd.mChannelsPerFrame);
	//printf("bytes per packet %i\n", asbd.mBytesPerPacket);
	
	err = QTSoundDescriptionCreate(&asbd,
								   NULL, 0,
								   NULL, 0,
								   kQTSoundDescriptionKind_Movie_Version2,
								   &soundDesc);
	checkErr(0x0200);
	
	audioTrack = NewMovieTrack(movie, Long2Fix(0), Long2Fix(0), kFullVolume);
	err = GetMoviesError();
	checkErr(0x0201);
	
	audioMedia = NewTrackMedia(audioTrack, SoundMediaType, sampleRate, NULL, 0);
	err = GetMoviesError();
	checkErr(0x0202);
	
	return;	
}
OSErr QTTarg_CreateTwinSpritesMovie (void)
{
	Movie					myMovie = NULL;
	Track					myTrack = NULL;
	Media					myMedia = NULL;
	FSSpec					myFile;
	Boolean					myIsSelected = false;
	Boolean					myIsReplacing = false;	
	Fixed					myHeight = 0;
	Fixed					myWidth = 0;
	StringPtr 				myPrompt = QTUtils_ConvertCToPascalString(kSpriteSavePrompt);
	StringPtr 				myFileName = QTUtils_ConvertCToPascalString(kSpriteSaveMovieFileName);
	long					myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
	OSType					myType = FOUR_CHAR_CODE('none');
	short					myResRefNum = 0;
	short					myResID = movieInDataForkResID;
	OSErr					myErr = noErr;

	//////////
	//
	// create a new movie file
	//
	//////////

	// prompt the user for the destination file name
	QTFrame_PutFile(myPrompt, myFileName, &myFile, &myIsSelected, &myIsReplacing);
	myErr = myIsSelected ? noErr : userCanceledErr;
	if (!myIsSelected)
		goto bail;

	// create a movie file for the destination movie
	myErr = CreateMovieFile(&myFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, myFlags, &myResRefNum, &myMovie);
	if (myErr != noErr)
		goto bail;
	
	// select the "no-interface" movie controller
	myType = EndianU32_NtoB(myType);
	SetUserDataItem(GetMovieUserData(myMovie), &myType, sizeof(myType), kUserDataMovieControllerType, 1);
	
	//////////
	//
	// create the sprite track and media
	//
	//////////
	
	myWidth = Long2Fix(kIconSpriteTrackWidth);
	myHeight = Long2Fix(kIconSpriteTrackHeight);

	myTrack = NewMovieTrack(myMovie, myWidth, myHeight, kNoVolume);
	myMedia = NewTrackMedia(myTrack, SpriteMediaType, kSpriteMediaTimeScale, NULL, 0);

	myErr = BeginMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;

	//////////
	//
	// add the appropriate samples to the sprite media
	//
	//////////
	
	myErr = QTTarg_AddIconMovieSamplesToMedia(myMedia);
	if (myErr != noErr)
		goto bail;
	
	myErr = EndMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;
	
	// add the media to the track
	InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
		
	//////////
	//
	// set the sprite track properties
	//
	//////////
	
	QTTarg_SetTrackProperties(myMedia, 1);
	
	//////////
	//
	// add the movie resource to the movie file
	//
	//////////
	
	myErr = AddMovieResource(myMovie, myResRefNum, &myResID, myFile.name);
		
bail:
	if (myResRefNum != 0)
		CloseMovieFile(myResRefNum);

	if (myMovie != NULL)
		DisposeMovie(myMovie);
		
	free(myPrompt);
	free(myFileName);

	return(myErr);
}
Beispiel #11
0
void QTSound_CreateMySoundTrack (Movie theMovie)
{
    Track theTrack;
    Media theMedia;
    Handle sndHandle = nil;
    SoundDescriptionHandle sndDesc = nil;
    long sndDataOffset;
    long sndDataSize;
    long numSamples;
    OSErr err = noErr;
#if TARGET_OS_WIN32

    char path[MAX_PATH+1];
    short resID;
    FSSpec fsspec;


    fsspec.vRefNum = 0;
    fsspec.parID = 0;
    GetModuleFileName( NULL, path, MAX_PATH+1);

    NativePathNameToFSSpec((char *)&path, &fsspec, 0);

    /* open our application resource file so we
    	can access the Macintosh 'snd ' resource */
    resID = FSpOpenResFile(&fsspec, fsRdPerm);
    CheckError (ResError(), "FSpOpenResFile error" );

#endif



    sndHandle = GetResource ('snd ', kOurSoundResourceID);
    CheckError (ResError(), "GetResource error" );
    if (sndHandle == nil)
    {
        return;
    }

    sndDesc = (SoundDescriptionHandle) NewHandle(4);
    CheckError (MemError(), "NewHandle error" );

    QTSound_CreateSoundDescription (sndHandle,
                                    sndDesc,
                                    &sndDataOffset,
                                    &numSamples,
                                    &sndDataSize );

    theTrack = NewMovieTrack (theMovie, 0, 0, kFullVolume);
    CheckError (GetMoviesError(), "NewMovieTrack error" );

    theMedia = NewTrackMedia (theTrack, SoundMediaType,
                              FixRound ((**sndDesc).sampleRate),
                              nil, 0);
    CheckError (GetMoviesError(), "NewTrackMedia error" );

    err = BeginMediaEdits (theMedia);
    CheckError( err, "BeginMediaEdits error" );

    err = AddMediaSample(theMedia,
                         sndHandle,
                         sndDataOffset,/* offset in data */
                         sndDataSize,
                         kSoundSampleDuration,/* duration of each sound sample */
                         (SampleDescriptionHandle) sndDesc,
                         numSamples,
                         kSyncSample,/* self-contained samples */
                         nil);
    CheckError( err, "AddMediaSample error" );

    err = EndMediaEdits (theMedia);
    CheckError( err, "EndMediaEdits error" );

    err = InsertMediaIntoTrack (theTrack,
                                kTrackStart,/* track start time */
                                kMediaStart,/* media start time */
                                GetMediaDuration (theMedia),
                                fixed1);
    CheckError( err, "InsertMediaIntoTrack error" );

    if (sndDesc != nil)
    {
        DisposeHandle( (Handle)sndDesc);
    }
}
Beispiel #12
0
void MolDisplayWin::WriteQTMovie(wxString & filepath) {
	//Create a QuickTime movie using the standard animation codecs with normal quality, and 
	//temporal compression. The final file is flattened for cross platform compatability
	
	QTExport * QTOptions = new QTExport(this);
	//setup controls for the current data
	if (MainData->GetNumFrames() > 1) { //default to frame animation
		QTOptions->SetMovieChoice(0);
	} else {
		QTOptions->EnableFrameMovie(false);
	}
	if (MainData->cFrame->GetNumberNormalModes() <= 0) {
		QTOptions->EnableModeMovie(false);
	}
	
	if (QTOptions->ShowModal() != wxID_OK) {
		//user cancelled the operation
		QTOptions->Destroy();
		return;
	}
	//retrieve the value of each option
	int MovieType = QTOptions->GetMovieChoice();
	bool IncludeEPlot = QTOptions->AddEnergyPlot();
	int compressorChoice = QTOptions->GetCompressorChoice();
	int keyFrameRate = QTOptions->GetKeyFrameRate();
	if (keyFrameRate < 0) keyFrameRate = 0;
	
	QTOptions->Destroy();
	
	CodecType mCodec;
	switch (compressorChoice) {
		case 0:
			mCodec = kCinepakCodecType;
			break;
		case 1:
			mCodec = kGraphicsCodecType;
			break;
		case 2:
			mCodec = kAnimationCodecType;
			break;
		case 3:
		default:
			mCodec = kMPEG4VisualCodecType;
	}

	OSStatus s;
	OSErr myErr = myErr;
	FSSpec targetSpec;
	//ugh I need to get an FSSpec to hand to quicktime, but these calls only seem to work if
	//the file already exists...
	const char * t = filepath.mb_str(wxConvUTF8);
	FILE * temp = fopen(t, "wb");
	fclose(temp);

#ifdef __WXOSX_COCOA__
	//This function is not found in the wxCocoa implementation, it is probably possible to work around it
	//Otherwise the code appears to link and run currently. However, it is probably better to redue the
	//code to use the Cocoa qtKit framework rather than the old Carbon QT library.
	
	//This path is not tested as the current Cocoa code does not properly support the extended save dialog.
	//	void wxMacFilename2FSSpec( const wxString& path , FSSpec *spec )
	{
		OSStatus err = noErr;
		FSRef fsRef;
		wxMacPathToFSRef( filepath , &fsRef );
		err = FSGetCatalogInfo(&fsRef, kFSCatInfoNone, NULL, NULL, &targetSpec, NULL);
		verify_noerr( err );
	}
#else
	wxMacFilename2FSSpec(filepath, &targetSpec);
#endif
	
	Movie	theMovie = NULL;
		
	FSSpec tempSpec = targetSpec;
	strcpy((char *) &(tempSpec.name[1]), "MacMolPlt8933tempMovie");
	tempSpec.name[0] = 22;

	BeginOperation();
	ProgressInd->ChangeText("Creating movie...");
		
	myErr = EnterMovies();	//initialize the quicktime manager
	if (myErr != noErr) {
		FinishOperation();
		MessageAlert("Error initializing QuickTime!");
		return;
	}
		//Create the movie file and initialize file data
		//Use Quicktime creator code 'TVOD' instead of simpletext 'ttxt'
	short	resRefNum = 0;
	short	resId = 0;
	myErr = CreateMovieFile(&tempSpec, 'TVOD', smCurrentScript, createMovieFileDeleteCurFile,
							&resRefNum, &theMovie);
	if (myErr != noErr) {
		MessageAlert("Error creating movie file!");
	} else {
		bool KillEPlot = false;
		int width, height, savedEPlotWidth, savedEPlotHeight;
		glCanvas->GetClientSize(&width, &height);
		Rect lDisplayRect={0,0,0,0};
		lDisplayRect.right = width;
		lDisplayRect.bottom = height;
		Rect		gRect = lDisplayRect;

		Rect EPlotRect = lDisplayRect;
		//If we are including an energy plot add space for it here
		if (IncludeEPlot && (MovieType == 0)) {
			EPlotRect.left = EPlotRect.right;
			EPlotRect.right = EPlotRect.left + height;
			if (!energyPlotWindow) {
				energyPlotWindow = new EnergyPlotDialog(this);
				KillEPlot = true;
			} else {
				energyPlotWindow->GetSize(&savedEPlotWidth, &savedEPlotHeight);
			}
			gRect.right += height;
			width += height;
			energyPlotWindow->Show(false);
			energyPlotWindow->SetSize(height, height);
			energyPlotWindow->Update();	//This is needed to initialise the window if we just created it
		}

		LocalToGlobal ((Point *) &(gRect.top));
		LocalToGlobal ((Point *) &(gRect.bottom));
		WindowRef TempWindow;
		s = CreateNewWindow(kDocumentWindowClass, kWindowNoAttributes, &gRect, &TempWindow);
		if (s == noErr) {
													//Create the video track
			Track theTrack = NewMovieTrack (theMovie, FixRatio(width,1),
											FixRatio(height,1), kNoVolume);
			if ((noErr == GetMoviesError())&&theTrack) {
				Media theMedia = NewTrackMedia (theTrack, VideoMediaType,
												60, // Video Time Scale
												NULL, 0);
				if ((noErr == GetMoviesError())&&theMedia) {
					myErr = BeginMediaEdits (theMedia);
					if (myErr == noErr) {
						//create the actual movie frames
						GWorldPtr	lgWorld=NULL;
						
						if (! NewGWorld (&lgWorld, 0, &gRect, (CTabHandle) NULL, (GDHandle) NULL,
										 (GWorldFlags) (pixPurge + useTempMem))) {
							long MaxCompressedSize;
							ImageSequence seqID;
							ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(4);
							PixMapHandle myPixMap = GetPortPixMap(lgWorld);
							LockPixels (myPixMap);
							myErr = CompressSequenceBegin(&seqID, myPixMap, NULL, &gRect, &gRect, 0,
														  mCodec, bestCompressionCodec, codecNormalQuality, codecNormalQuality, keyFrameRate, NULL,
														  codecFlagUpdatePreviousComp, imageDesc);
							GetMaxCompressionSize (myPixMap, &gRect,
												   0, codecNormalQuality, mCodec, (CompressorComponent) anyCodec, &MaxCompressedSize);
							Handle Buffer = TempNewHandle(MaxCompressedSize, &myErr);
							if (!Buffer)
								Buffer = NewHandle(MaxCompressedSize);
							if (Buffer) {
								qtData myqtData = {theMedia, imageDesc, seqID, lDisplayRect, gRect};
								if (MovieType == 0) {
									CreateFrameMovie(lgWorld, Buffer, myqtData, IncludeEPlot);
								} else {
									CreateModeMovie(lgWorld, Buffer, myqtData);
								}
								DisposeHandle(Buffer);
							}
							myErr = CDSequenceEnd(seqID);
							if (lgWorld != NULL) DisposeGWorld (lgWorld);
							if (imageDesc) DisposeHandle((Handle) imageDesc);
						}
						
						myErr = EndMediaEdits (theMedia);
					}
					myErr = InsertMediaIntoTrack (theTrack, 0,/* track start time */
						0,        /* media start time */
						GetMediaDuration (theMedia),
						FixRatio(1,1));
				}
				myErr = AddMovieResource (theMovie, resRefNum, &resId, NULL);
			}
			if (resRefNum) {
						//Create the actual file as a flat data fork so it can be placed on the www
				ProgressInd->ChangeText("Flattening movieÉ");
				FlattenMovie(theMovie, flattenAddMovieToDataFork, &targetSpec, 'TVOD', smCurrentScript, 
							 createMovieFileDeleteCurFile, &resId, NULL);
				CloseMovieFile (resRefNum);
			}
			DisposeWindow(TempWindow);
		}
		DisposeMovie (theMovie);
		DeleteMovieFile (&tempSpec);	//delete the temp file after disposing of the movie

		if (energyPlotWindow) {
			if (KillEPlot) {
				delete energyPlotWindow;
				energyPlotWindow = NULL;
			} else {
				energyPlotWindow->SetSize(savedEPlotWidth, savedEPlotHeight);
				energyPlotWindow->FrameChanged();
				energyPlotWindow->Show(true);
			}
		}
	}
	ExitMovies();	//Close out quicktime as we are done with it for now
	FinishOperation();
}
OSErr QTDR_CreateMovieInRAM (void)
{
	Movie					myMovie = NULL;
	Track					myTrack = NULL;
	Media					myMedia = NULL;
	short					myResRefNum = 0;
	short					myResID = 0;
	Handle					myDataRef = NULL;
	Handle					myHandle = NULL;
	FSSpec					myFSSpec;
	OSErr					myErr = noErr;
	
	// create a new handle to hold the media data
	myHandle = NewHandleClear(0);
	if (myHandle == NULL)
		goto bail;
	
	// create a data reference to that handle
	myDataRef = QTDR_MakeHandleDataRef(myHandle);
	if (myDataRef == NULL)
		goto bail;
		
	myMovie = NewMovie(newMovieActive);
	if (myMovie == NULL)
		goto bail;
	
	myErr = SetMovieDefaultDataRef(myMovie, myDataRef, HandleDataHandlerSubType);
	if (myErr != noErr)
		goto bail;

	// create the movie track and media
	myTrack = NewMovieTrack(myMovie, FixRatio(kVideoTrackWidth, 1), FixRatio(kVideoTrackHeight, 1), kNoVolume);
	myErr = GetMoviesError();
	if (myErr != noErr)
		goto bail;
		
	myMedia = NewTrackMedia(myTrack, VideoMediaType, kVideoTimeScale, NULL, 0);
	myErr = GetMoviesError();
	if (myErr != noErr)
		goto bail;

	// create the media samples
	myErr = BeginMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;

	myErr = QTDR_AddVideoSamplesToMedia(myMedia, kVideoTrackWidth, kVideoTrackHeight);
	if (myErr != noErr)
		goto bail;

	myErr = EndMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;
	
	// add the media to the track
	myErr = InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
	if (myErr != noErr)
		goto bail;
	
	// add the movie atom to the movie file
	myErr = AddMovieResource(myMovie, myResRefNum, &myResID, NULL);

	myFSSpec.name[0] = (unsigned char)0;
	myFSSpec.parID = 0;
	myFSSpec.vRefNum = 0;
	
	QTFrame_OpenMovieInWindow(myMovie, &myFSSpec);

bail:
	if (myDataRef != NULL)
		DisposeHandle(myDataRef);
		
	return(myErr);
}
void ofQtVideoSaver::setup( int width , int height, string movieName){

	w = width;
	h = height;
    
   
    fileName = (ofToDataPath(movieName));
    //pszFlatFilename = flatFileName;
    
    initializeQuicktime();
    	/*  Load the FSSpec structure to describe the receiving file.  For a 
    description of this and related calls see 
    http://developer.apple.com/quicktime/icefloe/dispatch004.html.
    ================================================================  */


	#ifdef TARGET_WIN32
		//FILE * pFile = NULL;
		//pFile = fopen (fileName.c_str(),"w");
		//fclose (pFile);
		char fileNameStr[255];
		sprintf(fileNameStr, "%s", fileName.c_str());
		osErr = NativePathNameToFSSpec (fileNameStr, &fsSpec, 0);
		
	#endif
	#ifdef TARGET_OSX
	
		/// kill a file and make a new one if needed:		
		FILE * pFile;
		pFile = fopen (fileName.c_str(),"w");
		fclose (pFile);
	
		Boolean isdir;
		osErr = FSPathMakeRef((const UInt8*)fileName.c_str(), &fsref, &isdir);
		osErr = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fsSpec, NULL);
	#endif

    if (osErr && (osErr != fnfErr))    /* File-not-found error is ok         */
      { 
      printf ("getting FSS spec failed %d\n", osErr); 
      goto bail; 
     }
	 

	/*  Step 1:  Create a new, empty movie file and a movie that references that 
    file (CreateMovieFile).  
    ======================================================================== */
            
    osErr = CreateMovieFile 
      (
      &fsSpec,                         /* FSSpec specifier                   */
      FOUR_CHAR_CODE('TVOD'),          /* file creator type, TVOD = QT player*/
      smCurrentScript,                 /* movie script system to use         */
      createMovieFileDeleteCurFile     /* movie file creation flags          */
        | createMovieFileDontCreateResFile,
      &sResRefNum,                     /* returned file ref num to data fork */
      &movie                           /* returned handle to open empty movie*/
                                       /*   that references the created file */
      );
    if (osErr) 
      { 
      printf ("CreateMovieFile failed %d\n", osErr); 
      goto bail; 
      }


	/*  Step 2:  Add a new track to that movie (NewMovieTrack).
    =======================================================  */

    track = NewMovieTrack 
      (
      movie,                           /* the movie to add track to          */
      ((long) w << 16),              /* width of track in pixels (Fixed)   */
      FixRatio (h, 1),               /* height of track in pixels (Fixed)  */ 
      kNoVolume                        /* default volume level               */
      );
    osErr = GetMoviesError ();
    if (osErr) 
      { 
      printf ("NewMovieTrack failed %d\n", osErr); 
      goto bail; 
      }
    

	/*  Step 3:  Add a new media to that track (NewTrackMedia).
    =======================================================  */
    
    media = NewTrackMedia 
      (
      track,                           /* the track to add the media to      */
      VideoMediaType,                  /* media type, e.g. SoundMediaType    */
      600,                             /* num media time units that elapse/sec*/
      NULL,                            /* ptr to file that holds media sampls*/
      0                                /* type of ptr to media samples       */
      );
    osErr = GetMoviesError ();
    if (osErr) 
      { 
      printf ("NewTrackMedia failed %d\n", osErr); 
      goto bail; 
      }

	/*  Step 4:  Add media samples to the media. 
    ========================================  */
    
    BeginMediaEdits (media);           /* Inform the Movie Toolbox that we   */
                                       /*   want to change the media samples */
                                       /*   referenced by a track's media.   */
                                       /*   This opens the media container   */
                                       /*   and makes it ready to receive    */
                                       /*   and/or remove sample data.       */
    
    
    

    // Step 5: setup graphics port for qt movie and compression type ---
    
    /*  Create a new offscreen graphics world that will hold the movie's
    drawing surface.  draw_image() copies the image of IceFlow to this
    surface with varying amounts of transparency.
    =================================================================  */
    
    MacSetRect (&rect, 0, 0, w, h);

    osErr = NewGWorld 
      (
      &pMovieGWorld,                   /* receives the new GWorld.           */
      24,                              /* pixel depth in bits/pixel          */
      &rect,                           /* desired size of the GWorld.        */
      NULL, 
      NULL, 
      (GWorldFlags) 0
      );
    if (osErr != noErr) 
      { 
      printf ("NewGWorld 1 failed %d\n", osErr); 
      goto bail; 
      }


/*  Retrieve the pixel map associated with that graphics world and lock 
    the pixel map in memory.  GetMaxCompressionSize() and CompressImage()
    only operate on pixel maps, not graphics worlds.
    =====================================================================  */
    
    pixMapHandle = GetGWorldPixMap (pMovieGWorld);
    if (pixMapHandle == NULL) 
      { 
      printf ("GetGWorldPixMap failed\n"); 
      goto bail; 
      }
    LockPixels (pixMapHandle);


/*  Get the maximum number of bytes required to hold an image having the 
    specified characteristics compressed using the specified compressor.
    ====================================================================  */

     
    osErr = GetMaxCompressionSize 
      (
      pixMapHandle,							/* the pixel map to compress from.    */
      &rect,								/* the image rectangle.               */
      0,									/* let ICM choose image bit depth.    */
      codecHighQuality,						/* compression quality specifier.     */
      kRawCodecType,						/* desired compression type           */   // < set to RAW in case we set to a new compression type...
      (CompressorComponent) anyCodec,		/* codec specifier.                   */
      &lMaxCompressionSize					/* receives max bytes needed for cmp. */
      );
    if (osErr != noErr) 
      { 
      printf ("GetMaxCompressionSize failed %d\n", osErr); 
      goto bail; 
      }


/*  Allocate a buffer to hold the compressed image data by creating a new
    handle.
    =====================================================================  */
    hCompressedData = NewHandle (lMaxCompressionSize);
    if (hCompressedData == NULL) 
      { 
      printf ("NewHandle(%ld) failed\n", lMaxCompressionSize); 
      goto bail; 
      }

/*  Lock the handle and then dereference it to obtain a pointer to the data 
    buffer because CompressImage() wants us to pass it a pointer, not a 
    handle. 
    =======================================================================  */

    HLockHi (hCompressedData);
    pCompressedData = *hCompressedData;

/*  Create an image description object in memory of minimum size to pass 
    to CompressImage().  CompressImage() will resize the memory as 
    necessary so create it small here.
    ====================================================================  */
    
    hImageDescription = (ImageDescriptionHandle) NewHandle (4);
    if (hImageDescription == NULL) 
      { 
      printf ("NewHandle(4) failed\n"); 
      goto bail; 
      }
	
	
	
	bSetupForRecordingMovie = true;
    return;
    
    
    
    
  bail:    
	printf("got to bail somehows \n");
    if (sResRefNum != 0) CloseMovieFile (sResRefNum);
    if (movie     != NULL) DisposeMovie (movie);

    //ExitMovies ();                     /* Finalize Quicktime                 */
    
    return;
}
OSErr QTWired_CreateWiredSpritesMovie (void)
{
	short					myResRefNum = 0;
	short					myResID = movieInDataForkResID;
	Movie					myMovie = NULL;
	Track					myTrack;
	Media					myMedia;
	FSSpec					myFile;
	Boolean					myIsSelected = false;
	Boolean					myIsReplacing = false;	
	StringPtr 				myPrompt = QTUtils_ConvertCToPascalString(kWiredSavePrompt);
	StringPtr 				myFileName = QTUtils_ConvertCToPascalString(kWiredSaveFileName);
	QTAtomContainer			mySample = NULL;
	QTAtomContainer			myActions = NULL;
	QTAtomContainer			myBeginButton, myPrevButton, myNextButton, myEndButton;
	QTAtomContainer			myPenguinOne, myPenguinTwo, myPenguinOneOverride;
	QTAtomContainer			myBeginActionButton, myPrevActionButton, myNextActionButton, myEndActionButton;
	QTAtomContainer			myPenguinOneAction, myPenguinTwoAction;
	RGBColor				myKeyColor;
	Point					myLocation;
	short					isVisible, myLayer, myIndex, myID, i, myDelta;
	Boolean					hasActions;
	long					myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
	OSType					myType = FOUR_CHAR_CODE('none');
	UInt32					myFrequency;
	QTAtom					myEventAtom;
	long					myLoopingFlags;
	ModifierTrackGraphicsModeRecord		myGraphicsMode;
	OSErr					myErr = noErr;

	//////////
	//
	// create a new movie file and set its controller type
	//
	//////////

	// ask the user for the name of the new movie file
	QTFrame_PutFile(myPrompt, myFileName, &myFile, &myIsSelected, &myIsReplacing);
	if (!myIsSelected)
		goto bail;

	// create a movie file for the destination movie
	myErr = CreateMovieFile(&myFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, myFlags, &myResRefNum, &myMovie);
	if (myErr != noErr)
		goto bail;
	
	// select the "no controller" movie controller
	myType = EndianU32_NtoB(myType);
	SetUserDataItem(GetMovieUserData(myMovie), &myType, sizeof(myType), kUserDataMovieControllerType, 1);
	
	//////////
	//
	// create the sprite track and media
	//
	//////////
	
	myTrack = NewMovieTrack(myMovie, ((long)kSpriteTrackWidth << 16), ((long)kSpriteTrackHeight << 16), kNoVolume);
	myMedia = NewTrackMedia(myTrack, SpriteMediaType, kSpriteMediaTimeScale, NULL, 0);

	//////////
	//
	// create a key frame sample containing six sprites and all of their shared images
	//
	//////////

	// create a new, empty key frame sample
	myErr = QTNewAtomContainer(&mySample);
	if (myErr != noErr)
		goto bail;

	myKeyColor.red = 0xffff;						// white
	myKeyColor.green = 0xffff;
	myKeyColor.blue = 0xffff;

	// add images to the key frame sample
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kGoToBeginningButtonUp, &myKeyColor, kGoToBeginningButtonUpIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kGoToBeginningButtonDown, &myKeyColor, kGoToBeginningButtonDownIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kGoToEndButtonUp, &myKeyColor, kGoToEndButtonUpIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kGoToEndButtonDown, &myKeyColor, kGoToEndButtonDownIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kGoToPrevButtonUp, &myKeyColor, kGoToPrevButtonUpIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kGoToPrevButtonDown, &myKeyColor, kGoToPrevButtonDownIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kGoToNextButtonUp, &myKeyColor, kGoToNextButtonUpIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kGoToNextButtonDown, &myKeyColor, kGoToNextButtonDownIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kPenguinForward, &myKeyColor, kPenguinForwardIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kPenguinLeft, &myKeyColor, kPenguinLeftIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kPenguinRight, &myKeyColor, kPenguinRightIndex, NULL, NULL);
	SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kPenguinClosed, &myKeyColor, kPenguinClosedIndex, NULL, NULL);

	for (myIndex = kPenguinDownRightCycleStartIndex, myID = kWalkDownRightCycleStart; myIndex <= kPenguinDownRightCycleEndIndex; myIndex++, myID++)
		SpriteUtils_AddPICTImageToKeyFrameSample(mySample, myID, &myKeyColor, myIndex, NULL, NULL);
	
	// assign group IDs to the images
	SpriteUtils_AssignImageGroupIDsToKeyFrame(mySample);
	
	//////////
	//
	// add samples to the sprite track's media
	//
	//////////
	
	BeginMediaEdits(myMedia);

	// go to beginning button with no actions
	myErr = QTNewAtomContainer(&myBeginButton);
	if (myErr != noErr)
		goto bail;
	myLocation.h	= (1 * kSpriteTrackWidth / 8) - (kStartEndButtonWidth / 2);
	myLocation.v	= (4 * kSpriteTrackHeight / 5) - (kStartEndButtonHeight / 2);
	isVisible		= false;
	myLayer			= 1;
	myIndex			= kGoToBeginningButtonUpIndex;
	myErr = SpriteUtils_SetSpriteData(myBeginButton, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, myActions);
	if (myErr != noErr)
		goto bail;

	// go to previous button with no actions
	myErr = QTNewAtomContainer(&myPrevButton);
	if (myErr != noErr)
		goto bail;
	myLocation.h 	= (3 * kSpriteTrackWidth / 8) - (kNextPrevButtonWidth / 2);
	myLocation.v	= (4 * kSpriteTrackHeight / 5) - (kStartEndButtonHeight / 2);
	isVisible		= false;
	myLayer			= 1;
	myIndex			= kGoToPrevButtonUpIndex;
	myErr = SpriteUtils_SetSpriteData(myPrevButton, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, myActions);
	if (myErr != noErr)
		goto bail;

	// go to next button with no actions
	myErr = QTNewAtomContainer(&myNextButton);
	if (myErr != noErr)
		goto bail;
	myLocation.h 	= (5 * kSpriteTrackWidth / 8) - (kNextPrevButtonWidth / 2);
	myLocation.v	= (4 * kSpriteTrackHeight / 5) - (kStartEndButtonHeight / 2);
	isVisible		= false;
	myLayer			= 1;
	myIndex			= kGoToNextButtonUpIndex;
	myErr = SpriteUtils_SetSpriteData(myNextButton, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, myActions);
	if (myErr != noErr)
		goto bail;

	// go to end button with no actions
	myErr = QTNewAtomContainer(&myEndButton);
	if (myErr != noErr)
		goto bail;
	myLocation.h 	= (7 * kSpriteTrackWidth / 8) - (kStartEndButtonWidth / 2);
	myLocation.v	= (4 * kSpriteTrackHeight / 5) - (kStartEndButtonHeight / 2);
	isVisible		= false;
	myLayer			= 1;
	myIndex			= kGoToEndButtonUpIndex;
	myErr = SpriteUtils_SetSpriteData(myEndButton, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, myActions);
	if (myErr != noErr)
		goto bail;

	// first penguin sprite with no actions
	myErr = QTNewAtomContainer(&myPenguinOne);
	if (myErr != noErr)
		goto bail;
	myLocation.h 	= (3 * kSpriteTrackWidth / 8) - (kPenguinWidth / 2);
	myLocation.v 	= (kSpriteTrackHeight / 4) - (kPenguinHeight / 2);
	isVisible		= true;
	myLayer			= 2;
	myIndex			= kPenguinDownRightCycleStartIndex;
	myGraphicsMode.graphicsMode = blend;
	myGraphicsMode.opColor.red = myGraphicsMode.opColor.green = myGraphicsMode.opColor.blue = 0x8FFF;	// grey
	myErr = SpriteUtils_SetSpriteData(myPenguinOne, &myLocation, &isVisible, &myLayer, &myIndex, &myGraphicsMode, NULL, myActions);
	if (myErr != noErr)
		goto bail;
		
	// second penguin sprite with no actions
	myErr = QTNewAtomContainer(&myPenguinTwo);
	if (myErr != noErr)
		goto bail;
	myLocation.h 	= (5 * kSpriteTrackWidth / 8) - (kPenguinWidth / 2);
	myLocation.v 	= (kSpriteTrackHeight / 4) - (kPenguinHeight / 2);
	isVisible		= true;
	myLayer			= 3;
	myIndex			= kPenguinForwardIndex;
	myErr = SpriteUtils_SetSpriteData(myPenguinTwo, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, myActions);
	if (myErr != noErr)
		goto bail;

	//////////
	//
	// add actions to the six sprites
	//
	//////////

	// add go to beginning button
	myErr = QTCopyAtom(myBeginButton, kParentAtomIsContainer, &myBeginActionButton);
	if (myErr != noErr)
		goto bail;

	WiredUtils_AddSpriteSetImageIndexAction(myBeginActionButton, kParentAtomIsContainer, kQTEventMouseClick, 0, NULL, 0, 0, NULL, kGoToBeginningButtonDownIndex, NULL);
	WiredUtils_AddSpriteSetImageIndexAction(myBeginActionButton, kParentAtomIsContainer, kQTEventMouseClickEnd, 0, NULL, 0, 0, NULL, kGoToBeginningButtonUpIndex, NULL);
	WiredUtils_AddMovieGoToBeginningAction(myBeginActionButton, kParentAtomIsContainer, kQTEventMouseClickEndTriggerButton);
	WiredUtils_AddSpriteSetVisibleAction(myBeginActionButton, kParentAtomIsContainer, kQTEventMouseEnter, 0, NULL, 0, 0, NULL, true, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myBeginActionButton, kParentAtomIsContainer, kQTEventMouseExit, 0, NULL, 0, 0, NULL, false, NULL);
	SpriteUtils_AddSpriteToSample(mySample, myBeginActionButton, kGoToBeginningSpriteID);	
	QTDisposeAtomContainer(myBeginActionButton);

	// add go to prev button
	myErr = QTCopyAtom(myPrevButton, kParentAtomIsContainer, &myPrevActionButton);
	if (myErr != noErr)
		goto bail;

	WiredUtils_AddSpriteSetImageIndexAction(myPrevActionButton, kParentAtomIsContainer, kQTEventMouseClick, 0, NULL, 0, 0, NULL, kGoToPrevButtonDownIndex, NULL);
	WiredUtils_AddSpriteSetImageIndexAction(myPrevActionButton, kParentAtomIsContainer, kQTEventMouseClickEnd, 0, NULL, 0, 0, NULL, kGoToPrevButtonUpIndex, NULL);
	WiredUtils_AddMovieStepBackwardAction(myPrevActionButton, kParentAtomIsContainer, kQTEventMouseClickEndTriggerButton);
	WiredUtils_AddSpriteSetVisibleAction(myPrevActionButton, kParentAtomIsContainer, kQTEventMouseEnter, 0, NULL, 0, 0, NULL, true, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myPrevActionButton, kParentAtomIsContainer, kQTEventMouseExit, 0, NULL, 0, 0, NULL, false, NULL);
	SpriteUtils_AddSpriteToSample(mySample, myPrevActionButton, kGoToPrevSpriteID);
	QTDisposeAtomContainer(myPrevActionButton);

	// add go to next button
	myErr = QTCopyAtom(myNextButton, kParentAtomIsContainer, &myNextActionButton);
	if (myErr != noErr)
		goto bail;

	WiredUtils_AddSpriteSetImageIndexAction(myNextActionButton, kParentAtomIsContainer, kQTEventMouseClick, 0, NULL, 0, 0, NULL, kGoToNextButtonDownIndex, NULL);
	WiredUtils_AddSpriteSetImageIndexAction(myNextActionButton, kParentAtomIsContainer, kQTEventMouseClickEnd, 0, NULL, 0, 0, NULL, kGoToNextButtonUpIndex, NULL);
	WiredUtils_AddMovieStepForwardAction(myNextActionButton, kParentAtomIsContainer, kQTEventMouseClickEndTriggerButton);
	WiredUtils_AddSpriteSetVisibleAction(myNextActionButton, kParentAtomIsContainer, kQTEventMouseEnter, 0, NULL, 0, 0, NULL, true, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myNextActionButton, kParentAtomIsContainer, kQTEventMouseExit, 0, NULL, 0, 0, NULL, false, NULL);
	SpriteUtils_AddSpriteToSample(mySample, myNextActionButton, kGoToNextSpriteID);
	QTDisposeAtomContainer(myNextActionButton);

	// add go to end button
	myErr = QTCopyAtom(myEndButton, kParentAtomIsContainer, &myEndActionButton);
	if (myErr != noErr)
		goto bail;

	WiredUtils_AddSpriteSetImageIndexAction(myEndActionButton, kParentAtomIsContainer, kQTEventMouseClick, 0, NULL, 0, 0, NULL, kGoToEndButtonDownIndex, NULL);
	WiredUtils_AddSpriteSetImageIndexAction(myEndActionButton, kParentAtomIsContainer, kQTEventMouseClickEnd, 0, NULL, 0, 0, NULL, kGoToEndButtonUpIndex, NULL);
	WiredUtils_AddMovieGoToEndAction(myEndActionButton, kParentAtomIsContainer, kQTEventMouseClickEndTriggerButton);
	WiredUtils_AddSpriteSetVisibleAction(myEndActionButton, kParentAtomIsContainer, kQTEventMouseEnter, 0, NULL, 0, 0, NULL, true, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myEndActionButton, kParentAtomIsContainer, kQTEventMouseExit, 0, NULL, 0, 0, NULL, false, NULL);
	SpriteUtils_AddSpriteToSample(mySample, myEndActionButton, kGoToEndSpriteID);
	QTDisposeAtomContainer(myEndActionButton);

	// add penguin one
	myErr = QTCopyAtom(myPenguinOne, kParentAtomIsContainer, &myPenguinOneAction);
	if (myErr != noErr)
		goto bail;

	// show the buttons on mouse enter and hide them on mouse exit
	WiredUtils_AddSpriteSetVisibleAction(myPenguinOneAction, kParentAtomIsContainer, kQTEventMouseEnter, 0, NULL, 0, kTargetSpriteID, (void *)kGoToBeginningSpriteID, true, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myPenguinOneAction, kParentAtomIsContainer, kQTEventMouseExit, 0, NULL, 0, kTargetSpriteID, (void *)kGoToBeginningSpriteID, false, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myPenguinOneAction, kParentAtomIsContainer, kQTEventMouseEnter, 0, NULL, 0, kTargetSpriteID, (void *)kGoToPrevSpriteID, true, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myPenguinOneAction, kParentAtomIsContainer, kQTEventMouseExit, 0, NULL, 0, kTargetSpriteID, (void *)kGoToPrevSpriteID, false, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myPenguinOneAction, kParentAtomIsContainer, kQTEventMouseEnter, 0, NULL, 0, kTargetSpriteID, (void *)kGoToNextSpriteID, true, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myPenguinOneAction, kParentAtomIsContainer, kQTEventMouseExit, 0, NULL, 0, kTargetSpriteID, (void *)kGoToNextSpriteID, false, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myPenguinOneAction, kParentAtomIsContainer, kQTEventMouseEnter, 0, NULL, 0, kTargetSpriteID, (void *)kGoToEndSpriteID, true, NULL);
	WiredUtils_AddSpriteSetVisibleAction(myPenguinOneAction, kParentAtomIsContainer, kQTEventMouseExit, 0, NULL, 0, kTargetSpriteID, (void *)kGoToEndSpriteID, false, NULL);
	SpriteUtils_AddSpriteToSample(mySample, myPenguinOneAction, kPenguinOneSpriteID);
	QTWired_AddCursorChangeOnMouseOver(mySample, kPenguinOneSpriteID);
	QTDisposeAtomContainer(myPenguinOneAction);

	// add penguin two
	myErr = QTCopyAtom(myPenguinTwo, kParentAtomIsContainer, &myPenguinTwoAction);
	if (myErr != noErr)
		goto bail;

	// blink when clicked on
	WiredUtils_AddSpriteSetImageIndexAction(myPenguinTwoAction, kParentAtomIsContainer, kQTEventMouseClick, 0, NULL, 0, 0, NULL, kPenguinClosedIndex, NULL);
	WiredUtils_AddSpriteSetImageIndexAction(myPenguinTwoAction, kParentAtomIsContainer, kQTEventMouseClickEnd, 0, NULL, 0, 0, NULL, kPenguinForwardIndex, NULL);

	WiredUtils_AddQTEventAtom(myPenguinTwoAction, kParentAtomIsContainer, kQTEventMouseClickEndTriggerButton, &myEventAtom);

	// toggle the movie rate and both of the birds' graphics modes
	QTWired_AddPenguinTwoConditionalActions(myPenguinTwoAction, myEventAtom);

	QTWired_AddWraparoundMatrixOnIdle(myPenguinTwoAction);

	SpriteUtils_AddSpriteToSample(mySample, myPenguinTwoAction, kPenguinTwoSpriteID);
	QTDisposeAtomContainer(myPenguinTwoAction);
	
	// add an action for when the key frame is loaded, to set the movie's looping mode to palindrome;
	// note that this will actually be triggered every time the key frame is reloaded,
	// so if the operation was expensive we could use a conditional to test if we've already done it
	myLoopingFlags = loopTimeBase | palindromeLoopTimeBase;
	WiredUtils_AddMovieSetLoopingFlagsAction(mySample, kParentAtomIsContainer, kQTEventFrameLoaded, myLoopingFlags);

	// add the key frame sample to the sprite track media
	//
	// to add the sample data in a compressed form, you would use a QuickTime DataCodec to perform the
	// compression; replace the call to the utility AddSpriteSampleToMedia with a call to the utility
	// AddCompressedSpriteSampleToMedia to do this
	
	SpriteUtils_AddSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, true, NULL);	
	//SpriteUtils_AddCompressedSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, true, zlibDataCompressorSubType, NULL);

	//////////
	//
	// add a few override samples to move penguin one and change its image index
	//
	//////////

	// original penguin one location
	myLocation.h 	= (3 * kSpriteTrackWidth / 8) - (kPenguinWidth / 2);
	myLocation.v 	= (kSpriteTrackHeight / 4) - (kPenguinHeight / 2);

	myDelta = (kSpriteTrackHeight / 2) / kNumOverrideSamples;
	myIndex = kPenguinDownRightCycleStartIndex;
	
	for (i = 1; i <= kNumOverrideSamples; i++) {
		QTRemoveChildren(mySample, kParentAtomIsContainer);
		QTNewAtomContainer(&myPenguinOneOverride);

		myLocation.h += myDelta;
		myLocation.v += myDelta;
		myIndex++;
		if (myIndex > kPenguinDownRightCycleEndIndex)
			myIndex = kPenguinDownRightCycleStartIndex;
			
		SpriteUtils_SetSpriteData(myPenguinOneOverride, &myLocation, NULL, NULL, &myIndex, NULL, NULL, NULL);
		SpriteUtils_AddSpriteToSample(mySample, myPenguinOneOverride, kPenguinOneSpriteID);
		SpriteUtils_AddSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, false, NULL);	
		QTDisposeAtomContainer(myPenguinOneOverride);
	}

	EndMediaEdits(myMedia);
	
	// add the media to the track
	InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
	
	//////////
	//
	// set the sprite track properties
	//
	//////////
	{
		QTAtomContainer		myTrackProperties;
		RGBColor			myBackgroundColor;
		
		// add a background color to the sprite track
		myBackgroundColor.red = EndianU16_NtoB(0x8000);
		myBackgroundColor.green = EndianU16_NtoB(0);
		myBackgroundColor.blue = EndianU16_NtoB(0xffff);
		
		QTNewAtomContainer(&myTrackProperties);
		QTInsertChild(myTrackProperties, 0, kSpriteTrackPropertyBackgroundColor, 1, 1, sizeof(RGBColor), &myBackgroundColor, NULL);

		// tell the movie controller that this sprite track has actions, Jackson
		hasActions = true;
		QTInsertChild(myTrackProperties, 0, kSpriteTrackPropertyHasActions, 1, 1, sizeof(hasActions), &hasActions, NULL);
	
		// tell the sprite track to generate QTIdleEvents
		myFrequency = EndianU32_NtoB(2);
		QTInsertChild(myTrackProperties, 0, kSpriteTrackPropertyQTIdleEventsFrequency, 1, 1, sizeof(myFrequency), &myFrequency, NULL);
		myErr = SetMediaPropertyAtom(myMedia, myTrackProperties);
		if (myErr != noErr)
			goto bail;

		QTDisposeAtomContainer(myTrackProperties);
	}
	
	//////////
	//
	// finish up
	//
	//////////
	
	// add the movie resource to the movie file
	myErr = AddMovieResource(myMovie, myResRefNum, &myResID, myFile.name);
	
bail:
	free(myPrompt);
	free(myFileName);

	if (mySample != NULL)
		QTDisposeAtomContainer(mySample);

	if (myBeginButton != NULL)
		QTDisposeAtomContainer(myBeginButton);	
			
	if (myPrevButton != NULL)
		QTDisposeAtomContainer(myPrevButton);
				
	if (myNextButton != NULL)
		QTDisposeAtomContainer(myNextButton);
				
	if (myEndButton != NULL)
		QTDisposeAtomContainer(myEndButton);		
		
	if (myResRefNum != 0)
		CloseMovieFile(myResRefNum);

	if (myMovie != NULL)
		DisposeMovie(myMovie);
		
	return(myErr);
}
Beispiel #16
0
void TLevelWriter3gp::saveSoundTrack(TSoundTrack *st)
{
	Track theTrack;
	OSErr myErr = noErr;
	SoundDescriptionV1Handle mySampleDesc;
	Media myMedia;
	Handle myDestHandle;
	SoundComponentData sourceInfo;
	SoundComponentData destInfo;
	SoundConverter converter;
	CompressionInfo compressionInfo;
	int err;

	if (!st)
		throw TException("null reference to soundtrack");

	if (st->getBitPerSample() != 16) {
		throw TImageException(m_path, "Only 16 bits per sample is supported");
	}

	theTrack = NewMovieTrack(m_movie, 0, 0, kFullVolume);
	myErr = GetMoviesError();
	if (myErr != noErr)
		throw TImageException(m_path, "error creating audio track");

	FailIf(myErr != noErr, CompressErr);

	myDestHandle = NewHandle(0);

	FailWithAction(myDestHandle == NULL, myErr = MemError(), NoDest);

	*myDestHandle = (char *)st->getRawData();

	//////////
	//
	// create a media for the track passed in
	//
	//////////

	// set new track to be a sound track
	m_soundDataRef = nil;
	m_hSoundMovieData = NewHandle(0);

	// Construct the Handle data reference
	err = PtrToHand(&m_hSoundMovieData, &m_soundDataRef, sizeof(Handle));

	if ((err = GetMoviesError() != noErr))
		throw TImageException(getFilePath(), "can't create Data Ref");

	myMedia = NewTrackMedia(theTrack, SoundMediaType, st->getSampleRate(), m_soundDataRef, HandleDataHandlerSubType); //track->rate >> 16

	myErr = GetMoviesError();
	if (myErr != noErr)
		throw TImageException(m_path, "error setting audio track");
	FailIf(myErr != noErr, Exit);

	// start a media editing session
	myErr = BeginMediaEdits(myMedia);
	if (myErr != noErr)
		throw TImageException(m_path, "error beginning edit audio track");

	FailIf(myErr != noErr, Exit);

	sourceInfo.flags = 0x0;
	sourceInfo.format = kSoundNotCompressed;
	sourceInfo.numChannels = st->getChannelCount();
	sourceInfo.sampleSize = st->getBitPerSample();
	sourceInfo.sampleRate = st->getSampleRate();
	sourceInfo.sampleCount = st->getSampleCount();
	sourceInfo.buffer = (unsigned char *)st->getRawData();
	sourceInfo.reserved = 0x0;

	destInfo.flags = kNoSampleRateConversion | kNoSampleSizeConversion |
					 kNoSampleFormatConversion | kNoChannelConversion |
					 kNoDecompression | kNoVolumeConversion |
					 kNoRealtimeProcessing;

	destInfo.format = k16BitNativeEndianFormat;

	destInfo.numChannels = st->getChannelCount();
	destInfo.sampleSize = st->getBitPerSample();
	destInfo.sampleRate = st->getSampleRate();
	destInfo.sampleCount = st->getSampleCount();
	destInfo.buffer = (unsigned char *)st->getRawData();
	destInfo.reserved = 0x0;

	SoundConverterOpen(&sourceInfo, &destInfo, &converter);

	myErr = SoundConverterGetInfo(converter, siCompressionFactor, &compressionInfo);
	if (myErr != noErr)
		throw TImageException(m_path, "error getting audio converter info");

	myErr = GetCompressionInfo(fixedCompression, sourceInfo.format, sourceInfo.numChannels, sourceInfo.sampleSize, &compressionInfo);
	if (myErr != noErr)
		throw TImageException(m_path, "error getting audio compression info");
	FailIf(myErr != noErr, ConverterErr);

	compressionInfo.bytesPerFrame = compressionInfo.bytesPerPacket * destInfo.numChannels;

	//////////
	//
	// create a sound sample description
	//
	//////////

	// use the SoundDescription format 1 because it adds fields for data size information
	// and is required by AddSoundDescriptionExtension if an extension is required for the compression format

	mySampleDesc = (SoundDescriptionV1Handle)NewHandleClear(sizeof(SoundDescriptionV1));
	FailWithAction(myErr != noErr, myErr = MemError(), Exit);

	(**mySampleDesc).desc.descSize = sizeof(SoundDescriptionV1);
	(**mySampleDesc).desc.dataFormat = destInfo.format;
	(**mySampleDesc).desc.resvd1 = 0;
	(**mySampleDesc).desc.resvd2 = 0;
	(**mySampleDesc).desc.dataRefIndex = 1;
	(**mySampleDesc).desc.version = 1;
	(**mySampleDesc).desc.revlevel = 0;
	(**mySampleDesc).desc.vendor = 0;
	(**mySampleDesc).desc.numChannels = destInfo.numChannels;
	(**mySampleDesc).desc.sampleSize = destInfo.sampleSize;
	(**mySampleDesc).desc.compressionID = 0;
	(**mySampleDesc).desc.packetSize = 0;
	(**mySampleDesc).desc.sampleRate = st->getSampleRate() << 16;
	(**mySampleDesc).samplesPerPacket = compressionInfo.samplesPerPacket;
	(**mySampleDesc).bytesPerPacket = compressionInfo.bytesPerPacket;
	(**mySampleDesc).bytesPerFrame = compressionInfo.bytesPerFrame;
	(**mySampleDesc).bytesPerSample = compressionInfo.bytesPerSample;

	//////////
	//
	// add samples to the media
	//
	//////////

	myErr = AddMediaSample(myMedia, myDestHandle,
						   0,
						   destInfo.sampleCount * compressionInfo.bytesPerFrame,
						   1,
						   (SampleDescriptionHandle)mySampleDesc,
						   destInfo.sampleCount * compressionInfo.samplesPerPacket,
						   0,
						   NULL);

	if (myErr != noErr)
		throw TImageException(m_path, "error adding audio samples");

	FailIf(myErr != noErr, MediaErr);

	myErr = EndMediaEdits(myMedia);
	if (myErr != noErr)
		throw TImageException(m_path, "error ending audio edit");

	FailIf(myErr != noErr, MediaErr);

	//////////
	//
	// insert the media into the track
	//
	//////////

	myErr = InsertMediaIntoTrack(theTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
	if (myErr != noErr)
		throw TImageException(m_path, "error inserting audio track");

	FailIf(myErr != noErr, MediaErr);
	goto Done;

ConverterErr:
NoDest:
CompressErr:
Exit:

Done:

MediaErr:
	if (mySampleDesc != NULL)
		DisposeHandle((Handle)mySampleDesc);

	if (converter)
		SoundConverterClose(converter);

	if (myErr != noErr)
		throw TImageException(m_path, "error saving audio track");
}
Beispiel #17
0
void TLevelWriter3gp::save(const TImageP &img, int frameIndex)
{
	if (m_cancelled)
		return;

	TRasterImageP image(img);
	int lx = image->getRaster()->getLx();
	int ly = image->getRaster()->getLy();
	//void *buffer = image->getRaster()->getRawData();
	int pixSize = image->getRaster()->getPixelSize();
	if (pixSize != 4)
		throw TImageException(getFilePath(), "Unsupported pixel type");

	QMutexLocker sl(&m_mutex);

	if (!m_properties)
		m_properties = new Tiio::MovWriterProperties();

	Tiio::MovWriterProperties *prop = (Tiio::MovWriterProperties *)(m_properties);

	//CodecType compression = StandardCompressionType;  prop->getCurrentCodec();
	//CodecQ quality = StandardQualityType;  prop->getCurrentQuality();

	if (!m_initDone) {
		//FSSpec fspec;
		Rect frame;
		long max_compressed_size;
		QDErr err;

		m_videoTrack = NewMovieTrack(m_movie, FixRatio((short)lx, 1), FixRatio((short)ly, 1), kNoVolume);

		if ((err = GetMoviesError() != noErr))
			throw TImageException(getFilePath(), "can't create video track");

		m_dataRef = nil;
		m_hMovieData = NewHandle(0);

		// Construct the Handle data reference
		err = PtrToHand(&m_hMovieData, &m_dataRef, sizeof(Handle));

		if ((err = GetMoviesError() != noErr))
			throw TImageException(getFilePath(), "can't create Data Ref");

		m_videoMedia = NewTrackMedia(m_videoTrack, VideoMediaType, (TINT32)m_frameRate, m_dataRef, HandleDataHandlerSubType);

		OpenADefaultComponent(MovieExportType, '3gpp', &m_myExporter);

		//  err = (short)MovieExportDoUserDialog(m_myExporter, m_movie, 0, 0, 0, &m_cancelled);

		//  if (m_cancelled)
		//	  throw TImageException(getFilePath(), "User abort of 3GP render");
		if ((err = GetMoviesError() != noErr))
			throw TImageException(getFilePath(), "can't create video media");
		if ((err = BeginMediaEdits(m_videoMedia)) != noErr)
			throw TImageException(getFilePath(), "can't begin edit video media");
		frame.left = 0;
		frame.top = 0;
		frame.right = lx;
		frame.bottom = ly;

#if 0
  if ((err = NewGWorld(&(m_gworld), pixSize * 8, &frame, 0, 0, 0))!=noErr)
#else /* Mac OSX 10.7 later */
		if ((err = QTNewGWorld(&(m_gworld), pixSize * 8, &frame, 0, 0, 0)) != noErr)
#endif
		throw TImageException(getFilePath(), "can't create movie buffer");
#ifdef WIN32
		LockPixels(m_gworld->portPixMap);
		if ((err = GetMaxCompressionSize(m_gworld->portPixMap, &frame, 0,
										 quality, compression, anyCodec,
										 &max_compressed_size)) != noErr)
			throw TImageException(getFilePath(), "can't get max compression size");

#else

#if 0
  PixMapHandle pixmapH = GetPortPixMap (m_gworld);
  LockPixels(pixmapH);
#else
		PixMapHandle pixmapH = NULL;
#endif
		max_compressed_size = lx * ly * 4 * 20;

/*if ((err = GetMaxCompressionSize(pixmapH, &frame, 0, 
                                quality,  compression,anyCodec, 
				 &max_compressed_size))!=noErr)
    throw TImageException(getFilePath(), "can't get max compression size");*/
#endif

		m_compressedData = NewHandle(max_compressed_size);

		if ((err = MemError()) != noErr)
			throw TImageException(getFilePath(), "can't allocate compressed data for movie");

		MoveHHi(m_compressedData);
		HLock(m_compressedData);
		if ((err = MemError()) != noErr)
			throw TImageException(getFilePath(), "can't allocate img handle");

#if 0
  m_pixmap = GetGWorldPixMap(m_gworld);
  
  
  if (!LockPixels(m_pixmap))
    throw TImageException(getFilePath(), "can't lock pixels");

  buf    = (PixelXRGB*) GetPixBaseAddr(m_pixmap);
#else
		m_pixmap = NULL;
		buf = NULL;
#endif
		buf_lx = lx;
		buf_ly = ly;

		m_initDone = true;
	}

	unsigned short rowBytes = (unsigned short)(((short)(*(m_pixmap))->rowBytes & ~(3 << 14)));

	Rect frame;
	ImageDescriptionHandle img_descr;
	Ptr compressed_data_ptr;
	QDErr err;

	frame.left = 0;
	frame.top = 0;
	frame.right = lx;
	frame.bottom = ly;

	TRasterP ras = image->getRaster();
#ifdef WIN32
	compressed_data_ptr = StripAddress(*(m_compressedData));
	copy(ras, buf, buf_lx, buf_ly);
#else
	compressed_data_ptr = *m_compressedData;
	copy(ras, buf, buf_lx, buf_ly, rowBytes);
#endif
	img_descr = (ImageDescriptionHandle)NewHandle(4);

#ifdef WIN32
	if ((err = CompressImage(m_gworld->portPixMap,
							 &frame,
							 quality, compression,
							 img_descr, compressed_data_ptr)) != noErr)
		throw TImageException(getFilePath(), "can't compress image");
#else

#if 0
 PixMapHandle pixmapH = GetPortPixMap (m_gworld);
 if ((err = CompressImage(pixmapH, 
	                 &frame, 
  			 codecNormalQuality, kJPEGCodecType,
			 img_descr, compressed_data_ptr))!=noErr)
	{
  throw TImageException(getFilePath(), "can't compress image");
}
#endif
#endif

	if ((err = AddMediaSample(m_videoMedia, m_compressedData, 0,
							  (*img_descr)->dataSize, 1,
							  (SampleDescriptionHandle)img_descr,
							  1, 0, 0)) != noErr)
		throw TImageException(getFilePath(), "can't add image to movie media");

	DisposeHandle((Handle)img_descr);
}
Beispiel #18
0
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;
}
OSErr QTDR_CreateReferenceCopy (Movie theSrcMovie, FSSpecPtr theDstMovieFile, FSSpecPtr theDstMediaFile)
{
	Track			mySrcTrack = NULL;
	Media			mySrcMedia = NULL;
	Movie			myDstMovie = NULL;
	Track			myDstTrack = NULL;
	Media			myDstMedia = NULL;
	Handle			myMediaRef = NULL;			// data reference for the media file
#if !USE_ADDEMPTYTRACKTOMOVIE
	Fixed			myWidth, myHeight;
	OSType			myType;
#endif
	long			myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
	short			myResRefNum = 0;
	short			myResID = movieInDataForkResID;
	OSErr			myErr = paramErr;
					
	// get the first video track and media in the source movie
	mySrcTrack = GetMovieIndTrackType(theSrcMovie, 1, VideoMediaType, movieTrackMediaType);
	if (mySrcTrack == NULL)
		goto bail;
	
	mySrcMedia = GetTrackMedia(mySrcTrack);
	if (mySrcMedia == NULL)
		goto bail;

	// create a file data reference for the new media file
	myMediaRef = QTDR_MakeFileDataRef(theDstMediaFile);
    if (myMediaRef == NULL)
    	goto bail;

	// create a file for the destination movie data
	myErr = FSpCreate(theDstMediaFile, sigMoviePlayer, MovieFileType, 0);
	if (myErr != noErr)
		goto bail;
	
	// create a file for the destination movie atom and create an empty movie
	myErr = CreateMovieFile(theDstMovieFile, sigMoviePlayer, smCurrentScript, myFlags, &myResRefNum, &myDstMovie);
	if (myErr != noErr)
		goto bail;
		
	// assign the default progress proc to the destination movie
	SetMovieProgressProc(myDstMovie, (MovieProgressUPP)-1, 0);

#if USE_ADDEMPTYTRACKTOMOVIE
	myErr = AddEmptyTrackToMovie(mySrcTrack, myDstMovie, myMediaRef, rAliasType, &myDstTrack);
	if (myErr != noErr)
		goto bail;
	
	myDstMedia = GetTrackMedia(myDstTrack);
	myErr = GetMoviesError();
	if (myErr != noErr)
		goto bail;
#else
	// get some information about the source track and media
	GetTrackDimensions(mySrcTrack, &myWidth, &myHeight);
	GetMediaHandlerDescription(mySrcMedia, &myType, 0, 0);

	// create the destination movie track and media
	myDstTrack = NewMovieTrack(myDstMovie, myWidth, myHeight, kNoVolume);
	myErr = GetMoviesError();
	if (myErr != noErr)
		goto bail;
		
	myDstMedia = NewTrackMedia(myDstTrack, myType, GetMediaTimeScale(mySrcMedia), myMediaRef, rAliasType);
	myErr = GetMoviesError();
	if (myErr != noErr)
		goto bail;

	CopyTrackSettings(mySrcTrack, myDstTrack);
#endif

	// copy the entire source track into the destination track; this copies the track's media
	// samples into the destination media file
	myErr = BeginMediaEdits(myDstMedia);
	if (myErr != noErr)
		goto bail;

	myErr = InsertTrackSegment(mySrcTrack, myDstTrack, 0, GetTrackDuration(mySrcTrack), 0);
	if (myErr != noErr)
		goto bail;

	myErr = EndMediaEdits(myDstMedia);
	if (myErr != noErr)
		goto bail;
	
	// add the movie atom to the data fork of the movie file
	myErr = AddMovieResource(myDstMovie, myResRefNum, &myResID, NULL);

bail:
	return(myErr);
}
Beispiel #20
0
quicktime_recorder* quicktime_recorder::create( const char *path2, int width, 
                                                int height, float fps ) {
    OSErr err;
    OSType   dataRefType;
    Handle   dataRef = NULL;
    impl *m = new impl(width, height);

    std::string pathStd = path2;
    #ifdef WIN32
    for (std::string::iterator p = pathStd.begin(); p != pathStd.end(); ++p) if (*p == '/') *p = '\\';    
    #endif

    CFStringRef cfPath = CFStringCreateWithCString(NULL, pathStd.c_str(), kCFStringEncodingISOLatin1);
    err = QTNewDataReferenceFromFullPathCFString(cfPath, kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType);
    CFRelease(cfPath);
    if (err != noErr) {
        delete m; 
        return NULL;
    }

    err = CreateMovieStorage(dataRef, dataRefType, FOUR_CHAR_CODE('TVOD'), smSystemScript, 
        createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, &m->data_handler, &m->movie);
    DisposeHandle(dataRef);
    if (err != noErr) {
        delete m; 
        return NULL;
    }

    m->track = NewMovieTrack(m->movie, FixRatio(m->width, 1), FixRatio(m->height, 1), kNoVolume);
    err &= GetMoviesError();
    TimeScale timeScale = (TimeScale)(fps * 100.0f);
    m->media = NewTrackMedia(m->track, VideoMediaType, timeScale, nil, 0 );
    err &= GetMoviesError();
    if (err != noErr) {
        delete m; 
        return NULL;
    }
    SetMovieTimeScale(m->movie, timeScale);

    m->buffer = new unsigned char[4 * m->width * m->height];

    Rect rect;
    rect.left = rect.top = 0;
    rect.right = m->width;
    rect.bottom = m->height;

    err = QTNewGWorldFromPtr(&m->gworld, k32BGRAPixelFormat, &rect, NULL, NULL, 0, m->buffer, 4 * m->width);
    if (err != noErr) {
        delete m; 
        return NULL;
    }

    m->pixmap = GetGWorldPixMap(m->gworld);
    if (!m->pixmap) {
        delete m; 
        return NULL;
    }
    LockPixels(m->pixmap);

    long maxSize = 0;
    err = GetMaxCompressionSize(m->pixmap, &rect, 0, codecNormalQuality, kPNGCodecType, anyCodec, &maxSize); 
    if (err != noErr) {
        delete m; 
        return NULL;
    }

    m->handle = NewHandle(maxSize);
    if (!m->handle) {
        delete m; 
        return NULL;
    }

    HLockHi(m->handle);
    m->ptr = *m->handle;

    m->image_desc = (ImageDescriptionHandle)NewHandle(4);
    if (!m->image_desc) {
        delete m; 
        return NULL;
    }

    err = BeginMediaEdits( m->media );
    if (err != noErr) {
        delete m; 
        return NULL;
    }

    return new quicktime_recorder(m);
}
OSErr QTTarg_MakeDualVRControllerMovie (void)
{
	Movie					myMovie = NULL;
	Track					myTrack = NULL;
	Media					myMedia = NULL;
	RGBColor				myKeyColor;
	Fixed					myWidth, myHeight;
	FSSpec					myFile;
	Boolean					myIsSelected = false;
	Boolean					myIsReplacing = false;	
	StringPtr 				myPrompt = QTUtils_ConvertCToPascalString(kSpriteSavePrompt);
	StringPtr 				myFileName = QTUtils_ConvertCToPascalString(kSpriteSaveMovieFileName);
	long					myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
	short					myResRefNum = 0;
	short					myResID = movieInDataForkResID;
	OSType					myType = FOUR_CHAR_CODE('none');
	OSErr					myErr = noErr;

	//////////
	//
	// create a new movie file
	//
	//////////

	// prompt the user for the destination file name
	QTFrame_PutFile(myPrompt, myFileName, &myFile, &myIsSelected, &myIsReplacing);
	myErr = myIsSelected ? noErr : userCanceledErr;
	if (!myIsSelected)
		goto bail;

	// create a movie file for the destination movie
	myErr = CreateMovieFile(&myFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, myFlags, &myResRefNum, &myMovie);
	if (myErr != noErr)
		goto bail;
	
	// select the "no-interface" movie controller
	myType = EndianU32_NtoB(myType);
	SetUserDataItem(GetMovieUserData(myMovie), &myType, sizeof(myType), kUserDataMovieControllerType, 1);

	//////////
	//
	// get some information about the target movie
	//
	//////////

	myWidth = Long2Fix(kVRControlMovieWidth);
	myHeight = Long2Fix(kVRControlMovieHeight);
	
	//////////
	//
	// create a new sprite track in the target movie
	//
	//////////
	
	myTrack = NewMovieTrack(myMovie, myWidth, myHeight, kNoVolume);
	myMedia = NewTrackMedia(myTrack, SpriteMediaType, kVRControlMovieDuration, NULL, 0);

	myErr = BeginMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;
	
	//////////
	//
	// add sprite images and sprites to the sprite track; add actions to the sprites
	//
	//////////
	
	QTTarg_AddVRControllerButtonSamplesToMedia(myMedia, kVRControlMovieWidth, kVRControlMovieHeight, kVRControlMovieDuration);
	
	//////////
	//
	// insert media into track
	//
	//////////
	
	myErr = EndMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;
	
	// add the media to the track
	InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
		
	//////////
	//
	// set the sprite track properties
	//
	//////////
	
	QTTarg_SetTrackProperties(myMedia, 0);								// idle as fast as possible
	
	myKeyColor.red = myKeyColor.green = myKeyColor.blue = 0xffff;		// white
	MediaSetGraphicsMode(GetMediaHandler(myMedia), transparent, &myKeyColor);
	
	//////////
	//
	// add the movie resource to the movie file
	//
	//////////
	
	myErr = AddMovieResource(myMovie, myResRefNum, &myResID, myFile.name);
		
bail:
	if (myResRefNum != 0)
		CloseMovieFile(myResRefNum);

	if (myMovie != NULL)
		DisposeMovie(myMovie);
		
	free(myPrompt);
	free(myFileName);

	return(myErr);
}
OSErr QTTarg_AddTextToggleButtonTrack (Movie theMovie)
{
	Track					myTrack = NULL;
	Media					myMedia = NULL;
	MatrixRecord			myMatrix;
	RGBColor				myKeyColor;
	Fixed					myWidth, myHeight;
	TimeValue				myDuration = 0L;
	TimeValue				myTimeScale = 0L;
	OSErr					myErr = noErr;

	//////////
	//
	// get some information about the target movie
	//
	//////////

	if (theMovie == NULL) {
		myErr = paramErr;
		goto bail;
	}

	myWidth = Long2Fix(2 * kButtonWidth);
	myHeight = Long2Fix(2 * kButtonHeight);
	myDuration = GetMovieDuration(theMovie);
	myTimeScale = GetMovieTimeScale(theMovie);
	
	//////////
	//
	// create a new sprite track in the target movie
	//
	//////////
	
	myTrack = NewMovieTrack(theMovie, myWidth, myHeight, kNoVolume);
	myMedia = NewTrackMedia(myTrack, SpriteMediaType, myTimeScale, NULL, 0);

	// set the track matrix to compensate for any existing movie matrix
	GetMovieMatrix(theMovie, &myMatrix);
	if (InverseMatrix(&myMatrix, &myMatrix))
		SetTrackMatrix(myTrack, &myMatrix);

	myErr = BeginMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;
	
	//////////
	//
	// add sprite images and sprites to the sprite track; add actions to the sprites
	//
	//////////
	
	QTTarg_AddTextButtonSamplesToMedia(myMedia, 2 * kButtonWidth, 2 * kButtonHeight, myDuration);
	
	//////////
	//
	// insert media into track
	//
	//////////
	
	myErr = EndMediaEdits(myMedia);
	if (myErr != noErr)
		goto bail;
	
	// add the media to the track
	InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
		
	//////////
	//
	// set the sprite track properties
	//
	//////////
	
	QTTarg_SetTrackProperties(myMedia, kNoQTIdleEvents);				// no idle events
	
	myKeyColor.red = myKeyColor.green = myKeyColor.blue = 0xffff;		// white
	MediaSetGraphicsMode(GetMediaHandler(myMedia), transparent, &myKeyColor);
	
	// make sure that the sprite track is in the frontmost layer
	SetTrackLayer(myTrack, kMaxLayerNumber);
	SetTrackLayer(myTrack, QTTarg_GetLowestLayerInMovie(theMovie) - 1);
		
bail:
	return(myErr);
}
Beispiel #23
0
void MacQTStartRecording(char *path)
{
	OSStatus	err;
	CFStringRef str;
	CFURLRef	url;

	memset(&sqt, 0, sizeof(sqt));

	// storage

	str = CFStringCreateWithCString(kCFAllocatorDefault, path, MAC_PATH_ENCODING);
	url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, str, kCFURLPOSIXPathStyle, false);
	err = QTNewDataReferenceFromCFURL(url, 0, &(sqt.dataRef), &(sqt.dataRefType));
	CheckError(err, 21);
	CFRelease(url);
	CFRelease(str);
	
	err = CreateMovieStorage(sqt.dataRef, sqt.dataRefType, 'TVOD', smSystemScript, createMovieFileDeleteCurFile | newMovieActive, &(sqt.dataHandler), &(sqt.movie));
	CheckError(err, 22);
	
	// video

	MacQTOpenVideoComponent(&(sqt.vci));
	
	SCTemporalSettings	ts;

	err = SCGetInfo(sqt.vci, scTemporalSettingsType, &ts);
	ts.frameRate = FixRatio(Memory.ROMFramesPerSecond, 1);
	if (ts.keyFrameRate < 1)
		ts.keyFrameRate = Memory.ROMFramesPerSecond;
	sqt.keyFrame  = sqt.keyFrameCount  = ts.keyFrameRate;
	sqt.frameSkip = sqt.frameSkipCount = (macQTMovFlag & 0xFF00) >> 8;
	err = SCSetInfo(sqt.vci, scTemporalSettingsType, &ts);

	sqt.frame.top    = 0;
	sqt.frame.left   = 0;
	sqt.frame.right  = ((macQTMovFlag & kMovDoubleSize) ? 2 : 1) * SNES_WIDTH;
	sqt.frame.bottom = ((macQTMovFlag & kMovDoubleSize) ? 2 : 1) * ((macQTMovFlag & kMovExtendedHeight) ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT);

	sqt.pw = sqt.ph = 0;
	sqt.firstFrame = true;
	
	Rect	rct;

	SetRect(&rct, 0, 0, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2 + 4);
	InitGWorld(&(sqt.bw), &rct, 16);

	sqt.vTrack = NewMovieTrack(sqt.movie, FixRatio(sqt.frame.right, 1), FixRatio(sqt.frame.bottom, 1), kNoVolume);
	CheckError(GetMoviesError(), 23);
	
	sqt.vMedia = NewTrackMedia(sqt.vTrack, VideoMediaType, Memory.ROMFramesPerSecond, nil, 0);
	CheckError(GetMoviesError(), 24);
	
	err = BeginMediaEdits(sqt.vMedia);
	CheckError(err, 25);
	
	// sound
	
	sqt.soundDesc = (SoundDescriptionHandle) NewHandleClear(sizeof(SoundDescription));
	CheckError(MemError(), 26);

	(**sqt.soundDesc).descSize    = sizeof(SoundDescription);
#ifdef __BIG_ENDIAN__
	(**sqt.soundDesc).dataFormat  = Settings.SixteenBitSound ? k16BitBigEndianFormat    : k8BitOffsetBinaryFormat;
#else
	(**sqt.soundDesc).dataFormat  = Settings.SixteenBitSound ? k16BitLittleEndianFormat : k8BitOffsetBinaryFormat;
#endif
	(**sqt.soundDesc).numChannels = Settings.Stereo ? 2 : 1;
	(**sqt.soundDesc).sampleSize  = Settings.SixteenBitSound ? 16 : 8;
	(**sqt.soundDesc).sampleRate  = (UnsignedFixed) FixRatio(Settings.SoundPlaybackRate, 1);
	
	sqt.samplesPerSec = Settings.SoundPlaybackRate / Memory.ROMFramesPerSecond;
	
	sqt.soundBufferSize = sqt.samplesPerSec;
	if (Settings.SixteenBitSound)
		sqt.soundBufferSize <<= 1;
	if (Settings.Stereo)
		sqt.soundBufferSize <<= 1;

	sqt.soundBuffer = NewHandleClear(sqt.soundBufferSize);
	CheckError(MemError(), 27);
	HLock(sqt.soundBuffer);
	
	sqt.sTrack = NewMovieTrack(sqt.movie, 0, 0, kFullVolume);
	CheckError(GetMoviesError(), 28);

	sqt.sMedia = NewTrackMedia(sqt.sTrack, SoundMediaType, Settings.SoundPlaybackRate, nil, 0);
	CheckError(GetMoviesError(), 29);

	err = BeginMediaEdits(sqt.sMedia);
	CheckError(err, 30);
}
Beispiel #24
0
static int init_audio(int speed, int channels, soundmovie_buffer_t **buffer)
{
    AudioStreamBasicDescription asbd = {0}; //see CoreAudioTypes.h

    asbd.mSampleRate = speed;
    asbd.mFormatID = kAudioFormatLinearPCM;
    asbd.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger;
    asbd.mChannelsPerFrame = channels;
    asbd.mBitsPerChannel = sizeof (SWORD) * 8;
    asbd.mBytesPerFrame = (asbd.mBitsPerChannel >> 3)      // number of *bytes* per channel
                          * asbd.mChannelsPerFrame;         // channels per frame
    asbd.mFramesPerPacket = 1;      // For PCM, frames per packet is always 1
    asbd.mBytesPerPacket = asbd.mBytesPerFrame * asbd.mFramesPerPacket;

    UInt32 layoutSize;
    layoutSize = offsetof(AudioChannelLayout, mChannelDescriptions[0]);
    AudioChannelLayout *layout = NULL;
    layout = calloc(layoutSize, 1);
    OSErr err = -1;
    if (layout != NULL) {
        if (channels == 1) {
            layout->mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
        } else if (channels == 2) {
            layout->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
        } else {
            log_debug("quicktime_audio: unsupported channels: %d", channels);
            return -1;
        }
        err = QTSoundDescriptionCreate(
            &asbd,                      // format description
            layout, layoutSize,         // channel layout
            NULL, 0,                    // magic cookie (compression parameters)
            kQTSoundDescriptionKind_Movie_LowestPossibleVersion,
            &soundDescriptionHandle);         // SoundDescriptionHandle returned here
        free(layout);
    }
    if (err != noErr) {
        log_debug("quicktime_audio: error creating sound description!");
        return -1;
    }

    //Add audio track
    audioTrack = NewMovieTrack(movie, 0, 0, kFullVolume);
    OSStatus theError = GetMoviesError();
    if (theError) {
        log_debug("quicktime_audio: error creating movie track");
        return theError;
    }

    //Create audio track media
    audioMedia = NewTrackMedia(audioTrack, SoundMediaType, speed, 0, 0);
    theError = GetMoviesError();
    if (theError) {
        log_debug("quicktime_audio: error creating track media!");
        return theError;
    }

    //Prepare media for editing
    theError = BeginMediaEdits(audioMedia);
    if (theError) {
        log_debug("quicktime_audio: error beginning media edits!");
        return theError;
    }

    *buffer = &audioBuffer;
    audioBuffer.size = speed * channels / 10;
    audioBuffer.buffer = malloc(sizeof(SWORD) * audioBuffer.size);
    audioBuffer.used = 0;

    audio_ready = 1;
    return 0;
}
Beispiel #25
0
/* This function prepares the movie to receivve the movie data,
 * After success, *out_map points to a valid stream maping
 * Return values:
 *	  0: ok
 */
OSStatus prepare_movie(ff_global_ptr storage, Movie theMovie, Handle dataRef, OSType dataRefType)
{
    int j;
    AVStream *st;
    NCStream *map;
    Track track = NULL;
    Track first_audio_track = NULL;
    AVFormatContext *ic = storage->format_context;
    OSStatus err = noErr;

    /* make the stream map structure */
    map = av_mallocz(ic->nb_streams * sizeof(NCStream));

    for(j = 0; j < ic->nb_streams; j++) {

        st = ic->streams[j];
        map[j].index = st->index;
        map[j].str = st;
        map[j].duration = -1;

        if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            Fixed width, height;

            get_track_dimensions_for_codec(st, &width, &height);
            track = NewMovieTrack(theMovie, width, height, kNoVolume);

            // Support for 'old' NUV files, that didn't put the codec_tag in the file.
            if( st->codec->codec_id == CODEC_ID_NUV && st->codec->codec_tag == 0 ) {
                st->codec->codec_tag = MKTAG( 'N', 'U', 'V', '1' );
            }

            initialize_video_map(&map[j], track, dataRef, dataRefType, storage->firstFrames + j);
            set_track_clean_aperture_ext((ImageDescriptionHandle)map[j].sampleHdl, width, height, IntToFixed(st->codec->width), IntToFixed(st->codec->height));
            set_track_colorspace_ext((ImageDescriptionHandle)map[j].sampleHdl, width, height);
        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
            if (st->codec->sample_rate > 0) {
                track = NewMovieTrack(theMovie, 0, 0, kFullVolume);
                err = initialize_audio_map(&map[j], track, dataRef, dataRefType, storage->firstFrames + j);

                if (first_audio_track == NULL)
                    first_audio_track = track;
                else
                    SetTrackAlternate(track, first_audio_track);
            }
        } else
            continue;

        // can't import samples if neither of these were created.
        map[j].valid = map[j].media && map[j].sampleHdl;

        if (err) {
            if (track)
                DisposeMovieTrack(track);
            return err;
        }
    }

    add_metadata(ic, theMovie);

    storage->stream_map = map;

    return 0;
} /* prepare_movie() */
Beispiel #26
0
void QTVectors_CreateVectorMovie (UInt32 theBuildAtomMethod)
{
	Handle						myHandle = NULL;
	ImageDescriptionHandle		mySampleDesc = NULL;
	short						myResRefNum = 0;
	short						myResID = movieInDataForkResID;
	Movie						myMovie = NULL;
	Track						myTrack;
	Media						myMedia;
	FSSpec						myFile;
	Boolean						myIsSelected = false;
	Boolean						myIsReplacing = false;	
	StringPtr 					myPrompt = QTUtils_ConvertCToPascalString(kVectorSavePrompt);
	StringPtr 					myFileName = QTUtils_ConvertCToPascalString(kVectorSaveMovieFileName);
	ComponentInstance			myComponent;
	ComponentResult				myResult;
	long						myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
	OSErr						myErr = noErr;
	
	// METHOD ONE: use a raw data stream
	
	if (theBuildAtomMethod == kUseRawDataStream) {
	
		// kUseRawDataStream: build the vector data using a stream of hard-coded raw data
		// NOTE: the data in the stream *must* be big-endian, since it's stored in a QuickTime atom container.

		long					myPath[] = {	
			
		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveAntialiasControlAtom),
			EndianU32_NtoB(kCurveAntialiasOn),

		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveFillTypeAtom),
			EndianU32_NtoB(gxEvenOddFill),

		// a big white enclosing rectangle (600 x 600)
		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(ARGBColor)), EndianU32_NtoB(kCurveARGBColorAtom),
			EndianU32_NtoB(0xffffffff),	// alpha, red
			EndianU32_NtoB(0xffffffff),	// green, blue
										// it's white!

		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)*11), EndianU32_NtoB(kCurvePathAtom),
			EndianU32_NtoB(1),			// one contour in path
			EndianU32_NtoB(4),			// four points in path
			EndianU32_NtoB(0x00000000),	// all points are on the curve: it's a rectangle! 
			EndianU32_NtoB(0x00000000), EndianU32_NtoB(0x00000000), 	// top left
			EndianU32_NtoB(0x02580000), EndianU32_NtoB(0x00000000),		// top right
			EndianU32_NtoB(0x02580000), EndianU32_NtoB(0x02580000),		// bottom right 
			EndianU32_NtoB(0x00000000), EndianU32_NtoB(0x02580000),		// bottom left

		// a black rounded square, centered at 150,150
		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(ARGBColor)), EndianU32_NtoB(kCurveARGBColorAtom),
			EndianU32_NtoB(0x00000000),	// alpha, red
			EndianU32_NtoB(0x00000000),	// green, blue
										// it's black!

		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)*11), EndianU32_NtoB(kCurvePathAtom),
			EndianU32_NtoB(1),			// one contour in path
			EndianU32_NtoB(4),			// four points in path
			EndianU32_NtoB(0xffffffff), // all points are off the curve: it's a rounded square! 
			EndianU32_NtoB(0x00640000), EndianU32_NtoB(0x00640000),
			EndianU32_NtoB(0x00C80000), EndianU32_NtoB(0x00640000),
			EndianU32_NtoB(0x00C80000), EndianU32_NtoB(0x00C80000), 
			EndianU32_NtoB(0x00640000), EndianU32_NtoB(0x00C80000),

		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveFillTypeAtom),
			EndianU32_NtoB(gxEvenOddFill),

		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurvePenThicknessAtom),
			EndianU32_NtoB(0x100000),
											
		// enable linear gradient for all following atoms
		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveGradientTypeAtom),
			EndianU32_NtoB(kLinearGradient),
		
		// define the gradient: red -> green -> red -> blue									
		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(GradientColorRecord)*4), EndianU32_NtoB(kCurveGradientRecordAtom),
										
			EndianU32_NtoB(0xffffffff),	// gradient color record 1:
			EndianU32_NtoB(0x00000000),	// red
			EndianU32_NtoB(0x00000000),	// beginning of gradient
										
			EndianU32_NtoB(0x77770000),	// gradient color record 2:
			EndianU32_NtoB(0xffff0000),	// green
			EndianU32_NtoB(0x00004000),
										
			EndianU32_NtoB(0x3333ffff),	// gradient color record 3:
			EndianU32_NtoB(0x00000000),	// red
			EndianU32_NtoB(0x0000C000),
										
			EndianU32_NtoB(0xffff0000),	// gradient color record 4:
			EndianU32_NtoB(0x0000ffff),	// blue
			EndianU32_NtoB(0x00010000),	// end of gradient

		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveGradientAngleAtom),
			EndianU32_NtoB(0x00450000),	// gradient at 45û angle
		
		// a green rectangle, centered at 40,40, painted with a linear gradient									
		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(ARGBColor)), EndianU32_NtoB(kCurveARGBColorAtom),
			EndianU32_NtoB(0x00000000),	// alpha, red
			EndianU32_NtoB(0xffff0000),	// green, blue
										// it's green!

		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)*11), EndianU32_NtoB(kCurvePathAtom),
			EndianU32_NtoB(1),			// one contour in path
			EndianU32_NtoB(4),			// four points in path
			EndianU32_NtoB(0x00000000),	// all points are on the curve: it's a rectangle! 
			EndianU32_NtoB(0x00100000), EndianU32_NtoB(0x00100000),
			EndianU32_NtoB(0x00400000), EndianU32_NtoB(0x00100000),
			EndianU32_NtoB(0x00400000), EndianU32_NtoB(0x00400000),
			EndianU32_NtoB(0x00100000), EndianU32_NtoB(0x00400000),

		// disable gradient for all following atoms (since no atom data)
		EndianU32_NtoB(kSizeOfSizeAndTagFields), EndianU32_NtoB(kCurveGradientRecordAtom),
									
		// a red rounded square, centered at 50,50
		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(ARGBColor)), EndianU32_NtoB(kCurveARGBColorAtom),
			EndianU32_NtoB(0x3333ffff),	// alpha, red
			EndianU32_NtoB(0x00000000),	// green, blue
										// it's red!

		EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)*11), EndianU32_NtoB(kCurvePathAtom),
			EndianU32_NtoB(1L),			// one contour in path
			EndianU32_NtoB(4L),			// four points in path
			EndianU32_NtoB(0xffffffff), // all points are off the curve: it's a rounded square! 
			EndianU32_NtoB(0x001e0000), EndianU32_NtoB(0x001e0000),
			EndianU32_NtoB(0x00460000), EndianU32_NtoB(0x001e0000),
			EndianU32_NtoB(0x00460000), EndianU32_NtoB(0x00460000),
			EndianU32_NtoB(0x001e0000), EndianU32_NtoB(0x00460000),

		EndianU32_NtoB(kSizeOfZeroAtomHeader), EndianU32_NtoB(kCurveEndAtom),
	};
			
		myHandle = NewHandle(sizeof(myPath));
		if (myHandle == NULL)
			goto bail;
			
		BlockMove(myPath, *myHandle, sizeof(myPath));
	
	}	// end of kUseRawDataStream

	
	// METHOD TWO: use the Curve Utilities API
	
	if (theBuildAtomMethod == kUseCurveUtilities) {
	
		// kUseCurveUtilities: build the vector data using the Curve Utilities API		
		Handle						myPath;
		gxPoint						myPoint;
		long						myAtomData[14];
		ARGBColor					myColor;
		GradientColorRecord			myGradients[4];
	
		// open the vector codec; we'll need it for some subsequent calls
		myComponent = OpenDefaultComponent(decompressorComponentType, kVectorCodecType);
		if (myComponent == NULL)
			goto bail;

		// create a new, empty vector data stream
		myResult = CurveCreateVectorStream(myComponent, &myHandle);
		if (myResult != noErr)
			goto bail;
		
		// now start adding atoms holding the vector data
		
		// set antialiasing on
		myAtomData[0] = EndianU32_NtoB(kCurveAntialiasOn);
		CurveAddAtomToVectorStream(myComponent, kCurveAntialiasControlAtom, sizeof(long), myAtomData, myHandle);

		// set fill type
		myAtomData[0] = EndianU32_NtoB(gxEvenOddFill);
		CurveAddAtomToVectorStream(myComponent, kCurveFillTypeAtom, sizeof(long), myAtomData, myHandle);

		// a big white enclosing rectangle (600 x 600)
		myColor.alpha = EndianU16_NtoB(0xffff);
		myColor.red = EndianU16_NtoB(0xffff);
		myColor.green = EndianU16_NtoB(0xffff);
		myColor.blue = EndianU16_NtoB(0xffff);
		CurveAddAtomToVectorStream(myComponent, kCurveARGBColorAtom, sizeof(ARGBColor), &myColor, myHandle);

#if USE_CURVE_INSERT_POINT_INTO_PATH
		// create a new, empty path
		CurveNewPath(myComponent, &myPath);

		myPoint.x = 0x00000000;
		myPoint.y = 0x00000000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 0, true);
		
		myPoint.x = 0x02580000;
		myPoint.y = 0x00000000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 1, true);
		
		myPoint.x = 0x02580000;
		myPoint.y = 0x02580000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 2, true);
		
		myPoint.x = 0x00000000;
		myPoint.y = 0x02580000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 3, true);

		// add the 'path' atom to the vector data stream
		CurveAddPathAtomToVectorStream(myComponent, myPath, myHandle);
		DisposeHandle(myPath);
#else
		myAtomData[0] = EndianU32_NtoB(1L);
		myAtomData[1] = EndianU32_NtoB(4L);
		myAtomData[2] = EndianU32_NtoB(0x00000000);
		myAtomData[3] = EndianU32_NtoB(0x00000000);
		myAtomData[4] = EndianU32_NtoB(0x00000000);
		myAtomData[5] = EndianU32_NtoB(0x02580000);
		myAtomData[6] = EndianU32_NtoB(0x00000000);
		myAtomData[7] = EndianU32_NtoB(0x02580000);
		myAtomData[8] = EndianU32_NtoB(0x02580000);
		myAtomData[9] = EndianU32_NtoB(0x00000000);
		myAtomData[10] = EndianU32_NtoB(0x02580000);
		CurveAddAtomToVectorStream(myComponent, kCurvePathAtom, sizeof(long)*11, myAtomData, myHandle);
#endif
		
		// a black rounded square, centered at 150,150
		myColor.alpha = EndianU16_NtoB(0x0000);
		myColor.red = EndianU16_NtoB(0x0000);
		myColor.green = EndianU16_NtoB(0x0000);
		myColor.blue = EndianU16_NtoB(0x0000);
		CurveAddAtomToVectorStream(myComponent, kCurveARGBColorAtom, sizeof(ARGBColor), &myColor, myHandle);

#if USE_CURVE_INSERT_POINT_INTO_PATH
		// create a new, empty path
		CurveNewPath(myComponent, &myPath);

		myPoint.x = 0x00640000;
		myPoint.y = 0x00640000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 0, false);
		
		myPoint.x = 0x00C80000;
		myPoint.y = 0x00640000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 1, false);
		
		myPoint.x = 0x00C80000;
		myPoint.y = 0x00C80000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 2, false);
		
		myPoint.x = 0x00640000;
		myPoint.y = 0x00C80000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 3, false);

		// add the 'path' atom to the vector data stream
		CurveAddPathAtomToVectorStream(myComponent, myPath, myHandle);
		DisposeHandle(myPath);
#else
		myAtomData[0] = EndianU32_NtoB(1L);
		myAtomData[1] = EndianU32_NtoB(4L);
		myAtomData[2] = EndianU32_NtoB(0xffffffff);
		myAtomData[3] = EndianU32_NtoB(0x00640000);
		myAtomData[4] = EndianU32_NtoB(0x00640000);
		myAtomData[5] = EndianU32_NtoB(0x00C80000);
		myAtomData[6] = EndianU32_NtoB(0x00640000);
		myAtomData[7] = EndianU32_NtoB(0x00C80000);
		myAtomData[8] = EndianU32_NtoB(0x00C80000);
		myAtomData[9] = EndianU32_NtoB(0x00640000);
		myAtomData[10] = EndianU32_NtoB(0x00C80000);
		CurveAddAtomToVectorStream(myComponent, kCurvePathAtom, sizeof(long)*11, myAtomData, myHandle);
#endif

		// set fill type
		myAtomData[0] = EndianU32_NtoB(gxEvenOddFill);
		CurveAddAtomToVectorStream(myComponent, kCurveFillTypeAtom, sizeof(long), myAtomData, myHandle);

		// set pen thickness
		myAtomData[0] = EndianU32_NtoB(0x100000);
		CurveAddAtomToVectorStream(myComponent, kCurvePenThicknessAtom, sizeof(long), myAtomData, myHandle);

		// enable linear gradient for all following atoms
		myAtomData[0] = EndianU32_NtoB(kLinearGradient);
		CurveAddAtomToVectorStream(myComponent, kCurveGradientTypeAtom, sizeof(long), myAtomData, myHandle);

		// define the gradient: red -> green -> red -> blue									
		myGradients[0].thisColor.alpha = EndianU16_NtoB(0xffff);
		myGradients[0].thisColor.red = EndianU16_NtoB(0xffff);
		myGradients[0].thisColor.green = EndianU16_NtoB(0x0000);
		myGradients[0].thisColor.blue = EndianU16_NtoB(0x0000);
		myGradients[0].endingPercentage = EndianU32_NtoB(0x00000000);
		myGradients[1].thisColor.alpha = EndianU16_NtoB(0x7777);
		myGradients[1].thisColor.red = EndianU16_NtoB(0x0000);
		myGradients[1].thisColor.green = EndianU16_NtoB(0xffff);
		myGradients[1].thisColor.blue = EndianU16_NtoB(0x0000);
		myGradients[1].endingPercentage = EndianU32_NtoB(0x00004000);
		myGradients[2].thisColor.alpha = EndianU16_NtoB(0x3333);
		myGradients[2].thisColor.red = EndianU16_NtoB(0xffff);
		myGradients[2].thisColor.green = EndianU16_NtoB(0x0000);
		myGradients[2].thisColor.blue = EndianU16_NtoB(0x0000);
		myGradients[2].endingPercentage = EndianU32_NtoB(0x0000C000);
		myGradients[3].thisColor.alpha = EndianU16_NtoB(0xffff);
		myGradients[3].thisColor.red = EndianU16_NtoB(0x0000);
		myGradients[3].thisColor.green = EndianU16_NtoB(0x0000);
		myGradients[3].thisColor.blue = EndianU16_NtoB(0xffff);
		myGradients[3].endingPercentage = EndianU32_NtoB(0x00010000);
		CurveAddAtomToVectorStream(myComponent, kCurveGradientRecordAtom, sizeof(GradientColorRecord)*4, myGradients, myHandle);

		// set gradient angle
		myAtomData[0] = EndianU32_NtoB(0x00450000);
		CurveAddAtomToVectorStream(myComponent, kCurveGradientAngleAtom, sizeof(long), myAtomData, myHandle);

		// a green rectangle, centered at 40,40, painted with a linear gradient									
		myColor.alpha = EndianU16_NtoB(0x0000);
		myColor.red = EndianU16_NtoB(0x0000);
		myColor.green = EndianU16_NtoB(0xffff);
		myColor.blue = EndianU16_NtoB(0x0000);
		CurveAddAtomToVectorStream(myComponent, kCurveARGBColorAtom, sizeof(ARGBColor), &myColor, myHandle);

#if USE_CURVE_INSERT_POINT_INTO_PATH
		// create a new, empty path
		CurveNewPath(myComponent, &myPath);

		myPoint.x = 0x00100000;
		myPoint.y = 0x00100000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 0, true);
		
		myPoint.x = 0x00400000;
		myPoint.y = 0x00100000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 1, true);
		
		myPoint.x = 0x00400000;
		myPoint.y = 0x00400000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 2, true);
		
		myPoint.x = 0x00100000;
		myPoint.y = 0x00400000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 3, true);

		// add the 'path' atom to the vector data stream
		CurveAddPathAtomToVectorStream(myComponent, myPath, myHandle);
		DisposeHandle(myPath);
#else
		myAtomData[0] = EndianU32_NtoB(1L);
		myAtomData[1] = EndianU32_NtoB(4L);
		myAtomData[2] = EndianU32_NtoB(0x00000000);
		myAtomData[3] = EndianU32_NtoB(0x00100000);
		myAtomData[4] = EndianU32_NtoB(0x00100000);
		myAtomData[5] = EndianU32_NtoB(0x00400000);
		myAtomData[6] = EndianU32_NtoB(0x00100000);
		myAtomData[7] = EndianU32_NtoB(0x00400000);
		myAtomData[8] = EndianU32_NtoB(0x00400000);
		myAtomData[9] = EndianU32_NtoB(0x00100000);
		myAtomData[10] = EndianU32_NtoB(0x00400000);
		CurveAddAtomToVectorStream(myComponent, kCurvePathAtom, sizeof(long)*11, myAtomData, myHandle);
#endif

		// disable gradient for all following atoms (since no atom data)
		CurveAddAtomToVectorStream(myComponent, kCurveGradientTypeAtom, 0, NULL, myHandle);
		
		// a red rounded square, centered at 50,50
		myColor.alpha = EndianU16_NtoB(0x3333);
		myColor.red = EndianU16_NtoB(0xffff);
		myColor.green = EndianU16_NtoB(0x0000);
		myColor.blue = EndianU16_NtoB(0x0000);
		CurveAddAtomToVectorStream(myComponent, kCurveARGBColorAtom, sizeof(ARGBColor), &myColor, myHandle);

#if USE_CURVE_INSERT_POINT_INTO_PATH
		// create a new, empty path
		CurveNewPath(myComponent, &myPath);

		myPoint.x = 0x001e0000;
		myPoint.y = 0x001e0000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 0, false);
		
		myPoint.x = 0x00460000;
		myPoint.y = 0x001e0000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 1, false);
		
		myPoint.x = 0x00460000;
		myPoint.y = 0x00460000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 2, false);
		
		myPoint.x = 0x001e0000;
		myPoint.y = 0x00460000;
		CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 3, false);

		// add the 'path' atom to the vector data stream
		CurveAddPathAtomToVectorStream(myComponent, myPath, myHandle);
		DisposeHandle(myPath);
#else
		myAtomData[0] = EndianU32_NtoB(1L);
		myAtomData[1] = EndianU32_NtoB(4L);
		myAtomData[2] = EndianU32_NtoB(0xffffffff);
		myAtomData[3] = EndianU32_NtoB(0x001e0000);
		myAtomData[4] = EndianU32_NtoB(0x001e0000);
		myAtomData[5] = EndianU32_NtoB(0x00460000);
		myAtomData[6] = EndianU32_NtoB(0x001e0000);
		myAtomData[7] = EndianU32_NtoB(0x00460000);
		myAtomData[8] = EndianU32_NtoB(0x00460000);
		myAtomData[9] = EndianU32_NtoB(0x001e0000);
		myAtomData[10] = EndianU32_NtoB(0x00460000);
		CurveAddAtomToVectorStream(myComponent, kCurvePathAtom, sizeof(long)*11, myAtomData, myHandle);
#endif

		// add the 'zero' atom to the vector data stream
		CurveAddZeroAtomToVectorStream(myComponent, myHandle);
		
	}	// end of kUseCurveUtilities
	
	// create the image description
	mySampleDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
	if (mySampleDesc == NULL)
		goto bail;
	
	// fill in the fields of the image description
	(**mySampleDesc).idSize = sizeof(ImageDescription);
	(**mySampleDesc).cType = kVectorCodecType;
	(**mySampleDesc).vendor = kAppleManufacturer;
	(**mySampleDesc).temporalQuality = codecNormalQuality;
	(**mySampleDesc).spatialQuality = codecNormalQuality;
	(**mySampleDesc).width = 300;
	(**mySampleDesc).height = 300;
	(**mySampleDesc).hRes = 72L << 16;
	(**mySampleDesc).vRes = 72L << 16;
	(**mySampleDesc).dataSize = 0L;
	(**mySampleDesc).frameCount = 1;
	(**mySampleDesc).depth = 0;
	(**mySampleDesc).clutID = -1;
		
	// prompt user for new file name
	QTFrame_PutFile(myPrompt, myFileName, &myFile, &myIsSelected, &myIsReplacing);
	if (!myIsSelected)
		goto bail;
	
	// create a movie file for the destination movie
	myErr = CreateMovieFile(&myFile, FOUR_CHAR_CODE('TVOD'), smCurrentScript, myFlags, &myResRefNum, &myMovie);
	if (myErr != noErr)
		goto bail;
	
	// create the vector track and media
	myTrack = NewMovieTrack(myMovie, FixDiv(300, 1), FixDiv(300, 1), kNoVolume);
	myMedia = NewTrackMedia(myTrack, VideoMediaType, 600, NULL, 0);
	
	// create the vector media sample
	BeginMediaEdits(myMedia);
		
	myErr = AddMediaSample(myMedia, myHandle, 0, GetHandleSize(myHandle), 600, (SampleDescriptionHandle)mySampleDesc, 1, 0, NULL);
	if (myErr != noErr)
		goto bail;
		
	EndMediaEdits(myMedia);
	
	// add the media to the track
	InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
	AddMovieResource(myMovie, myResRefNum, &myResID, NULL);

bail:
	free(myPrompt);
	free(myFileName);

	if (mySampleDesc != NULL)
		DisposeHandle((Handle)mySampleDesc);
	
	if (myResRefNum != 0)
		CloseMovieFile(myResRefNum);

	if (myHandle != NULL)
		DisposeHandle(myHandle);

	if (myMovie != NULL)
		DisposeMovie(myMovie);

	if (myComponent != NULL)
		CloseComponent(myComponent);
}
void QTEffects_RespondToDialogSelection (OSErr theErr)
{
	Boolean					myDialogWasCancelled = false;
	short					myResID = movieInDataForkResID;
	UInt16					myMovieIter;
	short					mySrcMovieRefNum = 0;
	Movie					myPrevSrcMovie = NULL;
	Track					myPrevSrcTrack = NULL;
	Movie					myNextSrcMovie = NULL;
	Track					myNextSrcTrack = NULL;
	short					myDestMovieRefNum = 0;
	FSSpec					myFile;
	Boolean					myIsSelected = false;
	Boolean					myIsReplacing = false;	
	StringPtr 				myPrompt = QTUtils_ConvertCToPascalString(kEffectsSaveMoviePrompt);
	StringPtr 				myFileName = QTUtils_ConvertCToPascalString(kEffectsSaveMovieFileName);
	Movie					myDestMovie = NULL;
	Fixed					myDestMovieWidth, myDestMovieHeight;
	ImageDescriptionHandle	myDesc = NULL;
	Track					videoTrackFX, videoTrackA, videoTrackB;
	Media					videoMediaFX, videoMediaA, videoMediaB;
	TimeValue				myCurrentDuration = 0;
	TimeValue				myReturnedDuration;
	Boolean					isFirstTransition = true;
	TimeValue				myMediaTransitionDuration;
	TimeValue				myMediaFXStartTime, myMediaFXDuration;
	OSType					myEffectCode;
	long					myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
	long					myLong;
	OSErr					myErr = noErr;

	// standard parameter box has been dismissed, so remember that fact
	gEffectsDialog = 0L;
	
	myDialogWasCancelled = (theErr == userCanceledErr);
	
	// we're finished with the effect list and movie posters	
	QTDisposeAtomContainer(gEffectList);
	
	if (gPosterA != NULL)
		KillPicture(gPosterA);
		
	if (gPosterB != NULL)
		KillPicture(gPosterB);
	
	// when the sign says stop, then stop
	if (myDialogWasCancelled)
		goto bail;

	// add atoms naming the sources to gEffectSample
	myLong = EndianU32_NtoB(kSourceOneName);
	QTInsertChild(gEffectSample, kParentAtomIsContainer, kEffectSourceName, 1, 0, sizeof(myLong), &myLong, NULL);

	myLong = EndianU32_NtoB(kSourceTwoName);
	QTInsertChild(gEffectSample, kParentAtomIsContainer, kEffectSourceName, 2, 0, sizeof(myLong), &myLong, NULL);
	
	// extract the 'what' atom to find out what kind of effect it is
	{
		QTAtom			myEffectAtom;
		QTAtomID		myEffectAtomID;
		long			myEffectCodeSize;
		Ptr				myEffectCodePtr;

		myEffectAtom = QTFindChildByIndex(gEffectSample, kParentAtomIsContainer, kParameterWhatName, kParameterWhatID, &myEffectAtomID);
		
		myErr = QTLockContainer(gEffectSample);
		BailError(myErr);

		myErr = QTGetAtomDataPtr(gEffectSample, myEffectAtom, &myEffectCodeSize, &myEffectCodePtr);
		BailError(myErr);

		if (myEffectCodeSize != sizeof(OSType)) {
			myErr = paramErr;
			goto bail;
		}
		
		myEffectCode = *(OSType *)myEffectCodePtr;		// "tsk"
		myEffectCode = EndianU32_BtoN(myEffectCode);	// because the data is read from an atom container
		
		myErr = QTUnlockContainer(gEffectSample);
		BailError(myErr);
	}

	// ask the user for the name of the new movie file
	QTFrame_PutFile(myPrompt, myFileName, &myFile, &myIsSelected, &myIsReplacing);
	if (!myIsSelected)
		goto bail;				// deal with user cancelling

	// create a movie file for the destination movie
	myErr = CreateMovieFile(&myFile, FOUR_CHAR_CODE('TVOD'), 0, myFlags, &myDestMovieRefNum, &myDestMovie);
	BailError(myErr);
	
	// open the first file as a movie; call the first movie myPrevSrcMovie
	myErr = OpenMovieFile(&gSpecList[0], &mySrcMovieRefNum, fsRdPerm);
	BailError(myErr);
	
	myErr = NewMovieFromFile(&myPrevSrcMovie, mySrcMovieRefNum, NULL, NULL, 0, NULL);
	BailError(myErr);
	
	myErr = CloseMovieFile(mySrcMovieRefNum);
	BailError(myErr);
	
	// if the movie is shorter than kMinimumDuration, scale it to that length
	SetMovieTimeScale(myPrevSrcMovie, kTimeScale);
	myErr = QTEffects_GetFirstVideoTrackInMovie(myPrevSrcMovie, &myPrevSrcTrack);
	BailNil(myPrevSrcTrack);
	
	if (GetTrackDuration(myPrevSrcTrack) < kMinimumDuration) {
		myErr = ScaleTrackSegment(myPrevSrcTrack, 0, GetTrackDuration(myPrevSrcTrack), kMinimumDuration);
		BailError(myErr);
	}
	
	// find out how big the first movie is; we'll use it as the size of all our tracks
	GetTrackDimensions(myPrevSrcTrack, &myDestMovieWidth, &myDestMovieHeight);
	
#if USES_MAKE_IMAGE_DESC_FOR_EFFECT
	// create a new sample description for the effect,
	// which is just an image description specifying the effect and its dimensions
	myErr = MakeImageDescriptionForEffect(myEffectCode, &myDesc);
	if (myErr != noErr)
		BailError(myErr);
#else
	// create a new sample description for the effect,
	// which is just an image description specifying the effect and its dimensions
	myDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
	BailNil(myDesc);
	
	(**myDesc).idSize = sizeof(ImageDescription);
	(**myDesc).cType = myEffectCode;
	(**myDesc).hRes = 72L << 16;
	(**myDesc).vRes = 72L << 16;
	(**myDesc).dataSize = 0L;
	(**myDesc).frameCount = 1;
	(**myDesc).depth = 0;
	(**myDesc).clutID = -1;
#endif
	
	// fill in the fields of the sample description
	(**myDesc).vendor = kAppleManufacturer;
	(**myDesc).temporalQuality = codecNormalQuality;
	(**myDesc).spatialQuality = codecNormalQuality;
	(**myDesc).width = FixRound(myDestMovieWidth);
	(**myDesc).height = FixRound(myDestMovieHeight);

	// add three video tracks to the destination movie:
	// 	- videoTrackFX is where the effects and stills live; it's user-visible.
	//	- videoTrackA is where the "source A"s for effects live; it's hidden by the input map
	//	- videoTrackB is where the "source B"s for effects live; it's hidden by the input map
	videoTrackFX = NewMovieTrack(myDestMovie, myDestMovieWidth, myDestMovieHeight, 0);
	BailNil(videoTrackFX);
	videoMediaFX = NewTrackMedia(videoTrackFX, VideoMediaType, kTimeScale, NULL, 0);
	BailNil(videoMediaFX);
	myErr = BeginMediaEdits(videoMediaFX);
	BailError(myErr);
	
	videoTrackA = NewMovieTrack(myDestMovie, myDestMovieWidth, myDestMovieHeight, 0);
	BailNil(videoTrackA);
	videoMediaA = NewTrackMedia(videoTrackA, VideoMediaType, kTimeScale, NULL, 0);
	BailNil(videoMediaA);

	videoTrackB = NewMovieTrack(myDestMovie, myDestMovieWidth, myDestMovieHeight, 0);
	BailNil(videoTrackB);
	videoMediaB = NewTrackMedia(videoTrackB, VideoMediaType, kTimeScale, NULL, 0);
	BailNil(videoMediaB);

	// create the input map
	{
		long				myRefIndex1, myRefIndex2;
		QTAtomContainer		myInputMap;
		QTAtom				myInputAtom;
		OSType				myInputType;

		QTNewAtomContainer(&myInputMap);

		// first input
		if (videoTrackA) {
		
			AddTrackReference(videoTrackFX, videoTrackA, kTrackModifierReference, &myRefIndex1);
			QTInsertChild(myInputMap, kParentAtomIsContainer, kTrackModifierInput, myRefIndex1, 0, 0, NULL, &myInputAtom);
	
			myInputType = EndianU32_NtoB(kTrackModifierTypeImage);
			QTInsertChild(myInputMap, myInputAtom, kTrackModifierType, 1, 0, sizeof(myInputType), &myInputType, NULL);
	
			myLong = EndianU32_NtoB(kSourceOneName);
			QTInsertChild(myInputMap, myInputAtom, kEffectDataSourceType, 1, 0, sizeof(myLong), &myLong, NULL);
		}

		// second input
		if (videoTrackB) {
		
			AddTrackReference(videoTrackFX, videoTrackB, kTrackModifierReference, &myRefIndex2);
			QTInsertChild(myInputMap, kParentAtomIsContainer, kTrackModifierInput, myRefIndex2, 0, 0, NULL, &myInputAtom);
	
			myInputType = EndianU32_NtoB(kTrackModifierTypeImage);
			QTInsertChild(myInputMap, myInputAtom, kTrackModifierType, 1, 0, sizeof(myInputType), &myInputType, NULL);
	
			myLong = EndianU32_NtoB(kSourceTwoName);
			QTInsertChild(myInputMap, myInputAtom, kEffectDataSourceType, 1, 0, sizeof(myLong), &myLong, NULL);
		}

		// set that map
		SetMediaInputMap(GetTrackMedia(videoTrackFX), myInputMap);
		
		QTDisposeAtomContainer(myInputMap);
	}

	myCurrentDuration = 0;

#if MAKE_STILL_SECTIONS
	// copy the first sample of the first video track of the first movie to videoTrackFX, with duration kStillDuration.
	myErr = CopyPortionOfTrackToTrack(myPrevSrcTrack, eStartPortion + eMiddlePortion, videoTrackFX, myCurrentDuration, &myReturnedDuration);
	BailError(myErr);
	
	myCurrentDuration += myReturnedDuration;
#endif 

	// now process any remaining files
	myMovieIter = 1;
	while (myMovieIter < gSpecCount) {
		
		// open the next file as a movie; call it nextSourceMovie
		myErr = OpenMovieFile(&gSpecList[myMovieIter], &mySrcMovieRefNum, fsRdPerm);
		BailError(myErr);
		
		myErr = NewMovieFromFile(&myNextSrcMovie, mySrcMovieRefNum, NULL, NULL, 0, NULL);
		BailError(myErr);
		
		// we're done with the movie file, so close it
		myErr = CloseMovieFile(mySrcMovieRefNum);
		BailError(myErr);
		
		// if the movie is shorter than kMinimumDuration, scale it to that length
		SetMovieTimeScale(myNextSrcMovie, kTimeScale);
		myErr = QTEffects_GetFirstVideoTrackInMovie(myNextSrcMovie, &myNextSrcTrack);
		BailNil(myNextSrcTrack);
		
		if (GetTrackDuration(myNextSrcTrack) < kMinimumDuration) {
			myErr = ScaleTrackSegment(myNextSrcTrack, 0, GetTrackDuration(myNextSrcTrack), kMinimumDuration);
			BailError(myErr);
		}

		// create a transition effect from the previous source movie's first video sample to the next source movie's first video sample
		// (the effect should have duration kEffectDuration);
		// this involves adding one sample to each of the three video tracks:
		
		//    sample from previous source movie	 -> videoTrackA
		myErr = QTEffects_CopyPortionOfTrackToTrack(myPrevSrcTrack, eFinishPortion, videoTrackA, myCurrentDuration, &myReturnedDuration);
		BailError(myErr);
		
		//    sample from next source movie    	 -> videoTrackB
		myErr = QTEffects_CopyPortionOfTrackToTrack(myNextSrcTrack, eStartPortion, videoTrackB, myCurrentDuration, &myReturnedDuration);
		BailError(myErr);
		
		//    effect sample                 	  -> videoTrackFX
		if (isFirstTransition) {
			myMediaTransitionDuration = myReturnedDuration;
			myMediaFXStartTime = GetMediaDuration(videoMediaFX);
			myErr = AddMediaSample(videoMediaFX, gEffectSample, 0, GetHandleSize(gEffectSample), myMediaTransitionDuration, (SampleDescriptionHandle)myDesc, 1, 0, NULL);
			BailError(myErr);
			
			myMediaFXDuration = GetMediaDuration(videoMediaFX) - myMediaFXStartTime;
			isFirstTransition = false;
		}
		
		myErr = InsertMediaIntoTrack(videoTrackFX, myCurrentDuration, myMediaFXStartTime, myMediaFXDuration, FixRatio(myReturnedDuration, myMediaTransitionDuration));
		BailError(myErr);
		
		myCurrentDuration += myReturnedDuration;
		
#if MAKE_STILL_SECTIONS
		// copy the first video sample of myNextSrcMovie to videoTrackFX, with duration kStillDuration.
		myErr = QTEffects_CopyPortionOfTrackToTrack(myNextSrcTrack, eMiddlePortion + (myMovieIter + 1 == theSpecCount) ? eFinishPortion : 0, videoTrackFX, myCurrentDuration, &myReturnedDuration);
		BailError(myErr);
		
		myCurrentDuration += myReturnedDuration;
#endif // MAKE_STILL_SECTIONS
		
		// dispose of previous source movie.  
		DisposeMovie(myPrevSrcMovie);
		
		myPrevSrcMovie = myNextSrcMovie;
		myPrevSrcTrack = myNextSrcTrack;
		myNextSrcMovie = NULL;
		myNextSrcTrack = NULL;
		
		myMovieIter++;
	} // while
	
	myErr = EndMediaEdits(videoMediaFX);
	BailError(myErr);

	myErr = AddMovieResource(myDestMovie, myDestMovieRefNum, &myResID, "\pMovie 1");
	BailError(myErr);
	
	CloseMovieFile(myDestMovieRefNum);
	
	if (myPrevSrcMovie != NULL)
		DisposeMovie(myPrevSrcMovie);
		
	DisposeMovie(myDestMovie);
	
bail:
	free(myPrompt);
	free(myFileName);

	QTDisposeAtomContainer(gEffectSample);
	DisposeHandle((Handle)myDesc);

	return;
}
OSErr makeMovieFromVideoFramesFile(char *inDestMovieFile)
{
    Handle					dataRef = NULL;
    OSType					dataRefType;
    ImageDescriptionHandle	videoDescH = NULL;
	OSErr					err;

#if TARGET_OS_WIN32
	err = InitializeQTML(0);
	if ((err = GetMoviesError()) != noErr) goto bail;
#endif
	err = EnterMovies();
	if ((err = GetMoviesError()) != noErr) goto bail;

	// create a data reference from the full path to the video frames file
	makeDataRefFromFullPath(inDestMovieFile, &dataRef, &dataRefType);
	if (dataRef == NULL) goto bail;

    Movie m = NewMovie(0);
	if ((err = GetMoviesError()) != noErr) goto bail;

	// create the video track for the movie
    Track videoT = NewMovieTrack( m, Long2Fix(kFrameWidth), Long2Fix(kFrameHeight), kNoVolume);
	if ((err = GetMoviesError()) != noErr) goto bail;
	
	// create the video track media
    Media videoM = NewTrackMedia( videoT, VideoMediaType, kMediaTimeScale, dataRef, dataRefType);
	if ((err = GetMoviesError()) != noErr) goto bail;
	
	videoDescH = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
	if (videoDescH == NULL) goto bail;
	
	// create the ImageDescription that will describe our video track media samples
    videoDescH[0]->idSize = sizeof(ImageDescription);
    videoDescH[0]->cType = kCodecType; // the codec type for your data 
    videoDescH[0]->temporalQuality = codecNormalQuality;
    videoDescH[0]->spatialQuality = codecNormalQuality;
    videoDescH[0]->width = kFrameWidth;
    videoDescH[0]->height = kFrameHeight;
    videoDescH[0]->hRes = 72L << 16;
    videoDescH[0]->vRes = 72L << 16;
    videoDescH[0]->depth = 32;
    videoDescH[0]->clutID = -1;

    SampleReference64Record videoRef;
    videoRef.dataOffset.hi = 0; videoRef.dataOffset.lo = 0;
    videoRef.dataSize = (kFrameWidth*kFrameHeight*4) * kNumberOfSamples; 
    videoRef.durationPerSample = kDurationPerSample;
    videoRef.numberOfSamples = kNumberOfSamples;
    videoRef.sampleFlags = 0;

	// now add all of our media samples to the movie data file.
    err = AddMediaSampleReferences64(videoM, (SampleDescriptionHandle)videoDescH,
                            1, &videoRef, 0);
	if (err != noErr) goto bail;

    TimeValue mediaDuration = kNumberOfSamples * kDurationPerSample;
	// inserts a reference to our media samples into the track.
    err = InsertMediaIntoTrack(videoT, 0, 0, mediaDuration, 
				fixed1);	// media's rate (1.0 = media's natural playback rate).
	if (err != noErr) goto bail;

    DataHandler outDataHandler;
	// opens a data handler for our movie storage (the video frames file)
    err = OpenMovieStorage (dataRef, dataRefType, kDataHCanWrite, &outDataHandler );
	if (err != noErr) goto bail;
	
	// add a movie to our movie storage container
    err = AddMovieToStorage (m, outDataHandler );
	if (err != noErr) goto bail;

    err = CloseMovieStorage (outDataHandler);
	outDataHandler = NULL;
	
bail:
	if (videoDescH)
	{
		DisposeHandle((Handle)videoDescH);
	}
	
	return err;
}
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);
}