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
00034 #include "TheoraDecodeFilter.h"
00035
00036
00037
00038
00039 CFactoryTemplate g_Templates[] =
00040 {
00041 {
00042 L"Theora Decode Filter",
00043 &CLSID_TheoraDecodeFilter,
00044 TheoraDecodeFilter::CreateInstance,
00045 NULL,
00046 NULL
00047 }
00048
00049 };
00050
00051
00052 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
00053
00054
00055
00056 TheoraDecodeFilter::TheoraDecodeFilter()
00057 : CTransformFilter( NAME("Theora Decode Filter"), NULL, CLSID_TheoraDecodeFilter)
00058 , mHeight(0)
00059 , mWidth(0)
00060 , mFrameSize(0)
00061 , mFrameCount(0)
00062 , mYOffset(0)
00063 , mXOffset(0)
00064 , mFrameDuration(0)
00065 , mBegun(false)
00066 , mSeekTimeBase(0)
00067 , mLastSeenStartGranPos(0)
00068 , mTheoraFormatInfo(NULL)
00069 {
00070 #ifdef OGGCODECS_LOGGING
00071 debugLog.open("G:\\logs\\newtheofilter.log", ios_base::out);
00072 #endif
00073 mTheoraDecoder = new TheoraDecoder;
00074 mTheoraDecoder->initCodec();
00075
00076 }
00077
00078 TheoraDecodeFilter::~TheoraDecodeFilter() {
00079 delete mTheoraDecoder;
00080 mTheoraDecoder = NULL;
00081
00082 delete mTheoraFormatInfo;
00083 mTheoraFormatInfo = NULL;
00084 debugLog.close();
00085
00086 }
00087
00088 CUnknown* WINAPI TheoraDecodeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
00089 {
00090
00091 TheoraDecodeFilter *pNewObject = new TheoraDecodeFilter();
00092 if (pNewObject == NULL) {
00093 *pHr = E_OUTOFMEMORY;
00094 }
00095 return pNewObject;
00096 }
00097 void TheoraDecodeFilter::FillMediaType(CMediaType* outMediaType, unsigned long inSampleSize) {
00098 outMediaType->SetType(&MEDIATYPE_Video);
00099 outMediaType->SetSubtype(&MEDIASUBTYPE_YV12);
00100 outMediaType->SetFormatType(&FORMAT_VideoInfo);
00101 outMediaType->SetTemporalCompression(FALSE);
00102 outMediaType->SetSampleSize(inSampleSize);
00103
00104 }
00105 bool TheoraDecodeFilter::FillVideoInfoHeader(VIDEOINFOHEADER* inFormatBuffer) {
00106 TheoraDecodeFilter* locFilter = this;
00107
00108 inFormatBuffer->AvgTimePerFrame = (UNITS * locFilter->mTheoraFormatInfo->frameRateDenominator) / locFilter->mTheoraFormatInfo->frameRateNumerator;
00109 inFormatBuffer->dwBitRate = locFilter->mTheoraFormatInfo->targetBitrate;
00110
00111 inFormatBuffer->bmiHeader.biBitCount = 12;
00112 inFormatBuffer->bmiHeader.biClrImportant = 0;
00113 inFormatBuffer->bmiHeader.biClrUsed = 0;
00114 inFormatBuffer->bmiHeader.biCompression = MAKEFOURCC('Y','V','1','2');
00115 inFormatBuffer->bmiHeader.biHeight = locFilter->mTheoraFormatInfo->pictureHeight;
00116 inFormatBuffer->bmiHeader.biPlanes = 1;
00117 inFormatBuffer->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00118 inFormatBuffer->bmiHeader.biSizeImage = ((locFilter->mTheoraFormatInfo->pictureHeight * locFilter->mTheoraFormatInfo->pictureWidth) * 3)/2;
00119 inFormatBuffer->bmiHeader.biWidth = locFilter->mTheoraFormatInfo->pictureWidth;
00120 inFormatBuffer->bmiHeader.biXPelsPerMeter = 2000;
00121 inFormatBuffer->bmiHeader.biYPelsPerMeter = 2000;
00122
00123 inFormatBuffer->rcSource.top = 0;
00124 inFormatBuffer->rcSource.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
00125 inFormatBuffer->rcSource.left = 0;
00126 inFormatBuffer->rcSource.right = locFilter->mTheoraFormatInfo->pictureWidth;
00127
00128 inFormatBuffer->rcTarget.top = 0;
00129 inFormatBuffer->rcTarget.bottom = locFilter->mTheoraFormatInfo->pictureHeight;
00130 inFormatBuffer->rcTarget.left = 0;
00131 inFormatBuffer->rcTarget.right = locFilter->mTheoraFormatInfo->pictureWidth;
00132
00133 inFormatBuffer->dwBitErrorRate=0;
00134 return true;
00135 }
00136
00137 HRESULT TheoraDecodeFilter::CheckInputType(const CMediaType* inMediaType) {
00138
00139 if ( (inMediaType->majortype == MEDIATYPE_Video) &&
00140 (inMediaType->subtype == MEDIASUBTYPE_Theora) && (inMediaType->formattype == FORMAT_Theora)
00141 )
00142 {
00143 return S_OK;
00144 } else {
00145 return S_FALSE;
00146 }
00147 }
00148 HRESULT TheoraDecodeFilter::CheckTransform(const CMediaType* inInputMediaType, const CMediaType* inOutputMediaType) {
00149 if ((CheckInputType(inInputMediaType) == S_OK) &&
00150 ((inOutputMediaType->majortype == MEDIATYPE_Video) && (inOutputMediaType->subtype == MEDIASUBTYPE_YV12) && (inOutputMediaType->formattype == FORMAT_VideoInfo)
00151 )) {
00152 VIDEOINFOHEADER* locVideoHeader = (VIDEOINFOHEADER*)inOutputMediaType->Format();
00153
00154
00155
00156 mHeight = (unsigned long)abs(locVideoHeader->bmiHeader.biHeight);
00157 mWidth = (unsigned long)abs(locVideoHeader->bmiHeader.biWidth);
00158 return S_OK;
00159
00160
00161
00162 } else {
00163 return S_FALSE;
00164 }
00165 }
00166 HRESULT TheoraDecodeFilter::DecideBufferSize(IMemAllocator* inAllocator, ALLOCATOR_PROPERTIES* inPropertyRequest) {
00167
00168
00169
00170
00171
00172
00173 HRESULT locHR = S_OK;
00174
00175
00176 ALLOCATOR_PROPERTIES locReqAlloc;
00177 ALLOCATOR_PROPERTIES locActualAlloc;
00178
00179
00180
00181
00182
00183
00184
00185
00186 const unsigned long MIN_BUFFER_SIZE = 16*16;
00187 const unsigned long DEFAULT_BUFFER_SIZE = 1024*1024 * 2;
00188 const unsigned long MIN_NUM_BUFFERS = 1;
00189 const unsigned long DEFAULT_NUM_BUFFERS = 1;
00190
00191
00192
00193
00194 if (inPropertyRequest->cbAlign <= 0) {
00195 locReqAlloc.cbAlign = 1;
00196 } else {
00197 locReqAlloc.cbAlign = inPropertyRequest->cbAlign;
00198 }
00199
00200
00201 if (inPropertyRequest->cbBuffer < MIN_BUFFER_SIZE) {
00202 locReqAlloc.cbBuffer = DEFAULT_BUFFER_SIZE;
00203 } else {
00204 locReqAlloc.cbBuffer = inPropertyRequest->cbBuffer;
00205 }
00206
00207
00208 if (inPropertyRequest->cbPrefix < 0) {
00209 locReqAlloc.cbPrefix = 0;
00210 } else {
00211 locReqAlloc.cbPrefix = inPropertyRequest->cbPrefix;
00212 }
00213
00214
00215 if (inPropertyRequest->cBuffers < MIN_NUM_BUFFERS) {
00216 locReqAlloc.cBuffers = DEFAULT_NUM_BUFFERS;
00217 } else {
00218
00219 locReqAlloc.cBuffers = inPropertyRequest->cBuffers;
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 locHR = inAllocator->SetProperties(&locReqAlloc, &locActualAlloc);
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 switch (locHR) {
00241 case E_POINTER:
00242
00243 return locHR;
00244
00245
00246 case VFW_E_ALREADY_COMMITTED:
00247
00248 return locHR;
00249
00250 case VFW_E_BADALIGN:
00251
00252 return locHR;
00253
00254 case VFW_E_BUFFERS_OUTSTANDING:
00255
00256 return locHR;
00257
00258
00259 case S_OK:
00260
00261 break;
00262 default:
00263
00264 break;
00265
00266 }
00267
00268
00269
00270
00271
00272 locHR = inAllocator->Commit();
00273
00274
00275
00276 switch (locHR) {
00277 case E_FAIL:
00278
00279 return locHR;
00280 case E_POINTER:
00281
00282 return locHR;
00283 case E_INVALIDARG:
00284
00285 return locHR;
00286 case E_NOTIMPL:
00287
00288 return locHR;
00289 case S_OK:
00290
00291 break;
00292 default:
00293
00294 return locHR;
00295 }
00296
00297
00298 return S_OK;
00299 }
00300 HRESULT TheoraDecodeFilter::GetMediaType(int inPosition, CMediaType* outOutputMediaType) {
00301 if (inPosition < 0) {
00302 return E_INVALIDARG;
00303 }
00304
00305 if (inPosition == 0) {
00306
00307 VIDEOINFOHEADER* locVideoFormat = (VIDEOINFOHEADER*)outOutputMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00308 FillVideoInfoHeader(locVideoFormat);
00309 FillMediaType(outOutputMediaType, locVideoFormat->bmiHeader.biSizeImage);
00310
00311
00312
00313 return S_OK;
00314 } else {
00315 return VFW_S_NO_MORE_ITEMS;
00316 }
00317 }
00318
00319 void TheoraDecodeFilter::ResetFrameCount() {
00320 mFrameCount = 0;
00321
00322 }
00323
00324 HRESULT TheoraDecodeFilter::NewSegment(REFERENCE_TIME inStart, REFERENCE_TIME inEnd, double inRate)
00325 {
00326 debugLog<<"Resetting frame count"<<endl;
00327 ResetFrameCount();
00328 return CTransformFilter::NewSegment(inStart, inEnd, inRate);
00329
00330 }
00331 HRESULT TheoraDecodeFilter::Transform(IMediaSample* inInputSample, IMediaSample* outOutputSample) {
00332
00333
00334
00335
00336 HRESULT locHR;
00337 BYTE* locBuff = NULL;
00338
00339 locHR = inInputSample->GetPointer(&locBuff);
00340
00341
00342 BYTE* locNewBuff = new unsigned char[inInputSample->GetActualDataLength()];
00343 memcpy((void*)locNewBuff, (const void*)locBuff, inInputSample->GetActualDataLength());
00344
00345
00346 if (locHR != S_OK) {
00347
00348 return S_FALSE;
00349 } else {
00350
00351
00352 REFERENCE_TIME locStart = 0;
00353 REFERENCE_TIME locEnd = 0;
00354 inInputSample->GetTime(&locStart, &locEnd);
00355
00356
00357
00358
00359 REFERENCE_TIME locTimeBase = 0;
00360 REFERENCE_TIME locDummy = 0;
00361 inInputSample->GetMediaTime(&locTimeBase, &locDummy);
00362 mSeekTimeBase = locTimeBase;
00363
00364
00365
00366
00367 if ((mLastSeenStartGranPos != locStart) && (locStart != -1)) {
00368
00369
00370
00371
00372
00373
00374 mLastSeenStartGranPos = locStart;
00375
00376 }
00377
00378
00379
00380
00381
00382 AM_MEDIA_TYPE* locMediaType = NULL;
00383 inInputSample->GetMediaType(&locMediaType);
00384 if (locMediaType == NULL) {
00385
00386 } else {
00387
00388 }
00389
00390
00391 StampedOggPacket* locPacket = new StampedOggPacket(locNewBuff, inInputSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);
00392
00393 bool locIsKeyFrame = mTheoraDecoder->isKeyFrame(locPacket);
00394 yuv_buffer* locYUV = mTheoraDecoder->decodeTheora(locPacket);
00395 if (locYUV != NULL) {
00396 if (TheoraDecoded(locYUV, outOutputSample, locIsKeyFrame) != 0) {
00397
00398 return S_FALSE;
00399 }
00400 } else {
00401
00402 return S_FALSE;
00403 }
00404
00405 return S_OK;
00406
00407 }
00408
00409 }
00410
00411 int TheoraDecodeFilter::TheoraDecoded (yuv_buffer* inYUVBuffer, IMediaSample* outSample, bool inIsKeyFrame)
00412 {
00413
00414
00415
00416 if (!mBegun) {
00417
00418 mBegun = true;
00419
00420
00421 mFrameDuration = (UNITS * mTheoraFormatInfo->frameRateDenominator) / (mTheoraFormatInfo->frameRateNumerator);
00422
00423 mFrameSize = (mHeight * mWidth * 3) / 2;
00424 mFrameCount = 0;
00425
00426
00427
00428
00429 }
00430
00431
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00444
00446
00447
00448
00449
00450 REFERENCE_TIME locFrameStart = (mFrameCount * mFrameDuration);
00451 mFrameCount++;
00452 REFERENCE_TIME locFrameEnd = (mFrameCount * mFrameDuration);
00453
00454
00455 debugLog<<"Sample times = "<<locFrameStart<<" to "<<locFrameEnd<<" frame "<<mFrameCount<<" KF = "<<((inIsKeyFrame) ? "YES" : "NO")<<endl;
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 AM_MEDIA_TYPE* locMediaType = NULL;
00468 outSample->GetMediaType(&locMediaType);
00469 if (locMediaType == NULL) {
00470
00471 } else {
00472
00473 if (locMediaType->majortype == MEDIATYPE_Video) {
00474
00475 }
00476
00477 if (locMediaType->subtype == MEDIASUBTYPE_YV12) {
00478
00479 }
00480
00481 if (locMediaType->formattype == FORMAT_VideoInfo) {
00482
00483 VIDEOINFOHEADER* locVF = (VIDEOINFOHEADER*)locMediaType->pbFormat;
00484
00485
00486 }
00487
00488
00489
00490
00491
00492
00493
00494 }
00495
00496
00498 BYTE* locBuffer = NULL;
00499
00500
00502 outSample->GetPointer(&locBuffer);
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 unsigned char* locDestUptoPtr = locBuffer;
00514 char* locSourceUptoPtr = inYUVBuffer->y;
00515
00516
00517 long locYStride = inYUVBuffer->y_stride;
00518 long locUVStride = inYUVBuffer->uv_stride;
00519
00520
00521
00522
00523
00524
00525
00526
00527 long locTopPad = inYUVBuffer->y_height - mHeight - mYOffset;
00528
00529 ASSERT(locTopPad >= 0);
00530 if (locTopPad < 0) {
00531 locTopPad = 0;
00532 } else {
00533
00534 }
00535
00536
00537 locSourceUptoPtr += (mYOffset * locYStride);
00538
00539 for (unsigned long line = 0; line < mHeight; line++) {
00540 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + mXOffset), mWidth);
00541 locSourceUptoPtr += locYStride;
00542 locDestUptoPtr += mWidth;
00543 }
00544
00545 locSourceUptoPtr += (locTopPad * locYStride);
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 locTopPad = locTopPad /2;
00558
00559 locSourceUptoPtr = inYUVBuffer->v;
00560
00561
00562 locSourceUptoPtr += ((mYOffset/2) * locYStride);
00563
00564 for (unsigned long line = 0; line < mHeight / 2; line++) {
00565 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mWidth / 2);
00566 locSourceUptoPtr += locUVStride;
00567 locDestUptoPtr += (mWidth / 2);
00568 }
00569 locSourceUptoPtr += (locTopPad * locUVStride);
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 locSourceUptoPtr = inYUVBuffer->u;
00584
00585
00586 locSourceUptoPtr += ((mYOffset/2) * locYStride);
00587
00588 for (unsigned long line = 0; line < mHeight / 2; line++) {
00589 memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mWidth / 2);
00590 locSourceUptoPtr += locUVStride;
00591 locDestUptoPtr += (mWidth / 2);
00592 }
00593 locSourceUptoPtr += (locTopPad * locUVStride);
00594
00595
00596
00597
00598
00599
00600 BOOL locIsKeyFrame = FALSE;
00601 if (inIsKeyFrame) {
00602 locIsKeyFrame = TRUE;
00603 };
00604 SetSampleParams(outSample, mFrameSize, &locFrameStart, &locFrameEnd, locIsKeyFrame);
00605
00606
00607
00608 return 0;
00609
00610
00611 }
00612
00613
00614 HRESULT TheoraDecodeFilter::SetMediaType(PIN_DIRECTION inDirection, const CMediaType* inMediaType) {
00615
00616 if (inDirection == PINDIR_INPUT) {
00617 if (inMediaType->subtype == MEDIASUBTYPE_Theora) {
00618
00619 setTheoraFormat((sTheoraFormatBlock*)inMediaType->pbFormat);
00620
00621
00622 mXOffset = ((sTheoraFormatBlock*)inMediaType->pbFormat)->xOffset;
00623 mYOffset = ((sTheoraFormatBlock*)inMediaType->pbFormat)->yOffset;
00624
00625
00626
00627
00628
00629 } else {
00630
00631 throw 0;
00632 }
00633 return CTransformFilter::SetMediaType(PINDIR_INPUT, inMediaType);
00634 } else {
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646 return CTransformFilter::SetMediaType(PINDIR_OUTPUT, inMediaType);
00647 }
00648 }
00649
00650
00651 bool TheoraDecodeFilter::SetSampleParams(IMediaSample* outMediaSample, unsigned long inDataSize, REFERENCE_TIME* inStartTime, REFERENCE_TIME* inEndTime, BOOL inIsSync)
00652 {
00653 outMediaSample->SetTime(inStartTime, inEndTime);
00654 outMediaSample->SetMediaTime(NULL, NULL);
00655 outMediaSample->SetActualDataLength(inDataSize);
00656 outMediaSample->SetPreroll(FALSE);
00657 outMediaSample->SetDiscontinuity(FALSE);
00658 outMediaSample->SetSyncPoint(inIsSync);
00659 return true;
00660 }
00661
00662
00663
00664
00665
00666
00667 sTheoraFormatBlock* TheoraDecodeFilter::getTheoraFormatBlock()
00668 {
00669 return mTheoraFormatInfo;
00670 }
00671 void TheoraDecodeFilter::setTheoraFormat(sTheoraFormatBlock* inFormatBlock)
00672 {
00673 delete mTheoraFormatInfo;
00674 mTheoraFormatInfo = new sTheoraFormatBlock;
00675 *mTheoraFormatInfo = *inFormatBlock;
00676 }
00677
00678 CBasePin* TheoraDecodeFilter::GetPin(int inPinNo)
00679 {
00680 HRESULT locHR = S_OK;
00681
00682
00683
00684 if (m_pInput == NULL) {
00685
00686 m_pInput = new TheoraDecodeInputPin(this, &locHR);
00687
00688
00689 if (m_pInput == NULL) {
00690 return NULL;
00691 }
00692 m_pOutput = new TheoraDecodeOutputPin(this, &locHR);
00693
00694
00695 if (m_pOutput == NULL) {
00696 delete m_pInput;
00697 m_pInput = NULL;
00698 }
00699 }
00700
00701
00702
00703 if (inPinNo == 0) {
00704 return m_pInput;
00705 } else if (inPinNo == 1) {
00706 return m_pOutput;
00707 } else {
00708 return NULL;
00709 }
00710 }
00711
00712
00713
00714
00715
00716
00717
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00732
00733
00734
00735
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797