OggRawAudioInserterInputPin.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 "OggRawAudioInserterInputPin.h"
00034 
00035 OggRawAudioInserterInputPin::OggRawAudioInserterInputPin(AbstractTransformFilter* inParentFilter, CCritSec* inFilterLock, AbstractTransformOutputPin* inOutputPin, vector<CMediaType*> inAcceptableMediaTypes)
00036         :       AbstractTransformInputPin(inParentFilter, inFilterLock, inOutputPin, NAME("OggRawAudioInserterInputPin"), L"PCM In", inAcceptableMediaTypes)
00037         //,     mWaveFormat(NULL)
00038         ,       mUptoFrame(0)
00039         ,       mNumBufferedBytes(0)
00040         ,       mWorkingBuffer(NULL)
00041         ,       mFrameByteWidth(0)
00042         ,       mFramesPerPacket(0)
00043         ,       mBytesPerPacket(0)
00044         ,       mSentHeaders(false)
00045 {
00046         //debugLog.open("C:\\temp\\speexenc.log", ios_base::out);
00047         mWorkingBuffer = new unsigned char[WORKING_BUFFER_SIZE];
00048 }
00049 
00050 OggRawAudioInserterInputPin::~OggRawAudioInserterInputPin(void)
00051 {
00052         //debugLog.close();
00053         DestroyCodec();
00054 
00055         delete[] mWorkingBuffer;
00056 }
00057 
00058 
00059 unsigned long OggRawAudioInserterInputPin::identifyFormat()
00060 {
00061         switch(((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.bitsPerSample) {
00062                 case 8:
00063                         return FMT_U8;
00064                 case 16:
00065                         return FMT_S16_LE;
00066                 default:
00067                         return 0xffffffff;
00068         }
00069 }
00070 bool OggRawAudioInserterInputPin::makeMainHeader(unsigned char** outBuff, unsigned long* outHeaderSize)
00071 {
00072         const unsigned long MAIN_HEADER_SIZE = 28;
00073         unsigned char* retBuff = new unsigned char[MAIN_HEADER_SIZE];
00074 
00075         //ID
00076         memcpy((void*)retBuff, "PCM     ", 8);
00077         //Versions
00078         retBuff[8] = 0;
00079         retBuff[9] = 0;
00080         retBuff[10] = 0;
00081         retBuff[11] = 0;
00082 
00083         //Format
00084         unsigned long locFormat = identifyFormat();
00085         iBE_Math::ULongToCharArr(locFormat, &retBuff[12]);
00086 
00087         //Sample Rate
00088         iBE_Math::ULongToCharArr(((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.samplesPerSec, &retBuff[16]);
00089 
00090         //Sig bits
00091         retBuff[20] = ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.bitsPerSample;
00092 
00093         //Num Channels
00094         retBuff[21] = ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.numChannels;
00095 
00096         //Frames per packet  (fixed to 1024 = 0x0400)
00097         retBuff[22] = (mFramesPerPacket & 0xff00) >> 8;
00098         retBuff[23] = (mFramesPerPacket & 0xff);
00099 
00100         //Extra Headers
00101         retBuff[24] = 0;
00102         retBuff[25] = 0;
00103         retBuff[26] = 0;
00104         retBuff[27] = 0;
00105 
00106         *outBuff = retBuff;
00107         *outHeaderSize = MAIN_HEADER_SIZE;
00108 
00109         return true;
00110 
00111 }
00112 bool OggRawAudioInserterInputPin::makeCommentHeader(unsigned char** outBuff, unsigned long* outHeaderSize)
00113 {
00114         char* locVendor = "oggcodecs testbuild";
00115         unsigned long locVendorLength = strlen(locVendor);
00116         unsigned long locPacketLength = locVendorLength + 4 + 4 + 1;
00117 
00118         unsigned char* retBuff = new unsigned char[locPacketLength];
00119         iLE_Math::ULongToCharArr(locVendorLength, retBuff);
00120 
00121         memcpy((void*)(&retBuff[4]), (const void*)locVendor, locVendorLength);
00122 
00123         //No user comments
00124         iLE_Math::ULongToCharArr(0, &retBuff[locVendorLength + 4]);
00125 
00126         //Framing bit
00127         retBuff[locVendorLength+8] = 1;
00128 
00129         *outBuff = retBuff;
00130         *outHeaderSize = locPacketLength;
00131 
00132         return true;
00133 
00134 
00135 }
00136 //PURE VIRTUALS
00137 HRESULT OggRawAudioInserterInputPin::TransformData(unsigned char* inBuf, long inNumBytes) 
00138 {
00139 
00140         if (!mSentHeaders) {
00141                 
00142 
00143                 unsigned char* locHeader = NULL;
00144                 unsigned long locHeaderLength = 0;
00145                 mFrameByteWidth = (((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.numChannels * ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.bitsPerSample) >> 3;
00146                 mBytesPerPacket = mFramesPerPacket * mFrameByteWidth;
00147 
00148                 makeMainHeader(&locHeader, &locHeaderLength);
00149 
00150                 sendPacket(locHeader, locHeaderLength, true);
00151 
00152                 delete[] locHeader;
00153                 locHeader = NULL;
00154                 locHeaderLength = 0;
00155 
00156                 makeCommentHeader(&locHeader, &locHeaderLength);
00157 
00158                 sendPacket(locHeader, locHeaderLength, true);
00159                 delete[] locHeader;
00160 
00161                 mSentHeaders = true;
00162         }
00163 
00164         //assert(inNumBytes < (WORKING_BUFFER_SIZE - mNumBufferedBytes));
00165         memcpy((void*)&mWorkingBuffer[mNumBufferedBytes], (const void*)inBuf, inNumBytes);
00166         mNumBufferedBytes+=inNumBytes;
00167 
00168         //How many full buffers full
00169         unsigned long locBuffersWorth = mNumBufferedBytes / mBytesPerPacket;
00170 
00171         for (int i = 0; i < locBuffersWorth; i++) {
00172                 sendPacket(&mWorkingBuffer[i*mBytesPerPacket], mBytesPerPacket, false);
00173         }
00174 
00175         unsigned long locLeftovers = mNumBufferedBytes % mBytesPerPacket;
00176 
00177         //assert((locLeftovers % mFrameByteWidth) == 0);
00178 
00179         //TODO::: This can be improved. For now it's easier to always clear out the buffer.
00180         //      Though overall it would be better to wait for the next lot of input, though then
00181         //      we have to worry about ending of stream and the data getting left here, etc.
00182         sendPacket(&mWorkingBuffer[locBuffersWorth*mBytesPerPacket], locLeftovers, false);
00183 
00184 
00185         mNumBufferedBytes = 0;
00186 
00187         return S_OK;
00188 }
00189 
00190 HRESULT OggRawAudioInserterInputPin::sendPacket(unsigned char* inPacketData, unsigned long inNumBytes, bool inIsHeader)
00191 {
00192         if (inIsHeader) {
00193                 mUptoFrame = 0;
00194 
00195         }
00196         IMediaSample* locSample;
00197         REFERENCE_TIME locFrameStart = 0;
00198         REFERENCE_TIME locFrameEnd = 0;
00199         HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, &locFrameStart, &locFrameEnd, NULL);
00200 
00201         if (FAILED(locHR)) {
00202                 return locHR;
00203         }       
00204         
00205         BYTE* locBuffer = NULL;
00206         
00207         //Make our pointers set to point to the samples buffer
00208         locSample->GetPointer(&locBuffer);
00209         
00210 
00211         if (locSample->GetSize() >= inNumBytes) {
00212 
00213                 memcpy((void*)locBuffer, (const void*)inPacketData, inNumBytes);
00214                 locSample->SetActualDataLength(inNumBytes);
00215 
00216                 if (!inIsHeader) {
00217                         //locFrameStart = (mUptoFrame * UNITS) / ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.samplesPerSec;
00218                         locFrameStart = mUptoFrame;
00219                         mUptoFrame += (inNumBytes / mFrameByteWidth);
00220 
00221                         locFrameEnd = mUptoFrame;
00222                         //locFrameEnd = (mUptoFrame * UNITS) / ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.samplesPerSec;
00223                 } else {
00224                         locFrameStart = 0;
00225                         locFrameEnd = 0;
00226 
00227                 }
00228                 locSample->SetMediaTime(&locFrameStart, &locFrameEnd);
00229                 locSample->SetTime(&locFrameStart, &locFrameEnd);
00230 
00231                 locSample->SetSyncPoint(TRUE);
00232                 
00233 
00234                 {
00235                         CAutoLock locLock(m_pLock);
00236 
00237                         //TODO::: Need to propagate error states.
00238                         HRESULT locHR = ((OggRawAudioInserterOutputPin*)(mOutputPin))->mDataQueue->Receive(locSample);                                          //->DownstreamFilter()->Receive(locSample);
00239                         if (locHR != S_OK) {
00240                                 return locHR;
00241                         } else {
00242                                 //locThis->debugLog<<"Sample Delivered"<<endl;
00243                                 return S_OK;
00244                         }
00245                 }
00246         } else {
00247                 throw 0;
00248         }
00249 
00250 }
00251 bool OggRawAudioInserterInputPin::ConstructCodec() {
00252 
00253         return true;
00254 
00255 }
00256 void OggRawAudioInserterInputPin::DestroyCodec() {
00257 
00258 }
00259 
00260 
00261 
00262 
00263 HRESULT OggRawAudioInserterInputPin::SetMediaType(const CMediaType* inMediaType) 
00264 {
00265         
00266         if (    (inMediaType->subtype == MEDIASUBTYPE_PCM) &&
00267                         (inMediaType->formattype == FORMAT_WaveFormatEx)) {
00268 
00269                 WAVEFORMATEX* locWaveFormat = (WAVEFORMATEX*)inMediaType->pbFormat;
00270 
00271                 mFramesPerPacket = 1024;
00272 
00273                 //TODO::: This needs to change with channel conversion/mapping headers
00274                 ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.numHeaders = 2;
00275                 ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.samplesPerSec = locWaveFormat->nSamplesPerSec;
00276                 ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.numChannels = locWaveFormat->nChannels;
00277                 ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.bitsPerSample = locWaveFormat->wBitsPerSample;
00278                 ((OggRawAudioInserterFilter*)mParentFilter)->mOggRawAudioFormatBlock.maxFramesPerPacket = 1024;
00279 
00280                 
00281         } else {
00282                 //Failed... should never be here !
00283                 throw 0;
00284         }
00285         //This is here and not the constructor because we need audio params from the
00286         // input pin to construct properly.     
00287         
00288         ConstructCodec();
00289 
00290         return CBaseInputPin::SetMediaType(inMediaType);
00291 
00292         
00293         
00294 }

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