读书人

解码YUV的filter

发布时间: 2012-03-22 17:43:57 作者: rapoo

求助解码YUV的filter
最近在写一个解码yuv的transform filter,文件为.yuv格式,视频大小为320*240,内容为YYYY...Y共320*240个,UUUU..U共160*120个,VVVV...V共160*120.由于不想写SourceFilter,就用系统自带的一个叫做:File Source(Async.)的Source Filter,但是在GraphEdit中调试时,一连线就停止工作,debug时看到Source Filter传过来的视频格式为MEDIATYPE_NULL,和MEDIASUBTYPE_NULL,这样一步一步的调试也不知道哪出了问题,希望大家能帮我一下,谢谢!
下面是大概的源代码
#include <windows.h>
#include <streams.h>
#include <initguid.h>
#include <olectl.h>
#include <fstream>
#include "Decoder.h"

const AMOVIESETUP_MEDIATYPE sudPinTypes=
{
&MEDIATYPE_NULL,
&MEDIASUBTYPE_NULL
};

const AMOVIESETUP_MEDIATYPE outputpinType=
{
&MEDIATYPE_Video,
&MEDIASUBTYPE_NULL
};

const AMOVIESETUP_PIN sudPins[]=
{
{
L"Input",// Pins string name
FALSE,// Is it rendered
FALSE,// Is it an output
FALSE,// Are we allowed none
FALSE,// And allowed many
&CLSID_NULL,// Connects to filter
NULL,// Connects to pin
1,// Number of types
&sudPinTypes// Pin information
},
{
L"Output",// Pins string name
FALSE,// Is it rendered
TRUE,// Is it an output
FALSE,// Are we allowed none
FALSE,// And allowed many
&CLSID_NULL,// Connects to filter
NULL,// Connects to pin
1,// Number of types
&outputpinType// Pin information
}
};

const AMOVIESETUP_FILTER sudDecoder=
{
&CLSID_Decoder,// Filter CLSID
L"A test Decoder",// String name
MERIT_PREFERRED,// Filter merit
2,// Number of pins
sudPins// Pin information
};

CFactoryTemplate g_Templates[]=
{
{
L"A Test Decoder",
&CLSID_Decoder,
Decoder::CreateInstance,
NULL,
&sudDecoder
}
};

int g_cTemplates=sizeof(g_Templates)/sizeof(g_Templates[0]);

STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}

STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}

extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

//
// DllMain
//
BOOL APIENTRY DllMain(HANDLE hModule,DWORD dwReason,LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule),dwReason,lpReserved);
}

//
// Debug
//
void Debuginfo(char *info)
{
FILE *pf;
fopen_s(&pf,"C:\\debug.txt","a+");
fprintf(pf,info);
fclose(pf);
}

Decoder::Decoder(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr):CTransformFilter(tszName, punk, CLSID_Decoder),fillnum(0),samplesize(115200),startTime(0)
{
buffers=(unsigned char *)malloc(1048576);//1048576:pow(2,20)
if(!buffers)
exit(-1);
}

Decoder::~Decoder()
{
free(buffers);
}

//
// CreateInstance
//
CUnknown *Decoder::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
ASSERT(phr);
Debuginfo("now create an intance\n");
Decoder *pNewObject=new Decoder(NAME("A Test Decoder"), punk, phr);
if (pNewObject == NULL)
{
if (phr)
*phr = E_OUTOFMEMORY;
}
return pNewObject;
}

STDMETHODIMP Decoder::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv,E_POINTER);
return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
}

//
// Transform
//
HRESULT Decoder::Transform(IMediaSample *pIn, IMediaSample *pOut)
{
Debuginfo("in Transform\n");
CheckPointer(pIn,E_POINTER);
CheckPointer(pOut,E_POINTER);
Debuginfo("in Transform\n");
BYTE *pSourceBuffer,*pDestBuffer;


long lSourceSize=pIn->GetActualDataLength();
pIn->GetPointer(&pSourceBuffer);
pOut->GetPointer(&pDestBuffer);
BYTE *ps=pSourceBuffer;
BYTE *pd=pDestBuffer;
BYTE *pm=buffers;
for(int i=fillnum;i<fillnum+lSourceSize;i++)
{
*pm=*ps;
ps++;
pm++;
}
fillnum+=lSourceSize;
if(fillnum>=samplesize)
{
YUVTORGB(buffers,pDestBuffer);
for(int j=0;j<fillnum-samplesize;j++)
{
*(buffers+j)=*(buffers+j+samplesize);
}
fillnum-=samplesize;
return NOERROR;
}
return E_FAIL;
}

//
// YUVTORGB
//
HRESULT Decoder::YUVTORGB(BYTE *pIn, BYTE *pOut)
{
Debuginfo(" in YUVTORGB\n");
BYTE *pU=pIn+320*240;
BYTE *pV=pIn+320*240+160*120;
RGBQUAD *pD=(RGBQUAD *)pOut;
for(int i=0;i<240;i++)
{
for(int j=0;j<320;j++)
{
int position=(i/2)*160+j/2;
pD->rgbRed=(BYTE)(*(pIn+i*320+j)+1.402*(*(pV+position)-128));
pD->rgbGreen=(BYTE)(*(pIn+i*320+j)-0.34414*(*(pU+position)-128)-0.71414*(*(pV+position)-128));
pD->rgbBlue=(BYTE)(*(pIn+i*320+j)+1.772*(*(pU+position)-128));
pD->rgbReserved=(BYTE)0;
pD++;
}
}
return NOERROR;
}

//
// Checktransform
//
HRESULT Decoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
{
Debuginfo(" in CheckTransform\n");
CheckPointer(mtIn,E_POINTER);
CheckPointer(mtOut,E_POINTER);
if(*mtIn==*mtOut)
{
return NOERROR;
}
return E_FAIL;
}

//
// DecideBufferSize: the size is trible of the samplesize
//
HRESULT Decoder::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
Debuginfo(" in DecideBufferSize\n");
CheckPointer(pAlloc,E_POINTER);
CheckPointer(pProperties,E_POINTER);
if(m_pInput->IsConnected()==FALSE)
{
return E_UNEXPECTED;
}
HRESULT hr=NOERROR;
pProperties->cBuffers=1;
pProperties->cbBuffer=samplesize*3;
ASSERT(pProperties->cbBuffer);
if(!m_pInput->CurrentMediaType().bFixedSizeSamples)
{
if(pProperties->cbBuffer<100000)
pProperties->cbBuffer=100000;
}
ALLOCATOR_PROPERTIES Actual;
hr=pAlloc->SetProperties(pProperties,&Actual);
if(FAILED(hr))
{
return hr;
}
ASSERT(Actual.cBuffers==1);
if(pProperties->cBuffers > Actual.cBuffers||pProperties->cbBuffer > Actual.cbBuffer)
{
return E_FAIL;
}
return NOERROR;
}


//
// GetMediaType
//
HRESULT Decoder::GetMediaType(int iPosition, CMediaType *pMediaType)
{
Debuginfo(" in GetMediaType\n");
VIDEOINFO *pvi=(VIDEOINFO *)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));
if(pvi==NULL)
return(E_OUTOFMEMORY);
ZeroMemory(pvi,sizeof(VIDEOINFO));
pvi->bmiHeader.biCompression=BI_RGB;
pvi->bmiHeader.biBitCount=32;
pvi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth=320;
pvi->bmiHeader.biHeight=240;
pvi->bmiHeader.biPlanes=1;
pvi->bmiHeader.biSizeImage=GetBitmapSize(&pvi->bmiHeader);
pvi->bmiHeader.biClrImportant=0;
pvi->bmiHeader.biClrUsed=256;
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetSubtype(&MEDIASUBTYPE_RGB32);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);
samplesize=pvi->bmiHeader.biSizeImage;
return NOERROR;
}

//
// CheckInputType
//
HRESULT Decoder::CheckInputType(const CMediaType *pMediaType)
{
CheckPointer(pMediaType,E_POINTER);
if((IsEqualGUID(*pMediaType->Type(),MEDIATYPE_NULL))&&(IsEqualGUID(*pMediaType->Subtype(),MEDIASUBTYPE_NULL)))


{
Debuginfo("the mediatype inputed is right\n");
return NOERROR;
}
Debuginfo("the type inputed isn't right\n");
return E_FAIL;
}

[解决办法]
应该是没有加时间戳:
REFERENCE_TIME rtStart = 0;
REFERENCE_TIME rtStop = 10000000i64; // 1s
pOut->SetTime(&rtStart, &rtStop);
pOut->SetSyncPoint(TRUE);

这个文件只有一帧数据?你这是YV12的格式,render可以直接渲染,不需要转换。
pvi->bmiHeader.biCompression='21VY';
pvi->bmiHeader.biBitCount=12;
pvi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth=320;
pvi->bmiHeader.biHeight=240;
pvi->bmiHeader.biPlanes=1;
pvi->bmiHeader.biSizeImage=320*240*12/8;
pvi->bmiHeader.biClrImportant=0;
pvi->bmiHeader.biClrUsed=0;
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetSubtype(&MEDIASUBTYPE_YV12);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);

读书人网 >多媒体

热点推荐