bool CFilterNetReceiver::DeliverBuffer(const unsigned char * pData, long nLen, unsigned int timestamp) { if (pData == NULL || nLen <= 0) return false; PBYTE pSampleBuffer = NULL; IMediaSample * pSample = NULL; // Receive media data BOOL pass = FALSE; do { pSample = GetMediaSample(); if (pSample != NULL) { pSample->GetPointer(&pSampleBuffer); if (pSampleBuffer != NULL) pass = TRUE; } Sleep(10); if (m_bIsStoped) break; } while (!pass); if (m_bIsStoped) return false; //MessageBox(NULL, L"CFilterNetReceiver::doSampleBuffer memcpy()", L"test", MB_OK); memcpy(pSampleBuffer, pData, nLen); // Deliver this sample BOOL ret = DeliverHoldingSample(pSample, nLen, timestamp); return ret ? true : false; }
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 pascal Boolean SoundConverterFillBufferCallback(SoundComponentDataPtr *outData, void *userData) { CallbackData *pFillData = (CallbackData*)userData; OSErr err; // if after getting the last chunk of data the total time is over the duration, we're done if (pFillData->getMediaAtThisTime >= pFillData->sourceDuration) { pFillData->isThereMoreSource = false; pFillData->compData.desc.buffer = NULL; pFillData->compData.desc.sampleCount = 0; pFillData->compData.bufferSize = 0; pFillData->compData.commonFrameSize = 0; } if (pFillData->isThereMoreSource) { long sourceBytesReturned; long numberOfSamples; TimeValue sourceReturnedTime, durationPerSample; // in calling GetMediaSample, we'll get a buffer that consists of equal // sized frames - the degenerate case is only 1 frame -- for // non-self-framed vbr formats (like AAC in QT 6.0) we need to provide // some more framing information - either the frameCount, frameSizeArray // pair or commonFrameSize field must be valid -- because we always get // equal sized frames, we use commonFrameSize and set the // kExtendedSoundCommonFrameSizeValid flag -- if there is only 1 frame // then (common frame size == media sample size), if there are multiple // frames, then (common frame size == media sample size / number of // frames). HUnlock(pFillData->hSource); err = GetMediaSample( pFillData->sourceMedia, // media to retrieve data from pFillData->hSource, // where to put the data pFillData->maxBufferSize, // maximum number of bytes to be returned &sourceBytesReturned, // number of bytes actually returned pFillData->getMediaAtThisTime, // starting time of the sample to be retrieved (must be in Media's TimeScale) &sourceReturnedTime, // actual time of the returned sample data &durationPerSample, // duration of each sample in the media NULL, // sample description of the returned data NULL, // index value to the sample description 0, // maximum number of samples to be returned (0 to use a value that is appropriate for the media) &numberOfSamples, // number of samples it actually returned NULL); // flags that describe the sample if ((noErr != err) || (sourceBytesReturned == 0)) { pFillData->isThereMoreSource = false; pFillData->compData.desc.buffer = NULL; pFillData->compData.desc.sampleCount = 0; pFillData->compData.bufferSize = 0; pFillData->compData.commonFrameSize = 0; if(sourceBytesReturned == 0) wxMessageBox(wxT("There were simply no bytes returned!")); if(err != noErr) wxMessageBox(wxString::Format(wxT("Error returned: %d"), err)); if ((err != noErr) && (sourceBytesReturned > 0)) wxMessageBox(wxT("GetMediaSample - Failed in FillBufferDataProc")); } pFillData->getMediaAtThisTime = sourceReturnedTime + (durationPerSample * numberOfSamples); // (the following comment is out of the example code. I would never call // a sound conversion routine "studly." -JH // // we've specified kExtendedSoundSampleCountNotValid and the 'studly' // Sound Converter will take care of sampleCount for us, so while this is // not required we fill out all the information we have to simply // demonstrate how this would be done sampleCount is the number of PCM // samples pFillData->compData.desc.sampleCount = numberOfSamples * durationPerSample; // kExtendedSoundBufferSizeValid was specified - make sure this field is // filled in correctly pFillData->compData.bufferSize = sourceBytesReturned; // for VBR audio we specified the kExtendedSoundCommonFrameSizeValid flag // - make sure this field is filled in correctly if (pFillData->isSourceVBR) pFillData->compData.commonFrameSize = sourceBytesReturned / numberOfSamples; } // set outData to a properly filled out ExtendedSoundComponentData struct *outData = (SoundComponentDataPtr)&pFillData->compData; return (pFillData->isThereMoreSource); }