00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "stdafx.h"
00033 #include "oggdemuxsourcefilter.h"
00034
00035
00036
00037 CFactoryTemplate g_Templates[] =
00038 {
00039 {
00040 L"OggDemuxFilter",
00041 &CLSID_OggDemuxSourceFilter,
00042 OggDemuxSourceFilter::CreateInstance,
00043 NULL,
00044 NULL
00045 },
00046
00047 {
00048 L"illiminable About Page",
00049 &CLSID_PropsAbout,
00050 PropsAbout::CreateInstance,
00051 NULL,
00052 NULL
00053 }
00054
00055 };
00056
00057
00058 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
00059
00060
00061
00062 CUnknown* WINAPI OggDemuxSourceFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
00063 {
00064 OggDemuxSourceFilter *pNewObject = new OggDemuxSourceFilter();
00065 if (pNewObject == NULL) {
00066 *pHr = E_OUTOFMEMORY;
00067 }
00068 return pNewObject;
00069 }
00070
00071
00072 STDMETHODIMP OggDemuxSourceFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00073 {
00074 if (riid == IID_IFileSourceFilter) {
00075 *ppv = (IFileSourceFilter*)this;
00076 ((IUnknown*)*ppv)->AddRef();
00077 return NOERROR;
00078
00079
00080
00081
00082 } else if (riid == IID_ISpecifyPropertyPages) {
00083 *ppv = (ISpecifyPropertyPages*)this;
00084 ((IUnknown*)*ppv)->AddRef();
00085 return NOERROR;
00086 } else if (riid == IID_IAMFilterMiscFlags) {
00087 *ppv = (IAMFilterMiscFlags*)this;
00088 ((IUnknown*)*ppv)->AddRef();
00089 return NOERROR;
00090 } else if (riid == IID_IAMMediaContent) {
00091
00092 *ppv = (IAMMediaContent*)this;
00093 ((IUnknown*)*ppv)->AddRef();
00094 return NOERROR;
00095 }
00096
00097 return CBaseFilter::NonDelegatingQueryInterface(riid, ppv);
00098 }
00099
00100
00101
00102
00103
00104 OggDemuxSourceFilter::OggDemuxSourceFilter()
00105 : CBaseFilter(NAME("OggDemuxSourceFilter"), NULL, m_pLock, CLSID_OggDemuxSourceFilter)
00106
00107 , mSeekTable(NULL)
00108 , mDataSource(NULL)
00109 , mSeekTimeBase(0)
00110 , mJustReset(true)
00111 {
00112
00113 m_pLock = new CCritSec;
00114 mSourceFileLock = new CCritSec;
00115 mDemuxLock = new CCritSec;
00116 mStreamLock = new CCritSec;
00117 mStreamMapper = new OggStreamMapper(this);
00118
00119 #ifdef OGGCODECS_LOGGING
00120 debugLog.open("g:\\logs\\sourcelog.log", ios_base::out);
00121 #endif
00122
00123 }
00124
00125
00126 OggDemuxSourceFilter::OggDemuxSourceFilter(REFCLSID inFilterGUID)
00127 : CBaseFilter(NAME("OggDemuxSourceFilter"), NULL, m_pLock, inFilterGUID)
00128 , mSeekTable(NULL)
00129 , mStreamMapper(NULL)
00130 , mSeekTimeBase(0)
00131 , mJustReset(true)
00132 {
00133
00134 m_pLock = new CCritSec;
00135 mSourceFileLock = new CCritSec;
00136 mDemuxLock = new CCritSec;
00137 mStreamLock = new CCritSec;
00138 #ifdef OGGCODECS_LOGGING
00139 debugLog.open("d:\\zen\\logs\\anx_base_sourcelog.log", ios_base::out);
00140 #endif
00141
00142
00143
00144
00145 }
00146
00147 OggDemuxSourceFilter::~OggDemuxSourceFilter(void)
00148 {
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 if (mDataSource != NULL) {
00161 mDataSource->close();
00162 }
00163 delete mDataSource;
00164
00165 debugLog.close();
00166
00167
00168 delete mStreamMapper;
00169 mStreamMapper = NULL;
00170
00171
00172 if (ThreadExists() == TRUE) {
00173
00174 Close();
00175 }
00176
00177 delete mSeekTable;
00178 mSeekTable = NULL;
00179 }
00180
00181
00182 ULONG OggDemuxSourceFilter::GetMiscFlags(void)
00183 {
00184 return AM_FILTER_MISC_FLAGS_IS_SOURCE;
00185 }
00186
00187 STDMETHODIMP OggDemuxSourceFilter::GetPages(CAUUID* outPropPages)
00188 {
00189
00190 if (outPropPages == NULL) return E_POINTER;
00191
00192 const int NUM_PROP_PAGES = 1;
00193 outPropPages->cElems = NUM_PROP_PAGES;
00194 outPropPages->pElems = (GUID*)(CoTaskMemAlloc(sizeof(GUID) * NUM_PROP_PAGES));
00195 if (outPropPages->pElems == NULL)
00196 {
00197 return E_OUTOFMEMORY;
00198 }
00199
00200 outPropPages->pElems[0] = CLSID_PropsAbout;
00201
00202 return S_OK;
00203
00204 }
00205
00206
00207 STDMETHODIMP OggDemuxSourceFilter::GetCurFile(LPOLESTR* outFileName, AM_MEDIA_TYPE* outMediaType)
00208 {
00209
00210 LPOLESTR x = SysAllocString(mFileName.c_str());
00211 *outFileName = x;
00212
00213 return S_OK;
00214 }
00215
00216
00217 STDMETHODIMP OggDemuxSourceFilter::Load(LPCOLESTR inFileName, const AM_MEDIA_TYPE* inMediaType)
00218 {
00219
00220 CAutoLock locLock(m_pLock);
00221 mFileName = inFileName;
00222
00223
00224
00225
00226 mSeekTable = new AutoOggSeekTable(StringHelper::toNarrowStr(mFileName));
00227 mSeekTable->buildTable();
00228
00229 return SetUpPins();
00230 }
00231
00232 STDMETHODIMP OggDemuxSourceFilter::GetCapabilities(DWORD* inCapabilities)
00233 {
00234 if (mSeekTable->enabled()) {
00235
00236 *inCapabilities = mSeekingCap;
00237 return S_OK;
00238 } else {
00239
00240 *inCapabilities = 0;
00241 return S_OK;;
00242 }
00243 }
00244 STDMETHODIMP OggDemuxSourceFilter::GetDuration(LONGLONG* outDuration)
00245 {
00246 if (mSeekTable->enabled()) {
00247
00248 *outDuration = mSeekTable->fileDuration();
00249 return S_OK;
00250 } else {
00251 return E_NOTIMPL;
00252 }
00253
00254 }
00255
00256 STDMETHODIMP OggDemuxSourceFilter::CheckCapabilities(DWORD *pCapabilities)
00257 {
00258
00259 return E_NOTIMPL;
00260 }
00261 STDMETHODIMP OggDemuxSourceFilter::IsFormatSupported(const GUID *pFormat)
00262 {
00263 ASSERT(pFormat != NULL);
00264 if (*pFormat == TIME_FORMAT_MEDIA_TIME) {
00265
00266 return S_OK;
00267 } else {
00268
00269 return S_FALSE;
00270 }
00271
00272
00273 }
00274 STDMETHODIMP OggDemuxSourceFilter::QueryPreferredFormat(GUID *pFormat){
00275
00276 *pFormat = TIME_FORMAT_MEDIA_TIME;
00277 return S_OK;
00278 }
00279 STDMETHODIMP OggDemuxSourceFilter::SetTimeFormat(const GUID *pFormat){
00280
00281 return E_NOTIMPL;
00282 }
00283 STDMETHODIMP OggDemuxSourceFilter::GetTimeFormat( GUID *pFormat){
00284 *pFormat = TIME_FORMAT_MEDIA_TIME;
00285 return S_OK;
00286 }
00287 STDMETHODIMP OggDemuxSourceFilter::GetStopPosition(LONGLONG *pStop){
00288 if (mSeekTable->enabled()) {
00289
00290
00291 *pStop = mSeekTable->fileDuration();
00292 return S_OK;
00293 } else {
00294
00295 return E_NOTIMPL;
00296 }
00297 }
00298 STDMETHODIMP OggDemuxSourceFilter::GetCurrentPosition(LONGLONG *pCurrent)
00299 {
00300
00301
00302
00303 return E_NOTIMPL;
00304 }
00305 STDMETHODIMP OggDemuxSourceFilter::ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat){
00306
00307 return E_NOTIMPL;
00308 }
00309 STDMETHODIMP OggDemuxSourceFilter::SetPositions(LONGLONG *pCurrent,DWORD dwCurrentFlags,LONGLONG *pStop,DWORD dwStopFlags){
00310
00311
00312 CAutoLock locLock(m_pLock);
00313
00314 if (mSeekTable->enabled()) {
00315
00316
00317
00318
00319 CAutoLock locSourceLock(mSourceFileLock);
00320 mSetIgnorePackets = false;
00321 DeliverBeginFlush();
00322
00323
00324
00325 OggSeekTable::tSeekPair locStartPos = mSeekTable->getStartPos(*pCurrent);
00326 bool locSendExcess = false;
00327
00328
00329
00330
00331 if (locStartPos.second == mStreamMapper->startOfData()) {
00332 locSendExcess = true;
00333
00334
00335 mSetIgnorePackets = true;
00336 }
00337
00338
00339
00340
00341
00342 *pCurrent = mSeekTimeBase
00343 = locStartPos.first;
00344
00345
00346 for (unsigned long i = 0; i < mStreamMapper->numStreams(); i++) {
00347 mStreamMapper->getOggStream(i)->setSendExcess(locSendExcess);
00348 mStreamMapper->getOggStream(i)->setLastEndGranPos(*pCurrent);
00349 }
00350 {
00351
00352 DeliverEndFlush();
00353
00354 DeliverNewSegment(*pCurrent, mSeekTable->fileDuration(), 1.0);
00355 }
00356
00357
00358 mDataSource->seek(locStartPos.second);
00359
00360
00361 } else {
00362
00363 return E_NOTIMPL;
00364 }
00365
00366 return S_OK;
00367 }
00368 STDMETHODIMP OggDemuxSourceFilter::GetPositions(LONGLONG *pCurrent, LONGLONG *pStop)
00369 {
00370
00371
00372 return E_NOTIMPL;
00373 }
00374 STDMETHODIMP OggDemuxSourceFilter::GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest){
00375
00376 if (mSeekTable->enabled()) {
00377
00378 *pEarliest = 0;
00379
00380 *pLatest = mSeekTable->fileDuration();
00381 return S_OK;
00382 } else {
00383 return E_NOTIMPL;
00384 }
00385 }
00386 STDMETHODIMP OggDemuxSourceFilter::SetRate(double dRate)
00387 {
00388
00389 return E_NOTIMPL;
00390 }
00391 STDMETHODIMP OggDemuxSourceFilter::GetRate(double *dRate)
00392 {
00393
00394 *dRate = 1.0;
00395 return S_OK;;
00396 }
00397 STDMETHODIMP OggDemuxSourceFilter::GetPreroll(LONGLONG *pllPreroll)
00398 {
00399
00400 *pllPreroll = 0;
00401
00402 return S_OK;
00403 }
00404 STDMETHODIMP OggDemuxSourceFilter::IsUsingTimeFormat(const GUID *pFormat){
00405 if (*pFormat == TIME_FORMAT_MEDIA_TIME) {
00406
00407 return S_OK;
00408 } else {
00409
00410 return S_FALSE;
00411 }
00412 }
00413
00414
00415
00416 int OggDemuxSourceFilter::GetPinCount()
00417 {
00418 return mStreamMapper->numStreams();
00419 }
00420 CBasePin* OggDemuxSourceFilter::GetPin(int inPinNo)
00421 {
00422
00423
00424 if ((inPinNo >= 0) && ((unsigned long)inPinNo < mStreamMapper->numStreams())) {
00425 return mStreamMapper->getOggStream(inPinNo)->getPin();
00426 } else {
00427 return NULL;
00428 }
00429 }
00430
00431
00432 DWORD OggDemuxSourceFilter::ThreadProc(void) {
00433
00434 while(true) {
00435 DWORD locThreadCommand = GetRequest();
00436
00437 switch(locThreadCommand) {
00438 case THREAD_EXIT:
00439
00440 Reply(S_OK);
00441 return S_OK;
00442
00443 case THREAD_RUN:
00444
00445 Reply(S_OK);
00446 DataProcessLoop();
00447 break;
00448 }
00449 }
00450 return S_OK;
00451 }
00452
00453
00454
00455 void OggDemuxSourceFilter::resetStream() {
00456 {
00457 debugLog<<"Reset stream pre-lock"<<endl;
00458 CAutoLock locDemuxLock(mDemuxLock);
00459 CAutoLock locSourceLock(mSourceFileLock);
00460 debugLog<<"RestStream post-lock"<<endl;
00461
00462
00463 mDataSource->clear();
00464
00465 debugLog<<"Pre close"<<endl;
00466 mDataSource->close();
00467 debugLog<<"Post close"<<endl;
00468
00469
00470 delete mDataSource;
00471 mDataSource = NULL;
00472
00473
00474
00475
00476 mOggBuffer.clearData();
00477
00478
00479 mDataSource = DataSourceFactory::createDataSource(StringHelper::toNarrowStr(mFileName).c_str());
00480
00481 debugLog<<"Pre open"<<endl;
00482 mDataSource->open(StringHelper::toNarrowStr(mFileName).c_str());
00483 debugLog<<"Post open"<<endl;
00484 mDataSource->seek(mStreamMapper->startOfData());
00485
00486
00487
00488 mJustReset = true;
00489 }
00490
00491 for (unsigned long i = 0; i < mStreamMapper->numStreams(); i++) {
00492 mStreamMapper->getOggStream(i)->setSendExcess(true);
00493 }
00494 }
00495
00496 void OggDemuxSourceFilter::DeliverBeginFlush()
00497 {
00498 CAutoLock locLock(m_pLock);
00499
00500 debugLog << "Delivering Begin Flush"<<endl;
00501 for (unsigned long i = 0; i < mStreamMapper->numStreams(); i++) {
00502 mStreamMapper->getOggStream(i)->getPin()->DeliverBeginFlush();
00503
00504 }
00505
00506
00507
00508 debugLog<<"Calling reset stream from begin flush"<<endl;
00509 resetStream();
00510 }
00511
00512 void OggDemuxSourceFilter::DeliverEndFlush()
00513 {
00514 CAutoLock locLock(m_pLock);
00515 debugLog << "Delivering End Flush"<<endl;
00516 if (mSetIgnorePackets == true) {
00517 mStreamMapper->toStartOfData();
00518 for (unsigned long i = 0; i < mStreamMapper->numStreams(); i++) {
00519
00520 mStreamMapper->getOggStream(i)->getPin()->DeliverEndFlush();
00521 }
00522
00523 } else {
00524
00525 for (unsigned long i = 0; i < mStreamMapper->numStreams(); i++) {
00526 mStreamMapper->getOggStream(i)->flush();
00527 mStreamMapper->getOggStream(i)->getPin()->DeliverEndFlush();
00528 }
00529 }
00530 mSetIgnorePackets = false;
00531 }
00532 void OggDemuxSourceFilter::DeliverEOS()
00533 {
00534 mStreamMapper->toStartOfData();
00535 for (unsigned long i = 0; i < mStreamMapper->numStreams(); i++) {
00536
00537 mStreamMapper->getOggStream(i)->getPin()->DeliverEndOfStream();
00538
00539 }
00540
00541 debugLog<<"Calling reset stream from DeliverEOS"<<endl;
00542 resetStream();
00543 }
00544
00545 void OggDemuxSourceFilter::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
00546 {
00547 debugLog<<"DeliverNewSegment : Delivering start = "<<tStart<<" end = "<< tStop<<"rate = "<<dRate<<endl;
00548
00549 for (unsigned long i = 0; i < mStreamMapper->numStreams(); i++) {
00550 mStreamMapper->getOggStream(i)->getPin()->DeliverNewSegment(tStart, tStop, dRate);
00551 }
00552 }
00553 HRESULT OggDemuxSourceFilter::DataProcessLoop()
00554 {
00555
00556
00557
00558 DWORD locCommand = 0;
00559 char* locBuff = new char[4096];
00560
00561 bool locKeepGoing = true;
00562 unsigned long locBytesRead = 0;
00563 bool locIsEOF = true;
00564 {
00565 CAutoLock locSourceLock(mSourceFileLock);
00566 locIsEOF = mDataSource->isEOF();
00567 }
00568
00569 while(true) {
00570 if(CheckRequest(&locCommand) == TRUE) {
00571
00572 delete[] locBuff;
00573 return S_OK;
00574 }
00575
00576 {
00577 CAutoLock locSourceLock(mSourceFileLock);
00578
00579 locBytesRead = mDataSource->read(locBuff, 4096);
00580 mJustReset = false;
00581 }
00582
00583 {
00584 CAutoLock locDemuxLock(mDemuxLock);
00585
00586 if (mJustReset) {
00587 continue;
00588 }
00589 locKeepGoing = ((mOggBuffer.feed((const unsigned char*)locBuff, locBytesRead)) == (OggDataBuffer::FEED_OK));;
00590 }
00591 if (!locKeepGoing) {
00592
00593
00594 DeliverEOS();
00595 }
00596 {
00597 CAutoLock locSourceLock(mSourceFileLock);
00598 locIsEOF = mDataSource->isEOF();
00599 }
00600 if (locIsEOF) {
00601
00602
00603 DeliverEOS();
00604 }
00605 }
00606
00607
00608
00609
00610 delete[] locBuff;
00611
00612
00613 return S_OK;
00614 }
00615
00616
00617 HRESULT OggDemuxSourceFilter::SetUpPins()
00618 {
00619 CAutoLock locDemuxLock(mDemuxLock);
00620 CAutoLock locSourceLock(mSourceFileLock);
00621
00622
00623
00624 mDataSource = DataSourceFactory::createDataSource(StringHelper::toNarrowStr(mFileName).c_str());
00625 mDataSource->open(StringHelper::toNarrowStr(mFileName).c_str());
00626
00627
00628
00629
00630 mOggBuffer.registerVirtualCallback(this);
00631
00632 char* locBuff = new char[RAW_BUFFER_SIZE];
00633 unsigned long locNumRead = 0;
00634
00635
00636 while(!mStreamMapper->isReady()) {
00637
00638 locNumRead = mDataSource->read(locBuff, RAW_BUFFER_SIZE);
00639
00640 if (locNumRead > 0) {
00641 mOggBuffer.feed((const unsigned char*)locBuff, locNumRead);
00642 }
00643 }
00644
00645 mStreamMapper->setAllowDispatch(true);
00646 mStreamMapper->toStartOfData();
00647 mOggBuffer.clearData();
00648 mDataSource->seek(0);
00649
00650
00651 delete[] locBuff;
00652 return S_OK;
00653 }
00654
00655
00656 bool OggDemuxSourceFilter::acceptOggPage(OggPage* inOggPage)
00657 {
00658 return mStreamMapper->acceptOggPage(inOggPage);
00659 }
00660
00661
00662 STDMETHODIMP OggDemuxSourceFilter::Run(REFERENCE_TIME tStart)
00663 {
00664 const REFERENCE_TIME A_LONG_TIME = UNITS * 1000;
00665 CAutoLock locLock(m_pLock);
00666 debugLog<<"Run : time = "<<tStart<<endl;
00667
00668 return CBaseFilter::Run(tStart);
00669
00670
00671 }
00672 STDMETHODIMP OggDemuxSourceFilter::Pause(void)
00673 {
00674 CAutoLock locLock(m_pLock);
00675 debugLog << "** Pause called **"<<endl;
00676 if (m_State == State_Stopped) {
00677
00678 if (ThreadExists() == FALSE) {
00679 Create();
00680 }
00681 CallWorker(THREAD_RUN);
00682 }
00683
00684
00685 HRESULT locHR = CBaseFilter::Pause();
00686
00687 return locHR;
00688
00689 }
00690 STDMETHODIMP OggDemuxSourceFilter::Stop(void)
00691 {
00692 CAutoLock locLock(m_pLock);
00693 debugLog<<"** Stop Called ** "<<endl;
00694 CallWorker(THREAD_EXIT);
00695 Close();
00696 DeliverBeginFlush();
00697 mSetIgnorePackets = true;
00698 DeliverEndFlush();
00699
00700 return CBaseFilter::Stop();
00701 }
00702
00703 CCritSec* OggDemuxSourceFilter::theLock()
00704 {
00705 return m_pLock;
00706 }
00707
00708
00709
00710 STDMETHODIMP OggDemuxSourceFilter::get_AuthorName(BSTR* outAuthorName) {
00711 return E_NOTIMPL;
00712 }
00713 STDMETHODIMP OggDemuxSourceFilter::get_Title(BSTR* outTitle) {
00714
00715 return E_NOTIMPL;
00716 }
00717 STDMETHODIMP OggDemuxSourceFilter::get_Rating(BSTR* outRating) {
00718 return E_NOTIMPL;
00719 }
00720 STDMETHODIMP OggDemuxSourceFilter::get_Description(BSTR* outDescription) {
00721 return E_NOTIMPL;
00722 }
00723 STDMETHODIMP OggDemuxSourceFilter::get_Copyright(BSTR* outCopyright) {
00724 return E_NOTIMPL;
00725 }
00726 STDMETHODIMP OggDemuxSourceFilter::get_BaseURL(BSTR* outBaseURL) {
00727 return E_NOTIMPL;
00728 }
00729 STDMETHODIMP OggDemuxSourceFilter::get_LogoURL(BSTR* outLogoURL) {
00730 return E_NOTIMPL;
00731 }
00732 STDMETHODIMP OggDemuxSourceFilter::get_LogoIconURL(BSTR* outLogoIconURL) {
00733 return E_NOTIMPL;
00734 }
00735 STDMETHODIMP OggDemuxSourceFilter::get_WatermarkURL(BSTR* outWatermarkURL) {
00736 return E_NOTIMPL;
00737 }
00738 STDMETHODIMP OggDemuxSourceFilter::get_MoreInfoURL(BSTR* outMoreInfoURL) {
00739 return E_NOTIMPL;
00740 }
00741 STDMETHODIMP OggDemuxSourceFilter::get_MoreInfoBannerImage(BSTR* outMoreInfoBannerImage) {
00742 return E_NOTIMPL;
00743 }
00744 STDMETHODIMP OggDemuxSourceFilter::get_MoreInfoBannerURL(BSTR* outMoreInfoBannerURL) {
00745 return E_NOTIMPL;
00746 }
00747 STDMETHODIMP OggDemuxSourceFilter::get_MoreInfoText(BSTR* outMoreInfoText) {
00748 return E_NOTIMPL;
00749 }
00750
00751
00752 STDMETHODIMP OggDemuxSourceFilter::GetTypeInfoCount( unsigned int FAR* pctinfo ) {
00753 return E_NOTIMPL;
00754
00755 }
00756 STDMETHODIMP OggDemuxSourceFilter::GetIDsOfNames( REFIID riid,
00757 OLECHAR FAR* FAR* rgszNames,
00758 unsigned int cNames,
00759 LCID lcid,
00760 DISPID FAR* rgDispId ) {
00761 return E_NOTIMPL;
00762 }
00763 STDMETHODIMP OggDemuxSourceFilter::GetTypeInfo( unsigned int iTInfo,
00764 LCID lcid,
00765 ITypeInfo FAR* FAR* ppTInfo ) {
00766 return E_NOTIMPL;
00767 }
00768 STDMETHODIMP OggDemuxSourceFilter::Invoke( DISPID dispIdMember,
00769 REFIID riid,
00770 LCID lcid,
00771 WORD wFlags,
00772 DISPPARAMS FAR* pDispParams,
00773 VARIANT FAR* pVarResult,
00774 EXCEPINFO FAR* pExcepInfo,
00775 unsigned int FAR* puArgErr ) {
00776 return E_NOTIMPL;
00777 }