OggDemuxPacketSourcePin.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 #include "StdAfx.h"
00032 #include ".\OggDemuxPacketsourcepin.h"
00033 
00034 OggDemuxPacketSourcePin::	OggDemuxPacketSourcePin(              TCHAR* inObjectName
00035                                                                                                 ,       OggDemuxPacketSourceFilter* inParentFilter
00036                                                                                                 ,       CCritSec* inFilterLock
00037                                                                                                 ,       OggPacket* inIdentHeader
00038                                                                                                 ,       unsigned long inSerialNo)
00039         :       CBaseOutputPin(                 NAME("Ogg Demux Output Pin")
00040                                                         ,       inParentFilter
00041                                                         ,       inFilterLock
00042                                                         ,       &mFilterHR
00043                                                         ,       L"Ogg Stream" )
00044         ,       mIdentHeader(inIdentHeader)
00045         ,       mSerialNo(inSerialNo)
00046         ,       mIsStreamReady(false)
00047         ,       mAcceptingData(false)
00048         ,       mNumBuffers(0)
00049         ,       mDataQueue(NULL)
00050         ,       mFilterHR(S_OK)
00051 {
00052 
00053         mPacketiserLock = new CCritSec;
00054         
00055                 //(BYTE*)inBOSPage->createRawPageData();
00056         mPacketiser.setPacketSink(this);
00057 
00058 
00059         //Subvert COM and do this directly... this way, the source filter won't expose the interface to the
00060         // graph but we can still delegate to it.
00061         IMediaSeeking* locSeeker = NULL;
00062         locSeeker = (IMediaSeeking*)inParentFilter;
00063         SetDelegate(locSeeker);
00064 }
00065 STDMETHODIMP OggDemuxPacketSourcePin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00066 {
00067         if (riid == IID_IMediaSeeking) {
00068                 //debugLog<<"Pin queried for IMediaSeeking"<<endl;
00069                 *ppv = (IMediaSeeking*)this;
00070                 ((IUnknown*)*ppv)->AddRef();
00071                 return NOERROR;
00072         } else if (riid == IID_IOggOutputPin) {
00073                 *ppv = (IOggOutputPin*)this;
00074                 //((IUnknown*)*ppv)->AddRef();
00075                 return NOERROR;         
00076         }
00077 
00078         return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv); 
00079 }
00080 OggDemuxPacketSourcePin::~OggDemuxPacketSourcePin(void)
00081 {
00082         //Since we didn't addref the filter when we set the seek delegate onto it, we have to avoid
00083         //      it getting released, so set it to NULL, to avoid the destructor releasing it.
00084         SetDelegate(NULL);
00085         //delete[] mBOSAsFormatBlock;
00086         //delete mBOSPage;
00087         delete mIdentHeader;
00088         delete mDataQueue;
00089 
00090         delete mPacketiserLock;
00091 
00092 
00093 }
00094 
00095 bool OggDemuxPacketSourcePin::acceptOggPage(OggPage* inOggPage)
00096 {
00097         CAutoLock locPackLock(mPacketiserLock);
00098         if (mIsStreamReady) {
00099                 mAcceptingData = true;
00100                 return mPacketiser.acceptOggPage(inOggPage);
00101         } else {
00102                 delete inOggPage;
00103         }
00104         return false;
00105 }
00106 BYTE* OggDemuxPacketSourcePin::getIdentAsFormatBlock()
00107 {
00108         return (BYTE*)mIdentHeader->packetData();
00109 }
00110 
00111 unsigned long OggDemuxPacketSourcePin::getIdentSize()
00112 {
00113         return mIdentHeader->packetSize();
00114 }
00115 
00116 unsigned long OggDemuxPacketSourcePin::getSerialNo()
00117 {
00118         return mSerialNo;//mBOSPage->header()->StreamSerialNo();
00119 }
00120 
00121 IOggDecoder* OggDemuxPacketSourcePin::getDecoderInterface()
00122 {
00123         if (mDecoderInterface == NULL) {
00124                 IOggDecoder* locDecoder = NULL;
00125                 if (IsConnected()) {
00126                         IPin* locPin = GetConnected();
00127                         if (locPin != NULL) {
00128                                 locPin->QueryInterface(IID_IOggDecoder, (void**)&locDecoder);
00129                         }
00130                 }
00131 
00132                 mDecoderInterface = locDecoder;
00133         }
00134         return mDecoderInterface;
00135         
00136 }
00137 HRESULT OggDemuxPacketSourcePin::GetMediaType(int inPosition, CMediaType* outMediaType) 
00138 {
00139         //Put it in from the info we got in the constructor.
00140         if (inPosition == 0) {
00141                 AM_MEDIA_TYPE locAMMediaType;
00142                 locAMMediaType.majortype = MEDIATYPE_OggPacketStream;
00143 
00144                 locAMMediaType.subtype = MEDIASUBTYPE_None;
00145                 locAMMediaType.formattype = FORMAT_OggIdentHeader;
00146                 locAMMediaType.cbFormat = getIdentSize();
00147                 locAMMediaType.pbFormat = getIdentAsFormatBlock();
00148                 locAMMediaType.pUnk = NULL;
00149         
00150                         
00151         
00152                 CMediaType locMediaType(locAMMediaType);                
00153                 *outMediaType = locMediaType;
00154                 return S_OK;
00155         } else {
00156                 return VFW_S_NO_MORE_ITEMS;
00157         }
00158 }
00159 HRESULT OggDemuxPacketSourcePin::CheckMediaType(const CMediaType* inMediaType) {
00160         if (            (inMediaType->majortype == MEDIATYPE_OggPacketStream) 
00161                         &&      (inMediaType->subtype == MEDIASUBTYPE_None)
00162                         &&      (inMediaType->formattype == FORMAT_OggIdentHeader)) {
00163                         //&&    (inMediaType->cbFormat == mBOSPage->pageSize()) {
00164 
00165                 return S_OK;
00166         } else {
00167                 return E_FAIL;
00168         }
00169 }
00170 HRESULT OggDemuxPacketSourcePin::DecideBufferSize(IMemAllocator* inoutAllocator, ALLOCATOR_PROPERTIES* inoutInputRequest) 
00171 {
00172         HRESULT locHR = S_OK;
00173 
00174         ALLOCATOR_PROPERTIES locReqAlloc = *inoutInputRequest;
00175         ALLOCATOR_PROPERTIES locActualAlloc;
00176 
00177         //locReqAlloc.cbAlign = 1;
00178         //locReqAlloc.cbBuffer = 65536; //BUFFER_SIZE;
00179         //locReqAlloc.cbPrefix = 0;
00180         //locReqAlloc.cBuffers = NUM_PAGE_BUFFERS; //NUM_BUFFERS;
00181 
00182         locHR = inoutAllocator->SetProperties(&locReqAlloc, &locActualAlloc);
00183 
00184         if (locHR != S_OK) {
00185                 return locHR;
00186         }
00187 
00188         mNumBuffers = locActualAlloc.cBuffers;
00189         
00190         locHR = inoutAllocator->Commit();
00191 
00192         return locHR;
00193 
00194 }
00195 
00196 
00197 //Pin Conenction Methods
00198 HRESULT OggDemuxPacketSourcePin::BreakConnect()
00199 {
00200         delete mDataQueue;
00201         mDataQueue = NULL;
00202         return CBaseOutputPin::BreakConnect();
00203 }
00204 HRESULT OggDemuxPacketSourcePin::CompleteConnect(IPin *inReceivePin)
00205 {
00206         IOggDecoder* locDecoder = NULL;
00207         inReceivePin->QueryInterface(IID_IOggDecoder, (void**)&locDecoder);
00208         if (locDecoder != NULL) {
00209                 mDecoderInterface = locDecoder;
00210 
00211                 IOggDecoder::eAcceptHeaderResult locResult = mDecoderInterface->showHeaderPacket(mIdentHeader->clone());
00212                 if (locResult == IOggDecoder::AHR_ALL_HEADERS_RECEIVED) {
00213                         mIsStreamReady = true;
00214 
00215                 } else {
00216                         OggPacketiser locPacketiser;
00217                         locPacketiser.setPacketSink(this);
00218                         OggDemuxPacketSourceFilter* locParent = (OggDemuxPacketSourceFilter*)m_pFilter;
00219                         vector<OggPage*> locList = locParent->getMatchingBufferedPages(mSerialNo);
00220                         
00221                         for (size_t i = 0; i < locList.size(); i++) {
00222                                 locPacketiser.acceptOggPage(locList[i]);
00223                         }
00224 
00225                         locParent->removeMatchingBufferedPages(mSerialNo);
00226 
00227                         
00228                 }
00229 
00230                 if (mIsStreamReady) {
00231                         HRESULT locHR = CBaseOutputPin::CompleteConnect(inReceivePin);
00232                         if (locHR == S_OK) {
00233                                 ((OggDemuxPacketSourceFilter*)m_pFilter)->notifyPinConnected();
00234                                 mDataQueue = new COutputQueue (inReceivePin, &mFilterHR, FALSE, TRUE,1,TRUE, mNumBuffers);
00235                                 return S_OK;
00236                         }  else {
00237                                 return locHR;
00238                         }
00239                         
00240                 }       
00241 
00242                 
00243         }
00244         return E_FAIL;
00245         
00246 }
00247 
00248 bool OggDemuxPacketSourcePin::dispatchPacket(StampedOggPacket* inPacket)
00249 {
00250         CAutoLock locStreamLock(((OggDemuxPacketSourceFilter*)m_pFilter)->streamLock());
00251 
00252 
00253         //Set up the sample info
00254         IMediaSample* locSample = NULL;
00255         REFERENCE_TIME locStart = inPacket->startTime();
00256         REFERENCE_TIME locStop = inPacket->endTime();
00257         
00258         //Get a delivery buffer
00259         HRESULT locHR = GetDeliveryBuffer(&locSample, &locStart, &locStop, NULL);
00260         
00261         //Error checks
00262         if (locHR != S_OK) {
00263                 //Stopping, fluching or error
00264 
00265                 delete inPacket;
00266                 return false;
00267         }
00268 
00269         //Set time stamps. These are granule pos, and may be -1
00270         locSample->SetTime(&locStart, &locStop);
00271         
00272         locSample->SetMediaTime(&locStart, &locStop);
00273         locSample->SetSyncPoint(TRUE);
00274         
00275 
00276         // Create a pointer for the samples buffer
00277         BYTE* locBuffer = NULL;
00278         locSample->GetPointer(&locBuffer);
00279 
00280         if (locSample->GetSize() >= inPacket->packetSize()) {
00281 
00282                 memcpy((void*)locBuffer, (const void*)inPacket->packetData(), inPacket->packetSize());
00283                 locSample->SetActualDataLength(inPacket->packetSize());
00284 
00285                 locHR = mDataQueue->Receive(locSample);
00286 
00287                 if (locHR != S_OK) {
00288                         //debugLog << "Failure... Queue rejected sample..."<<endl;
00289                         //Stopping ??
00290 
00291                         delete inPacket;
00292                         return false;
00293                 } else {
00294                         delete inPacket;
00295                         return true;
00296                 }
00297         } else {
00298                 //DbgLog((LOG_TRACE, 2, "* BUFFER TOO SMALL... FATALITY !!"));
00299                 throw 0;
00300         }       
00301 }
00302 bool OggDemuxPacketSourcePin::acceptStampedOggPacket(StampedOggPacket* inPacket)
00303 {
00304         if (mAcceptingData) {
00305                 return dispatchPacket(inPacket);
00306         } else {
00307                 //This handles callbacks with header packets
00308                 IOggDecoder::eAcceptHeaderResult locResult;
00309                 if ((mDecoderInterface != NULL) && (!mIsStreamReady)) {
00310                         locResult = mDecoderInterface->showHeaderPacket(inPacket);
00311                         if (locResult == IOggDecoder::AHR_ALL_HEADERS_RECEIVED) {
00312                                 mIsStreamReady = true;
00313                         }
00314                 }
00315                 delete inPacket;
00316                 return true;
00317         }
00318 }
00319 
00320 //Pin streaming methods
00321 HRESULT OggDemuxPacketSourcePin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
00322 {
00323         NewSegment(tStart, tStop, dRate);
00324 
00325         if (mDataQueue != NULL) {
00326                 mDataQueue->NewSegment(tStart, tStop, dRate);
00327         }
00328 
00329         return S_OK;
00330 }
00331 HRESULT OggDemuxPacketSourcePin::DeliverEndOfStream(void)
00332 {
00333         if (mDataQueue != NULL) {
00334                 mDataQueue->EOS();
00335         }
00336     return S_OK;
00337 }
00338 
00339 HRESULT OggDemuxPacketSourcePin::DeliverEndFlush(void)
00340 {
00341         CAutoLock locPackLock(mPacketiserLock);
00342         
00343         if (mDataQueue != NULL) {
00344                 mDataQueue->EndFlush();
00345         }
00346 
00347         mPacketiser.reset();
00348     return S_OK;
00349 }
00350 
00351 HRESULT OggDemuxPacketSourcePin::DeliverBeginFlush(void)
00352 {
00353         if (mDataQueue != NULL) {
00354                 mDataQueue->BeginFlush();
00355         }
00356         
00357     return S_OK;
00358 }
00359 
00360 bool OggDemuxPacketSourcePin::notifyStreamBaseTime(__int64 inStreamTime)
00361 {
00362         return ((OggDemuxPacketSourceFilter*)m_pFilter)->notifyStreamBaseTime(inStreamTime);
00363 }
00364 __int64 OggDemuxPacketSourcePin::getGlobalBaseTime()
00365 {
00366         return ((OggDemuxPacketSourceFilter*)m_pFilter)->getGlobalBaseTime();
00367 }

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