OggMuxFilter.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 "oggmuxfilter.h"
00033 
00034 
00035 //+++++++++++++++++++++++++++++++++
00036 //-------------------
00037 // This template lets the Object factory create us properly and work with COM infrastructure.
00038 CFactoryTemplate g_Templates[] = 
00039 {
00040     { 
00041                 L"OggMuxFilter",                                                // Name
00042             &CLSID_OggMuxFilter,            // CLSID
00043             OggMuxFilter::CreateInstance,       // Method to create an instance of MyComponent
00044         NULL,                                                                   // Initialization function
00045         NULL                                                                    // Set-up information (for filters)
00046     }
00047         //,
00048  //   { 
00049         //      L"Ogg Muxer Properties",                                                // Name
00050         //    &CLSID_PropsOggMux,            // CLSID
00051         //    PropsOggMux::CreateInstance,      // Method to create an instance of MyComponent
00052  //       NULL,                                                                 // Initialization function
00053  //       NULL                                                                  // Set-up information (for filters)
00054  //   }
00055 
00056 };
00057 
00058 // Generic way of determining the number of items in the template
00059 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 
00060 
00061 
00062 
00063 CUnknown* WINAPI OggMuxFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
00064 {
00065         OggMuxFilter *pNewObject = new OggMuxFilter();
00066     if (pNewObject == NULL) {
00067         *pHr = E_OUTOFMEMORY;
00068     }
00069     return pNewObject;
00070 } 
00071 
00072 void OggMuxFilter::NotifyComplete() {
00073         HRESULT locHR = NotifyEvent(EC_COMPLETE, S_OK, NULL);
00074 
00075 }
00076 
00077 STDMETHODIMP OggMuxFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00078 {
00079         if (riid == IID_IFileSinkFilter) {
00080                 *ppv = (IFileSinkFilter*)this;
00081                 ((IUnknown*)*ppv)->AddRef();
00082                 return NOERROR;
00083         } else if (riid == IID_IAMFilterMiscFlags) {
00084                 debugLog<<"Queried for IAMMiscFlags"<<endl;
00085                 *ppv = (IAMFilterMiscFlags*)this;
00086                 ((IUnknown*)*ppv)->AddRef();
00087                 return NOERROR;
00088         } else if (riid == IID_IMediaSeeking) {
00089                 debugLog<<"Queried for IMediaSeeking"<<endl;
00090                 *ppv = (IMediaSeeking*)this;
00091                 ((IUnknown*)*ppv)->AddRef();
00092                 return NOERROR;
00093         } else if (riid == IID_IOggMuxProgress) {
00094                 debugLog<<"Queried for IMediaSeeking"<<endl;
00095                 *ppv = (IOggMuxProgress*)this;
00096                 ((IUnknown*)*ppv)->AddRef();
00097                 return NOERROR;
00098         } else if (riid == IID_IOggMuxSettings) {
00099                 *ppv = (IOggMuxSettings*)this;
00100                 ((IUnknown*)*ppv)->AddRef();
00101                 return NOERROR;
00102         }
00103         //else if (riid == IID_ISpecifyPropertyPages) {
00104         //      *ppv = (ISpecifyPropertyPages*)this;
00105         //      ((IUnknown*)*ppv)->AddRef();
00106         //      return NOERROR;
00107         //}
00108 
00109         return CBaseFilter::NonDelegatingQueryInterface(riid, ppv); 
00110 }
00111 
00112 STDMETHODIMP_(LONGLONG) OggMuxFilter::getProgressTime() 
00113 {
00114         if (mInterleaver != NULL) {
00115                 return mInterleaver->progressTime();
00116         } else {
00117                 return -1;
00118         }
00119 
00120 }
00121 
00122 STDMETHODIMP_(LONGLONG) OggMuxFilter::getBytesWritten() {
00123         if (mInterleaver != NULL) {
00124                 return mInterleaver->bytesWritten();
00125         } else {
00126                 return -1;
00127         }
00128 
00129 }
00130 ULONG OggMuxFilter::GetMiscFlags(void) 
00131 {
00132         debugLog<<"GetMiscflags"<<endl;
00133         return AM_FILTER_MISC_FLAGS_IS_RENDERER;
00134 }
00135 
00136 //------------------
00137 
00138 OggMuxFilter::OggMuxFilter()
00139         :       CBaseFilter(NAME("OggMuxFilter"), NULL, m_pLock, CLSID_OggMuxFilter)
00140         ,       mInterleaver(NULL)
00141 {
00142         mInterleaver = new OggPageInterleaver(this, this);
00143         //LEAK CHECK:::Both get deleted in constructor.
00144 
00145         m_pLock = new CCritSec;
00146         mStreamLock = new CCritSec;
00147         mInputPins.push_back(new OggMuxInputPin(this, m_pLock, &mHR, mInterleaver->newStream()));
00148 
00149 #ifdef OGGCODECS_LOGGING
00150         debugLog.open("g:\\logs\\muxer.log", ios_base::out);
00151 #endif
00152 
00153         //IMediaSeeking* locSeeker = NULL;
00154         //mInputPins[0]->NonDelegatingQueryInterface(IID_IMediaSeeking, (void**)&locSeeker);
00155         //SetDelegate(locSeeker);
00156 
00157         //To avoid a circular reference... we do this without the addref.
00158         // This is safe because we control the lifetime of this pin, and it won't be deleted until we are.
00159         IMediaSeeking* locSeeker = (IMediaSeeking*)mInputPins[0];
00160         SetDelegate(locSeeker);
00161         
00162 }
00163 
00164 OggMuxFilter::OggMuxFilter(REFCLSID inFilterGUID)
00165         :       CBaseFilter(NAME("OggMuxFilter"), NULL, m_pLock, inFilterGUID)
00166         ,       mInterleaver(NULL)
00167 {
00168         //Do this in derived class
00169         //mInterleaver = new OggPageInterleaver(this, this);
00170         
00171 
00172         m_pLock = new CCritSec;
00173         mStreamLock = new CCritSec;
00174 
00175         //In the derived class
00176         //mInputPins.push_back(new OggMuxInputPin(this, m_pLock, &mHR, mInterleaver->newStream()));
00177         //debugLog.open("C:\\temp\\muxer.log", ios_base::out);
00178 
00179         //Make our delegate pin[0], the top pin... we send all out requests there.
00180         //IMediaSeeking* locSeeker = NULL;
00181         //mInputPins[0]->NonDelegatingQueryInterface(IID_IMediaSeeking, (void**)&locSeeker);
00182         //SetDelegate(locSeeker);
00183 
00184 
00185 
00186         
00187 }
00188 
00189 OggMuxFilter::~OggMuxFilter(void)
00190 {
00191         //debugLog.close();
00192         //DbgLog((LOG_ERROR, 1, TEXT("****************** DESTRUCTOR **********************")));
00193 
00194         //ReleaseDelegate();
00195 
00196         //This is not a leak !! We just don't want it to be released... we never addreffed it.. see constructor.
00197         SetDelegate(NULL);
00198         
00199         delete mInterleaver;
00200         for (size_t i = 0; i < mInputPins.size(); i++) {
00201                 delete mInputPins[i];
00202         }
00203 
00204 
00205         delete m_pLock;
00206         delete mStreamLock;
00207         
00208         //Need to delete the pins !!
00209 
00210         
00211         //if (ThreadExists() == TRUE) {
00212         //      //DbgLog((LOG_ERROR, 1, TEXT("******** Thread exists - closing *****")));
00213         //      Close();
00214         //}
00215 
00216 }
00217 
00218 HRESULT OggMuxFilter::addAnotherPin() {
00219         mInputPins.push_back(new OggMuxInputPin(this, m_pLock, &mHR, mInterleaver->newStream()));
00220         return S_OK;
00221 }
00222 
00223         //IFileSinkFilter Implementation
00224 HRESULT OggMuxFilter::SetFileName(LPCOLESTR inFileName, const AM_MEDIA_TYPE* inMediaType) {
00225         CAutoLock locLock(m_pLock);
00226         mFileName = inFileName;
00227 
00228         SetupOutput();
00229         return S_OK;
00230 }
00231 HRESULT OggMuxFilter::GetCurFile(LPOLESTR* outFileName, AM_MEDIA_TYPE* outMediaType) {
00232         //Return the filename and mediatype of the raw data
00233 
00234          
00235         LPOLESTR x = SysAllocString(mFileName.c_str());
00236         *outFileName = x;
00237         
00238         return S_OK;
00239 }
00240 
00241 bool OggMuxFilter::acceptOggPage(OggPage* inOggPage) {                  //Deletes Page correctly.
00242         //debugLog<<"Page accepted... writing..."<<endl;
00243         unsigned char* locPageData = inOggPage->createRawPageData();
00244         mOutputFile.write((char*)locPageData, inOggPage->pageSize());
00245 
00246         delete inOggPage;
00247         delete[] locPageData;
00248         return true;
00249 }
00250 bool OggMuxFilter::SetupOutput() {
00251         mOutputFile.open(StringHelper::toNarrowStr(mFileName).c_str(), ios_base::out | ios_base::binary);
00252         return mOutputFile.is_open();
00253 }
00254 bool OggMuxFilter::CloseOutput() {
00255         mOutputFile.close();
00256         return true;
00257 
00258 }
00259 
00260 //      //IFileSource Interface
00261 //STDMETHODIMP OggMuxFilter::GetCurFile(LPOLESTR* outFileName, AM_MEDIA_TYPE* outMediaType) {
00262 //      //Return the filename and mediatype of the raw data
00263 //
00264 //       
00265 //      LPOLESTR x = SysAllocString(mFileName.c_str());
00266 //      *outFileName = x;
00267 //      
00268 //      return S_OK;
00269 //}
00270 //STDMETHODIMP OggMuxFilter::Load(LPCOLESTR inFileName, const AM_MEDIA_TYPE* inMediaType) {
00271 //      //Initialise the file here and setup all the streams
00272 //      CAutoLock locLock(m_pLock);
00273 //      mFileName = inFileName;
00274 //      
00275 //      return SetUpPins();
00276 //}
00277 
00278 //BaseFilter Interface
00279 int OggMuxFilter::GetPinCount() {
00280         //TO DO::: Change this for multiple streams
00281         return (int)mInputPins.size();
00282 }
00283 CBasePin* OggMuxFilter::GetPin(int inPinNo) {
00284 
00285         if ((inPinNo >= 0) && ((size_t)inPinNo < mInputPins.size()) ) {
00286                 return mInputPins[inPinNo];
00287         } else {
00288                 return NULL;
00289         }
00290         //if (inPinNo >= 0 && inPinNo < mStreamMapper->numStreams()) {
00291         //      return mStreamMapper->getOggStream(inPinNo)->getPin();
00292         //} else {
00293         //      return NULL;
00294         //}
00295 }
00296 
00297 //CAMThread Stuff
00298 //DWORD OggMuxFilter::ThreadProc(void) {
00299 //      while(true) {
00300 //              DWORD locThreadCommand = GetRequest();
00301 //              switch(locThreadCommand) {
00302 //                      case THREAD_EXIT:
00303 //                              Reply(S_OK);
00304 //                              return S_OK;
00305 //
00306 //                      //case THREAD_PAUSE:
00307 //                      //      // we are paused already
00308 //                      //      Reply(S_OK);
00309 //                      //      break;
00310 //
00311 //                      case THREAD_RUN:
00312 //                              Reply(S_OK);
00313 //                              DataProcessLoop();
00314 //                              break;
00315 //              }
00316 //      
00317 //      
00318 //      }
00319 //      return S_OK;
00320 //}
00321 
00322 //Helper methods
00323 
00324 //void OggMuxFilter::resetStream() {
00325 //
00326 //      mSourceFile.clear();
00327 //      mSourceFile.close();
00328 //      mOggBuffer.clearData();
00329 //      mSourceFile.open(StringHelper::toNarrowStr(mFileName).c_str(), ios_base::in|ios_base::binary);
00330 //
00331 //      mSourceFile.seekg(mStreamMapper->startOfData(), ios_base::beg);
00332 //      for (unsigned long i = 0; i < mStreamMapper->numStreams(); i++) {
00333 //              mStreamMapper->getOggStream(i)->setSendExcess(true);    
00334 //      }
00335 //}
00336 
00337 //HRESULT OggMuxFilter::DataProcessLoop() {
00338 //      DWORD locCommand = 0;
00339 //      char* locBuff = new  char[4096];
00340 //      bool locKeepGoing = true;;
00341 //      while (!mSourceFile.eof() && locKeepGoing) {
00342 //              if(CheckRequest(&locCommand) == TRUE) {
00343 //                      return S_OK;
00344 //              }
00345 //
00346 //              mSourceFile.read(locBuff, 4096);
00347 //              unsigned long locBytesRead = mSourceFile.gcount();
00348 //              locKeepGoing = mOggBuffer.feed(locBuff, locBytesRead);
00349 //      }
00350 //      DeliverEOS();
00351 //      delete locBuff;
00352 //      //Memory leak
00353 //      //FIXED
00354 //      
00355 //      
00356 //}
00357 //HRESULT OggMuxFilter::SetUpPins() {
00358 //      mSourceFile.open(StringHelper::toNarrowStr(mFileName).c_str(), ios_base::in|ios_base::binary);
00359 //      //Error check
00360 //      
00361 //      //Register a callback
00362 //      mOggBuffer.registerVirtualCallback(this);
00363 //
00364 //      char* locBuff = new char[RAW_BUFFER_SIZE];
00365 //      
00366 //      //Feed the data in until we have seen all BOS pages.
00367 //      while(!mStreamMapper->isReady()) {
00368 //              mSourceFile.read(locBuff, RAW_BUFFER_SIZE);
00369 //              mOggBuffer.feed(locBuff, RAW_BUFFER_SIZE);
00370 //
00371 //      }
00372 //      //Memory leak
00373 //      //FIXED
00374 //      delete locBuff;
00375 //      return S_OK;
00376 //}
00377 //IOggCallback Interface
00378 
00379 //bool OggMuxFilter::acceptOggPage(OggPage* inOggPage) {
00380 //      return mStreamMapper->acceptOggPage(inOggPage);
00381 //}
00382 
00383 //IMEdiaStreaming
00384 STDMETHODIMP OggMuxFilter::Run(REFERENCE_TIME tStart) {
00385         //const REFERENCE_TIME A_LONG_TIME = UNITS * 1000;
00386         CAutoLock locLock(m_pLock);
00387         //DeliverNewSegment(tStart, tStart + A_LONG_TIME, 1.0);
00388         return CBaseFilter::Run(tStart);
00389         
00390 
00391 }
00392 STDMETHODIMP OggMuxFilter::Pause(void) {
00393         CAutoLock locLock(m_pLock);
00394         //if (m_State == State_Stopped) {
00395         //      if (ThreadExists() == FALSE) {
00396         //              Create();
00397         //      }
00398         //      CallWorker(THREAD_RUN);
00399         //}
00400         
00401         HRESULT locHR = CBaseFilter::Pause();
00402         
00403         return locHR;
00404         
00405 }
00406 STDMETHODIMP OggMuxFilter::Stop(void) {
00407         CAutoLock locLock(m_pLock);
00408         //CallWorker(THREAD_EXIT);
00409         //Close();
00410         //DeliverBeginFlush();
00411         //DeliverEndFlush();
00412 
00413         CloseOutput();
00414         return CBaseFilter::Stop();
00415 }
00416 
00417 STDMETHODIMP OggMuxFilter::GetPositions(LONGLONG *pCurrent, LONGLONG *pStop) {
00418         HRESULT locHR = BasicSeekPassThrough::GetPositions(pCurrent, pStop);
00419         debugLog<<"GetPos Before : "<<*pCurrent<<" - "<<*pStop<<endl;
00420         *pCurrent = mInterleaver->progressTime();
00421         debugLog<<"GetPos After : "<<*pCurrent<<" - "<<*pStop<<endl;
00422         return locHR;
00423 }
00424 
00425 STDMETHODIMP OggMuxFilter::GetCurrentPosition(LONGLONG *pCurrent) {
00426         *pCurrent = mInterleaver->progressTime();
00427         debugLog<<"GetCurrentPos : "<<*pCurrent<<endl;
00428         return S_OK;
00429 }
00430 
00431 //SpecifyPropertyPages Implementation
00432 //STDMETHODIMP OggMuxFilter::GetPages(CAUUID* outPropPages) {
00433 //      if (outPropPages == NULL) return E_POINTER;
00434 //
00435 //      const int NUM_PROP_PAGES = 1;
00436 //    outPropPages->cElems = NUM_PROP_PAGES;
00437 //    outPropPages->pElems = (GUID*)(CoTaskMemAlloc(sizeof(GUID) * NUM_PROP_PAGES));
00438 //    if (outPropPages->pElems == NULL) 
00439 //    {
00440 //        return E_OUTOFMEMORY;
00441 //    }
00442 //
00443 //      outPropPages->pElems[0] = CLSID_PropsOggMux;
00444 //    
00445 //    return S_OK;
00446 //
00447 //}
00448 
00449 STDMETHODIMP_(bool) OggMuxFilter::setMaxPacketsPerPage(unsigned long inMaxPacketsPerPage) {
00450         for (std::vector<OggMuxInputPin*>::iterator locPinIterator = mInputPins.begin();
00451                  locPinIterator != mInputPins.end();
00452                  locPinIterator++) {
00453                 OggMuxInputPin* locPin = *locPinIterator;
00454                 locPin->SetPaginatorMaximumPacketsPerPage(inMaxPacketsPerPage);
00455         }
00456 
00457         return true;
00458 }
00459 
00460 STDMETHODIMP_(unsigned long) OggMuxFilter::maxPacketsPerPage() {
00461         unsigned long locCurrentMaximumPacketsPerPage = 0;
00462 
00463         for (std::vector<OggMuxInputPin*>::iterator locPinIterator = mInputPins.begin();
00464                  locPinIterator != mInputPins.end();
00465                  locPinIterator++) {
00466                 
00467                 OggMuxInputPin* locPin = *locPinIterator;
00468 
00469                 unsigned long locMaximumPacketsPerPageForThisPin =
00470                         locPin->PaginatorMaximumPacketsPerPage();
00471 
00472                 if (locMaximumPacketsPerPageForThisPin > locCurrentMaximumPacketsPerPage) {
00473                         locCurrentMaximumPacketsPerPage = locMaximumPacketsPerPageForThisPin;
00474                 }
00475         }
00476 
00477         return locCurrentMaximumPacketsPerPage;
00478 }

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