⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cresizer.cpp

📁 视频放大或缩小的滤波器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	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 + -