📄 theoradecodefilter.cpp
字号:
long locDestPad = (mBMIWidth - mPictureWidth) * 2;
long locSourceYPad = (locYStride - mPictureWidth);
long locSourceUVPad = (locUVStride - (mPictureWidth/2));//locSourceYPad>>1;
//Setup the source pointers into the planar data
unsigned char* locSourceY = (unsigned char*)inYUVBuffer->y;
unsigned char* locSourceU = (unsigned char*)inYUVBuffer->u;
unsigned char* locSourceV = (unsigned char*)inYUVBuffer->v;
//Skip over the Y Offset at the top of the picture and the X offset into the line
locSourceY += (mYOffset * locYStride) + mXOffset;
locSourceU += ((mYOffset/2) * locUVStride) + mXOffset/2;
locSourceV += ((mYOffset/2) * locUVStride) + mXOffset/2;
unsigned char* locSecondLineBuffer;
for (int line = 0; line < mPictureHeight; line+= 2) {
locSecondLineBuffer = mScratchBuffer;
for (int col = 0; col < mPictureWidth; col+=2) {
//Line 1
*(locBuffer) = *(locSourceY);
*(locBuffer+1) = *(locSourceU);
*(locBuffer+2) = *(locSourceY+1);
*(locBuffer+3) = *(locSourceV);
//Line 2
*(locSecondLineBuffer) = *(locSourceY+locYStride);
*(locSecondLineBuffer+1) = *(locSourceU);
*(locSecondLineBuffer+2) = *(locSourceY+locYStride+1);
*(locSecondLineBuffer+3) = *(locSourceV);
//Advance the pointers for this chunk of columns
locBuffer += 4;
locSecondLineBuffer += 4;
locSourceY += 2;
locSourceU++;
locSourceV++;
}
//Advance the pointers for the line and copy the second line into the buffer
locBuffer += locDestPad;
memcpy((void*)locBuffer, (const void*)mScratchBuffer, mPictureWidth*2);
locBuffer += mBMIWidth*2;
locSourceY += locSourceYPad + locYStride;
locSourceU += locSourceUVPad; //+ locUVStride;
locSourceV += locSourceUVPad; //+ locUVStride;
}
REFERENCE_TIME locStart = inStart;
REFERENCE_TIME locEnd = inEnd;
BOOL locIsKeyFrame = FALSE;
if (inIsKeyFrame) {
locIsKeyFrame = TRUE;
};
SetSampleParams(outSample, mBMIFrameSize, &locStart, &locEnd, locIsKeyFrame);
return S_OK;
}
HRESULT TheoraDecodeFilter::DecodeToYV12(yuv_buffer* inYUVBuffer, IMediaSample* outSample, bool inIsKeyFrame, REFERENCE_TIME inStart, REFERENCE_TIME inEnd)
{
BYTE* locBuffer = NULL;
outSample->GetPointer(&locBuffer);
//Set up the pointers
unsigned char* locDestUptoPtr = locBuffer;
unsigned char* locSourceUptoPtr = inYUVBuffer->y;
//Strides from theora are generally -'ve
long locYStride = inYUVBuffer->y_stride;
long locUVStride = inYUVBuffer->uv_stride;
debugLog<<"Y Stride = "<<locYStride<<endl;
debugLog<<"UV Stride = "<<locUVStride<<endl;
debugLog<<"PictureHeight = "<<mPictureHeight<<endl;
debugLog<<"PictureWidth = "<<mPictureWidth<<endl;
debugLog<<"BMIHeight = "<<mBMIHeight<<endl;
debugLog<<"BMIWidth = "<<mBMIWidth<<endl;
//
//Y DATA
//
//Offsets Y Data
long locTopPad = inYUVBuffer->y_height - mPictureHeight - mYOffset;
debugLog<<"--------- TOP PAD = "<<locTopPad<<endl;
//ASSERT(locTopPad >= 0);
if (locTopPad < 0) {
locTopPad = 0;
} else {
}
//Skip the offset padding
locSourceUptoPtr += (mYOffset * locYStride);
for (unsigned long line = 0; line < mPictureHeight; line++) {
//Ignore the x offset, and copy mPictureWidth bytes onto the destination
memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + mXOffset), mPictureWidth);
//Advance the source pointer by the stride
locSourceUptoPtr += locYStride;
//Advance the destination pointer by the BMI Width
locDestUptoPtr += mBMIWidth;
}
//Skip the other padding
locSourceUptoPtr += (locTopPad * locYStride);
//Advance the destination to pad to the size the video renderer wants
locDestUptoPtr += ((mBMIHeight - mPictureHeight) * mBMIWidth);
//debugLog<<"Dest Distance(y) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
//Source advances by (y_height * y_stride)
//Dest advances by (mHeight * mWidth)
//
//V DATA
//
//TODO::: May be issue here with odd numbers
//Half the padding for uv planes... is this correct ?
locTopPad = locTopPad /2;
locSourceUptoPtr = inYUVBuffer->v;
//Skip the top padding
locSourceUptoPtr += ((mYOffset/2) * locYStride);
for (unsigned long line = 0; line < mPictureHeight / 2; line++) {
//Ignore the x offset and copy mPictureWidth/2 bytes to the destination
memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mPictureWidth / 2);
locSourceUptoPtr += locUVStride;
locDestUptoPtr += (mBMIWidth / 2);
}
locSourceUptoPtr += (locTopPad * locUVStride);
locDestUptoPtr += (((mBMIHeight/2) - (mPictureHeight/2)) * (mBMIWidth/2));
//Source advances by (locTopPad + mYOffset/2 + mHeight /2) * uv_stride
//where locTopPad for uv = (inYUVBuffer->y_height - mHeight - mYOffset) / 2
// = (inYUVBuffer->yheight/2 - mHeight/2 - mYOffset/2)
// so source advances by (y_height/2) * uv_stride
//Dest advances by (mHeight * mWidth) /4
//debugLog<<"Dest Distance(V) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
//
//U DATA
//
locSourceUptoPtr = inYUVBuffer->u;
//Skip the top padding
locSourceUptoPtr += ((mYOffset/2) * locYStride);
for (unsigned long line = 0; line < mPictureHeight / 2; line++) {
memcpy((void*)(locDestUptoPtr), (const void*)(locSourceUptoPtr + (mXOffset / 2)), mPictureWidth / 2);
locSourceUptoPtr += locUVStride;
locDestUptoPtr += (mBMIWidth / 2);
}
//Redundant
locSourceUptoPtr += (locTopPad * locUVStride);
locDestUptoPtr += (((mBMIHeight/2) - (mPictureHeight/2)) * (mBMIWidth/2));
//debugLog<<"Dest Distance(U) = "<<(unsigned long)(locDestUptoPtr - locBuffer)<<endl;
//debugLog<<"Frame Size = "<<mFrameSize<<endl;
//Set the sample parameters.
//BOOL locIsKeyFrame = (locInterFrameNo == 0);
BOOL locIsKeyFrame = FALSE;
if (inIsKeyFrame) {
locIsKeyFrame = TRUE;
};
REFERENCE_TIME locStart = inStart;
REFERENCE_TIME locEnd = inEnd;
SetSampleParams(outSample, mBMIFrameSize, &locStart, &locEnd, locIsKeyFrame);
return S_OK;
}
HRESULT TheoraDecodeFilter::TheoraDecoded (yuv_buffer* inYUVBuffer, IMediaSample* outSample, bool inIsKeyFrame, REFERENCE_TIME inStart, REFERENCE_TIME inEnd)
{
if (mCurrentOutputSubType == MEDIASUBTYPE_YV12) {
debugLog<<"Decoding to YV12"<<endl;
return DecodeToYV12(inYUVBuffer, outSample, inIsKeyFrame, inStart, inEnd);
} else if (mCurrentOutputSubType == MEDIASUBTYPE_YUY2) {
debugLog<<"Decoding to YUY2"<<endl;
return DecodeToYUY2(inYUVBuffer, outSample, inIsKeyFrame, inStart, inEnd);
//} else if (mCurrentOutputSubType == MEDIASUBTYPE_RGB565) {
// debugLog<<"Decoding to RGB565"<<endl;
// return DecodeToRGB565(inYUVBuffer, outSample, inIsKeyFrame, inStart, inEnd);
//} else if (mCurrentOutputSubType == MEDIASUBTYPE_RGB24) {
// debugLog<<"Decoding to RGB24"<<endl;
// return DecodeToRGB24(inYUVBuffer, outSample, inIsKeyFrame, inStart, inEnd);
} else {
debugLog<<"Decoding to unknown type - failure"<<endl;
return E_FAIL;
}
}
HRESULT TheoraDecodeFilter::SetMediaType(PIN_DIRECTION inDirection, const CMediaType* inMediaType)
{
if (inDirection == PINDIR_INPUT) {
if (CheckInputType(inMediaType) == S_OK) {
//debugLog<<"Setting format block"<<endl;
setTheoraFormat(inMediaType->pbFormat);
//Set some other stuff here too...
mXOffset = mTheoraFormatInfo->xOffset;
mYOffset = mTheoraFormatInfo->yOffset;
mPictureWidth = mTheoraFormatInfo->pictureWidth;
mPictureHeight = mTheoraFormatInfo->pictureHeight;
//How many UNITS does one frame take.
mFrameDuration = (UNITS * mTheoraFormatInfo->frameRateDenominator) / (mTheoraFormatInfo->frameRateNumerator);
mFrameCount = 0;
} else {
//Failed... should never be here !
throw 0;
}
debugLog<<"SETTING input type"<<endl;
return CTransformFilter::SetMediaType(PINDIR_INPUT, inMediaType);//CVideoTransformFilter::SetMediaType(PINDIR_INPUT, inMediaType);
} else {
mCurrentOutputSubType = inMediaType->subtype;
debugLog<<"SETTING output type"<<endl;
return CTransformFilter::SetMediaType(PINDIR_OUTPUT, inMediaType);//CVideoTransformFilter::SetMediaType(PINDIR_OUTPUT, inMediaType);
}
}
bool TheoraDecodeFilter::SetSampleParams(IMediaSample* outMediaSample, unsigned long inDataSize, REFERENCE_TIME* inStartTime, REFERENCE_TIME* inEndTime, BOOL inIsSync)
{
outMediaSample->SetTime(inStartTime, inEndTime);
outMediaSample->SetMediaTime(NULL, NULL);
outMediaSample->SetActualDataLength(inDataSize);
outMediaSample->SetPreroll(FALSE);
outMediaSample->SetDiscontinuity(FALSE);
outMediaSample->SetSyncPoint(inIsSync);
return true;
}
//BOOL TheoraDecodeFilter::ShouldSkipFrame(IMediaSample* inSample) {
// //m_bSkipping = FALSE;
// debugLog<<"Don't skip"<<endl;
// return FALSE;
//}
sTheoraFormatBlock* TheoraDecodeFilter::getTheoraFormatBlock()
{
return mTheoraFormatInfo;
}
void TheoraDecodeFilter::setTheoraFormat(BYTE* inFormatBlock)
{
delete mTheoraFormatInfo;
mTheoraFormatInfo = new sTheoraFormatBlock; //Deelted in destructor.
//0 - 55 theora ident 0 - 6
//56 - 63 ver major 7 - 7
//64 - 71 ver minor 8 - 8
//72 - 79 ver subversion 9 = 9
//80 - 95 width/16 10 - 11
//96 - 111 height/16 12 - 13
//112 - 135 framewidth 14 - 16
//136 - 159 frameheight 17 - 19
//160 - 167 xoffset 20 - 20
//168 - 175 yoffset 21 - 21
//176 - 207 framerateNum 22 - 25
//208 - 239 frameratedenom 26 - 29
//240 - 263 aspectNum 30 - 32
//264 - 287 aspectdenom 33 - 35
//288 - 295 colourspace 36 - 36
//296 - 319 targetbitrate 37 - 39
//320 - 325 targetqual 40 - 40.75
//326 - 330 keyframintlog 40.75- 41.375
unsigned char* locIdentHeader = inFormatBlock;
mTheoraFormatInfo->theoraVersion = (iBE_Math::charArrToULong(locIdentHeader + 7)) >>8;
mTheoraFormatInfo->outerFrameWidth = (iBE_Math::charArrToUShort(locIdentHeader + 10)) * 16;
mTheoraFormatInfo->outerFrameHeight = (iBE_Math::charArrToUShort(locIdentHeader + 12)) * 16;
mTheoraFormatInfo->pictureWidth = (iBE_Math::charArrToULong(locIdentHeader + 14)) >>8;
mTheoraFormatInfo->pictureHeight = (iBE_Math::charArrToULong(locIdentHeader + 17)) >>8;
mTheoraFormatInfo->xOffset = locIdentHeader[20];
mTheoraFormatInfo->yOffset = locIdentHeader[21];
mTheoraFormatInfo->frameRateNumerator = iBE_Math::charArrToULong(locIdentHeader + 22);
mTheoraFormatInfo->frameRateDenominator = iBE_Math::charArrToULong(locIdentHeader + 26);
mTheoraFormatInfo->aspectNumerator = (iBE_Math::charArrToULong(locIdentHeader + 30)) >>8;
mTheoraFormatInfo->aspectDenominator = (iBE_Math::charArrToULong(locIdentHeader + 33)) >>8;
mTheoraFormatInfo->colourSpace = locIdentHeader[36];
mTheoraFormatInfo->targetBitrate = (iBE_Math::charArrToULong(locIdentHeader + 37)) >>8;
mTheoraFormatInfo->targetQuality = (locIdentHeader[40]) >> 2;
mTheoraFormatInfo->maxKeyframeInterval= (((locIdentHeader[40]) % 4) << 3) + (locIdentHeader[41] >> 5);
}
CBasePin* TheoraDecodeFilter::GetPin(int inPinNo)
{
HRESULT locHR = S_OK;
// Create an input pin if necessary
if (m_pInput == NULL) {
m_pInput = new TheoraDecodeInputPin(this, &locHR); //Deleted in base destructor
if (m_pInput == NULL) {
return NULL;
}
m_pOutput = new TheoraDecodeOutputPin(this, &locHR); //Deleted in base destructor
if (m_pOutput == NULL) {
delete m_pInput;
m_pInput = NULL;
}
}
// Return the pin
if (inPinNo == 0) {
return m_pInput;
} else if (inPinNo == 1) {
return m_pOutput;
} else {
return NULL;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -