📄 cresizer.cpp
字号:
#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 + -