OggMuxInputPin.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 #include "stdafx.h"
00032 #include "oggmuxinputpin.h"
00033 
00034 OggMuxInputPin::OggMuxInputPin(OggMuxFilter* inParentFilter, CCritSec* inFilterLock, HRESULT* inHR, OggMuxStream* inMuxStream)
00035         :       CBaseInputPin(NAME("OggMuxInputPin"), inParentFilter, inFilterLock, inHR, L"Ogg Packet In")
00036         ,       mParentFilter(inParentFilter)
00037         ,       mMuxStream(inMuxStream)
00038         ,       mNeedsFLACHeaderTweak(false)
00039         ,       mNeedsFLACHeaderCount(false)
00040 
00041 {
00042 
00043         
00044         OggPaginatorSettings* locSettings = new OggPaginatorSettings;
00045         locSettings->mMinPageSize = 4096;
00046         locSettings->mMaxPageSize = 8192;
00047         
00048         LARGE_INTEGER locTicks;
00049         QueryPerformanceCounter(&locTicks);
00050         srand((unsigned int)locTicks.LowPart);
00051         locSettings->mSerialNo = ((unsigned long)(rand() + 1)) * ((unsigned long)(rand() + 1));
00052         //string x = "G:\\logs\\muxinput_";
00053         //char* ser = new char[10];
00054         //itoa(locSettings->mSerialNo, ser, 10);
00055         //x = x + ser;
00056         //x = x +".log";
00057 
00058         //debugLog.open(x.c_str(), ios_base::out);
00059         //locSettings->mSerialNo = 13130;
00060         
00061         mPaginator.setParameters(locSettings);
00062         mPaginator.setPageCallback(mMuxStream);
00063 
00064         
00065 }
00066 
00067 OggMuxInputPin::~OggMuxInputPin(void)
00068 {
00069         //debugLog.close();
00070 }
00071 
00072 STDMETHODIMP OggMuxInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00073 {
00074         if (riid == IID_IMediaSeeking) {
00075                 *ppv = (IMediaSeeking*)this;
00076                 ((IUnknown*)*ppv)->AddRef();
00077                 return NOERROR;
00078         }
00079 
00080         return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv); 
00081 }
00082 
00083 //ANX::: Override and insert an anxdata into the stream.
00084 HRESULT OggMuxInputPin::SetMediaType(const CMediaType* inMediaType) {
00085         //debugLog.open("G:\\logs\\oggmuxinpin.log", ios_base::out);
00086         //debugLog<<"Set media type..."<<endl;
00087         if ((inMediaType->majortype == MEDIATYPE_Video) && (inMediaType->subtype == MEDIASUBTYPE_Theora)) {
00088                 //Theora
00089                 
00090                 sTheoraFormatBlock* locTheora = (sTheoraFormatBlock*)inMediaType->pbFormat;
00091                 //debugLog<<"Theo sample rate = "<<locTheora->frameRateNumerator<<" / "<<locTheora->frameRateDenominator<<endl;
00092                 //debugLog<<"Theo KFI = "<<locTheora->maxKeyframeInterval<<endl;
00093                 mMuxStream->setConversionParams(locTheora->frameRateNumerator, locTheora->frameRateDenominator, 10000000, locTheora->maxKeyframeInterval);
00094                 mMuxStream->setNumHeaders(3);
00095                 mPaginator.setNumHeaders(3);
00096         } else if (inMediaType->majortype == MEDIATYPE_Audio) {
00097                 if (inMediaType->subtype == MEDIASUBTYPE_Vorbis) {
00098                         //Vorbis
00099                         sVorbisFormatBlock* locVorbis = (sVorbisFormatBlock*)inMediaType->pbFormat;
00100                         //debugLog<<"Vorbis sample rate = "<<locVorbis->samplesPerSec<<endl;
00101                         mMuxStream->setConversionParams(locVorbis->samplesPerSec, 1, 10000000);
00102                         mMuxStream->setNumHeaders(3);
00103                         mPaginator.setNumHeaders(3);
00104                         
00105                 } else if (inMediaType->subtype == MEDIASUBTYPE_Speex) {
00106                         //Speex
00107                         sSpeexFormatBlock* locSpeex = (sSpeexFormatBlock*)inMediaType->pbFormat;
00108                         mMuxStream->setConversionParams(locSpeex->samplesPerSec, 1, 10000000);
00109                         mMuxStream->setNumHeaders(2);
00110                         mPaginator.setNumHeaders(2);
00111                 } else if (inMediaType->subtype == MEDIASUBTYPE_OggFLAC_1_0) {
00112                         //We are connected to the encoder nd getting individual metadata packets.
00113                         sFLACFormatBlock* locFLAC = (sFLACFormatBlock*)inMediaType->pbFormat;
00114                         mMuxStream->setConversionParams(locFLAC->samplesPerSec, 1, 10000000);
00115                         //debugLog<<"FLAC sample rate = "<<locFLAC->samplesPerSec<<endl;
00116                         //mNeedsFLACHeaderTweak = true;
00117                         mNeedsFLACHeaderCount = true;
00118                 } else if (inMediaType->subtype == MEDIASUBTYPE_FLAC) {
00119                         //We are connected directly to the demux and are getting metadata in one block
00120                         // Need to use the header splitter class.
00121                         sFLACFormatBlock* locFLAC = (sFLACFormatBlock*)inMediaType->pbFormat;
00122                         mMuxStream->setConversionParams(locFLAC->samplesPerSec, 1, 10000000);
00123                         //debugLog<<"FLAC sample rate = "<<locFLAC->samplesPerSec<<endl;
00124                         mNeedsFLACHeaderTweak = true;
00125                 }
00126 
00127                 
00128         } else if (inMediaType->majortype == MEDIATYPE_Text) {
00129                 if (inMediaType->subtype == MEDIASUBTYPE_CMML) {
00130                         sCMMLFormatBlock* locCMML = (sCMMLFormatBlock*)inMediaType->pbFormat;
00131                         mMuxStream->setConversionParams(locCMML->granuleNumerator,locCMML->granuleDenominator, 10000000);
00132                         mMuxStream->setNumHeaders(1);
00133                         mPaginator.setNumHeaders(1);
00134 
00135                 }
00136 
00137         }
00138         return S_OK;
00139 }
00140 
00141 HRESULT OggMuxInputPin::GetMediaType(int inPosition, CMediaType* outMediaType) {
00142         switch(inPosition) {
00143                 case 0:
00144                         outMediaType->majortype = MEDIATYPE_Video;
00145                         outMediaType->subtype = MEDIASUBTYPE_Theora;
00146                         return S_OK;
00147                 case 1:
00148                         outMediaType->majortype = MEDIATYPE_Audio;
00149                         outMediaType->subtype = MEDIASUBTYPE_Vorbis;
00150                         return S_OK;
00151                 case 2:
00152                         outMediaType->majortype = MEDIATYPE_Audio;
00153                         outMediaType->subtype = MEDIASUBTYPE_Speex;
00154                         return S_OK;
00155                 case 3:
00156                         outMediaType->majortype = MEDIATYPE_Audio;
00157                         outMediaType->subtype = MEDIASUBTYPE_OggFLAC_1_0;
00158                         return S_OK;
00159                 case 4:
00160                         outMediaType->majortype = MEDIATYPE_Audio;
00161                         outMediaType->subtype = MEDIASUBTYPE_FLAC;
00162                         return S_OK;
00163 
00164                 case 5:
00165                         outMediaType->majortype = MEDIATYPE_Text;
00166                         outMediaType->subtype = MEDIASUBTYPE_CMML;
00167                         return S_OK;
00168 
00169 
00170                 default:
00171                         return VFW_S_NO_MORE_ITEMS;
00172         
00173         }
00174 }
00175 HRESULT OggMuxInputPin::CheckMediaType(const CMediaType* inMediaType) {
00176         if      (       (inMediaType->majortype == MEDIATYPE_Video 
00177                                 && inMediaType->subtype == MEDIASUBTYPE_Theora 
00178                                 && inMediaType->formattype == FORMAT_Theora) 
00179                         ||
00180                         (inMediaType->majortype == MEDIATYPE_Audio 
00181                                 && inMediaType->subtype == MEDIASUBTYPE_Vorbis 
00182                                 && inMediaType->formattype == FORMAT_Vorbis)
00183                         ||
00184                         (inMediaType->majortype == MEDIATYPE_Audio 
00185                                 && inMediaType->subtype == MEDIASUBTYPE_Speex 
00186                                 && inMediaType->formattype == FORMAT_Speex)
00187                         ||
00188                         (inMediaType->majortype == MEDIATYPE_Audio
00189                                 &&      inMediaType->subtype == MEDIASUBTYPE_OggFLAC_1_0
00190                                 &&      inMediaType->formattype == FORMAT_FLAC)
00191                         ||
00192                         (inMediaType->majortype == MEDIATYPE_Audio
00193                                 &&      inMediaType->subtype == MEDIASUBTYPE_FLAC
00194                                 &&      inMediaType->formattype == FORMAT_FLAC)
00195                         ||
00196                         (inMediaType->majortype == MEDIATYPE_Text
00197                                 &&      inMediaType->subtype == MEDIASUBTYPE_CMML
00198                                 &&      inMediaType->formattype == FORMAT_CMML)
00199 
00200                 ) {
00201                 return S_OK;
00202         } else {
00203                 return E_FAIL;
00204         }
00205 }
00206 
00207 STDMETHODIMP OggMuxInputPin::Receive(IMediaSample* inSample) {
00208         CAutoLock locLock(mParentFilter->mStreamLock);
00209         LONGLONG locStart = 0;
00210         LONGLONG locEnd = 0;
00211         BYTE* locSampleBuff;
00212         inSample->GetPointer(&locSampleBuff);
00213         HRESULT locHR = inSample->GetTime(&locStart, &locEnd);
00214 
00215         //debugLog <<"Received "<<locStart<<" - "<<locEnd<<endl;
00216         long locBuffSize = inSample->GetActualDataLength();
00217         unsigned char* locBuff = new unsigned char[locBuffSize];
00218         memcpy((void*)locBuff, (const void*)locSampleBuff, inSample->GetActualDataLength());
00219         StampedOggPacket* locPacket = new StampedOggPacket(locBuff, inSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);
00220         
00221         if (mNeedsFLACHeaderCount) {
00222                 mNeedsFLACHeaderCount = false;
00223                 //This is to set the number of headers on the paginator for OggFLAC_1_0
00224                 mPaginator.setNumHeaders( (locPacket->packetData()[8]) + 1 );
00225         }
00226         if ((mNeedsFLACHeaderTweak)) {
00227                 //The first packet in FLAC has all the metadata in one block...
00228                 // It needs to be broken up for correct muxing....
00229 
00230                 //A note about the header formats used for flac in directshow.
00231                 //
00232                 //MEDIASUBTYPE_FLAC
00233                 //      The first packet is all the meta data in one block.
00234                 //      The only filter to output this is the demux.
00235                 //      The demux never outputs type MEDIASUBTYPE_OGG_FLAC_1_0
00236                 //      Even if the input is a new FLAC stream, it is translated before leaving the filter.
00237                 //
00238                 //MEDIASUBTYPE_OggFLAC_1_0
00239                 //      The metadata packets are all seperated.
00240                 //      This is the only format outputted by the encoder
00241                 //
00242                 //
00243 
00244                 //If we are in this section of code... it means that the demux has
00245                 // been connected directly to the mux.
00246                 //This could be to mux multi stream flac.
00247                 //Alternatively this configuration could be used to convert the old format to the new.
00248 
00249                 //debugLog<<"In the header tweak section..."<<endl;
00250                 FLACMetadataSplitter* locFLACSplitter = new FLACMetadataSplitter;
00251 
00252                 //debugLog<<"Feeding metadata..."<<endl;
00253                 locFLACSplitter->loadMetadata(locPacket->clone());
00254                 
00255                 //delete locPacket;             //Don't delete the splitter will delete when it's done.
00256 
00257                 for (unsigned long i = 0; i < locFLACSplitter->numHeaders(); i++) {
00258                         //debugLog<<"Giving pager, packet "<<i<<endl;
00259                         //debugLog<<locFLACSplitter->getHeader(i)->toPackDumpString()<<endl;            //This is a leak !!
00260                         if (i == 0) {
00261                                 //Set the number of headers in the paginator for FLAC classic.
00262                                 StampedOggPacket* locHeadPack = locFLACSplitter->getHeader(i);
00263                                 mPaginator.setNumHeaders((locHeadPack->packetData()[8]) + 1);
00264                                 delete locHeadPack;
00265                         }
00266                         mPaginator.acceptStampedOggPacket(locFLACSplitter->getHeader(i));               //This get function returns our copy which we give away.
00267                         //debugLog<<"After paginator feed..."<<endl;
00268                 }
00269                 mNeedsFLACHeaderTweak = false;
00270                 //debugLog<<"Pre delete of splitter..."<<endl;
00271                 delete locFLACSplitter;
00272                 //debugLog<<"Post delete of splitter"<<endl;
00273 
00274         } else {
00275                 //Not truncated or contuned... its a full packet.
00276                 
00277                 //debugLog<<"Normal add packet..."<<endl;
00278                 mPaginator.acceptStampedOggPacket(locPacket);
00279         }
00280 
00281         return S_OK;
00282          
00283 
00284 
00285 }
00286 
00287 HRESULT OggMuxInputPin::CompleteConnect(IPin* inReceivePin) {
00288         
00289         //Set our delegate to the pin that is connecting to us... we'll send them our seek messages.
00290         IMediaSeeking* locSeeker = NULL;
00291         inReceivePin->QueryInterface(IID_IMediaSeeking, (void**)&locSeeker);
00292         SetDelegate(locSeeker);
00293         
00294         
00295         mMuxStream->setIsActive(true);
00296         return mParentFilter->addAnotherPin();
00297 
00298 
00299 }
00300 
00301 HRESULT OggMuxInputPin::BreakConnect() 
00302 {
00303         CAutoLock locLock(m_pLock);
00304         //Release the seeking delegate
00305         ReleaseDelegate();
00306         return CBaseInputPin::BreakConnect();
00307 }
00308 
00309 
00310 
00311 
00312 STDMETHODIMP OggMuxInputPin::EndOfStream(void) {
00313         CAutoLock locLock(mParentFilter->mStreamLock);
00314         mPaginator.finishStream();
00315         mMuxStream->setIsEOS(true);
00316         
00317         
00318         //HRESULT locHR = mParentFilter->NotifyEvent(EC_COMPLETE, S_OK, NULL);
00319         return S_OK;
00320         
00321 }

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