问题描述
嗨专家,
链接到我的完整源代码:
[]
(在Debug文件夹中有Resizer.dll,需要先注册然后再注册在图形编辑中选择任何视频文件(使用文件源文件管理器),然后添加RGB Resizer并使用它来调整视频大小)
我正在创建一个新的缩放器滤镜,我添加了一个属性页面,用户可以选择不同的输出(朋友(720X576),ntsc(720X480)......)
默认情况下选择pal,如果我播放它工作正常。
玩朋友后如果我将输出更改为ntsc视频显示不正确(问题是标题的顶部部分正在崩溃。)
如果我断开输出和输入我的过滤器的引脚,然后更改输出设置,重新连接后它似乎工作正常。
如何解决这个问题?(没有断开引脚我需要更改输出设置)
以下是我的代码(我使用的代码来自我在网上找到的样本,我添加了属性页面)
我想我需要更改ScaleBuf()但我没有任何线索如何解决这个问题。
Hi Experts,
Link to my Full source code:
https://docs.google.com/file/d/0B9qC3OVDGTjuM2xaeGx1Q0NUYWs/edit[^]
(in the Debug folder there is Resizer.dll, and need to register it first then in graph edit select any video file(using file source filer), then add "RGB Resizer" and use it to resize the video)
I am creating a new resizer Filter, I added a property page where user can select different outputs (pal(720X576), ntsc(720X480)...)
By default pal is selected and if i played it working fine.
after playing with pal and if i changed the output to ntsc video is not displaying correctly(problem is top part of the header is getting croped.)
If i disconnect the output and input pins of my filter and then change the output settings and after reconnecting it seems to be working fine.
How to fix this issue?(with out disconnecting the pins i need to change the output settings)
below is my code(the code i am using is from a sample i found online, i added the property page)
I guess i need to change ScaleBuf() but i dont have any clues how to fix this.
HRESULT CResizer::CheckInputType(const CMediaType *mtIn)
{
// check this is a VIDEOINFOHEADER type and RGB
GUID subtypeIn = *mtIn->Subtype();
if( *mtIn->FormatType() == FORMAT_VideoInfo &&
(subtypeIn == MEDIASUBTYPE_RGB555 || subtypeIn == MEDIASUBTYPE_RGB565 ||
subtypeIn == MEDIASUBTYPE_RGB24 || subtypeIn == MEDIASUBTYPE_RGB32))
{
BITMAPINFOHEADER *pbih = &((VIDEOINFOHEADER*)mtIn->Format())->bmiHeader;
m_inX = pbih->biWidth;
m_inY = pbih->biHeight;
m_bMakeTables = true;
return S_OK;
}
return VFW_E_INVALID_MEDIA_TYPE;
}
HRESULT CResizer::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
{
GUID subtypeIn = *mtIn->Subtype();
GUID subtypeOut = *mtOut->Subtype();
if(subtypeIn == subtypeOut && (subtypeIn == MEDIASUBTYPE_RGB555 || subtypeIn == MEDIASUBTYPE_RGB565 ||
subtypeIn == MEDIASUBTYPE_RGB24 || subtypeIn == MEDIASUBTYPE_RGB32) )
return S_OK;
return VFW_E_INVALID_MEDIA_TYPE;
}
HRESULT CResizer::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
if (!m_pInput->IsConnected())
return E_UNEXPECTED;
//HRESULT hr = NOERROR;
ALLOCATOR_PROPERTIES InputProps;
IMemAllocator *pAllocInput = 0;
HRESULT hr = m_pInput->GetAllocator(&pAllocInput);
if (FAILED(hr))
{
return hr;
}
hr = pAllocInput->GetProperties(&InputProps);
pAllocInput->Release();
if (FAILED(hr))
{
return hr;
}
if (pProperties->cbAlign == 0)
{
pProperties->cbAlign = 1;
}
if (pProperties->cbBuffer == 0)
{
pProperties->cBuffers = 1;
}
pProperties->cbBuffer = max(InputProps.cbBuffer, pProperties->cbBuffer);
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProperties, &Actual);
if (FAILED(hr))
{
return hr;
}
if (InputProps.cbBuffer > Actual.cbBuffer)
{
return E_FAIL;
}
return S_OK;
}
HRESULT CResizer::GetMediaType(int iPosition, CMediaType *pMediaType)
{
// Is the input pin connected
if (!m_pInput->IsConnected())
return E_UNEXPECTED;
if (iPosition < 0)
return E_INVALIDARG;
// Do we have more items to offer
if (iPosition > 0)
return VFW_S_NO_MORE_ITEMS;
// get input dimensions
CMediaType *inMediaType = &m_pInput->CurrentMediaType();
VIDEOINFOHEADER *vihIn = (VIDEOINFOHEADER*)inMediaType->Format();
m_bytesPerPixel = vihIn->bmiHeader.biBitCount / 8;
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetSubtype(inMediaType->Subtype());
pMediaType->SetSampleSize(RowWidth(m_outX) * m_outY * m_bytesPerPixel);
pMediaType->SetTemporalCompression(FALSE);
VIDEOINFOHEADER *vihOut = (VIDEOINFOHEADER *)pMediaType->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));
// set VIDEOINFOHEADER
memset(vihOut, 0, sizeof(VIDEOINFOHEADER));
double frameRate = vihIn->AvgTimePerFrame / 10000000.0;
vihOut->dwBitRate = (int)(frameRate * m_outY * m_outX * m_bytesPerPixel);
vihOut->AvgTimePerFrame = vihIn->AvgTimePerFrame;
// set BITMAPINFOHEADER
vihOut->bmiHeader.biBitCount = m_bytesPerPixel * 8;
vihOut->bmiHeader.biCompression = BI_RGB;
vihOut->bmiHeader.biHeight = m_outY;
vihOut->bmiHeader.biWidth = m_outX;
vihOut->bmiHeader.biPlanes = 1;
vihOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
vihOut->bmiHeader.biSizeImage = RowWidth(m_outX) * m_outY * m_bytesPerPixel;
return NOERROR;
}
//////////////////////////////////////////////////////////////////////////
// Build the lookup tables used for scaling the input into the output
// For each destination pixel x and y the corresponding offset in the
// source buffer is stored
//////////////////////////////////////////////////////////////////////////
void CResizer::MakeScaleTables()
{
double xStep = (double)m_inX / m_outX;
double yStep = (double)m_inY / m_outY;
int inRowBytes = RowWidth(m_inX * m_bytesPerPixel);
int inY, inX;
for(int y = 0; y < m_outY; ++y)
{
inY = y * yStep;
m_iSrcScanLine[y] = (inY * inRowBytes);
}
for(int x = 0; x < m_outX; ++x)
{
inX = x * xStep;
m_iSrcPixelOffset[x] = (inX * m_bytesPerPixel);
}
}
//////////////////////////////////////////////////////////////////////////
// This method scales the bitmap data from the input to output buffer
// When either of the formats change, the tables are rebuilt
//////////////////////////////////////////////////////////////////////////
void CResizer::ScaleBuf(BYTE *in, BYTE *out)
{
UCHAR *dstPixel = out;
UCHAR *srcScanLine, *srcPixel;
// separate loops for each bpp
for(int y = 0; y < m_outY; ++y)
{
srcScanLine = in + m_iSrcScanLine[y];
switch(m_bytesPerPixel)
{
case 4:
for(int x = 0; x < m_outX; ++x)
{
srcPixel = srcScanLine + m_iSrcPixelOffset[x];
*dstPixel++ = *srcPixel++;
*dstPixel++ = *srcPixel++;
*dstPixel++ = *srcPixel++;
*dstPixel++ = *srcPixel++;
}
break;
case 3:
for(int x = 0; x < m_outX; ++x)
{
srcPixel = srcScanLine + m_iSrcPixelOffset[x];
*dstPixel++ = *srcPixel++;
*dstPixel++ = *srcPixel++;
*dstPixel++ = *srcPixel++;
}
break;
case 2:
for(int x = 0; x < m_outX; ++x)
{
srcPixel = srcScanLine + m_iSrcPixelOffset[x];
*dstPixel++ = *srcPixel++;
*dstPixel++ = *srcPixel++;
}
break;
case 1:
for(int x = 0; x < m_outX; ++x)
{
srcPixel = srcScanLine + m_iSrcPixelOffset[x];
*dstPixel++ = *srcPixel++;
}
break;
}
}
}
推荐答案
这篇关于如何缩放视频的输出缓冲区大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!