?? dshowtools.cpp
字號(hào):
CxImageRenderer::CxImageRenderer(LPUNKNOWN pUnk, HRESULT* phr)
: CBaseRenderer(CxImageRenderer_GUID, NAME("CxImageRenderer"), pUnk, phr)
{
NOTE("CxImageRenderer::CxImageRenderer()");
*phr = S_OK;
m_ImageValid = false;
};
HRESULT CxImageRenderer::CheckMediaType(const CMediaType* pmt)
{
NOTE("CxImageRenderer::CheckMediaType()");
//Check the stream type
bool bIsVideo = (pmt->majortype == MEDIATYPE_Video)
&& ((pmt->formattype == FORMAT_VideoInfo)
|| (pmt->formattype == FORMAT_VideoInfo2));
//Check the colorspace
bool bColorspaceOk =
pmt->subtype == MEDIASUBTYPE_RGB32
|| pmt->subtype == MEDIASUBTYPE_RGB24
|| pmt->subtype == MEDIASUBTYPE_YUY2
|| pmt->subtype == MEDIASUBTYPE_YV12
;
if (bIsVideo && bColorspaceOk)
return S_OK;
else
return E_FAIL;
};
HRESULT CxImageRenderer::DoRenderSample(IMediaSample *pSample)
{
NOTE("CxImageRenderer::DoRenderSample()");
CMediaType mt;
m_pInputPin->ConnectionMediaType(&mt);
BITMAPINFOHEADER bih;
//See if we are using VideoHeader2
if (mt.formattype == FORMAT_VideoInfo2) {
VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)mt.Format();
bih = vih2->bmiHeader;
} else {
VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)mt.Format();
bih = vih->bmiHeader;
}
if (bih.biSize == 0) {
// A hack for a strange bug, it's VideoHeader2 but it's not?
VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)mt.Format();
bih = vih->bmiHeader;
}
BYTE* p;
pSample->GetPointer(&p);
long dataSize = pSample->GetSize();
//Do something with the pic
if (mt.subtype == MEDIASUBTYPE_RGB32) {
lastImage.CreateFromARGB(bih.biWidth, bih.biHeight, p);
lastImage.Flip();
m_ImageValid = lastImage.IsValid();
} else if (mt.subtype == MEDIASUBTYPE_RGB24) {
lastImage.Create(bih.biWidth, bih.biHeight, 24);
// Do a direct memory copy
memcpy(lastImage.GetBits(), p, bih.biWidth * bih.biHeight * 3);
m_ImageValid = lastImage.IsValid();
} else if (mt.subtype == MEDIASUBTYPE_YV12) {
BYTE *yuvBuffer = new BYTE[bih.biHeight * bih.biWidth * 16];
// Call Klaus Post's mmx YV12->YUY2 conversion routine
BYTE *y = p;
BYTE *u = y + (bih.biHeight/2 * bih.biWidth/2);
BYTE *v = u + (bih.biHeight/2 * bih.biWidth/2);
mmx_yv12_to_yuy2(
y,
u,
v,
bih.biWidth, // rowsize
bih.biWidth, // pitch
bih.biWidth/2, // pitch_uv
yuvBuffer,
bih.biWidth*2, // dst_pitch
bih.biHeight);
lastImage.Create(bih.biWidth, bih.biHeight, 24);
//Using alexnoe's YUV2->RGB24 Assembly rountines
YUV422toRGB24_MMX(yuvBuffer, lastImage.GetBits(), 0, bih.biWidth, bih.biHeight, bih.biWidth * 2, bih.biWidth * 3);
m_ImageValid = lastImage.IsValid();
//lastImage.Draw(GetDC(NULL));
delete [] yuvBuffer;
}else if (mt.subtype == MEDIASUBTYPE_YUY2) {
lastImage.Create(bih.biWidth, bih.biHeight, 24);
//Using alexnoe's YUV2->RGB24 Assembly rountines
YUV422toRGB24_MMX(p, lastImage.GetBits(), 0, bih.biWidth, bih.biHeight, bih.biWidth * 2, bih.biWidth * 3);
m_ImageValid = lastImage.IsValid();
}
//We only need one good sample
m_bAbort = true;
return S_OK;
};
CxImage &CxImageRenderer::GetImage()
{
NOTE("CxImageRenderer::GetImage()");
return lastImage;
};
bool CxImageRenderer::GetImageOk()
{
NOTE("CxImageRenderer::GetImageOk()");
return m_ImageValid;
}
/*************************************
* Progressive YV12 -> YUY2 conversion
*
* (c) 2003, Klaus Post.
*
* Requires mod 8 rowsize.
* MMX version.
*************************************/
void mmx_yv12_to_yuy2(const BYTE* srcY, const BYTE* srcU, const BYTE* srcV, int src_rowsize, int src_pitch, int src_pitch_uv,
BYTE* dst, int dst_pitch,
int height) {
static __int64 add_64=0x0002000200020002;
const BYTE** srcp= new const BYTE*[3];
int src_pitch_uv2 = src_pitch_uv*2;
int skipnext = 0;
int dst_pitch2=dst_pitch*2;
int src_pitch2 = src_pitch*2;
/**** Do first and last lines - NO interpolation: *****/
// MMX loop relies on C-code to adjust the lines for it.
const BYTE* _srcY=srcY;
const BYTE* _srcU=srcU;
const BYTE* _srcV=srcV;
BYTE* _dst=dst;
for (int i=0;i<4;i++) {
switch (i) {
case 1:
_srcY+=src_pitch; // Same chroma as in 0
_dst+=dst_pitch;
break;
case 2:
_srcY=srcY+(src_pitch*(height-2));
_srcU=srcU+(src_pitch_uv*((height>>1)-1));
_srcV=srcV+(src_pitch_uv*((height>>1)-1));
_dst = dst+(dst_pitch*(height-2));
break;
case 3: // Same chroma as in 4
_srcY += src_pitch;
_dst += dst_pitch;
break;
default: // Nothing, case 0
break;
}
__asm {
mov edi, [_dst]
mov eax, [_srcY]
mov ebx, [_srcU]
mov ecx, [_srcV]
mov edx,0
pxor mm7,mm7
jmp xloop_test_p
xloop_p:
movq mm0,[eax] //Y
movd mm1,[ebx] //U
movq mm3,mm0
movd mm2,[ecx] //V
punpcklbw mm0,mm7 // Y low
punpckhbw mm3,mm7 // Y high
punpcklbw mm1,mm7 // 00uu 00uu
punpcklbw mm2,mm7 // 00vv 00vv
movq mm4,mm1
movq mm5,mm2
punpcklbw mm1,mm7 // 0000 00uu low
punpcklbw mm2,mm7 // 0000 00vv low
punpckhbw mm4,mm7 // 0000 00uu high
punpckhbw mm5,mm7 // 0000 00vv high
pslld mm1,8
pslld mm4,8
pslld mm2,24
pslld mm5,24
por mm0, mm1
por mm3, mm4
por mm0, mm2
por mm3, mm5
movq [edi],mm0
movq [edi+8],mm3
add eax,8
add ebx,4
add ecx,4
add edx,8
add edi, 16
xloop_test_p:
cmp edx,[src_rowsize]
jl xloop_p
}
}
/****************************************
* Conversion main loop.
* The code properly interpolates UV from
* interlaced material.
* We process two lines in the same field
* in the same loop, to avoid reloading
* chroma each time.
*****************************************/
height-=4;
dst+=dst_pitch2;
srcY+=src_pitch2;
srcU+=src_pitch_uv;
srcV+=src_pitch_uv;
srcp[0] = srcY;
srcp[1] = srcU-src_pitch_uv;
srcp[2] = srcV-src_pitch_uv;
int y=0;
int x=0;
__asm {
mov esi, [srcp]
mov edi, [dst]
mov eax,[esi]
mov ebx,[esi+4]
mov ecx,[esi+8]
mov edx,0
jmp yloop_test
align 16
yloop:
mov edx,0 // x counter
jmp xloop_test
align 16
xloop:
mov edx, src_pitch_uv
movq mm0,[eax] // mm0 = Y current line
pxor mm7,mm7
movd mm2,[ebx+edx] // mm2 = U top field
movd mm3, [ecx+edx] // mm3 = V top field
movd mm4,[ebx] // U prev top field
movq mm1,mm0 // mm1 = Y current line
movd mm5,[ecx] // V prev top field
punpcklbw mm2,mm7 // U 00uu 00uu 00uu 00uu
punpcklbw mm3,mm7 // V 00vv 00vv 00vv 00vv
punpcklbw mm4,mm7 // U 00uu 00uu 00uu 00uu
punpcklbw mm5,mm7 // V 00vv 00vv 00vv 00vv
paddusw mm4,mm2
paddusw mm5,mm3
paddusw mm4,mm2
paddusw mm5,mm3
paddusw mm4,mm2
paddusw mm5,mm3
paddusw mm4, [add_64]
paddusw mm5, [add_64]
psrlw mm4,2
psrlw mm5,2
punpcklbw mm0,mm7 // Y low
punpckhbw mm1,mm7 // Y high*
pxor mm6,mm6
punpcklbw mm6,mm4 // U 0000 uu00 0000 uu00 (low)
punpckhbw mm7,mm4 // V 0000 uu00 0000 uu00 (high
por mm0,mm6
por mm1,mm7
movq mm6,mm5
punpcklbw mm5,mm5 // V 0000 vvvv 0000 vvvv (low)
punpckhbw mm6,mm6 // V 0000 vvvv 0000 vvvv (high)
pslld mm5,24
pslld mm6,24
por mm0,mm5
por mm1,mm6
mov edx, src_pitch_uv2
movq [edi],mm0
movq [edi+8],mm1
//Next line
movd mm4,[ebx+edx] // U next top field
movd mm5,[ecx+edx] // V prev top field
mov edx, [src_pitch]
pxor mm7,mm7
movq mm0,[eax+edx] // Next U-line
movq mm1,mm0 // mm1 = Y current line
punpcklbw mm4,mm7 // U 00uu 00uu 00uu 00uu
punpcklbw mm5,mm7 // V 00vv 00vv 00vv 00vv
paddusw mm4,mm2
paddusw mm5,mm3
paddusw mm4,mm2
paddusw mm5,mm3
paddusw mm4,mm2
paddusw mm5,mm3
paddusw mm4, [add_64]
paddusw mm5, [add_64]
psrlw mm4,2
psrlw mm5,2
punpcklbw mm0,mm7 // Y low
punpckhbw mm1,mm7 // Y high*
pxor mm6,mm6
punpcklbw mm6,mm4 // U 0000 uu00 0000 uu00 (low)
punpckhbw mm7,mm4 // V 0000 uu00 0000 uu00 (high
por mm0,mm6
por mm1,mm7
movq mm6,mm5
punpcklbw mm5,mm5 // V 0000 vvvv 0000 vvvv (low)
punpckhbw mm6,mm6 // V 0000 vvvv 0000 vvvv (high)
pslld mm5,24
mov edx,[dst_pitch]
pslld mm6,24
por mm0,mm5
por mm1,mm6
movq [edi+edx],mm0
movq [edi+edx+8],mm1
add edi,16
mov edx, [x]
add eax, 8
add ebx, 4
add edx, 8
add ecx, 4
xloop_test:
cmp edx,[src_rowsize]
mov x,edx
jl xloop
mov edi, dst
mov eax,[esi]
mov ebx,[esi+4]
mov ecx,[esi+8]
add edi,[dst_pitch2]
add eax,[src_pitch2]
add ebx,[src_pitch_uv]
add ecx,[src_pitch_uv]
mov edx, [y]
mov [esi],eax
mov [esi+4],ebx
mov [esi+8],ecx
mov [dst],edi
add edx, 2
yloop_test:
cmp edx,[height]
mov [y],edx
jl yloop
emms
}
delete[] srcp;
}
HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
IMoniker * pMoniker;
IRunningObjectTable *pROT;
if (FAILED(GetRunningObjectTable(0, &pROT)))
{
return E_FAIL;
}
WCHAR wsz[128];
wsprintfW(wsz, L"FilterGraph %08x pid %08x - AudioDShowEncoder", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
if (SUCCEEDED(hr))
{
// Use the ROTFLAGS_REGISTRATIONKEEPSALIVE to ensure a strong reference
// to the object. Using this flag will cause the object to remain
// registered until it is explicitly revoked with the Revoke() method.
//
// Not using this flag means that if GraphEdit remotely connects
// to this graph and then GraphEdit exits, this object registration
// will be deleted, causing future attempts by GraphEdit to fail until
// this application is restarted or until the graph is registered again.
hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, pdwRegister);
pMoniker->Release();
}
pROT->Release();
return hr;
}
void RemoveGraphFromRot(DWORD pdwRegister)
{
IRunningObjectTable *pROT;
if (SUCCEEDED(GetRunningObjectTable(0, &pROT)))
{
pROT->Revoke(pdwRegister);
pROT->Release();
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -