Exemple #1
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" );
} 
Exemple #2
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);
} 
/*

Given a reference to the media that contains the sample data for a track,
calculate the static frame rate.

*/
OSErr MediaGetStaticFrameRate(Media inMovieMedia, double *outFPS)
{
  *outFPS = 0;

    /* get the number of samples in the media */
  long sampleCount = GetMediaSampleCount(inMovieMedia);
  OSErr err = GetMoviesError();

  if (sampleCount && err == noErr)
  {
      /* find the media duration */

    //Quicktime 7.0 code
    //TimeValue64 duration = GetMediaDisplayDuration(inMovieMedia);
    TimeValue64 duration = GetMediaDuration(inMovieMedia);


    err = GetMoviesError();
    if (err == noErr)
    {
        /* get the media time scale */
      TimeValue64 timeScale = GetMediaTimeScale(inMovieMedia);
      err = GetMoviesError();
      if (err == noErr)
      {
        /* calculate the frame rate:
          frame rate = (sample count * media time scale) / media duration
          */
        *outFPS = (double)sampleCount * (double)timeScale / (double)duration;
      }
    }
  }

  return err;
}
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);
}
Exemple #5
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 ofxQtAudioRecorder::closeMovie(){
	
	short movieResId = movieInDataForkResID;
	AddMovieResource(movie, movieResRefNum, &movieResId, NULL);
	OSErr err = GetMoviesError();
	
	if(err != noErr){
		
		printf("error adding movie resource\n");
		return;
	}
	
	if(movieResRefNum != 0)
	{
		CloseMovieFile(movieResRefNum);
	}
	
	if(movie != NULL)
	{
		DisposeMovie(movie);
	}
	
	if(soundDesc != NULL)
	{
		DisposeHandle((Handle)soundDesc);
		soundDesc = NULL;
	}
	
	movie = NULL;
	movieResRefNum = 0;
	audioMedia = NULL;
	audioTrack = NULL;
	
	printf("closed movie file\n");
}
Exemple #7
0
/*  returns the ImageDescriptionHandle for the track.
    If it's not a video track, return NULL
*/
static ImageDescriptionHandle track_image_description(VALUE obj)
{
  OSErr osErr;

	/* restrict reporting to video track */
  if (track_get_media_type(obj) != VideoMediaType)
    return NULL;
  
	SampleDescriptionHandle sample_description = NULL;
  sample_description = (SampleDescriptionHandle)NewHandle(sizeof(SampleDescription));
  if (LMGetMemErr() != noErr) {
    rb_raise(eQuickTime, "Memory Error %d when determining image description", LMGetMemErr());
    return NULL;
  }

	GetMediaSampleDescription(TRACK_MEDIA(obj), 1, sample_description);
	osErr = GetMoviesError();
  if (osErr != noErr) {
    rb_raise(eQuickTime, "Movie Error %d when determining image description", osErr);
    DisposeHandle((Handle)sample_description);
    return NULL;
  }
  
  return (ImageDescriptionHandle)sample_description;
}
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;	
}
Exemple #9
0
OSErr QTCode_GetStartPointOfFirstVideoSample(Movie		theMovie,
											TimeValue	*startPoint) 
{
	OSErr	anErr = noErr;
	OSType	media = VideoMediaType;
	
	*startPoint = -1;

	GetMovieNextInterestingTime(theMovie, nextTimeMediaSample+nextTimeEdgeOK, (TimeValue)1, &media, 0, 
								fixed1, startPoint, NULL);
	anErr = GetMoviesError();

	return anErr;
}
OSErr QTDR_PlayMovieFromRAM (Movie theMovie)
{
	WindowPtr				myWindow = NULL;
	Rect					myBounds = {50, 50, 100, 100};
	Rect					myRect;
	StringPtr				myTitle = QTUtils_ConvertCToPascalString(kWindowTitle);
	OSErr					myErr = memFullErr;

	myWindow = NewCWindow(NULL, &myBounds, myTitle, false, 0, (WindowPtr)-1, false, 0);
	if (myWindow == NULL)
		goto bail;
		
	myErr = noErr;
	
	MacSetPort((GrafPtr)GetWindowPort(myWindow));

	GetMovieBox(theMovie, &myRect);
	MacOffsetRect(&myRect, -myRect.left, -myRect.top);
	SetMovieBox(theMovie, &myRect);

	if (!EmptyRect(&myRect))
		SizeWindow(myWindow, myRect.right, myRect.bottom, false);
	else
		SizeWindow(myWindow, 200, 0, false);
		
	MacShowWindow(myWindow);

	SetMovieGWorld(theMovie, GetWindowPort(myWindow), NULL);
	GoToBeginningOfMovie(theMovie);
	MoviesTask(theMovie, 0);
	StartMovie(theMovie);
	
	myErr = GetMoviesError();
	if (myErr != noErr)
		goto bail;
	
	while (!IsMovieDone(theMovie))
		MoviesTask(theMovie, 0);

bail:
	free(myTitle);
	
	if (theMovie != NULL)
		DisposeMovie(theMovie);

	if (myWindow != NULL)
		DisposeWindow(myWindow);
		
	return(myErr);
}
Exemple #11
0
TLevelWriter3gp::TLevelWriter3gp(const TFilePath &path, TPropertyGroup *winfo)
	: TLevelWriter(path, winfo), m_initDone(false), m_IOError(QTNoError), m_pixmap(0), m_compressedData(0), m_gworld(0), m_videoMedia(0), m_videoTrack(0), m_movie(0), m_cancelled(false), m_soundDataRef(0), m_hSoundMovieData(0)

{
	m_frameRate = 12.;
	QDErr err;
	//FSSpec fspec;
	if (QuickTimeStuff::instance()->getStatus() != noErr) {
		m_IOError = QTNotInstalled;
		throw TImageException(m_path, buildQTErrorString(m_IOError));
	}

	m_movie = NewMovie(0);
	if ((err = GetMoviesError() != noErr))
		throw TImageException(getFilePath(), "can't create movie");
}
bool
qtCanvas::Impl::setupMovie()
{
	OSErr err;

	Handle dataRefH = nil;
	OSType dataRefType = 0;
	
	err = QTNewDataReferenceFromFullPathCFString(
			mPath, (UInt32)kQTNativeDefaultPathStyle, 0,
			&dataRefH, &dataRefType);
    CheckError(err, "QTNewDataReferenceFromFullPathCFString");

	CreateMovieStorage(dataRefH, dataRefType,
			'TVOD', smSystemScript,
			createMovieFileDeleteCurFile |
				createMovieFileDontCreateResFile |
				newMovieActive,
			&mDataHandler, &mMovie);
    CheckMoviesError("CreateMovieStorage");
    CheckError((OSErr)((nil != mMovie) ? noErr : -1), "CreateMovieStorage movie");
    
    return (err == noErr) && (GetMoviesError() == noErr) && (nil != mMovie);
}
Exemple #13
0
//------------------------------------------------------
bool ofVideoGrabber::qtInitSeqGrabber(){

		if (bSgInited != true){

			OSErr err = noErr;

			ComponentDescription	theDesc;
			Component				sgCompID;

			// this crashes when we get to
			// SGNewChannel
			// we get -9405 as error code for the channel
			// -----------------------------------------
			// gSeqGrabber = OpenDefaultComponent(SeqGrabComponentType, 0);

			// this seems to work instead (got it from hackTV)
			// -----------------------------------------
			theDesc.componentType = SeqGrabComponentType;
			theDesc.componentSubType = NULL;
			theDesc.componentManufacturer = 'appl';
			theDesc.componentFlags = NULL;
			theDesc.componentFlagsMask = NULL;
			sgCompID = FindNextComponent (NULL, &theDesc);
			// -----------------------------------------

			if (sgCompID == NULL){
				ofLog(OF_LOG_ERROR, "error:FindNextComponent did not return a valid component");
				return false;
			}

			gSeqGrabber = OpenComponent(sgCompID);

			err = GetMoviesError();
			if (gSeqGrabber == NULL || err) {
				ofLog(OF_LOG_ERROR, "error: can't get default sequence grabber component");
				return false;
			}

			err = SGInitialize(gSeqGrabber);
			if (err != noErr) {
				ofLog(OF_LOG_ERROR, "error: can't initialize sequence grabber component");
				return false;
			}

			err = SGSetDataRef(gSeqGrabber, 0, 0, seqGrabDontMakeMovie);
			if (err != noErr) {
				ofLog(OF_LOG_ERROR, "error: can't set the destination data reference");
				return false;
			}

			// windows crashes w/ out gworld, make a dummy for now...
			// this took a long time to figure out.
			err = SGSetGWorld(gSeqGrabber, 0, 0);
			if (err != noErr) {
				ofLog(OF_LOG_ERROR, "error: setting up the gworld");
				return false;
			}

			err = SGNewChannel(gSeqGrabber, VideoMediaType, &(gVideoChannel));
			if (err != noErr) {
				ofLog(OF_LOG_ERROR, "error: creating a channel.  Check if you have any qt capable cameras attached");
				return false;
			}

			bSgInited = true;
			return true;
		}

		return false;
}
Exemple #14
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);
    }
}
Exemple #15
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;
  }
static bool
CheckMoviesError(const char* name)
{
	return CheckError(GetMoviesError(), name);
}
Exemple #17
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();
}
/*
 *  PsychQTGetTextureFromMovie() -- Create an OpenGL texture map from a specific videoframe from given movie object.
 *
 *  win = Window pointer of onscreen window for which a OpenGL texture should be created.
 *  moviehandle = Handle to the movie object.
 *  checkForImage = true == Just check if new image available, false == really retrieve the image, blocking if necessary.
 *  timeindex = When not in playback mode, this allows specification of a requested frame by presentation time.
 *              If set to -1, or if in realtime playback mode, this parameter is ignored and the next video frame is returned.
 *  out_texture = Pointer to the Psychtoolbox texture-record where the new texture should be stored.
 *  presentation_timestamp = A ptr to a double variable, where the presentation timestamp of the returned frame should be stored.
 *
 *  Returns true (1) on success, false (0) if no new image available, -1 if no new image available and there won't be any in future.
 */
int PsychQTGetTextureFromMovie(PsychWindowRecordType *win, int moviehandle, int checkForImage, double timeindex, PsychWindowRecordType *out_texture, double *presentation_timestamp)
{
	static TimeValue myNextTimeCached = -2;
	static TimeValue nextFramesTimeCached = -2;
    TimeValue		myCurrTime;
    TimeValue		myNextTime;
    TimeValue       nextFramesTime=0;
    short		myFlags;
    OSType		myTypes[1];
    OSErr		error = noErr;
    Movie               theMovie;
    CVOpenGLTextureRef newImage = NULL;
    QTVisualContextRef  theMoviecontext;
    unsigned int failcount=0;
    float lowerLeft[2];
    float lowerRight[2];    
    float upperRight[2];    
    float upperLeft[2];
    GLuint texid;
    Rect rect;
    float rate;
    double targetdelta, realdelta, frames;
	PsychRectType outRect;

    if (!PsychIsOnscreenWindow(win)) {
        PsychErrorExitMsg(PsychError_user, "Need onscreen window ptr!!!");
    }
    
    // Activate OpenGL context of target window:
    PsychSetGLContext(win);

    // Explicitely disable Apple's Client storage extensions. For now they are not really useful to us.
    glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
    
    if (moviehandle < 0 || moviehandle >= PSYCH_MAX_MOVIES) {
        PsychErrorExitMsg(PsychError_user, "Invalid moviehandle provided.");
    }
    
    if ((timeindex!=-1) && (timeindex < 0 || timeindex >= 10000.0)) {
        PsychErrorExitMsg(PsychError_user, "Invalid timeindex provided.");
    }
    
    if (NULL == out_texture && !checkForImage) {
        PsychErrorExitMsg(PsychError_internal, "NULL-Ptr instead of out_texture ptr passed!!!");
    }
    
    // Fetch references to objects we need:
    theMovie = movieRecordBANK[moviehandle].theMovie;
    theMoviecontext = movieRecordBANK[moviehandle].QTMovieContext;

    if (theMovie == NULL) {
        PsychErrorExitMsg(PsychError_user, "Invalid moviehandle provided. No movie associated with this handle.");
    }

    // Check if end of movie is reached. Rewind, if so...
    if (IsMovieDone(theMovie) && movieRecordBANK[moviehandle].loopflag > 0) {
        if (GetMovieRate(theMovie)>0) {
            GoToBeginningOfMovie(theMovie);
        } else {
            GoToEndOfMovie(theMovie);
        }
    }
    
    // Is movie actively playing (automatic async playback, possibly with synced sound)?
    // If so, then we ignore the 'timeindex' parameter, because the automatic playback
    // process determines which frames should be delivered to PTB when. This function will
    // simply wait or poll for arrival/presence of a new frame that hasn't been fetched
    // in previous calls.
    if (0 == GetMovieRate(theMovie)) {
        // Movie playback inactive. We are in "manual" mode: No automatic async playback,
        // no synced audio output. The user just wants to manually fetch movie frames into
        // textures for manual playback in a standard Matlab-loop.

		// First pass - checking for new image?
		if (checkForImage) {
			// Image for specific point in time requested?
			if (timeindex >= 0) {
				// Yes. We try to retrieve the next possible image for requested timeindex.
				myCurrTime = (TimeValue) ((timeindex * (double) GetMovieTimeScale(theMovie)) + 0.5f);
			}
			else {
				// No. We just retrieve the next frame, given the current movie time.
				myCurrTime = GetMovieTime(theMovie, NULL);
			}
            
			// Retrieve timeindex of the closest image sample after myCurrTime:
			myFlags = nextTimeStep + nextTimeEdgeOK;	// We want the next frame in the movie's media.
			myTypes[0] = VisualMediaCharacteristic;		// We want video samples.
			GetMovieNextInterestingTime(theMovie, myFlags, 1, myTypes, myCurrTime, FloatToFixed(1), &myNextTime, &nextFramesTime);
			error = GetMoviesError();
			if (error != noErr) {
				PsychErrorExitMsg(PsychError_internal, "Failed to fetch texture from movie for given timeindex!");
			}
			
			// Found useful event?
			if (myNextTime == -1) {
				if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-WARNING: Bogus timevalue in movie track for movie %i. Trying to keep going.\n", moviehandle);
				
				// No. Just push timestamp to current time plus a little bit in the hope
				// this will get us unstuck:
				myNextTime = myCurrTime + (TimeValue) 1;
				nextFramesTime = (TimeValue) 0;
			}
			
			if (myNextTime != myNextTimeCached) {
				// Set movies current time to myNextTime, so the next frame will be fetched from there:
				SetMovieTimeValue(theMovie, myNextTime);
				
				// nextFramesTime is the timeindex to which we need to advance for retrieval of next frame: (see code below)
				nextFramesTime=myNextTime + nextFramesTime;
				
				if (PsychPrefStateGet_Verbosity() > 5) printf("PTB-DEBUG: Current timevalue in movie track for movie %i is %lf secs.\n", moviehandle, (double) myNextTime / (double) GetMovieTimeScale(theMovie));
				if (PsychPrefStateGet_Verbosity() > 5) printf("PTB-DEBUG: Next timevalue in movie track for movie %i is %lf secs.\n", moviehandle, (double) nextFramesTime / (double) GetMovieTimeScale(theMovie));
				
				// Cache values for 2nd pass:
				myNextTimeCached = myNextTime;
				nextFramesTimeCached = nextFramesTime;
			}
			else {
				// Somehow got stuck? Do nothing...
				if (PsychPrefStateGet_Verbosity() > 5) printf("PTB-DEBUG: Seem to be a bit stuck at timevalue [for movie %i] of %lf secs. Nudging a bit forward...\n", moviehandle, (double) myNextTime / (double) GetMovieTimeScale(theMovie));
				// Nudge the timeindex a bit forware in the hope that this helps:
				SetMovieTimeValue(theMovie, GetMovieTime(theMovie, NULL) + 1);
			}
		}
		else {
			// This is the 2nd pass: Image fetching. Use cached values from first pass:
			// Caching in a static works because we're always called immediately for 2nd
			// pass after successfull return from 1st pass, and we're not multi-threaded,
			// i.e., don't need to be reentrant or thread-safe here:
			myNextTime = myNextTimeCached;
			nextFramesTime = nextFramesTimeCached;
			myNextTimeCached = -2;
		}
	}
    else {
        // myNextTime unavailable if in autoplayback-mode:
        myNextTime=-1;
    }
    
    // Presentation timestamp requested?
    if (presentation_timestamp) {
        // Already available?
        if (myNextTime==-1) {
            // Retrieve the exact presentation timestamp of the retrieved frame (in movietime):
            myFlags = nextTimeStep + nextTimeEdgeOK;            // We want the next frame in the movie's media.
            myTypes[0] = VisualMediaCharacteristic;		// We want video samples.
                                                                // We search backward for the closest available image for the current time. Either we get the current time
                                                                // if we happen to fetch a frame exactly when it becomes ready, or we get a bit earlier timestamp, which is
                                                                // the optimal presentation timestamp for this frame:
            GetMovieNextInterestingTime(theMovie, myFlags, 1, myTypes, GetMovieTime(theMovie, NULL), FloatToFixed(-1), &myNextTime, NULL);
        }
        // Convert pts (in Quicktime ticks) to pts in seconds since start of movie and return it:
        *presentation_timestamp = (double) myNextTime / (double) GetMovieTimeScale(theMovie);
    }

    // Allow quicktime visual context task to do its internal bookkeeping and cleanup work:
    if (theMoviecontext) QTVisualContextTask(theMoviecontext);

    // Perform decompress-operation:
    if (checkForImage) MoviesTask(theMovie, 0);
    
    // Should we just check for new image? If so, just return availability status:
    if (checkForImage) {
        if (PSYCH_USE_QT_GWORLDS) {
            // We use GWorlds. In this case we either suceed immediately due to the
            // synchronous nature of GWorld rendering, or we fail completely at end
            // of non-looping movie:
            if (IsMovieDone(theMovie) && movieRecordBANK[moviehandle].loopflag == 0) {
                // No new frame available and there won't be any in the future, because this is a non-looping
                // movie that has reached its end.
                return(-1);
            }
            
            // Is this the special case of a movie without video, but only sound? In that case,
			// we always return a 'false' because there ain't no image to return.
			if (movieRecordBANK[moviehandle].QTMovieGWorld == NULL) return(false);
			
			// Success!
            return(true);
        }
        
        // Code which uses QTVisualContextTasks...
        if (QTVisualContextIsNewImageAvailable(theMoviecontext, NULL)) {
            // New frame ready!
            return(true);
        }
        else if (IsMovieDone(theMovie) && movieRecordBANK[moviehandle].loopflag == 0) {
            // No new frame available and there won't be any in the future, because this is a non-looping
            // movie that has reached its end.
            return(-1);
        }
        else {
            // No new frame available yet:
            return(false);
        }
    }
    
    if (!PSYCH_USE_QT_GWORLDS) {
        // Blocking wait-code for non-GWorld mode:
        // Try up to 1000 iterations for arrival of requested image data in wait-mode:
        failcount=0;
        while ((failcount < 1000) && !QTVisualContextIsNewImageAvailable(theMoviecontext, NULL)) {
            PsychWaitIntervalSeconds(0.005);
            MoviesTask(theMovie, 0);
            failcount++;
        }
        
        // No new frame available and there won't be any in the future, because this is a non-looping
        // movie that has reached its end.
        if ((failcount>=1000) && IsMovieDone(theMovie) && (movieRecordBANK[moviehandle].loopflag == 0)) {
            return(-1);
        }
        
        // Fetch new OpenGL texture with the new movie image frame:
        error = QTVisualContextCopyImageForTime(theMoviecontext, kCFAllocatorDefault, NULL, &newImage);
        if ((error!=noErr) || newImage == NULL) {
            PsychErrorExitMsg(PsychError_internal, "OpenGL<->Quicktime texture fetch failed!!!");
        }
    
        // Disable client storage, if it was enabled:
        glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
        
        // Build a standard PTB texture record:    
        CVOpenGLTextureGetCleanTexCoords (newImage, lowerLeft, lowerRight, upperRight, upperLeft);
        texid = CVOpenGLTextureGetName(newImage);
        
        // Assign texture rectangle:
        PsychMakeRect(outRect, upperLeft[0], upperLeft[1], lowerRight[0], lowerRight[1]);    
        
        // Set texture orientation as if it were an inverted Offscreen window: Upside-down.
        out_texture->textureOrientation = (CVOpenGLTextureIsFlipped(newImage)) ? 3 : 4;

        // Assign OpenGL texture id:
        out_texture->textureNumber = texid;
        
        // Store special texture object as part of the PTB texture record:
        out_texture->targetSpecific.QuickTimeGLTexture = newImage;
    }
    else {
        // Synchronous texture fetch code for GWorld rendering mode:
        // At this point, the GWorld should contain the source image for creating a
        // standard OpenGL texture:
        
        // Disable client storage, if it was enabled:
        glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
        
        // Build a standard PTB texture record:    

        // Assign texture rectangle:
        GetMovieBox(theMovie, &rect);

        // Hack: Need to extend rect by 4 pixels, because GWorlds are 4 pixels-aligned via
        // image row padding:
        rect.right = rect.right + 4;
        PsychMakeRect(out_texture->rect, rect.left, rect.top, rect.right, rect.bottom);    
        
        // Set NULL - special texture object as part of the PTB texture record:
        out_texture->targetSpecific.QuickTimeGLTexture = NULL;

        // Set texture orientation as if it were an inverted Offscreen window: Upside-down.
        out_texture->textureOrientation = 3;
        
        // Setup a pointer to our GWorld as texture data pointer:
        out_texture->textureMemorySizeBytes = 0;

		// Quicktime textures are aligned on 4 Byte boundaries:
		out_texture->textureByteAligned = 4;

        // Lock GWorld:
        if(!LockPixels(GetGWorldPixMap(movieRecordBANK[moviehandle].QTMovieGWorld))) {
            // Locking surface failed! We abort.
            PsychErrorExitMsg(PsychError_internal, "PsychQTGetTextureFromMovie(): Locking GWorld pixmap surface failed!!!");
        }
        
        // This will retrieve an OpenGL compatible pointer to the GWorlds pixel data and assign it to our texmemptr:
        out_texture->textureMemory = (GLuint*) GetPixBaseAddr(GetGWorldPixMap(movieRecordBANK[moviehandle].QTMovieGWorld));
            
        // Let PsychCreateTexture() do the rest of the job of creating, setting up and
        // filling an OpenGL texture with GWorlds content:
        PsychCreateTexture(out_texture);
        
        // Undo hack from above after texture creation: Now we need the real width of the
        // texture for proper texture coordinate assignments in drawing code et al.
        rect.right = rect.right - 4;
        PsychMakeRect(outRect, rect.left, rect.top, rect.right, rect.bottom);    

        // Unlock GWorld surface. We do a glFinish() before, for safety reasons...
        //glFinish();
        UnlockPixels(GetGWorldPixMap(movieRecordBANK[moviehandle].QTMovieGWorld));

        // Ready to use the texture... We're done.
    }
    
	// Normalize texture rectangle and assign it:
	PsychNormalizeRect(outRect, out_texture->rect);
	
    rate = FixedToFloat(GetMovieRate(theMovie));
    
    // Detection of dropped frames: This is a heuristic. We'll see how well it works out...
    if (rate && presentation_timestamp) {
        // Try to check for dropped frames in playback mode:

        // Expected delta between successive presentation timestamps:
        targetdelta = 1.0f / (movieRecordBANK[moviehandle].fps * rate);

        // Compute real delta, given rate and playback direction:
        if (rate>0) {
            realdelta = *presentation_timestamp - movieRecordBANK[moviehandle].last_pts;
            if (realdelta<0) realdelta = 0;
        }
        else {
            realdelta = -1.0 * (*presentation_timestamp - movieRecordBANK[moviehandle].last_pts);
            if (realdelta<0) realdelta = 0;
        }
        
        frames = realdelta / targetdelta;
        // Dropped frames?
        if (frames > 1 && movieRecordBANK[moviehandle].last_pts>=0) {
            movieRecordBANK[moviehandle].nr_droppedframes += (int) (frames - 1 + 0.5);
        }

        movieRecordBANK[moviehandle].last_pts = *presentation_timestamp;
    }
    
    // Manually advance movie time, if in fetch mode:
    if (0 == GetMovieRate(theMovie)) {
        // We are in manual fetch mode: Need to manually advance movie time to next
        // media sample:
		if (nextFramesTime == myNextTime) {
			// Invalid value? Try to hack something that gets us unstuck:
			myNextTime = GetMovieTime(theMovie, NULL);
			nextFramesTime = myNextTime + (TimeValue) 1;
		}

        SetMovieTimeValue(theMovie, nextFramesTime);        
    }
    
    // Check if end of movie is reached. Rewind, if so...
    if (IsMovieDone(theMovie) && movieRecordBANK[moviehandle].loopflag > 0) {
        if (GetMovieRate(theMovie)>0) {
            GoToBeginningOfMovie(theMovie);
        } else {
            GoToEndOfMovie(theMovie);
        }
    }

    return(TRUE);
}
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);
}
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;
}
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);
}
Exemple #22
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);
}
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;
}
Exemple #24
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;
}
Exemple #25
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);
}
Exemple #26
0
void TLevelReader3gp::load(const TRasterP &rasP, int frameIndex, const TPoint &pos, int shrinkX, int shrinkY)
{
	TRaster32P ras = rasP;

	{
		QMutexLocker sl(&m_mutex);
		ras->lock();
		if (m_IOError != QTNoError)
			goto error;

		Rect rect;
		rect.right = pos.x + ras->getLx();
		rect.left = pos.x;
		rect.bottom = pos.y + ras->getLy();
		rect.top = pos.y;

		GWorldPtr offscreenGWorld;
		OSErr err;

#if defined TNZ_MACHINE_CHANNEL_ORDER_BGRM
		OSType pixelFormat = k32BGRAPixelFormat;
#elif defined TNZ_MACHINE_CHANNEL_ORDER_MRGB
		OSType pixelFormat = k32ARGBPixelFormat;
#endif

		err = QTNewGWorldFromPtr(
			&offscreenGWorld, pixelFormat,
			&rect, 0, 0, 0, ras->getRawData(), ras->getWrap() * 4);

		if (err != noErr) {
			m_IOError = QTUnableToCreateResource;
			goto error;
		}

		SetMovieBox(m_movie, &rect);
		err = GetMoviesError();
		if (err != noErr) {
			m_IOError = QTUnableToSetMovieBox;
#if 0
    DisposeGWorld(offscreenGWorld);
#endif
			goto error;
		}

#if 0
  SetMovieGWorld(m_movie, offscreenGWorld, GetGWorldDevice(offscreenGWorld));
#endif
		err = GetMoviesError();
		if (err != noErr) {
			m_IOError = QTUnableToSetMovieGWorld;
#if 0
    DisposeGWorld(offscreenGWorld);
#endif
			goto error;
		}

		TimeValue currentTime = currentTimes[frameIndex];

		SetMovieTimeValue(m_movie, currentTime);

		err = GetMoviesError();
		if (err != noErr) {
			m_IOError = QTUnableToSetTimeValue;
#if 0
    DisposeGWorld(offscreenGWorld);
#endif
			goto error;
		}

		err = UpdateMovie(m_movie);
		if (err != noErr) {
			m_IOError = QTUnableToUpdateMovie;
#if 0
    DisposeGWorld(offscreenGWorld);
#endif
			goto error;
		}

		MoviesTask(m_movie, 0);
		err = GetMoviesError();
		if (err != noErr) {
			m_IOError = QTUnableToDoMovieTask;
#if 0
    DisposeGWorld(offscreenGWorld);
#endif
			goto error;
		}

		SetMovieGWorld(m_movie, 0, 0);
#if 0
  DisposeGWorld(offscreenGWorld);
#endif
		ras->unlock();
	}

	if (m_depth != 32) {
		setMatteAndYMirror(rasP);
	} else {
		rasP->yMirror();
	}

	return;

error:
	ras->unlock();
	throw TImageException(m_path, buildQTErrorString(m_IOError));
}
Exemple #27
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;
}
Exemple #28
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");
}
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;
}
Exemple #30
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);
}