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

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