SpeexEncodeInputPin.cpp

Go to the documentation of this file.
00001 //===========================================================================
00002 //Copyright (C) 2003, 2004 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 "SpeexEncodeInputPin.h"
00034 
00035 SpeexEncodeInputPin::SpeexEncodeInputPin(AbstractTransformFilter* inParentFilter, CCritSec* inFilterLock, AbstractTransformOutputPin* inOutputPin, vector<CMediaType*> inAcceptableMediaTypes)
00036         :       AbstractTransformInputPin(inParentFilter, inFilterLock, inOutputPin, NAME("SpeexEncodeInputPin"), L"PCM In", inAcceptableMediaTypes)
00037         ,       mFishSound(NULL)
00038         ,       mWaveFormat(NULL)
00039 
00040         ,       mUptoFrame(0)
00041 {
00042         //debugLog.open("C:\\temp\\speexenc.log", ios_base::out);
00043 }
00044 
00045 SpeexEncodeInputPin::~SpeexEncodeInputPin(void)
00046 {
00047         //debugLog.close();
00048         DestroyCodec();
00049 }
00050 
00051 
00052 //PURE VIRTUALS
00053 HRESULT SpeexEncodeInputPin::TransformData(unsigned char* inBuf, long inNumBytes) {
00054 
00055         //TODO::: There is a problem when we get 8 bit samples.
00056         //=====================================================
00057         //debugLog << "encodeData receives : "<<inNumBytes<<" bytes"<<endl;
00058         
00059 
00060         //************************************ Check this line... the +(inNumBytes%2) is new
00061         //Note the 2 is because a float is twice the width of a short.
00062         float* locFloatBuf = new float[inNumBytes/2];   // + (inNumBytes % 2)];
00063         //************************************ 
00064         short locTempShort = 0;
00065         float locTempFloat = 0;
00066 
00067 
00068         for (int i = 0; i < inNumBytes; i += 2) {
00069                 locTempShort = *((short*)(inBuf + i));
00070                 locTempFloat = (float)locTempShort;
00071                 locTempFloat /= 32767.0;
00072                 locFloatBuf[i/2] = locTempFloat;;
00073         }
00074         //debugLog<<"Calling encode"<<endl;
00075         //FIX::: The 2 is the size of a sample ie 16 bits
00076         long locErr = fish_sound_encode(mFishSound, (float**)locFloatBuf, inNumBytes/(mFishInfo.channels*2));
00077         delete[] locFloatBuf;
00078         //FIX::: Do something here ?
00079         if (locErr < 0) {
00080                 //debugLog<<"Fishsound reports error"<<endl;
00081         } else {
00082         
00083         }
00084         return S_OK;
00085 }
00086 bool SpeexEncodeInputPin::ConstructCodec() {
00087         mFishInfo.channels = mWaveFormat->nChannels;
00088         mFishInfo.format = FISH_SOUND_SPEEX;
00089         mFishInfo.samplerate = mWaveFormat->nSamplesPerSec;
00090 
00091         //Change to fill in vorbis format block so muxer can work
00092         ((SpeexEncodeFilter*)mParentFilter)->mSpeexFormatBlock.numChannels = mWaveFormat->nChannels;
00093         ((SpeexEncodeFilter*)mParentFilter)->mSpeexFormatBlock.samplesPerSec = mWaveFormat->nSamplesPerSec;
00094         
00095         //
00096         
00097         mFishSound = fish_sound_new (FISH_SOUND_ENCODE, &mFishInfo);
00098 
00099         int i = 1;
00100         //FIX::: Use new API for interleave setting
00101         fish_sound_command(mFishSound, FISH_SOUND_SET_INTERLEAVE, &i, sizeof(int));
00102 
00103         fish_sound_set_encoded_callback (mFishSound, SpeexEncodeInputPin::SpeexEncoded, this);
00104         //FIX::: Proper return value
00105         return true;
00106 
00107 }
00108 void SpeexEncodeInputPin::DestroyCodec() {
00109         fish_sound_delete(mFishSound);
00110         mFishSound = NULL;
00111 }
00112 
00113 
00114 //Encoded callback
00115 int SpeexEncodeInputPin::SpeexEncoded (FishSound* inFishSound, unsigned char* inPacketData, long inNumBytes, void* inThisPointer) 
00116 {
00117 
00118 
00119         SpeexEncodeInputPin* locThis = reinterpret_cast<SpeexEncodeInputPin*> (inThisPointer);
00120         SpeexEncodeFilter* locFilter = reinterpret_cast<SpeexEncodeFilter*>(locThis->m_pFilter);
00121         //locThis->debugLog << "SpeexEncoded called with "<<inNumBytes<< " byte of data"<<endl;
00122 
00123         //Time stamps are granule pos not directshow times
00124         LONGLONG locFrameStart = locThis->mUptoFrame;
00125         LONGLONG locFrameEnd    = locThis->mUptoFrame
00126                                                         = fish_sound_get_frameno(locThis->mFishSound);
00127 
00128         
00129         //locThis->debugLog << "Stamping packet "<<locFrameStart<< " to "<<locFrameEnd<<endl;
00130         //Get a pointer to a new sample stamped with our time
00131         IMediaSample* locSample;
00132         HRESULT locHR = locThis->mOutputPin->GetDeliveryBuffer(&locSample, &locFrameStart, &locFrameEnd, NULL);
00133 
00134         if (FAILED(locHR)) {
00135                 //We get here when the application goes into stop mode usually.
00136                 //locThis->debugLog<<"Getting buffer failed"<<endl;
00137                 return locHR;
00138         }       
00139         
00140         BYTE* locBuffer = NULL;
00141 
00142         
00143         //Make our pointers set to point to the samples buffer
00144         locSample->GetPointer(&locBuffer);
00145 
00146         
00147 
00148         if (locSample->GetSize() >= inNumBytes) {
00149 
00150                 memcpy((void*)locBuffer, (const void*)inPacketData, inNumBytes);
00151                 
00152                 //Set the sample parameters.
00153                 locThis->SetSampleParams(locSample, inNumBytes, &locFrameStart, &locFrameEnd);
00154 
00155                 {
00156                         CAutoLock locLock(locThis->m_pLock);
00157 
00158                         //Add a reference so it isn't deleted en route.
00159                         //locSample->AddRef();
00160                         //NO - It alrady has a ref on it.
00161 
00162                         //TODO::: Need to propagate error states.
00163                         HRESULT locHR = ((SpeexEncodeOutputPin*)(locThis->mOutputPin))->mDataQueue->Receive(locSample);                                         //->DownstreamFilter()->Receive(locSample);
00164                         if (locHR != S_OK) {
00165                                 //locThis->debugLog<<"Sample rejected"<<endl;
00166                         } else {
00167                                 //locThis->debugLog<<"Sample Delivered"<<endl;
00168                         }
00169                 }
00170 
00171                 return 0;
00172         } else {
00173                 throw 0;
00174         }
00175 }
00176 
00177 
00178 HRESULT SpeexEncodeInputPin::SetMediaType(const CMediaType* inMediaType) 
00179 {
00180         
00181         if (    (inMediaType->subtype == MEDIASUBTYPE_PCM) &&
00182                         (inMediaType->formattype == FORMAT_WaveFormatEx)) {
00183 
00184                 mWaveFormat = (WAVEFORMATEX*)inMediaType->pbFormat;
00185                 
00186         } else {
00187                 //Failed... should never be here !
00188                 throw 0;
00189         }
00190         //This is here and not the constructor because we need audio params from the
00191         // input pin to construct properly.     
00192         
00193         ConstructCodec();
00194 
00195         return CBaseInputPin::SetMediaType(inMediaType);
00196 
00197         
00198         
00199 }

Generated on Tue Feb 15 14:54:16 2005 for oggdsf by  doxygen 1.3.9