OggRawAudioExtractorFilter.cpp

Go to the documentation of this file.
00001 //===========================================================================
00002 //Copyright (C) 2003, 2004, 2005 Zentaro Kavanagh
00003 //
00004 //Redistribution and use in source and binary forms, with or without
00005 //modification, are permitted provided that the following conditions
00006 //are met:
00007 //
00008 //- Redistributions of source code must retain the above copyright
00009 //  notice, this list of conditions and the following disclaimer.
00010 //
00011 //- Redistributions in binary form must reproduce the above copyright
00012 //  notice, this list of conditions and the following disclaimer in the
00013 //  documentation and/or other materials provided with the distribution.
00014 //
00015 //- Neither the name of Zentaro Kavanagh nor the names of contributors 
00016 //  may be used to endorse or promote products derived from this software 
00017 //  without specific prior written permission.
00018 //
00019 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00022 //PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
00023 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00024 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00025 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 //===========================================================================
00031 
00032 #include "StdAfx.h"
00033 #include "OggRawAudioExtractorFilter.h"
00034 
00035 
00036 
00037 //COM Factory Template
00038 CFactoryTemplate g_Templates[] = 
00039 {
00040     { 
00041                 L"Ogg Raw Audio Extractor Filter",                                      // Name
00042             &CLSID_OggRawAudioExtractorFilter,                          // CLSID
00043             OggRawAudioExtractorFilter::CreateInstance,         // Method to create an instance of Speex Decoder
00044         NULL,                                                                   // Initialization function
00045         NULL                                                                    // Set-up information (for filters)
00046     }
00047 
00048 };
00049 
00050 // Generic way of determining the number of items in the template
00051 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 
00052 
00053 OggRawAudioExtractorFilter::OggRawAudioExtractorFilter()
00054         :       CTransformFilter(NAME("Ogg Raw Audio Extractor"), NULL, CLSID_OggRawAudioExtractorFilter)
00055         ,       mInputPin(NULL)
00056         ,       mOutputPin(NULL)
00057 
00058         ,       mWorkingBuff(NULL)
00059         ,       mBytesBuffered(0)
00060 
00061         ,       mSegStart(0)
00062         ,       mSegEnd(0)
00063         ,       mSegRate(0)
00064         
00065 {
00066         mWorkingBuff = new unsigned char[1<<20];        //1 meg
00067         
00068 }
00069 
00070 
00071 
00072 OggRawAudioExtractorFilter::~OggRawAudioExtractorFilter(void)
00073 {
00074         delete[] mWorkingBuff;
00075 }
00076 
00077 CUnknown* WINAPI OggRawAudioExtractorFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
00078 {
00079         //This routine is the COM implementation to create a new Filter
00080         OggRawAudioExtractorFilter *pNewObject = new OggRawAudioExtractorFilter();
00081     if (pNewObject == NULL) {
00082         *pHr = E_OUTOFMEMORY;
00083     }
00084         return pNewObject;
00085 } 
00086 
00087 HRESULT OggRawAudioExtractorFilter::CheckInputType(const CMediaType* inMediaType)
00088 {
00089         return mInputPin->CheckMediaType(inMediaType);
00090 }
00091 HRESULT OggRawAudioExtractorFilter::CheckTransform(const CMediaType* inInputMediaType, const CMediaType* inOutputMediaType)
00092 {
00093 
00094         return S_OK;
00095 }
00096 HRESULT OggRawAudioExtractorFilter::DecideBufferSize(IMemAllocator* inAllocator, ALLOCATOR_PROPERTIES* inPropertyRequest)
00097 {
00098         HRESULT locHR = S_OK;
00099 
00100         ALLOCATOR_PROPERTIES locReqAlloc;
00101         ALLOCATOR_PROPERTIES locActualAlloc;
00102         
00103         if (inPropertyRequest->cbAlign <= 0) {
00104                 locReqAlloc.cbAlign = 1;
00105         } else {
00106                 locReqAlloc.cbAlign = inPropertyRequest->cbAlign;
00107         }
00108 
00109 
00110         if (inPropertyRequest->cbBuffer == 0) {
00111                 locReqAlloc.cbBuffer = 65536*16;
00112         } else {
00113                 locReqAlloc.cbBuffer = inPropertyRequest->cbBuffer;
00114         }
00115         
00116 
00117         if (inPropertyRequest->cbPrefix < 0) {
00118                         locReqAlloc.cbPrefix = 0;
00119         } else {
00120                 locReqAlloc.cbPrefix = inPropertyRequest->cbPrefix;
00121         }
00122         
00123         if (inPropertyRequest->cBuffers == 0) {
00124                 locReqAlloc.cBuffers = 5;
00125         } else {
00126                 locReqAlloc.cBuffers = inPropertyRequest->cBuffers;
00127         }
00128 
00129         
00130         locHR = inAllocator->SetProperties(&locReqAlloc, &locActualAlloc);
00131 
00132         if (locHR != S_OK) {
00133                 //TODO::: Handle a fail state here.
00134                 return locHR;
00135         } else {
00136                 //TODO::: Need to save this pointer to decommit in destructor ???
00137                 locHR = inAllocator->Commit();
00138 
00139         
00140                 return locHR;
00141         }
00142         
00143 }
00144 
00145 HRESULT OggRawAudioExtractorFilter::NewSegment(REFERENCE_TIME inStartTime, REFERENCE_TIME inStopTime, double inRate)
00146 {
00147         mSegStart = inStartTime;
00148         mSegEnd = inStopTime;
00149         mSegRate = inRate;
00150         return CTransformFilter::NewSegment(inStartTime, inStopTime, inRate);
00151 }
00152 HRESULT OggRawAudioExtractorFilter::GetMediaType(int inPosition, CMediaType* outMediaType)
00153 {
00154         
00155         if (inPosition < 0) {
00156                 return E_INVALIDARG;
00157         }
00158         
00159         if ((inPosition == 0) && (mInputPin != NULL) && (mInputPin->IsConnected())) {
00160                 
00161                 WAVEFORMATEX* locWaveFormat = (WAVEFORMATEX*)outMediaType->AllocFormatBuffer(sizeof(WAVEFORMATEX));
00162                 //*locVideoFormat = *mInputPin->getVideoFormatBlock();
00163 
00164                 sOggRawAudioFormatBlock locOggFormat =  mInputPin->getFormatBlock();
00165                 locWaveFormat->wFormatTag = WAVE_FORMAT_PCM;
00166                 locWaveFormat->nChannels = locOggFormat.numChannels;
00167                 locWaveFormat->nSamplesPerSec = locOggFormat.samplesPerSec;
00168                 locWaveFormat->wBitsPerSample = locOggFormat.bitsPerSample;
00169                 locWaveFormat->nBlockAlign = (locWaveFormat->nChannels) * (locWaveFormat->wBitsPerSample >> 3);
00170                 locWaveFormat->nAvgBytesPerSec = ((locWaveFormat->nChannels) * (locWaveFormat->wBitsPerSample >> 3)) * locWaveFormat->nSamplesPerSec;
00171                 locWaveFormat->cbSize = 0;
00172                 
00173                 outMediaType->majortype = MEDIATYPE_Audio;
00174                 outMediaType->subtype = MEDIASUBTYPE_PCM;
00175                 outMediaType->formattype = FORMAT_WaveFormatEx;
00176 
00177                 return S_OK;
00178         } else {
00179                 return VFW_S_NO_MORE_ITEMS;
00180         }
00181 
00182 
00183 }
00184 
00185 HRESULT OggRawAudioExtractorFilter::Receive(IMediaSample* inSample)
00186 {
00187         BYTE* locInBuff = NULL;
00188         HRESULT locHR = inSample->GetPointer(&locInBuff);
00189 
00190         if (locHR == S_OK) {
00191                 REFERENCE_TIME locStart = -1;
00192                 REFERENCE_TIME locEnd = -1;
00193                 inSample->GetTime(&locStart, &locEnd);
00194                 if (locEnd == 0) {
00195                         return S_OK;
00196                 }
00197 
00198                 memcpy((void*)&mWorkingBuff[mBytesBuffered], (const void*)locInBuff, inSample->GetActualDataLength());
00199                 mBytesBuffered += inSample->GetActualDataLength();
00200 
00201 
00202 
00203                 if (locEnd > 0) {
00204                         //Can dump it all downstream now        
00205                         IMediaSample* locSample;
00206                         unsigned long locSampleDuration = 0;
00207                         unsigned long locBytesCopied = 0;
00208                         unsigned long locBytesToCopy = 0;
00209                         unsigned long locSampleRate = mInputPin->getFormatBlock().samplesPerSec;
00210                         unsigned long locFrameSize = (mInputPin->getFormatBlock().bitsPerSample * mInputPin->getFormatBlock().numChannels) >> 3;
00211 
00212                         locStart = mInputPin->convertGranuleToTime(locEnd) - (((mBytesBuffered / locFrameSize) * UNITS) / locSampleRate);
00213                         do {
00214                                 //HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, NULL, NULL, NULL);
00215                                 HRESULT locHR = InitializeOutputSample(inSample, &locSample);
00216                                 if (locHR != S_OK) {
00217                                         return locHR;
00218                                 }
00219 
00220                                 BYTE* locBuffer = NULL;
00221                                 locHR = locSample->GetPointer(&locBuffer);
00222                         
00223                                 if (locHR != S_OK) {
00224                                         return locHR;
00225                                 }
00226 
00227                                 locBytesToCopy = ((mBytesBuffered - locBytesCopied) <= locSample->GetSize()) ? (mBytesBuffered - locBytesCopied) : locSample->GetSize();
00228                                 //locBytesCopied += locBytesToCopy;
00229 
00230                                 locSampleDuration = (((locBytesToCopy/locFrameSize) * UNITS) / locSampleRate);
00231                                 locEnd = locStart + locSampleDuration;
00232 
00233                                 //Adjust the time stamps for rate and seeking
00234                                 REFERENCE_TIME locAdjustedStart = locStart; //(locStart * RATE_DENOMINATOR) / mRateNumerator;
00235                                 REFERENCE_TIME locAdjustedEnd = locEnd; //(locEnd * RATE_DENOMINATOR) / mRateNumerator;
00236                                 locAdjustedStart -= mSegStart;
00237                                 locAdjustedEnd -= mSegStart;
00238 
00239                                 __int64 locSeekStripOffset = 0;
00240                                 if (locAdjustedEnd < 0) {
00241                                         locSample->Release();
00242                                 } else {
00243                                         if (locAdjustedStart < 0) {
00244                                                 locSeekStripOffset = (-locAdjustedStart) * locSampleRate;
00245                                                 locSeekStripOffset *= locFrameSize;
00246                                                 locSeekStripOffset /= UNITS;
00247                                                 locSeekStripOffset += (locFrameSize - (locSeekStripOffset % locFrameSize));
00248                                                 __int64 locStrippedDuration = (((locSeekStripOffset/locFrameSize) * UNITS) / locSampleRate);
00249                                                 locAdjustedStart += locStrippedDuration;
00250                                         }
00251                                                 
00252 
00253                                 
00254 
00255                                         memcpy((void*)locBuffer, (const void*)&mWorkingBuff[locBytesCopied + locSeekStripOffset], locBytesToCopy - locSeekStripOffset);
00256 
00257                                         locSample->SetTime(&locAdjustedStart, &locAdjustedEnd);
00258                                         locSample->SetMediaTime(&locStart, &locEnd);
00259                                         locSample->SetSyncPoint(TRUE);
00260                                         locSample->SetActualDataLength(locBytesToCopy - locSeekStripOffset);
00261                                         locHR = mOutputPin->Deliver(locSample); //((SpeexDecodeOutputPin*)(mOutputPin))->mDataQueue->Receive(locSample);
00262                                         locSample->Release();
00263                                         if (locHR != S_OK) {
00264                                                 return locHR;
00265                                         }
00266                                         locStart += locSampleDuration;
00267 
00268                                 }
00269                                 locBytesCopied += locBytesToCopy;
00270 
00271                         
00272                         } while(locBytesCopied < mBytesBuffered);
00273 
00274                         mBytesBuffered = 0;
00275 
00276                 }
00277 
00278                 return S_OK;
00279 
00280         }
00281 
00282         return S_FALSE;
00283 
00284 }
00285 
00286 HRESULT OggRawAudioExtractorFilter::Transform(IMediaSample* inInputSample, IMediaSample* inOutputSample)
00287 {
00288 
00289         return E_NOTIMPL;
00290 }
00291 
00292 CBasePin* OggRawAudioExtractorFilter::GetPin(int inPinNo)
00293 {
00294 
00295     HRESULT locHR = S_OK;
00296 
00297     // Create an input pin if necessary
00298 
00299     if (m_pInput == NULL) {
00300 
00301         m_pInput = new OggRawAudioExtractorInputPin(this, &locHR);              //Deleted in base destructor
00302 
00303 
00304                 mInputPin = (OggRawAudioExtractorInputPin*)m_pInput;
00305         m_pOutput = new CTransformOutputPin(NAME("PCM Out"), this, &locHR, L"PCM Out"); //Deleted in base destructor
00306                 mOutputPin = m_pOutput;
00307                         
00308 
00309     }
00310 
00311     // Return the pin
00312 
00313     if (inPinNo == 0) {
00314         return m_pInput;
00315     } else if (inPinNo == 1) {
00316         return m_pOutput;
00317     } else {
00318         return NULL;
00319     }
00320 
00321 }

Generated on Thu Feb 16 23:48:08 2006 for oggdsf by  doxygen 1.3.9