📄 cresizer.cpp
字号:
if (iPosition < 0)
{
return E_INVALIDARG;
}
if (iPosition > 1)
{
return VFW_S_NO_MORE_ITEMS;
}
// VIDEOINFOHEADER
VIDEOINFOHEADER videoInfo;
ZeroMemory (&videoInfo, sizeof (VIDEOINFOHEADER));
videoInfo.rcSource.left = 0;
videoInfo.rcSource.top = 0;
videoInfo.rcSource.right = output_width;
videoInfo.rcSource.bottom = output_height;
videoInfo.rcTarget.left = 0;
videoInfo.rcTarget.top = 0;
videoInfo.rcTarget.right = output_width;
videoInfo.rcTarget.bottom = output_height;
videoInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
videoInfo.bmiHeader.biWidth = output_width;
videoInfo.bmiHeader.biHeight = output_height;
videoInfo.bmiHeader.biPlanes = 1;
videoInfo.bmiHeader.biBitCount = 16;
videoInfo.bmiHeader.biSizeImage = output_width*output_height*2;
videoInfo.bmiHeader.biCompression = mmioFOURCC('Y','U','Y','2');
videoInfo.AvgTimePerFrame = temp_AvgTimePerFrame;
// initialize media type
pMediaType->InitMediaType ();
// set major type
pMediaType->SetType (&MEDIATYPE_Video);
// Set sub type
pMediaType->SetSubtype (&MEDIASUBTYPE_YUY2);
// format type VIDEOINFOHEADER
pMediaType->SetFormatType (&FORMAT_VideoInfo);
if (pMediaType->SetFormat (reinterpret_cast<BYTE*> (&videoInfo), sizeof (VIDEOINFOHEADER)) == FALSE)
return E_FAIL;
// sample size
pMediaType->SetSampleSize ( videoInfo.bmiHeader.biSizeImage );
return S_OK;
} // GetMediaType
HRESULT CResizer::SetMediaType (PIN_DIRECTION direction, const CMediaType* mediaType)
{
// assertion
CheckPointer (mediaType, E_POINTER);
// super
HRESULT result = this->CTransformFilter::SetMediaType (direction, mediaType);
if (result != S_OK)
{
return result;
}
// set media type for input pin?
if (direction == PINDIR_INPUT)
{
this->SetInputMediaType (mediaType);
}
// set media type for the output pin
else if (direction == PINDIR_OUTPUT)
{
this->SetOutputMediaType (mediaType);
}
// unrecognized pin direction
else
{
return E_FAIL;
}
return S_OK;
}
HRESULT CResizer::SetInputMediaType (const CMediaType* mediaType)
{
// get image description
int width = 0;
int height = 0;
int bitsPerPixel = 0;
// VIDEOINFOHEADER
if (*mediaType->FormatType () == FORMAT_VideoInfo) {
VIDEOINFOHEADER* header = reinterpret_cast<VIDEOINFOHEADER*> (mediaType->Format ());
if ( header == 0 ) {
return E_FAIL;
}
width = (int)(header->bmiHeader.biWidth);
height = (int)(header->bmiHeader.biHeight);
bitsPerPixel = (int)(header->bmiHeader.biBitCount);
temp_AvgTimePerFrame = header->AvgTimePerFrame;
} else if ( *mediaType->FormatType () == FORMAT_VideoInfo2) {
// VIDEOINFOHEADER2
VIDEOINFOHEADER2* header = reinterpret_cast<VIDEOINFOHEADER2*> (mediaType->Format ());
if (header == 0)
{
return E_FAIL;
}
width = (int)(header->bmiHeader.biWidth);
height = (int)(header->bmiHeader.biHeight);
bitsPerPixel = (int)(header->bmiHeader.biBitCount);
temp_AvgTimePerFrame = header->AvgTimePerFrame;
} else {
// unrecognized format
return E_FAIL;
}
// adjust image information
if ( bitsPerPixel != 16 || *mediaType->Subtype() != MEDIASUBTYPE_YUY2 )
return E_FAIL;
// c_width = c_height = 0;
input_width = width;
input_height = height;
// output_width = m_width_set;//registry_config.options.width;
// output_height = m_height_set;//registry_config.options.height;
return S_OK;
}
//
// set output media type
//
HRESULT CResizer::SetOutputMediaType (const CMediaType* mediaType)
{
// copy media type
this->outputMediaType = *mediaType;
// setup format info
// VIDEOINFOHEADER
if (*mediaType->FormatType () == FORMAT_VideoInfo)
{
VIDEOINFOHEADER header;
ZeroMemory (&header, sizeof (VIDEOINFOHEADER));
header.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
header.bmiHeader.biWidth = output_width;
header.bmiHeader.biHeight = output_height;
header.bmiHeader.biPlanes = 1;
header.bmiHeader.biBitCount = 16;
header.bmiHeader.biCompression = mmioFOURCC('Y','U','Y','2');
header.bmiHeader.biSizeImage = output_width*output_height*2;
header.AvgTimePerFrame = temp_AvgTimePerFrame;
this->outputMediaType.SetFormat (reinterpret_cast<BYTE*> (&header), sizeof (VIDEOINFOHEADER));
}
// VIDEOINFOHEADER2
else if (*mediaType->FormatType () == FORMAT_VideoInfo2)
{
VIDEOINFOHEADER2 header;
ZeroMemory (&header, sizeof (VIDEOINFOHEADER2));
header.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
header.bmiHeader.biWidth = output_width;
header.bmiHeader.biHeight = output_height;
header.bmiHeader.biPlanes = 1;
header.bmiHeader.biBitCount = 16;
header.bmiHeader.biCompression = mmioFOURCC('Y','U','Y','2');
header.bmiHeader.biSizeImage = output_width*output_height*2;
header.AvgTimePerFrame = temp_AvgTimePerFrame;
this->outputMediaType.SetFormat (reinterpret_cast<BYTE*> (&header), sizeof (VIDEOINFOHEADER2));
}
// unrecognized type
else
{
return E_FAIL;
}
return S_OK;
}
/*
STDMETHODIMP CResizer::SetFormat(AM_MEDIA_TYPE *pmt)
{
set_VideoSize(368,256);
return S_OK;
}
STDMETHODIMP CResizer::GetFormat(AM_MEDIA_TYPE **pmt)
{
return S_OK;
}
STDMETHODIMP CResizer::GetNumberOfCapabilities(int *piCount, int *piSize)
{
return S_OK;
}
STDMETHODIMP CResizer::GetStreamCaps(int iIndex, AM_MEDIA_TYPE **pmt, BYTE *pSCC)
{
return S_OK;
}
*/
STDMETHODIMP CResizer::GetPages(CAUUID *pPages)
{
pPages->cElems = 1;
pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
if (pPages->pElems == NULL) {
return E_OUTOFMEMORY;
}
*(pPages->pElems) = CLSID_TIMResizerPropertyPage;
return NOERROR;
return m_height_set;
} // GetPages
STDMETHODIMP CResizer::set_VideoSize(int nWidth, int nHeight)
{
output_width = nWidth;
output_height = nHeight;
return S_OK;
}
STDMETHODIMP CResizer::get_VideoSize(int &nWidth, int &nHeight)
{
nWidth = output_width;
nHeight = output_height;
return S_OK;
}
STDMETHODIMP CResizer::notuse2()
{
return S_OK;
}
//
// DllRegisterServer
//
// Handle registration of this filter
//
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
} // DllRegisterServer
//
// DllUnregisterServer
//
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
} // DllUnregisterServer
FilteredResizeH::FilteredResizeH(int isYUV, int wi, int he, double subrange_left, double subrange_width, int target_width, TriangleFilter* func):tempY(0), tempUV(0), width(wi), height(he), m_YUV(isYUV)
{
pattern_chroma = 0;
original_width = wi;
if (isYUV)
{
tempY = (unsigned char*)aligned_malloc(original_width*2+4, 64); // aligned for Athlon cache line
tempUV = (unsigned char*)aligned_malloc(original_width*4+8, 64); // aligned for Athlon cache line
pattern_chroma = GetResamplingPatternYUV(width>>1, subrange_left/2, subrange_width/2, target_width>>1, func, false, tempUV);
pattern_luma = GetResamplingPatternYUV(width, subrange_left, subrange_width, target_width, func, true, tempY);
}
else
pattern_luma = GetResamplingPatternRGB(width, subrange_left, subrange_width, target_width, func);
width = target_width;
}
FilteredResizeH::~FilteredResizeH()
{
aligned_free(pattern_luma);
if (pattern_chroma)
aligned_free(pattern_chroma);
if (tempY)
aligned_free(tempY);
if (tempUV)
aligned_free(tempUV);
}
void FilteredResizeH::ResizeFrame(unsigned char* srcp, unsigned char* dstp, int src_pitch, int dst_pitch)
{
if (m_YUV)
{
int fir_filter_size_luma = pattern_luma[0];
int fir_filter_size_chroma = pattern_chroma[0];
static const __int64 x0000000000FF00FF = 0x0000000000FF00FF;
static const __int64 x00FF000000FF0000 = 0x00FF000000FF0000;
static const __int64 FPround = 0x0000200000002000; // 16384/2
__asm
{
emms
pxor mm0, mm0
movq mm7, x0000000000FF00FF
movq mm6, FPround
movq mm5, x00FF000000FF0000
}
for (int y=0; y<height; ++y)
{
int* cur_luma = pattern_luma+2;
int* cur_chroma = pattern_chroma+2;
int x = width >> 1;
__asm
{
mov edi, this
mov ecx, [edi].original_width
mov edx, [edi].tempY
mov ebx, [edi].tempUV
mov esi, srcp
mov eax, -1
// deinterleave current line
deintloop:
inc eax
movd mm1, [esi] ;mm1 = 0000VYUY
movq mm2, mm1
punpcklbw mm2, mm0 ;mm2 = 0V0Y0U0Y
pand mm1, mm7 ;mm1 = 00000Y0Y
psrld mm2, 16 ;mm2 = 000V000U
movd [edx+eax*4], mm1
add esi, 4
movq [ebx+eax*8], mm2
sub ecx, 2
jnz deintloop
// use this as source from now on
mov eax, cur_luma
mov ebx, cur_chroma
mov edx, dstp
xloopYUV:
mov esi, [eax] ;esi=&tempY[ofs0]
movq mm1, mm0
mov edi, [eax+4] ;edi=&tempY[ofs1]
movq mm3, mm0
mov ecx, fir_filter_size_luma
add eax, 8 ;cur_luma++
aloopY:
// Identifiers:
// Ya, Yb: Y values in srcp[ofs0]
// Ym, Yn: Y values in srcp[ofs1]
movd mm2, [esi] ;mm2 = 0| 0|Yb|Ya
punpckldq mm2, [edi] ;mm2 = Yn|Ym|Yb|Ya
;[eax] = COn|COm|COb|COa
pmaddwd mm2, [eax] ;mm2 = Y1|Y0 (DWORDs)
paddd mm1, mm2 ;accumulate
add esi, 4
add edi, 4
add eax, 8 ;cur_luma++
dec ecx
jnz aloopY
mov esi, [ebx] ;esi=&tempUV[ofs]
add ebx, 8 ;cur_chroma++
mov ecx, fir_filter_size_chroma
aloopUV:
movq mm2, [esi] ;mm2 = 0|V|0|U
;[ebx] = 0|COv|0|COu
pmaddwd mm2, [ebx] ;mm2 = V|U (DWORDs)
paddd mm3, mm2 ;accumulate
add esi, 8
add ebx, 8 ;cur_chroma++
dec ecx
jnz aloopUV
paddd mm1, mm6 ;Y1|Y1|Y0|Y0
paddd mm3, mm6 ; V| V| U| U
pslld mm3, 2
pand mm3, mm5 ;mm3 = v| 0|u| 0
psrld mm1, 14 ;mm1 = 0|y1|0|y0
por mm3, mm1
packuswb mm3, mm3 ;mm3 = ...|v|y1|u|y0
movd [edx], mm3
add edx, 4
dec x
jnz xloopYUV
}
srcp += src_pitch;
dstp += dst_pitch;
}
__asm { emms }
}
else
{
// RGB24 is not recommended. 75% of all pixels are not aligned.
int y = height;
int w = (width<<1) + width;
int fir_filter_size = pattern_luma[0];
int* pattern_lumaP1 = pattern_luma+1 - fir_filter_size;
static const __int64 xFF000000 = 0xFF000000;
__asm
{
emms
mov esi, srcp
mov edi, dstp
pxor mm2, mm2
movq mm4, xFF000000
yloop24:
xor ecx, ecx
mov edx, pattern_lumaP1 ;cur - fir_filter_size
xloop24:
mov eax, fir_filter_size
lea edx, [edx+eax*4] ;cur += fir_filter_size
mov ebx, [edx]
lea ebx, [ebx+ebx*2] ;ebx = ofs = *cur * 3
add edx, 4 ;cur++
pxor mm0, mm0 ;btotal, gtotal
pxor mm1, mm1 ;rtotal
lea edx, [edx+eax*4] ;cur += fir_filter_size
add ebx, esi ;ebx = srcp + ofs*3
lea eax, [eax+eax*2] ;eax = a = fir_filter_size*3
aloop24:
sub edx, 4 ;cur--
movd mm7, [ebx+eax] ;mm7 = srcp[ofs+a] = 0|0|0|0|x|r|g|b
punpcklbw mm7, mm2 ;mm7 = 0x|0r|0g|0b
movq mm6, mm7
punpcklwd mm7, mm2 ;mm7 = 00|0g|00|0b
punpckhwd mm6, mm2 ;mm6 = 00|0x|00|0r
movd mm5, [edx] ;mm5 = 00|co (co = coefficient)
packssdw mm5, mm2
punpckldq mm5, mm5 ;mm5 = co|co
pmaddwd mm7, mm5 ;mm7 = g*co|b*co
pmaddwd mm6, mm5 ;mm6 = x*co|r*co
paddd mm0, mm7
paddd mm1, mm6
sub eax, 3
jnz aloop24
pslld mm0, 2
pslld mm1, 2 ;compensate the fact that FPScale = 16384
packuswb mm0, mm1 ;mm0 = x|_|r|_|g|_|b|_
psrlw mm0, 8 ;mm0 = 0|x|0|r|0|g|0|b
packuswb mm0, mm2 ;mm0 = 0|0|0|0|x|r|g|b
pslld mm0, 8
psrld mm0, 8 ;mm0 = 0|0|0|0|0|r|g|b
movd mm3, [edi+ecx] ;mm3 = 0|0|0|0|x|r|g|b (dst)
pand mm3, mm4 ;mm3 = 0|0|0|0|x|0|0|0 (dst)
por mm3, mm0
movd [edi+ecx], mm3
add ecx, 3
cmp ecx, w
jnz xloop24
add esi, src_pitch
add edi, dst_pitch
dec y
jnz yloop24
emms
}
}
}
FilteredResizeV::FilteredResizeV(int isYUV,int wi, int he, int subrange_top, int subrange_height, int target_height, TriangleFilter* func):width(wi),height(he),m_YUV(isYUV)
{
//if (!isYUV)
// subrange_top = height - subrange_top - subrange_height;
resampling_pattern = GetResamplingPatternRGB(height, subrange_top, subrange_height, target_height, func);
height = target_height;
int sh = he;
yOfs = (int*)aligned_malloc(sizeof(int)*sh, 64);
for (int i = 0; i < sh; i++)
yOfs[i] = (isYUV ? (wi*2) * i : (wi*3) * i);
}
void FilteredResizeV::ResizeFrame(unsigned char* srcp, unsigned char* dstp, int src_pitch, int dst_pitch, int row_size)
{
const int* cur = resampling_pattern;
const int fir_filter_size = *cur++;
const int xloops = row_size>>2;
int y = height;
int *yOfs = this->yOfs;
__asm
{
emms
mov edx, cur
pxor mm0, mm0
mov edi, fir_filter_size
yloop:
mov esi, yOfs
mov eax, [edx] ;eax = *cur
mov esi, [esi+eax*4]
add esi, srcp ;esi = srcp + yOfs[*cur]
add edx, 4 ;cur++
xor ecx, ecx ;ecx = x = 0
xloop:
pxor mm7, mm7
pxor mm1, mm1 ;total = 0
lea eax, [esi+ecx*4] ;eax = srcp2 = srcp + x
xor ebx, ebx ;ebx = b = 0
bloop:
movd mm2, [eax] ;mm2 = *srcp2 = 0|0|0|0|d|c|b|a
movd mm3, [edx+ebx*4] ;mm3 = cur[b] = 0|co
punpckldq mm3, mm3 ;mm3 = co|co
punpcklbw mm2, mm0 ;mm2 = 0d|0c|0b|0a
movq mm4, mm2
punpcklwd mm2, mm0 ;mm2 = 00|0b|00|0a
punpckhwd mm4, mm0 ;mm4 = 00|0d|00|0c
pmaddwd mm2, mm3 ;mm2 = b*co|a*co
pmaddwd mm4, mm3 ;mm4 = d*co|c*co
paddd mm1, mm2
paddd mm7, mm4 ;accumulate
add eax, src_pitch ;srcp2 += src_pitch
inc ebx
cmp ebx, edi
jnz bloop
mov eax, dstp
pslld mm1, 2
pslld mm7, 2 ;compensate the fact that FPScale = 16384
packuswb mm1, mm7 ;mm1 = d|_|c|_|b|_|a|_
psrlw mm1, 8 ;mm1 = 0|d|0|c|0|b|0|a
packuswb mm1, mm2 ;mm1 = 0|0|0|0|d|c|b|a
movd [eax+ecx*4], mm1
inc ecx
cmp ecx, xloops
jnz xloop
add eax, dst_pitch
lea edx, [edx+edi*4] ;cur += fir_filter_size
mov dstp, eax
dec y
jnz yloop
emms
}
}
FilteredResizeV::~FilteredResizeV()
{
aligned_free(resampling_pattern);
aligned_free(yOfs);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -