OSErr QTEffects_GetFirstVideoTrackInMovie (Movie theMovie, Track *theTrack)
{
	*theTrack = GetMovieIndTrackType(theMovie, 1, kCharacteristicCanSendVideo, movieTrackCharacteristic | movieTrackEnabledOnly);
	
	if (*theTrack == NULL)
		return(invalidTrack);
		
	return(noErr);
}
Ejemplo n.º 2
0
TLevelReader3gp::TLevelReader3gp(const TFilePath &path)
	: TLevelReader(path), m_IOError(QTNoError), m_track(0), m_movie(0), m_depth(0)
//                ,m_timeScale(0)
{

	FSSpec fspec;
	QDErr err;
	Boolean dataRefWasChanged;
	if (QuickTimeStuff::instance()->getStatus() != noErr) {
		m_IOError = QTNotInstalled;
		return;
	}

	const char *pStr = toString(m_path.getWideString()).c_str();
	FSMakeFSSpec(0, 0, (const unsigned char *)pStr, &fspec);
	getFSSpecFromPosixPath(pStr, &fspec, false);
	pStr = 0;

	if ((err = OpenMovieFile(&fspec, &m_refNum, fsRdPerm))) {
		m_IOError = QTUnableToOpenFile;
		return;
	}

	m_resId = 0;
	Str255 name;
	err = NewMovieFromFile(&m_movie, m_refNum, &m_resId,
						   name, fsRdPerm, &dataRefWasChanged);

	int numTracks = GetMovieTrackCount(m_movie);
	assert(numTracks == 1 || numTracks == 2);

	m_track = GetMovieIndTrackType(m_movie, 1, VideoMediaType, movieTrackMediaType);

	//m_track=GetMovieTrack(m_movie,numTracks);

	ImageDescriptionHandle imageH;
	imageH = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
	TINT32 index = 1;
	Media theMedia = GetTrackMedia(m_track);

	GetMediaSampleDescription(theMedia, index, (SampleDescriptionHandle)imageH);
	ImageDescriptionPtr imagePtr = *imageH;
	m_lx = imagePtr->width;
	m_ly = imagePtr->height;
	m_depth = imagePtr->depth;
	m_info = new TImageInfo();
	m_info->m_lx = m_lx;
	m_info->m_ly = m_ly;
	Tiio::MovWriterProperties *prop = new Tiio::MovWriterProperties();
	m_info->m_properties = prop;

	DisposeHandle((Handle)imageH);

	m_info->m_frameRate = GetMediaTimeScale(theMedia);
}
Ejemplo n.º 3
0
Media GetMediaFromMovie(Movie mov)
{
   Track theTrack;

   // get the first sound track
   theTrack = GetMovieIndTrackType(mov, 1,
				   SoundMediaType, movieTrackMediaType);
   if(theTrack == NULL)
      return NULL;

   return GetTrackMedia(theTrack);
}
Ejemplo n.º 4
0
quicktime_player* quicktime_player::open( const char *path ) {
    OSErr err;
    OSType dataRefType;
    Handle dataRef = NULL;
    short resID = 0;
    impl *m = new impl;

    std::string pathStd = path;
    #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, (QTPathStyle)kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType);
    CFRelease(cfPath);
    if (err != noErr) {
        delete m;
        return NULL;
    }

    err = NewMovieFromDataRef(&m->movie, newMovieActive, &resID, dataRef, dataRefType);
    DisposeHandle(dataRef);
    if (err != noErr) {
        delete m;
        return NULL;
    }   

    m->track = GetMovieIndTrackType(m->movie, 1, VisualMediaCharacteristic, movieTrackCharacteristic);
    m->media = GetTrackMedia(m->track);

    Rect bounds;
    GetMovieBox(m->movie, &bounds);
    m->width = bounds.right;
    m->height = bounds.bottom;

    m->buffer = (unsigned char*)malloc(4 * m->width * m->height);
    err = QTNewGWorldFromPtr(&m->gworld, k32BGRAPixelFormat, &bounds, NULL, NULL, 0, m->buffer, 4 * m->width);
    if (err != noErr) {
        delete m;
        return NULL;
    }
    SetMovieGWorld(m->movie, m->gworld, NULL);

    return new quicktime_player(m);
}
/*

Get the media identifier for the media that contains the first
video track's sample data, and also get the media handler for
this media.

*/
void MovieGetVideoMediaAndMediaHandler(Movie inMovie, Media *outMedia, MediaHandler *outMediaHandler)
{

  *outMedia = NULL;
  *outMediaHandler = NULL;

  /* get first video track */
  Track videoTrack = GetMovieIndTrackType(inMovie, 1, kCharacteristicHasVideoFrameRate,
              movieTrackCharacteristic | movieTrackEnabledOnly);
  if (videoTrack != NULL)
  {
    /* get media ref. for track's sample data */
    *outMedia = GetTrackMedia(videoTrack);
    if (*outMedia)
    {
      /* get a reference to the media handler component */
      *outMediaHandler = GetMediaHandler(*outMedia);
    }
  }
}
Ejemplo n.º 6
0
int main( int argc, char **argv ) {

    Movie movie;
    Track track;
    Media media;
    short refNum;
    short resID = 0;
    Boolean wasChanged;
    OSErr err = noErr;
    FSSpec fsspec;
    AudioFormatAtomPtr outAudioAtom;
    CmpSoundHeader outSoundInfo;
    SoundComponentData theInputFormat,
                       theOutputFormat;
    SoundConverter mySoundConverter = NULL;
//    SCFillBufferData scFillBufferData = { NULL };
    Ptr pDecomBuffer0 = NULL,
        pDecomBuffer1 = NULL;
    long kMaxOutputBuffer = 64 * 1024;
    long noFrames = 0,
                  niFrames = 0,
                  noBytes = 0,
                  noSamples = 0;
#define MAX_BUFFER_SIZE 256 * 1024 * 1024


    /** Initialise MovieToolbox */
    EnterMovies();

    /** Open the movie file from the first argument */
    printf( "opening audio file: '%s'\n", argv[1] );
    path2fss( &fsspec, argv[1] );
    err = OpenMovieFile( &fsspec, &refNum, fsRdPerm );
    if ( err != noErr ) {
        printf( "failed to open audio: %d\n", GetMoviesError() );
        exit( -1 );
      }

    /** Instantiate the movie */
    err = NewMovieFromFile( &movie, refNum, &resID, NULL,
                            newMovieActive, &wasChanged );
    if ( err ) {
        printf( "failed to instantiate movie\n" );
        exit( -1 );
      }

    CloseMovieFile( refNum );
    refNum = 0;

    /** Get the first sound track */
    track = GetMovieIndTrackType( movie, 1, SoundMediaType,
                                  movieTrackMediaType );
    if ( track == NULL ) {
        printf( "failed to get sound track\n" );
        exit( -1 );
      }

    /** Get the sound track media */
    media = GetTrackMedia( track );
    if ( media == NULL ) {
        printf( "failed to get media from audio track\n" );
        exit( -1 );
      }

    Size size;
    Handle extension;
    SoundDescriptionHandle sourceSoundDescription;

    sourceSoundDescription = (SoundDescriptionHandle)NewHandle(0);

    /** Get the description of the sample data */
    GetMediaSampleDescription( media, 1,
                               (SampleDescriptionHandle)sourceSoundDescription );
    err = GetMoviesError();
    if ( err ) {
        printf( "failed to get description of sample data\n" );
        exit( -1 );
      }

    extension = NewHandle( 0 );

    // get the "magic" decompression atom
    // This extension to the SoundDescription information stores
    // data specific to a given audio decompressor. Some audio
    // decompression algorithms require a set of out-of-stream
    // values to configure the decompressor.
    err = 
        GetSoundDescriptionExtension( (SoundDescriptionHandle)sourceSoundDescription,
                                      &extension, siDecompressionParams );
    if ( noErr == err ) {
        size = GetHandleSize( extension );
        printf( "transferring data to audio buffer: %d bytes\n", size );
        HLock( extension );
        outAudioAtom = (AudioFormatAtom*)NewPtr( size );
        err = MemError();
        // copy the atom data to our buffer...
        BlockMoveData( *extension, outAudioAtom, size );
        HUnlock( extension );
      } else {
        // if it doesn't have an atom, that's ok
        outAudioAtom = NULL;
        err = noErr;
      }

    /** Setup our sound header */
    outSoundInfo.format = (*sourceSoundDescription)->dataFormat;
    outSoundInfo.numChannels = (*sourceSoundDescription)->numChannels;
    outSoundInfo.sampleSize = (*sourceSoundDescription)->sampleSize;
    outSoundInfo.sampleRate = (*sourceSoundDescription)->sampleRate;
    outSoundInfo.compressionID = (*sourceSoundDescription)->compressionID;

    float db = ((float)outSoundInfo.sampleRate)/(1<<16);

    printf( "sample: %d\tchannels: %d\tsample size: %d\tsample rate: %f\tcompressionID: %d\n",
            outSoundInfo.format, outSoundInfo.numChannels, outSoundInfo.sampleSize,
            db, outSoundInfo.compressionID );

    DisposeHandle( extension );
    DisposeHandle( (Handle)sourceSoundDescription );

    /** 
     * Now that we've figured out what the audio file is, allocate buffers
     * and so on for conversion and playback
     */

    printf( "initialising input/output conversion buffers\n" );

    /** setup input/output format for sound converter */
    theInputFormat.flags = 0;
    theInputFormat.format = outSoundInfo.format;
    theInputFormat.numChannels = outSoundInfo.numChannels;
    theInputFormat.sampleSize = outSoundInfo.sampleSize;
    theInputFormat.sampleRate = outSoundInfo. sampleRate;
    theInputFormat.sampleCount = 0;
    theInputFormat.buffer = NULL;
    theInputFormat.reserved = 0;

    theOutputFormat.flags = 0;
    theOutputFormat.format = kSoundNotCompressed;
    theOutputFormat.numChannels = theInputFormat.numChannels;
    theOutputFormat.sampleSize = theInputFormat.sampleSize;
    theOutputFormat.sampleRate = theInputFormat.sampleRate;
    theOutputFormat.sampleCount = 0;
    theOutputFormat.buffer = NULL;
    theOutputFormat.reserved = 0;

    // variableCompression means we're going to use the commonFrameSize field and the kExtendedSoundCommonFrameSizeValid flag
//    scFillBufferData.isSourceVBR = (outSoundInfo.compressionID == variableCompression );

    err = SoundConverterOpen( &theInputFormat, &theOutputFormat, 
                              &mySoundConverter );
    if ( err != noErr ) {
        printf( "failed to open sound converter\n" );
        exit( -1 );
      } else {
        printf( "opened sound converter ok\n" );
      }

    // this isn't crucial or even required for decompression only, but it does tell
    // the sound converter that we're cool with VBR audio
    Ptr tptr = NewPtr( 1 );
    tptr[0] = 1;
    SoundConverterSetInfo( mySoundConverter, siClientAcceptsVBR, tptr );
    free( tptr );

    /**
     * Set up the sound converters decompresson 'environment' by passing
     * in the 'magic' decompression atom
     */
    err = 
        SoundConverterSetInfo( mySoundConverter, siDecompressionParams,
                               outAudioAtom );
    if ( err != noErr ) {
        printf( "failed to set sound converter info\n" );
        exit( -1 );
      } else {
        printf( "set sound converter info ok\n" );
      }

    if ( outAudioAtom ) {
        DisposePtr( (Ptr)outAudioAtom );
      }

    if ( siUnknownInfoType == err ) {
        // clear this error, the decompressor didn't
        // need the decompression atom and that's OK
        err = noErr;
      } else {
//        BailErr(err);
      }

    /** 
     * The input buffer has to be large enough so GetMediaSample isn't
     * going to fail, your mileage may vary
     */
    Handle inputBuffer = NewHandle( MAX_BUFFER_SIZE );
//    HLock( inputBuffer );

    /** Start the sound conversion */
    err = SoundConverterBeginConversion(mySoundConverter);
//    BailErr(err);

    /** Extract compressed audio from media track */
    TimeValue tperSample = 0;
    err = 
        GetMediaSample( media, inputBuffer, 0, 
                        &noBytes, 0, NULL, &tperSample, NULL, NULL, 0, &noSamples, NULL );
    if ( err != noErr ) {
        printf( "failed to fetch media sample data: %d\n", GetMoviesError() );
        exit( -1 );
      } else {
        printf( "media sample: %d (%d) bytes / %ld samples / %d per sample\n", 
                noBytes, GetHandleSize( inputBuffer ), noSamples, tperSample );
      }

    unsigned long niBytes = 0;
    SoundConverterGetBufferSizes( mySoundConverter, noBytes * noSamples,
                                  &niFrames, &niBytes, &noBytes );

    printf( "buffer sizes: frames: %d\tibytes: %d\tobytes: %d\n",
            niFrames, niBytes, noBytes );

    /** Convert into uncompressed audio */
    Ptr outputBuffer = NewPtr( noBytes * 1.2 );
    SoundConverterConvertBuffer( mySoundConverter, inputBuffer, noSamples /* niFrames */, 
                                 outputBuffer, &noFrames, &noBytes );

    printf( "converted: %d frames / %d bytes\n", noFrames, noBytes );

    /** Shutdown the sound converter */
    err = SoundConverterEndConversion( mySoundConverter, outputBuffer, &noFrames, &noBytes );

    printf( "converted final: %d frames / %d bytes\n", noFrames, noBytes );

//    HUnlock( inputBuffer );

    /** We now should have decompressed audio for the input file */
    /** 
     * So, generate visuals using a sliding sample grid at the
     * given framerate
     */

    /** Create a new movie clip with audio and video tracks */

    /** PROJECTM CRAP HERE -- stuff frames into QuickTime */

    /** Close movie file */

    /** Shutdown MovieToolbox */
    ExitMovies();

    return 0;
  }
Ejemplo n.º 7
0
static HRESULT QT_Process_Movie(QTSplitter* filter)
{
    HRESULT hr = S_OK;
    OSErr err;
    WineDataRefRecord ptrDataRefRec;
    Handle dataRef = NULL;
    Track trk;
    short id = 0;
    DWORD tid;
    LONGLONG time;

    TRACE("Trying movie connect\n");

    ptrDataRefRec.pReader = filter->pInputPin.pReader;
    ptrDataRefRec.streamSubtype = filter->pInputPin.subType;
    PtrToHand( &ptrDataRefRec, &dataRef, sizeof(WineDataRefRecord));

    err = NewMovieFromDataRef(&filter->pQTMovie, newMovieActive|newMovieDontInteractWithUser|newMovieDontAutoUpdateClock|newMovieDontAskUnresolvedDataRefs|newMovieAsyncOK, &id, dataRef, 'WINE');

    DisposeHandle(dataRef);

    if (err != noErr)
    {
        FIXME("QuickTime cannot handle media type(%i)\n",err);
        return VFW_E_TYPE_NOT_ACCEPTED;
    }

    PrePrerollMovie(filter->pQTMovie, 0, fixed1, NULL, NULL);
    PrerollMovie(filter->pQTMovie, 0, fixed1);
    GoToBeginningOfMovie(filter->pQTMovie);
    SetMovieActive(filter->pQTMovie,TRUE);

    if (GetMovieLoadState(filter->pQTMovie) < kMovieLoadStateLoaded)
        MoviesTask(filter->pQTMovie,100);

    trk = GetMovieIndTrackType(filter->pQTMovie, 1, VisualMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly);
    TRACE("%p is a video track\n",trk);
    if (trk)
       hr = QT_Process_Video_Track(filter, trk);

    if (FAILED(hr))
        return hr;

    trk = GetMovieIndTrackType(filter->pQTMovie, 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly);
    TRACE("%p is a audio track\n",trk);
    if (trk)
        hr = QT_Process_Audio_Track(filter, trk);

    time = GetMovieDuration(filter->pQTMovie);
    filter->movie_scale = GetMovieTimeScale(filter->pQTMovie);
    filter->sourceSeeking.llDuration = ((double)time / filter->movie_scale) * 10000000;
    filter->sourceSeeking.llStop = filter->sourceSeeking.llDuration;

    TRACE("Movie duration is %s\n",wine_dbgstr_longlong(filter->sourceSeeking.llDuration));

    filter->loaderThread = CreateThread(NULL, 0, QTSplitter_loading_thread, filter, 0, &tid);
    if (filter->loaderThread)
        TRACE("Created loading thread 0x%08x\n", tid);
    filter->splitterThread = CreateThread(NULL, 0, QTSplitter_thread, filter, 0, &tid);
    if (filter->splitterThread)
        TRACE("Created processing thread 0x%08x\n", tid);
    else
        hr = HRESULT_FROM_WIN32(GetLastError());

    return hr;
}
Ejemplo n.º 8
0
Boolean QTApp_HandleMenu (UInt16 theMenuItem)
{
	WindowObject		myWindowObject = NULL;
	ApplicationDataHdl	myAppData = NULL;
	MovieController 	myMC = NULL;
	Movie			 	myMovie = NULL;
	Boolean				myIsHandled = false;			// false => allow caller to process the menu item
	OSErr				myErr = noErr;
	
	myWindowObject = QTFrame_GetWindowObjectFromFrontWindow();
	if (myWindowObject != NULL) {
		myMC = (**myWindowObject).fController;
		myMovie = (**myWindowObject).fMovie;
		myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(myWindowObject);
	}
	
	switch (theMenuItem) {
	
		case IDM_SET_TEXT:
			// put up a dialog box to get a text string
			QTText_SetSearchText();
			myIsHandled = true;
			break;
				
		case IDM_FIND_TEXT:
			QTText_FindText(myWindowObject, gSearchText);
			myIsHandled = true;
			break;
				
		case IDM_EDIT_TEXT:
			QTText_EditText(myWindowObject);
			myIsHandled = true;
			break;
				
		case IDM_SEARCH_FORWARD:
			gSearchForward = true;	
			myIsHandled = true;
			break;
				
		case IDM_SEARCH_BACKWARD:
			gSearchForward = false;	
			myIsHandled = true;
			break;
				
		case IDM_WRAP_SEARCH:
			gSearchWrap = !gSearchWrap;	
			myIsHandled = true;
			break;
				
		case IDM_USE_CASE:
			gSearchWithCase = !gSearchWithCase;	
			myIsHandled = true;
			break;
				
		case IDM_ADD_TEXT_TRACK:
			{
				// add a text track to the specified movie;
				// for purposes of illustration, we'll add 11 (count 'em!) text strings to the movie,
				// with each string occupying about one-tenth of the movie duration
				
				Track		myTypeTrack = NULL;
				Track		myTextTrack = NULL;
				TimeValue	myMovieDuration = 0;
				TimeValue	mySampleDuration = 0;
				char		*myStrings[] = {"0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"};
				short		myFrames[11];
				Boolean		isChapter = true;
				
				myTypeTrack = GetMovieIndTrackType(myMovie, 1, VideoMediaType, movieTrackMediaType);
				if (myTypeTrack == NULL)
					break;
					
				// get the duration of the movie and the duration of a single frame;
				// this tells us how many frames fit into one-tenth of the movie
				myMovieDuration = GetMovieDuration(myMovie);
				mySampleDuration = QTUtils_GetFrameDuration(myTypeTrack);
				
				myFrames[0] = (myMovieDuration / mySampleDuration) / 10;
				myFrames[1] = (myMovieDuration / mySampleDuration) / 10;
				myFrames[2] = (myMovieDuration / mySampleDuration) / 10;				
				myFrames[3] = (myMovieDuration / mySampleDuration) / 10;
				myFrames[4] = (myMovieDuration / mySampleDuration) / 10;
				myFrames[5] = (myMovieDuration / mySampleDuration) / 10;				
				myFrames[6] = (myMovieDuration / mySampleDuration) / 10;
				myFrames[7] = (myMovieDuration / mySampleDuration) / 10;
				myFrames[8] = (myMovieDuration / mySampleDuration) / 10;				
				myFrames[9] = ((myMovieDuration / mySampleDuration) / 10) - 1;
				myFrames[10] = 1;
								
				myTextTrack = QTText_AddTextTrack(myMovie, myStrings, myFrames, 11, VideoMediaType, isChapter);
				if (myTextTrack != NULL) {

					MCMovieChanged(myMC, myMovie);

					// stamp the movie as dirty and update our saved data
					(**myWindowObject).fIsDirty = true;
					(**myAppData).fMovieHasText = true;
					(**myAppData).fTextIsChapter = isChapter;
					(**myAppData).fTextTrack = myTextTrack;
					(**myAppData).fTextHandler = GetMediaHandler(GetTrackMedia(myTextTrack));
				}
			}
			myIsHandled = true;
			break;
				
		case IDM_CUT_TEXT_TRACK:
			// remove all existing text tracks from the specified movie
			myErr = QTText_RemoveIndTextTrack(myWindowObject, kAllTextTracks);
			if (myErr == noErr) {
			
				MCMovieChanged(myMC, myMovie);

				// stamp the movie as dirty and update our saved data
				(**myWindowObject).fIsDirty = true;
				(**myAppData).fMovieHasText = false;
				(**myAppData).fTextIsChapter = false;
				(**myAppData).fTextIsHREF = false;
				(**myAppData).fTextTrack = NULL;
				(**myAppData).fTextHandler = NULL;
			}
			myIsHandled = true;
			break;
				
		case IDM_CHAPTER_TRACK:
			(**myAppData).fTextIsChapter = !(**myAppData).fTextIsChapter;
			QTText_SetTextTrackAsChapterTrack(myWindowObject, VideoMediaType, (**myAppData).fTextIsChapter);
			(**myWindowObject).fIsDirty = true;
			myIsHandled = true;
			break;
			
		case IDM_HREF_TRACK:
			(**myAppData).fTextIsHREF = !(**myAppData).fTextIsHREF;
			QTText_SetTextTrackAsHREFTrack((**myAppData).fTextTrack, (**myAppData).fTextIsHREF);
			(**myWindowObject).fIsDirty = true;
			myIsHandled = true;
			break;
			
		default:
			break;
	} // switch (theMenuItem)
	
	return(myIsHandled);
}
QuickTimeFileReader::QuickTimeFileReader(FileSource source,
                                         DecodeMode decodeMode,
                                         CacheMode mode,
                                         size_t targetRate,
                                         ProgressReporter *reporter) :
    CodedAudioFileReader(mode, targetRate),
    m_source(source),
    m_path(source.getLocalFilename()),
    m_d(new D),
    m_reporter(reporter),
    m_cancelled(false),
    m_completion(0),
    m_decodeThread(0)
{
    m_channelCount = 0;
    m_fileRate = 0;

    Profiler profiler("QuickTimeFileReader::QuickTimeFileReader", true);

SVDEBUG << "QuickTimeFileReader: path is \"" << m_path << "\"" << endl;

    long QTversion;

#ifdef WIN32
    InitializeQTML(0); // FIXME should check QT version
#else
    m_d->err = Gestalt(gestaltQuickTime,&QTversion);
    if ((m_d->err != noErr) || (QTversion < 0x07000000)) {
        m_error = QString("Failed to find compatible version of QuickTime (version 7 or above required)");
        return;
    }
#endif 

    EnterMovies();
	
    Handle dataRef; 
    OSType dataRefType;

//    CFStringRef URLString = CFStringCreateWithCString
 //       (0, m_path.toLocal8Bit().data(), 0);


    QByteArray ba = m_path.toLocal8Bit();

    CFURLRef url = CFURLCreateFromFileSystemRepresentation
        (kCFAllocatorDefault,
         (const UInt8 *)ba.data(),
         (CFIndex)ba.length(),
         false);


//    m_d->err = QTNewDataReferenceFromURLCFString
    m_d->err = QTNewDataReferenceFromCFURL
        (url, 0, &dataRef, &dataRefType);

    if (m_d->err) { 
        m_error = QString("Error creating data reference for QuickTime decoder: code %1").arg(m_d->err);
        return;
    }
    
    short fileID = movieInDataForkResID; 
    short flags = 0; 
    m_d->err = NewMovieFromDataRef
        (&m_d->movie, flags, &fileID, dataRef, dataRefType);

    DisposeHandle(dataRef);
    if (m_d->err) { 
        m_error = QString("Error creating new movie for QuickTime decoder: code %1").arg(m_d->err); 
        return;
    }

    Boolean isProtected = 0;
    Track aTrack = GetMovieIndTrackType
        (m_d->movie, 1, SoundMediaType,
         movieTrackMediaType | movieTrackEnabledOnly);

    if (aTrack) {
        Media aMedia = GetTrackMedia(aTrack);	// get the track media
        if (aMedia) {
            MediaHandler mh = GetMediaHandler(aMedia);	// get the media handler we can query
            if (mh) {
                m_d->err = QTGetComponentProperty(mh,
                                                  kQTPropertyClass_DRM,
                                                  kQTDRMPropertyID_IsProtected,
                                                  sizeof(Boolean), &isProtected,nil);
            } else {
                m_d->err = 1;
            }
        } else {
            m_d->err = 1;
        }
    } else {
        m_d->err = 1;
    }
	
    if (m_d->err && m_d->err != kQTPropertyNotSupportedErr) { 
        m_error = QString("Error checking for DRM in QuickTime decoder: code %1").arg(m_d->err);
        return;
    } else if (!m_d->err && isProtected) { 
        m_error = QString("File is protected with DRM");
        return;
    } else if (m_d->err == kQTPropertyNotSupportedErr && !isProtected) {
        std::cerr << "QuickTime: File is not protected with DRM" << std::endl;
    }

    if (m_d->movie) {
        SetMovieActive(m_d->movie, TRUE);
        m_d->err = GetMoviesError();
        if (m_d->err) {
            m_error = QString("Error in QuickTime decoder activation: code %1").arg(m_d->err);
            return;
        }
    } else {
	m_error = QString("Error in QuickTime decoder: Movie object not valid");
	return;
    }
    
    m_d->err = MovieAudioExtractionBegin
        (m_d->movie, 0, &m_d->extractionSessionRef);
    if (m_d->err) {
        m_error = QString("Error in QuickTime decoder extraction init: code %1").arg(m_d->err);
        return;
    }

    m_d->err = MovieAudioExtractionGetProperty
        (m_d->extractionSessionRef,
         kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
         sizeof(m_d->asbd),
         &m_d->asbd,
         nil);

    if (m_d->err) {
        m_error = QString("Error in QuickTime decoder property get: code %1").arg(m_d->err);
        return;
    }
	
    m_channelCount = m_d->asbd.mChannelsPerFrame;
    m_fileRate = m_d->asbd.mSampleRate;

    std::cerr << "QuickTime: " << m_channelCount << " channels, " << m_fileRate << " kHz" << std::endl;

    m_d->asbd.mFormatFlags =
        kAudioFormatFlagIsFloat |
        kAudioFormatFlagIsPacked |
        kAudioFormatFlagsNativeEndian;
    m_d->asbd.mBitsPerChannel = sizeof(float) * 8;
    m_d->asbd.mBytesPerFrame = sizeof(float) * m_d->asbd.mChannelsPerFrame;
    m_d->asbd.mBytesPerPacket = m_d->asbd.mBytesPerFrame;
	
    m_d->err = MovieAudioExtractionSetProperty
        (m_d->extractionSessionRef,
         kQTPropertyClass_MovieAudioExtraction_Audio,
         kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
         sizeof(m_d->asbd),
         &m_d->asbd);

    if (m_d->err) {
        m_error = QString("Error in QuickTime decoder property set: code %1").arg(m_d->err);
        m_channelCount = 0;
        return;
    }
    m_d->buffer.mNumberBuffers = 1;
    m_d->buffer.mBuffers[0].mNumberChannels = m_channelCount;
    m_d->buffer.mBuffers[0].mDataByteSize =
        sizeof(float) * m_channelCount * m_d->blockSize;
    m_d->data = new float[m_channelCount * m_d->blockSize];
    m_d->buffer.mBuffers[0].mData = m_d->data;

    initialiseDecodeCache();

    if (decodeMode == DecodeAtOnce) {

        if (m_reporter) {
            connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled()));
            m_reporter->setMessage
                (tr("Decoding %1...").arg(QFileInfo(m_path).fileName()));
        }

        while (1) {
            
            UInt32 framesRead = m_d->blockSize;
            UInt32 extractionFlags = 0;
            m_d->err = MovieAudioExtractionFillBuffer
                (m_d->extractionSessionRef, &framesRead, &m_d->buffer,
                 &extractionFlags);
            if (m_d->err) {
                m_error = QString("Error in QuickTime decoding: code %1")
                    .arg(m_d->err);
                break;
            }

            //!!! progress?

//    std::cerr << "Read " << framesRead << " frames (block size " << m_d->blockSize << ")" << std::endl;

            // QuickTime buffers are interleaved unless specified otherwise
            addSamplesToDecodeCache(m_d->data, framesRead);

            if (framesRead < m_d->blockSize) break;
        }
        
        finishDecodeCache();
        endSerialised();

        m_d->err = MovieAudioExtractionEnd(m_d->extractionSessionRef);
        if (m_d->err) {
            m_error = QString("Error ending QuickTime extraction session: code %1").arg(m_d->err);
        }

        m_completion = 100;

    } else {
        if (m_reporter) m_reporter->setProgress(100);

        if (m_channelCount > 0) {
            m_decodeThread = new DecodeThread(this);
            m_decodeThread->start();
        }
    }

    std::cerr << "QuickTimeFileReader::QuickTimeFileReader: frame count is now " << getFrameCount() << ", error is \"\"" << m_error << "\"" << std::endl;
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
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);
}