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