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 #include "stdafx.h"
00032 #include "oggmuxinputpin.h"
00033
00034 OggMuxInputPin::OggMuxInputPin(OggMuxFilter* inParentFilter, CCritSec* inFilterLock, HRESULT* inHR, OggMuxStream* inMuxStream)
00035 : CBaseInputPin(NAME("OggMuxInputPin"), inParentFilter, inFilterLock, inHR, L"Ogg Packet In")
00036 , mParentFilter(inParentFilter)
00037 , mMuxStream(inMuxStream)
00038 , mNeedsFLACHeaderTweak(false)
00039 , mNeedsFLACHeaderCount(false)
00040
00041 {
00042
00043
00044 OggPaginatorSettings* locSettings = new OggPaginatorSettings;
00045 locSettings->mMinPageSize = 4096;
00046 locSettings->mMaxPageSize = 8192;
00047
00048 LARGE_INTEGER locTicks;
00049 QueryPerformanceCounter(&locTicks);
00050 srand((unsigned int)locTicks.LowPart);
00051 locSettings->mSerialNo = ((unsigned long)(rand() + 1)) * ((unsigned long)(rand() + 1));
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 mPaginator.setParameters(locSettings);
00062 mPaginator.setPageCallback(mMuxStream);
00063
00064
00065 }
00066
00067 OggMuxInputPin::~OggMuxInputPin(void)
00068 {
00069
00070 }
00071
00072 STDMETHODIMP OggMuxInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00073 {
00074 if (riid == IID_IMediaSeeking) {
00075 *ppv = (IMediaSeeking*)this;
00076 ((IUnknown*)*ppv)->AddRef();
00077 return NOERROR;
00078 }
00079
00080 return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv);
00081 }
00082
00083
00084 HRESULT OggMuxInputPin::SetMediaType(const CMediaType* inMediaType) {
00085
00086
00087 if ((inMediaType->majortype == MEDIATYPE_Video) && (inMediaType->subtype == MEDIASUBTYPE_Theora)) {
00088
00089
00090 sTheoraFormatBlock* locTheora = (sTheoraFormatBlock*)inMediaType->pbFormat;
00091
00092
00093 mMuxStream->setConversionParams(locTheora->frameRateNumerator, locTheora->frameRateDenominator, 10000000, locTheora->maxKeyframeInterval);
00094 mMuxStream->setNumHeaders(3);
00095 mPaginator.setNumHeaders(3);
00096 } else if (inMediaType->majortype == MEDIATYPE_Audio) {
00097 if (inMediaType->subtype == MEDIASUBTYPE_Vorbis) {
00098
00099 sVorbisFormatBlock* locVorbis = (sVorbisFormatBlock*)inMediaType->pbFormat;
00100
00101 mMuxStream->setConversionParams(locVorbis->samplesPerSec, 1, 10000000);
00102 mMuxStream->setNumHeaders(3);
00103 mPaginator.setNumHeaders(3);
00104
00105 } else if (inMediaType->subtype == MEDIASUBTYPE_Speex) {
00106
00107 sSpeexFormatBlock* locSpeex = (sSpeexFormatBlock*)inMediaType->pbFormat;
00108 mMuxStream->setConversionParams(locSpeex->samplesPerSec, 1, 10000000);
00109 mMuxStream->setNumHeaders(2);
00110 mPaginator.setNumHeaders(2);
00111 } else if (inMediaType->subtype == MEDIASUBTYPE_OggFLAC_1_0) {
00112
00113 sFLACFormatBlock* locFLAC = (sFLACFormatBlock*)inMediaType->pbFormat;
00114 mMuxStream->setConversionParams(locFLAC->samplesPerSec, 1, 10000000);
00115
00116
00117 mNeedsFLACHeaderCount = true;
00118 } else if (inMediaType->subtype == MEDIASUBTYPE_FLAC) {
00119
00120
00121 sFLACFormatBlock* locFLAC = (sFLACFormatBlock*)inMediaType->pbFormat;
00122 mMuxStream->setConversionParams(locFLAC->samplesPerSec, 1, 10000000);
00123
00124 mNeedsFLACHeaderTweak = true;
00125 } else if (inMediaType->subtype == MEDIASUBTYPE_RawOggAudio) {
00126 sOggRawAudioFormatBlock* locRawAudio = (sOggRawAudioFormatBlock*)inMediaType->pbFormat;
00127 mMuxStream->setConversionParams(locRawAudio->samplesPerSec, 1, 10000000);
00128 mMuxStream->setNumHeaders(locRawAudio->numHeaders);
00129 mPaginator.setNumHeaders(locRawAudio->numHeaders);
00130 }
00131
00132
00133 } else if (inMediaType->majortype == MEDIATYPE_Text) {
00134 if (inMediaType->subtype == MEDIASUBTYPE_CMML) {
00135 sCMMLFormatBlock* locCMML = (sCMMLFormatBlock*)inMediaType->pbFormat;
00136 mMuxStream->setConversionParams(locCMML->granuleNumerator,locCMML->granuleDenominator, 10000000);
00137 mMuxStream->setNumHeaders(1);
00138 mPaginator.setNumHeaders(1);
00139
00140 }
00141
00142 }
00143 return S_OK;
00144 }
00145
00146 HRESULT OggMuxInputPin::GetMediaType(int inPosition, CMediaType* outMediaType) {
00147 switch(inPosition) {
00148 case 0:
00149 outMediaType->majortype = MEDIATYPE_Video;
00150 outMediaType->subtype = MEDIASUBTYPE_Theora;
00151 return S_OK;
00152 case 1:
00153 outMediaType->majortype = MEDIATYPE_Audio;
00154 outMediaType->subtype = MEDIASUBTYPE_Vorbis;
00155 return S_OK;
00156 case 2:
00157 outMediaType->majortype = MEDIATYPE_Audio;
00158 outMediaType->subtype = MEDIASUBTYPE_Speex;
00159 return S_OK;
00160 case 3:
00161 outMediaType->majortype = MEDIATYPE_Audio;
00162 outMediaType->subtype = MEDIASUBTYPE_OggFLAC_1_0;
00163 return S_OK;
00164 case 4:
00165 outMediaType->majortype = MEDIATYPE_Audio;
00166 outMediaType->subtype = MEDIASUBTYPE_FLAC;
00167 return S_OK;
00168
00169 case 5:
00170 outMediaType->majortype = MEDIATYPE_Text;
00171 outMediaType->subtype = MEDIASUBTYPE_CMML;
00172 return S_OK;
00173
00174 case 6:
00175 outMediaType->majortype = MEDIATYPE_Audio;
00176 outMediaType->subtype = MEDIASUBTYPE_RawOggAudio;
00177 return S_OK;
00178
00179
00180 default:
00181 return VFW_S_NO_MORE_ITEMS;
00182
00183 }
00184 }
00185 HRESULT OggMuxInputPin::CheckMediaType(const CMediaType* inMediaType) {
00186 if ( (inMediaType->majortype == MEDIATYPE_Video
00187 && inMediaType->subtype == MEDIASUBTYPE_Theora
00188 && inMediaType->formattype == FORMAT_Theora)
00189 ||
00190 (inMediaType->majortype == MEDIATYPE_Audio
00191 && inMediaType->subtype == MEDIASUBTYPE_Vorbis
00192 && inMediaType->formattype == FORMAT_Vorbis)
00193 ||
00194 (inMediaType->majortype == MEDIATYPE_Audio
00195 && inMediaType->subtype == MEDIASUBTYPE_Speex
00196 && inMediaType->formattype == FORMAT_Speex)
00197 ||
00198 (inMediaType->majortype == MEDIATYPE_Audio
00199 && inMediaType->subtype == MEDIASUBTYPE_OggFLAC_1_0
00200 && inMediaType->formattype == FORMAT_FLAC)
00201 ||
00202 (inMediaType->majortype == MEDIATYPE_Audio
00203 && inMediaType->subtype == MEDIASUBTYPE_FLAC
00204 && inMediaType->formattype == FORMAT_FLAC)
00205 ||
00206 (inMediaType->majortype == MEDIATYPE_Audio
00207 && inMediaType->subtype == MEDIASUBTYPE_RawOggAudio
00208 && inMediaType->formattype == FORMAT_RawOggAudio)
00209 ||
00210 (inMediaType->majortype == MEDIATYPE_Text
00211 && inMediaType->subtype == MEDIASUBTYPE_CMML
00212 && inMediaType->formattype == FORMAT_CMML)
00213
00214 ) {
00215 return S_OK;
00216 } else {
00217 return E_FAIL;
00218 }
00219 }
00220
00221 STDMETHODIMP OggMuxInputPin::Receive(IMediaSample* inSample) {
00222 CAutoLock locLock(mParentFilter->mStreamLock);
00223 LONGLONG locStart = 0;
00224 LONGLONG locEnd = 0;
00225 BYTE* locSampleBuff;
00226 inSample->GetPointer(&locSampleBuff);
00227 HRESULT locHR = inSample->GetTime(&locStart, &locEnd);
00228
00229
00230 long locBuffSize = inSample->GetActualDataLength();
00231 unsigned char* locBuff = new unsigned char[locBuffSize];
00232 memcpy((void*)locBuff, (const void*)locSampleBuff, inSample->GetActualDataLength());
00233 StampedOggPacket* locPacket = new StampedOggPacket(locBuff, inSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);
00234
00235 if (mNeedsFLACHeaderCount) {
00236 mNeedsFLACHeaderCount = false;
00237
00238 mPaginator.setNumHeaders( (locPacket->packetData()[8]) + 1 );
00239 }
00240 if ((mNeedsFLACHeaderTweak)) {
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 FLACMetadataSplitter* locFLACSplitter = new FLACMetadataSplitter;
00265
00266
00267 locFLACSplitter->loadMetadata(locPacket->clone());
00268
00269
00270
00271 for (unsigned long i = 0; i < locFLACSplitter->numHeaders(); i++) {
00272
00273
00274 if (i == 0) {
00275
00276 StampedOggPacket* locHeadPack = locFLACSplitter->getHeader(i);
00277 mPaginator.setNumHeaders((locHeadPack->packetData()[8]) + 1);
00278 delete locHeadPack;
00279 }
00280 mPaginator.acceptStampedOggPacket(locFLACSplitter->getHeader(i));
00281
00282 }
00283 mNeedsFLACHeaderTweak = false;
00284
00285 delete locFLACSplitter;
00286
00287
00288 } else {
00289
00290
00291
00292 mPaginator.acceptStampedOggPacket(locPacket);
00293 }
00294
00295 return S_OK;
00296
00297
00298
00299 }
00300
00301 HRESULT OggMuxInputPin::CompleteConnect(IPin* inReceivePin) {
00302
00303
00304 IMediaSeeking* locSeeker = NULL;
00305 inReceivePin->QueryInterface(IID_IMediaSeeking, (void**)&locSeeker);
00306 SetDelegate(locSeeker);
00307
00308
00309 mMuxStream->setIsActive(true);
00310 return mParentFilter->addAnotherPin();
00311
00312
00313 }
00314
00315 HRESULT OggMuxInputPin::BreakConnect()
00316 {
00317 CAutoLock locLock(m_pLock);
00318
00319 ReleaseDelegate();
00320 return CBaseInputPin::BreakConnect();
00321 }
00322
00323
00324
00325
00326 STDMETHODIMP OggMuxInputPin::EndOfStream(void) {
00327 CAutoLock locLock(mParentFilter->mStreamLock);
00328 mPaginator.finishStream();
00329 mMuxStream->setIsEOS(true);
00330
00331
00332
00333 return S_OK;
00334
00335 }
00336
00337 unsigned long OggMuxInputPin::PaginatorMaximumPacketsPerPage()
00338 {
00339 return mPaginator.parameters()->mMaxPacksPerPage;
00340 }
00341
00342 void OggMuxInputPin::SetPaginatorMaximumPacketsPerPage(unsigned long inMaxPacketsPerPage)
00343 {
00344 mPaginator.parameters()->mMaxPacksPerPage = inMaxPacketsPerPage;
00345 }
00346