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                 } else if (inMediaType->subtype == MEDIASUBTYPE_RawOggAudio) {
00126                         sOggRawAudioFormatBlock* locRawAudio = (sOggRawAudioFormatBlock*)inMediaType->pbFormat;
00127                         mMuxStream->setConversionParams(locRawAudio->samplesPerSec, 1, 10000000);
00128                         mMuxStream->setNumHeaders(locRawAudio->numHeaders);
00129                         mPaginator.setNumHeaders(locRawAudio->numHeaders);
00130                 }
00131 
00132                 
00133         } else if (inMediaType->majortype == MEDIATYPE_Text) {
00134                 if (inMediaType->subtype == MEDIASUBTYPE_CMML) {
00135                         sCMMLFormatBlock* locCMML = (sCMMLFormatBlock*)inMediaType->pbFormat;
00136                         mMuxStream->setConversionParams(locCMML->granuleNumerator,locCMML->granuleDenominator, 10000000);
00137                         mMuxStream->setNumHeaders(1);
00138                         mPaginator.setNumHeaders(1);
00139 
00140                 }
00141 
00142         }
00143         return S_OK;
00144 }
00145 
00146 HRESULT OggMuxInputPin::GetMediaType(int inPosition, CMediaType* outMediaType) {
00147         switch(inPosition) {
00148                 case 0:
00149                         outMediaType->majortype = MEDIATYPE_Video;
00150                         outMediaType->subtype = MEDIASUBTYPE_Theora;
00151                         return S_OK;
00152                 case 1:
00153                         outMediaType->majortype = MEDIATYPE_Audio;
00154                         outMediaType->subtype = MEDIASUBTYPE_Vorbis;
00155                         return S_OK;
00156                 case 2:
00157                         outMediaType->majortype = MEDIATYPE_Audio;
00158                         outMediaType->subtype = MEDIASUBTYPE_Speex;
00159                         return S_OK;
00160                 case 3:
00161                         outMediaType->majortype = MEDIATYPE_Audio;
00162                         outMediaType->subtype = MEDIASUBTYPE_OggFLAC_1_0;
00163                         return S_OK;
00164                 case 4:
00165                         outMediaType->majortype = MEDIATYPE_Audio;
00166                         outMediaType->subtype = MEDIASUBTYPE_FLAC;
00167                         return S_OK;
00168 
00169                 case 5:
00170                         outMediaType->majortype = MEDIATYPE_Text;
00171                         outMediaType->subtype = MEDIASUBTYPE_CMML;
00172                         return S_OK;
00173 
00174                 case 6:
00175                         outMediaType->majortype = MEDIATYPE_Audio;
00176                         outMediaType->subtype = MEDIASUBTYPE_RawOggAudio;
00177                         return S_OK;
00178 
00179 
00180                 default:
00181                         return VFW_S_NO_MORE_ITEMS;
00182         
00183         }
00184 }
00185 HRESULT OggMuxInputPin::CheckMediaType(const CMediaType* inMediaType) {
00186         if      (       (inMediaType->majortype == MEDIATYPE_Video 
00187                                 && inMediaType->subtype == MEDIASUBTYPE_Theora 
00188                                 && inMediaType->formattype == FORMAT_Theora) 
00189                         ||
00190                         (inMediaType->majortype == MEDIATYPE_Audio 
00191                                 && inMediaType->subtype == MEDIASUBTYPE_Vorbis 
00192                                 && inMediaType->formattype == FORMAT_Vorbis)
00193                         ||
00194                         (inMediaType->majortype == MEDIATYPE_Audio 
00195                                 && inMediaType->subtype == MEDIASUBTYPE_Speex 
00196                                 && inMediaType->formattype == FORMAT_Speex)
00197                         ||
00198                         (inMediaType->majortype == MEDIATYPE_Audio
00199                                 &&      inMediaType->subtype == MEDIASUBTYPE_OggFLAC_1_0
00200                                 &&      inMediaType->formattype == FORMAT_FLAC)
00201                         ||
00202                         (inMediaType->majortype == MEDIATYPE_Audio
00203                                 &&      inMediaType->subtype == MEDIASUBTYPE_FLAC
00204                                 &&      inMediaType->formattype == FORMAT_FLAC)
00205                         ||
00206                         (inMediaType->majortype == MEDIATYPE_Audio
00207                                 &&      inMediaType->subtype == MEDIASUBTYPE_RawOggAudio
00208                                 &&      inMediaType->formattype == FORMAT_RawOggAudio)
00209                         ||
00210                         (inMediaType->majortype == MEDIATYPE_Text
00211                                 &&      inMediaType->subtype == MEDIASUBTYPE_CMML
00212                                 &&      inMediaType->formattype == FORMAT_CMML)
00213 
00214                 ) {
00215                 return S_OK;
00216         } else {
00217                 return E_FAIL;
00218         }
00219 }
00220 
00221 STDMETHODIMP OggMuxInputPin::Receive(IMediaSample* inSample) {
00222         CAutoLock locLock(mParentFilter->mStreamLock);
00223         LONGLONG locStart = 0;
00224         LONGLONG locEnd = 0;
00225         BYTE* locSampleBuff;
00226         inSample->GetPointer(&locSampleBuff);
00227         HRESULT locHR = inSample->GetTime(&locStart, &locEnd);
00228 
00229         //debugLog <<"Received "<<locStart<<" - "<<locEnd<<endl;
00230         long locBuffSize = inSample->GetActualDataLength();
00231         unsigned char* locBuff = new unsigned char[locBuffSize];
00232         memcpy((void*)locBuff, (const void*)locSampleBuff, inSample->GetActualDataLength());
00233         StampedOggPacket* locPacket = new StampedOggPacket(locBuff, inSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);
00234         
00235         if (mNeedsFLACHeaderCount) {
00236                 mNeedsFLACHeaderCount = false;
00237                 //This is to set the number of headers on the paginator for OggFLAC_1_0
00238                 mPaginator.setNumHeaders( (locPacket->packetData()[8]) + 1 );
00239         }
00240         if ((mNeedsFLACHeaderTweak)) {
00241                 //The first packet in FLAC has all the metadata in one block...
00242                 // It needs to be broken up for correct muxing....
00243 
00244                 //A note about the header formats used for flac in directshow.
00245                 //
00246                 //MEDIASUBTYPE_FLAC
00247                 //      The first packet is all the meta data in one block.
00248                 //      The only filter to output this is the demux.
00249                 //      The demux never outputs type MEDIASUBTYPE_OGG_FLAC_1_0
00250                 //      Even if the input is a new FLAC stream, it is translated before leaving the filter.
00251                 //
00252                 //MEDIASUBTYPE_OggFLAC_1_0
00253                 //      The metadata packets are all seperated.
00254                 //      This is the only format outputted by the encoder
00255                 //
00256                 //
00257 
00258                 //If we are in this section of code... it means that the demux has
00259                 // been connected directly to the mux.
00260                 //This could be to mux multi stream flac.
00261                 //Alternatively this configuration could be used to convert the old format to the new.
00262 
00263                 //debugLog<<"In the header tweak section..."<<endl;
00264                 FLACMetadataSplitter* locFLACSplitter = new FLACMetadataSplitter;
00265 
00266                 //debugLog<<"Feeding metadata..."<<endl;
00267                 locFLACSplitter->loadMetadata(locPacket->clone());
00268                 
00269                 //delete locPacket;             //Don't delete the splitter will delete when it's done.
00270 
00271                 for (unsigned long i = 0; i < locFLACSplitter->numHeaders(); i++) {
00272                         //debugLog<<"Giving pager, packet "<<i<<endl;
00273                         //debugLog<<locFLACSplitter->getHeader(i)->toPackDumpString()<<endl;            //This is a leak !!
00274                         if (i == 0) {
00275                                 //Set the number of headers in the paginator for FLAC classic.
00276                                 StampedOggPacket* locHeadPack = locFLACSplitter->getHeader(i);
00277                                 mPaginator.setNumHeaders((locHeadPack->packetData()[8]) + 1);
00278                                 delete locHeadPack;
00279                         }
00280                         mPaginator.acceptStampedOggPacket(locFLACSplitter->getHeader(i));               //This get function returns our copy which we give away.
00281                         //debugLog<<"After paginator feed..."<<endl;
00282                 }
00283                 mNeedsFLACHeaderTweak = false;
00284                 //debugLog<<"Pre delete of splitter..."<<endl;
00285                 delete locFLACSplitter;
00286                 //debugLog<<"Post delete of splitter"<<endl;
00287 
00288         } else {
00289                 //Not truncated or contuned... its a full packet.
00290                 
00291                 //debugLog<<"Normal add packet..."<<endl;
00292                 mPaginator.acceptStampedOggPacket(locPacket);
00293         }
00294 
00295         return S_OK;
00296          
00297 
00298 
00299 }
00300 
00301 HRESULT OggMuxInputPin::CompleteConnect(IPin* inReceivePin) {
00302         
00303         //Set our delegate to the pin that is connecting to us... we'll send them our seek messages.
00304         IMediaSeeking* locSeeker = NULL;
00305         inReceivePin->QueryInterface(IID_IMediaSeeking, (void**)&locSeeker);
00306         SetDelegate(locSeeker);
00307         
00308         
00309         mMuxStream->setIsActive(true);
00310         return mParentFilter->addAnotherPin();
00311 
00312 
00313 }
00314 
00315 HRESULT OggMuxInputPin::BreakConnect() 
00316 {
00317         CAutoLock locLock(m_pLock);
00318         //Release the seeking delegate
00319         ReleaseDelegate();
00320         return CBaseInputPin::BreakConnect();
00321 }
00322 
00323 
00324 
00325 
00326 STDMETHODIMP OggMuxInputPin::EndOfStream(void) {
00327         CAutoLock locLock(mParentFilter->mStreamLock);
00328         mPaginator.finishStream();
00329         mMuxStream->setIsEOS(true);
00330         
00331         
00332         //HRESULT locHR = mParentFilter->NotifyEvent(EC_COMPLETE, S_OK, NULL);
00333         return S_OK;
00334         
00335 }
00336 
00337 unsigned long OggMuxInputPin::PaginatorMaximumPacketsPerPage()
00338 {
00339         return mPaginator.parameters()->mMaxPacksPerPage;
00340 }
00341 
00342 void OggMuxInputPin::SetPaginatorMaximumPacketsPerPage(unsigned long inMaxPacketsPerPage)
00343 {
00344         mPaginator.parameters()->mMaxPacksPerPage = inMaxPacketsPerPage;
00345 }
00346 

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