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

📄 cresizer.cpp

📁 视频放大或缩小的滤波器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <windows.h>
#include <streams.h>
#include <initguid.h>
#include <olectl.h>
#if (1100 > _MSC_VER)
#include <olectlid.h>
#endif

#include "resource.h"
#include "iresizer.h"
#include "cresizer.h"
#include "resizeuids.h"
#include "propdialog.h"





int a = 1;

typedef struct tagVIDEOINFOHEADER2 {
    RECT                rcSource;
    RECT                rcTarget;
    DWORD               dwBitRate;
    DWORD               dwBitErrorRate;
    REFERENCE_TIME      AvgTimePerFrame;
    DWORD               dwInterlaceFlags;
    DWORD               dwCopyProtectFlags;
    DWORD               dwPictAspectRatioX; 
    DWORD               dwPictAspectRatioY; 
    DWORD               dwReserved1;        
    DWORD               dwReserved2;        
    BITMAPINFOHEADER    bmiHeader;
} VIDEOINFOHEADER2;

REFERENCE_TIME temp_AvgTimePerFrame;

const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
    &MEDIATYPE_Video,       // Major type
    &MEDIASUBTYPE_NULL      // Minor type
};

const AMOVIESETUP_PIN psudPins[] =
{
    {
        L"Input",           // String pin name
        FALSE,              // Is it rendered
        FALSE,              // Is it an output
        FALSE,              // Allowed none
        FALSE,              // Allowed many
        &CLSID_NULL,        // Connects to filter
        L"Output",          // Connects to pin
        1,                  // Number of types
        &sudPinTypes },     // The pin details
      { L"Output",          // String pin name
        FALSE,              // Is it rendered
        TRUE,               // Is it an output
        FALSE,              // Allowed none
        FALSE,              // Allowed many
        &CLSID_NULL,        // Connects to filter
        L"Input",           // Connects to pin
        1,                  // Number of types
        &sudPinTypes        // The pin details
    }
};


const AMOVIESETUP_FILTER sudContrast =
{
    &CLSID_TIMResizer,        // Filter CLSID
    L"Video Resizer",      // Filter name
    MERIT_DO_NOT_USE,       // Its merit
    2,                      // Number of pins
    psudPins                // Pin details
};

CFactoryTemplate g_Templates[2] = {

    { L"Video Resizer"
    , &CLSID_TIMResizer
    , CResizer::CreateInstance
    , NULL
    , &sudContrast }
  ,
    { L"Video Resizer Property Page"
    , &CLSID_TIMResizerPropertyPage
    , SizeSelect_Dialog::CreateInstance }
};


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


struct alloc_info
{
	void *raw;
	void *aligned;
};

#define POOL_SIZE 512
static alloc_info malloc_tab[POOL_SIZE];

CResizer::CResizer(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr) :
    CTransformFilter(tszName, punk, CLSID_TIMResizer)
{
  	ASSERT(tszName);
    ASSERT(phr);
	output_width = 352;
	output_height = 240;
}

CResizer::~CResizer()
{
	a++;
}
void *aligned_malloc(size_t size, size_t alignement)
{
	for(int i=0;i<POOL_SIZE;i++)
	{
		if (malloc_tab[i].aligned == 0)
		{
			void *data = malloc(size+alignement);
			malloc_tab[i].raw = data;
			data = (void*)(((size_t)data + alignement) & ~alignement);
			malloc_tab[i].aligned = data;

			return data;
		}
	}

	return malloc(size);
}

//extern "C" 
void aligned_free(void *aligned)
{
	for(int i=0;i<POOL_SIZE;i++)
	{
		if (malloc_tab[i].aligned == aligned)
		{
			malloc_tab[i].aligned = 0;
			free(malloc_tab[i].raw);
			return;
		}
	}

	free(aligned);
}
const int FPScale = 16384;

static int* GetResamplingPatternYUV(int original_width, double subrange_start, double subrange_width, int target_width, TriangleFilter* func, bool luma, unsigned char *temp)
{
	double scale = double(target_width) / subrange_width;
	double filter_step = min(scale, 1.0);
	double filter_support = func->support() / filter_step;
	int fir_filter_size = int(ceil(filter_support*2));
	int fir_fs_mmx = (fir_filter_size / 2) +1;  // number of loops in MMX code
	int* result = luma ?
		(int*)aligned_malloc(2*4 + target_width*(1+fir_fs_mmx)*8, 8) :
    (int*)aligned_malloc(2*4 + target_width*(1+fir_filter_size)*8, 8);
	
	int* cur[2] = { result +2, result +3 };
	*result = luma ? fir_fs_mmx : fir_filter_size;
	
	double pos_step = subrange_width / target_width;
	// the following translates such that the image center remains fixed
	double pos = subrange_start + ((subrange_width - target_width) / (target_width*2));
	
	for (int i=0; i<target_width; ++i)
	{
		int end_pos = int(pos + filter_support);
		if (end_pos > original_width-1)
			end_pos = original_width-1;
		int start_pos = end_pos - fir_filter_size + 1;
		if (start_pos < 0)
			start_pos = 0;
		int ii = luma ? i&1 : 0;
		*(cur[ii]) = luma ?
			(int)(temp + (start_pos & -2) * 2) :
		(int)(temp + start_pos * 8);
		cur[ii] += 2;
		// the following code ensures that the coefficients add to exactly FPScale
		double total = 0.0;
		for (int j=0; j<fir_filter_size; ++j)
			total += func->f((start_pos+j - pos) * filter_step);
		double total2 = 0.0;
		int oldCoeff = 0;
		for (int k=0; k<fir_filter_size; ++k)
		{
			double total3 = total2 + func->f((start_pos+k - pos) * filter_step) / total;
			int coeff = int(total3*FPScale+0.5) - int(total2*FPScale+0.5);
			total2 = total3;
			if (luma)
			{
				if ((k + start_pos) & 1)
				{
					*(cur[ii]) = (coeff << 16) + (oldCoeff & 0xFFFF);
					cur[ii] += 2;
				}
				else
					oldCoeff = coeff;
			}
			else
			{
				*(cur[0]) = coeff;  cur[0] += 1;
				*(cur[0]) = coeff;  cur[0] += 1;
			}
		}
		if (luma)
		{
			if ((start_pos + fir_filter_size) & 1)
			{
				*(cur[ii]) = 0 + (oldCoeff & 0xFFFF);
				cur[ii] += 2;
			}
			else
				if ((fir_filter_size & 1) == 0)
				{
					*(cur[ii]) = 0;  cur[ii] += 2;
				}
		}
		pos += pos_step;
	}
	return result;
}

static int* GetResamplingPatternRGB(int original_width, double subrange_start, double subrange_width, int target_width, TriangleFilter* func)
{
	double scale = double(target_width) / subrange_width;
	double filter_step = min(scale, 1.0);
	double filter_support = func->support() / filter_step;
	int fir_filter_size = int(ceil(filter_support*2));
	int* result = (int*)aligned_malloc((1 + target_width*(1+fir_filter_size)) * 4, 4);
	
	int* cur = result;
	*cur++ = fir_filter_size;
	
	double pos_step = subrange_width / target_width;
	// the following translates such that the image center remains fixed
	double pos = subrange_start + ((subrange_width - target_width) / (target_width*2));
	
	for (int i=0; i<target_width; ++i)
	{
		int end_pos = int(pos + filter_support);
		if (end_pos > original_width-1)
			end_pos = original_width-1;
		int start_pos = end_pos - fir_filter_size + 1;
		if (start_pos < 0)
			start_pos = 0;
		*cur++ = start_pos;
		// the following code ensures that the coefficients add to exactly FPScale
		double total = 0.0;
		for (int j=0; j<fir_filter_size; ++j)
			total += func->f((start_pos+j - pos) * filter_step);
		double total2 = 0.0;
		for (int k=0; k<fir_filter_size; ++k)
		{
			double total3 = total2 + func->f((start_pos+k - pos) * filter_step) / total;
			*cur++ = int(total3*FPScale+0.5) - int(total2*FPScale+0.5);
			total2 = total3;
		}
		pos += pos_step;
	}
	return result;
}

CUnknown * WINAPI CResizer::CreateInstance(LPUNKNOWN punk, HRESULT *phr) {

    CResizer *pNewObject = new CResizer(NAME("TIMResizer"), punk, phr);
    if (pNewObject == NULL) {
        *phr = E_OUTOFMEMORY;
    }
    return pNewObject;

} // CreateInstance

STDMETHODIMP CResizer::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
    CheckPointer(ppv,E_POINTER);

    if (riid == IID_ITIMResizer) {
        return GetInterface((IResizer *) this, ppv);
    } else if (riid == IID_ISpecifyPropertyPages) {
        return GetInterface((ISpecifyPropertyPages *) this, ppv);
    } else {
        return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
    }

} // NonDelegatingQueryInterface


HRESULT CResizer::PrepareOutputSample (IMediaSample* inSample, IMediaSample* outSample)
{
	// assertions
	CheckPointer (inSample, E_POINTER);
	CheckPointer (outSample, E_POINTER);	

	// set media type
	outSample->SetMediaType (&this->outputMediaType);


	// copy the sample times
	REFERENCE_TIME timeStart = 0;
	REFERENCE_TIME timeEnd = 0;
	if (inSample->GetTime (&timeStart, &timeEnd) == S_OK)
	{
		outSample->SetTime (&timeStart, &timeEnd);
	}

	LONGLONG mediaStart = 0;
	LONGLONG mediaEnd = 0;
	if (inSample->GetMediaTime (&mediaStart, &mediaEnd) == S_OK)
	{
			outSample->SetMediaTime (&mediaStart,&mediaEnd);
	}

	// copy the sync point property
	HRESULT result = inSample->IsSyncPoint ();
	if (result == S_OK)
	{
		outSample->SetSyncPoint (TRUE);
	}
	else if (result == S_FALSE)
	{
		outSample->SetSyncPoint (FALSE);
	}
	else
	{	// an unexpected error has occured...
		return E_UNEXPECTED;
	}

	// copy the preroll property
	result = inSample->IsPreroll ();
	if (result == S_OK)
	{
		outSample->SetPreroll (TRUE);
	}
	else if (result == S_FALSE)
	{
		outSample->SetPreroll (FALSE);
	}
	else
	{	// an unexpected error has occured...
		return E_UNEXPECTED;
	}

	// copy the discontinuity property
	result = inSample->IsDiscontinuity ();
	if (result == S_OK)
	{
		outSample->SetDiscontinuity (TRUE);
	}
	else if (result == S_FALSE)
	{
		outSample->SetDiscontinuity(FALSE);
	}
	else
	{	// an unexpected error has occured...
		return E_UNEXPECTED;
	}


	return S_OK;

} // VideoResizer_Filter::PrepareOutputSample

HRESULT CResizer::Transform(IMediaSample *pIn, IMediaSample *pOut)
{
	HRESULT result = this->PrepareOutputSample (pIn, pOut);
	if (result != S_OK)
	{
		return result;
	}
	
	FilteredResizeV* v_filter;
	FilteredResizeH* h_filter;
	
	h_filter = new FilteredResizeH(1,input_width,input_height,0,input_width,
		output_width, &TriangleFilter());
	v_filter = new FilteredResizeV(1,output_width,input_height,0,input_height, 
		output_height, &TriangleFilter());

	BYTE* srcBuffer = 0;
	BYTE* dstBuffer = 0;
	pIn->GetPointer (&srcBuffer);
	pOut->GetPointer (&dstBuffer);

	unsigned char* loc_result = srcBuffer;
	unsigned char* yuy2_temp = (unsigned char*)aligned_malloc(input_width*input_height*2,64);;
	
	if (h_filter)
	{
		h_filter->ResizeFrame(loc_result, yuy2_temp, input_width<<1, output_width<<1);
		loc_result = yuy2_temp;
	}
	if (v_filter)
	{
		v_filter->ResizeFrame(loc_result, (loc_result == yuy2_temp ? dstBuffer : yuy2_temp), 
			output_width<<1, output_width<<1, output_width<<1);
//		loc_result = (loc_result == yuy2_temp ? srcBuffer : yuy2_temp);
	}
	
	aligned_free (yuy2_temp);
	delete(h_filter);
	delete(v_filter);

//	dstBuffer = loc_result;

	return S_OK;
} // Transform

HRESULT CResizer::CheckInputType(const CMediaType *mtIn)
{
	CheckPointer (mtIn, E_POINTER);
	
	if (!IsEqualGUID (*mtIn->Type (), MEDIATYPE_Video))
	{
		return E_FAIL;
	}

	// minor type supported?
	if ( (!IsEqualGUID (*mtIn->Subtype (), MEDIASUBTYPE_YUY2))) {
		return E_FAIL;
	}

	// format type supported
	if ((!IsEqualGUID (*mtIn->FormatType (), FORMAT_VideoInfo)) &&
			(!IsEqualGUID (*mtIn->FormatType (), FORMAT_VideoInfo2)))
	{
		return E_FAIL;
	}

	// we can support this connection
	return S_OK;

} // CheckInputType
HRESULT CResizer::CheckOutputType(const CMediaType *mtOut)
{
	CheckPointer (mtOut, E_POINTER);

	// major type supported?
	if (!IsEqualGUID (*mtOut->Type (), MEDIATYPE_Video))
	{
		return E_FAIL;
	}

	// minor type supported?
	if ( !IsEqualGUID (*mtOut->Subtype (), MEDIASUBTYPE_YUY2) )
	{
		return E_FAIL;
	}
	// format type supported
	if ((!IsEqualGUID (*mtOut->FormatType (), FORMAT_VideoInfo)) &&
			(!IsEqualGUID (*mtOut->FormatType (), FORMAT_VideoInfo2)))
	{
		return E_FAIL;
	}

	// we can support this connection
	return S_OK;
}
HRESULT CResizer::CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut)
{
	HRESULT result = S_OK;

	// test input media
	if (mtIn != 0)
	{
		result = this->CheckInputType (mtIn);
		if (result != S_OK)
		{
			return result;
		}
	}

	// test output media
	if (mtOut != 0)
	{
		result = this->CheckOutputType (mtOut);
		if (result != S_OK)
		{
			return result;
		}
	}
	// this transform supported
	return S_OK;
} // CheckTransform

HRESULT CResizer::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
 	// make sure the input pin is connected
	if (this->m_pInput->IsConnected () == FALSE)
	{
		return E_UNEXPECTED;
	}

	// assertions
	CheckPointer (pAlloc, E_POINTER);
	CheckPointer (pProperties, E_POINTER);

	pProperties->cBuffers	= 1;

	pProperties->cbBuffer	= output_width*output_height*2;

	// set properties
	ALLOCATOR_PROPERTIES actualProperties;
	HRESULT result = pAlloc->SetProperties (pProperties, &actualProperties);
	if (result != S_OK)
	{
		return result;
	}

	// verify we got enough stuff
	if ((actualProperties.cBuffers < pProperties->cBuffers) ||
			(actualProperties.cbBuffer < pProperties->cbBuffer))
	{
		return E_FAIL;
	}

	return S_OK;

} // DecideBufferSize

HRESULT CResizer::GetMediaType(int iPosition, CMediaType *pMediaType)
{
	// make sure the input pin is connected
	if (this->m_pInput->IsConnected () == FALSE)
	{
		return E_UNEXPECTED;
	}

	// assertion
	if (pMediaType == 0)
	{
		return E_POINTER;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -