关于改变视频大小的问题

NewDX 2010-10-28 09:05:42
我的问题是这样的,假如进来的视频数据的大小为300 * 400的,现在我怎么把它变成600 * 2并且传下去了?
...全文
1009 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaobing_912 2012-03-06
  • 打赏
  • 举报
回复
请问CVideoProcessorOutputPin这个类是需要自己定义还是本来就有的?本来就有的话,是在哪的呢?
mlhy20060406 2011-03-10
  • 打赏
  • 举报
回复
我也遇到这个问题了,好好仔细看看
tufaqing 2010-10-28
  • 打赏
  • 举报
回复
可以啊,那就什么都不做了,直接GetMediaType的时候固定就行了,这个本来就是给后面连接的嘛。
实现这个:HRESULT CVideoProcessor::GetMediaType(int iPosition, CMediaType *pMediaType)
NewDX 2010-10-28
  • 打赏
  • 举报
回复
To tufaqing
请问一下,上面的代码能不能用在,当以开始Filter链接,判断媒体类型时,在自己的Filter中,修改输出端媒体类型的信息,就是修改视频的宽度和高度了?
tufaqing 2010-10-28
  • 打赏
  • 举报
回复
是改变你的输出端视频的宽度和高度吧,如何传到下一个filter的输入端。要保证下一个filter支持媒体改变,否则没用,但这个不是你的filter的问题,而是下一个filter的问题。video render是支持动态尺寸改变的,不过他的width宽会自己调整,你的outputpin内存要适应它的width,否则就出现条纹。

// 媒体改变
STDMETHODIMP CVideoProcessorOutputPin::ChangeMediaType(const AM_MEDIA_TYPE *pmt)
{
CheckPointer(m_Connected, E_POINTER);
CheckPointer(pmt, E_POINTER);

HRESULT hr = m_Connected->QueryAccept(pmt);
if(FAILED(hr))
{
return hr;
}

hr = m_Connected->ReceiveConnection(this, pmt);
if(FAILED(hr))
{
return hr;
}

CMediaType mt = *pmt;
SetMediaType(&mt);

hr = m_pAllocator->Decommit();
if(FAILED(hr))
{
return hr;
}

hr = CompleteConnect(m_Connected);
if(FAILED(hr))
{
return hr;
}

hr = m_pAllocator->Commit();
if(FAILED(hr))
{
return hr;
}

return S_OK;
}
// 分配空间 (这个只处理YV12)
HRESULT CVideoProcessor::DecideBufferSize(IMemAllocator *pAllocator, ALLOCATOR_PROPERTIES *pprop)
{
CheckPointer(pAllocator, E_POINTER);
CheckPointer(pprop, E_POINTER);

int width = m_nWidthOut ? m_nWidthOut : m_nWidthIn;
int height = m_nHeightOut ? m_nHeightOut : m_nHeightIn;

pprop->cbBuffer = width * height * 3 / 2;
pprop->cBuffers = 1;

ALLOCATOR_PROPERTIES Actual;
HRESULT hr = pAllocator->SetProperties(pprop, &Actual);
if(FAILED(hr))
{
return E_UNEXPECTED;
}

m_nWidthOutRender = 0;

return S_OK;
}

HRESULT CVideoProcessor::Receive(IMediaSample *pSample)
{
...

if(m_bOutSizeChanged)
{
CMediaType mt;
... // 设置媒体类型

HRESULT hr = ((CVideoProcessorOutputPin *)m_pOutput)->ChangeMediaType(&mt);
if(SUCCEEDED(hr))
{
IMediaSample *pOutSample = NULL;
hr = m_pOutput->GetDeliveryBuffer(&pOutSample, NULL, NULL, 0);
if(SUCCEEDED(hr))
{
pmt = NULL;
hr = pOutSample->GetMediaType(&pmt);
if(SUCCEEDED(hr) && pmt)
{
if(pmt->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER* hrIn = (VIDEOINFOHEADER*)pmt->pbFormat;
m_nWidthOutRender = hrIn->bmiHeader.biWidth;
}
else if(pmt->formattype == FORMAT_VideoInfo2)
{
VIDEOINFOHEADER2* hrIn = (VIDEOINFOHEADER2*)pmt->pbFormat;
m_nWidthOutRender = hrIn->bmiHeader.biWidth;
}

DeleteMediaType(pmt);
}

pOutSample->Release();
}

int nWidth = m_nWidthOut ? m_nWidthOut : m_nWidthIn;
int nHeight = m_nHeightOut ? m_nHeightOut : m_nHeightIn;
NotifyEvent(EC_VIDEO_SIZE_CHANGED, MAKELPARAM(nWidth, nHeight), 0);
}
}
...
}
NewDX 2010-10-28
  • 打赏
  • 举报
回复
不好意思,上面写错了一些字。
应该是下面才对

To tufaqing
多谢了。可能我说的不太清楚.我现在想如果我要改变输入端进来的视频的宽度和高度.假如我已经实现并且转换也实现了.我现在怎么把这个新的视频高度和宽度应用到下一个Filter中.应该是要改变CMediaType这些视频格式吧。然后传到下一个Filter。我想问的是这个应该如何实现?
NewDX 2010-10-28
  • 打赏
  • 举报
回复
To tufaqing
多谢了。可能我说太明白.我现在想如果我要改变输入端进来的视频的宽度和高度.假如我已经实现了.我现在怎么把这个新的视频高度和宽度应用到下一个Filter中.应该是要改变CMediaType这些视频格式吧。然后传到下一个Filter。我想问的是这个应该如何实现?

tufaqing 2010-10-28
  • 打赏
  • 举报
回复
Directshow的开发要不断看BaseClasses里面的代码,不断调试,要很长时间才能弄得比较清楚的,通过几句话是很难说清楚的。视频缩放不属于directshow部分,这是纯粹的数学逻辑算法问题,原理也很简单,就是两个函数的映射问题,不同的映射方法就是不同的缩放方法,双线性插值法是比较常用的一种。
你留个邮箱,我给你一个视频缩放filter吧,自己调试一下代码,双线性插值法搜一下baidu或Google理解一下。
NewDX 2010-10-28
  • 打赏
  • 举报
回复
To tufaqing
我写了一个Filter,是继承CTransformFilter来的,我可以在Transform函数哪里得到视频数据,假如我知道视频的格式,这样应该知道它们在内存是怎样表示的,这样我可以用一些算法视频有300 * 400变成600 * 200这样的显示.现在我就想知道怎样可以修改输入端进来的视频信息,视频头信息里面的宽度和高度,应用到下一个Filter中?
tufaqing 2010-10-28
  • 打赏
  • 举报
回复
是写filter吗?缩放有算法啊,常用的是双线性插值法,视频一般都是YUV的,要清楚YUY2,YV12的数据排列。如果是写filter,要实现媒体动态改变代码,视频尺寸改变了,要通知下面。
NewDX 2010-10-28
  • 打赏
  • 举报
回复
怎么没有人回答的呀。我顶.....................
NewDX 2010-10-28
  • 打赏
  • 举报
回复
To AudioAEC
不好意思,是600 * 200,应该跟原来的大小一样的,就是宽度和高度变了。
AudioAEC 2010-10-28
  • 打赏
  • 举报
回复
600 * 2
有这么小的视频?是不是600*200 ?
NewDX 2010-10-28
  • 打赏
  • 举报
回复
请tufaqing到下面留一下言吧。
http://topic.csdn.net/u/20101028/15/141f970b-c5b7-4e4b-9911-711b01c2d3a3.html
NewDX 2010-10-28
  • 打赏
  • 举报
回复
To tufaqing
不好意思看错了。给错人了。
我在看一个贴,你进来拿分吧。不好意思了。
NewDX 2010-10-28
  • 打赏
  • 举报
回复
多谢两位.
你在CheckTransform里面做了比较,这里出问题了,直接返回NOERROR就行了。
if(memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0)
{
return NOERROR;
}
return E_INVALIDARG;
试过可以连接上而且可以看到了效果。
再一次谢谢两位了。
结贴...................
tufaqing 2010-10-28
  • 打赏
  • 举报
回复
你在CheckTransform里面做了比较,这里出问题了,直接返回NOERROR就行了。
if(memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0)
{
return NOERROR;
}
return E_INVALIDARG;
rageliu 2010-10-28
  • 打赏
  • 举报
回复
大概看了下

1。下面这里要修改全,把所有改变的地方都修改到

if(pMediaType->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER* hrIn = (VIDEOINFOHEADER*)pMediaType->pbFormat;
hrIn->bmiHeader.biWidth = hrIn->bmiHeader.biWidth / 2;
hrIn->bmiHeader.biHeight = hrIn->bmiHeader.biHeight * 2 ;
}
else if(pMediaType->formattype == FORMAT_VideoInfo2)
{
VIDEOINFOHEADER2* hrIn = (VIDEOINFOHEADER2*)pMediaType->pbFormat;
hrIn->bmiHeader.biWidth = hrIn->bmiHeader.biWidth / 2;
hrIn->bmiHeader.biHeight = hrIn->bmiHeader.biHeight * 2 ;
}

2。DecideBufferSize里面

pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();向这类型的使用,不要再用input的格式来计算了,最好用output的格式来计算
rageliu 2010-10-28
  • 打赏
  • 举报
回复
如果是连接的时候就修改w和h,按上面说的就可以,
如果是想在运行的过程中,动态的改变的话,就需要先查询下游filter是否支持新的格式,如果支持的话,将新的格式设置到sample中,随sample带下去,同时修改output pin的格式,就可以了。
由于后面的render可能会在这个格式改变后再给你返回一个 -h 的新的格式(为了使用加速功能)。这时候由于你是filter内部自己做了格式的改变,所以新的这个格式改变请求,filter内部响应就可以了,不要再向上游filter传递了。
NewDX 2010-10-28
  • 打赏
  • 举报
回复
To tufaqing
下面就是我根据ds的例子改写的,根据你说的改了,但不能改变视频的宽度。但不知道错在哪里?
const AMOVIESETUP_MEDIATYPE sudPinTypes[] =
{
//&MEDIATYPE_Video, // Major type
//&MEDIASUBTYPE_NULL // Minor type
{ &MEDIATYPE_Video, &MEDIASUBTYPE_RGB32 },
{ &MEDIATYPE_Video, &MEDIASUBTYPE_YV12 },
};
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
2, // 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
2, // Number of types
sudPinTypes // The pin details
}
};
const AMOVIESETUP_FILTER sudContrast =
{
&CLSID_Contrast, // Filter CLSID
L"Video Contrast", // Filter name
MERIT_DO_NOT_USE, // Its merit
2, // Number of pins
psudPins // Pin details
};

CFactoryTemplate g_Templates[1] =
{
{ L"Video Contrast"
, &CLSID_Contrast
, CContrast::CreateInstance
, NULL
, &sudContrast }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

CContrast::CContrast(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr) :
CTransformFilter(tszName, punk, CLSID_Contrast),
m_ContrastLevel(2),
m_nUpStream(0),
m_lBufferRequest(1)
{
ASSERT(tszName);
ASSERT(phr);

} // Contrast
CUnknown * WINAPI CContrast::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
ASSERT(phr);

CContrast *pNewObject = new CContrast(NAME("Contrast"), punk, phr);
if (pNewObject == NULL) {
if (phr)
*phr = E_OUTOFMEMORY;
}

return pNewObject;

} // CreateInstance
STDMETHODIMP CContrast::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv,E_POINTER);

if (riid == IID_IContrast) {
return GetInterface((IContrast *) this, ppv);

}else {
return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
}
} // NonDelegatingQueryInterface

HRESULT CContrast::Transform(IMediaSample *pIn, IMediaSample *pOut)
{
HRESULT hr = Copy(pIn, pOut);
if (FAILED(hr)) {
return hr;
}
return Transform(pOut);

} // Transform
HRESULT CContrast::Copy(IMediaSample *pSource, IMediaSample *pDest) const
{
CheckPointer(pSource,E_POINTER);
CheckPointer(pDest,E_POINTER);
BYTE *pSourceBuffer, *pDestBuffer;
long lSourceSize = pSource->GetActualDataLength();

#ifdef DEBUG
long lDestSize = pDest->GetSize();
ASSERT(lDestSize >= lSourceSize);
#endif

pSource->GetPointer(&pSourceBuffer);
pDest->GetPointer(&pDestBuffer);

CopyMemory((PVOID) pDestBuffer,(PVOID) pSourceBuffer,lSourceSize);
REFERENCE_TIME TimeStart, TimeEnd;
if(NOERROR == pSource->GetTime(×tart, &TimeEnd))
{
pDest->SetTime(×tart, &TimeEnd);
}
LONGLONG MediaStart, MediaEnd;
if(pSource->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR)
{
pDest->SetMediaTime(&MediaStart,&MediaEnd);
}
HRESULT hr = pSource->IsSyncPoint();
if(hr == S_OK)
{
pDest->SetSyncPoint(TRUE);
}
else if(hr == S_FALSE)
{
pDest->SetSyncPoint(FALSE);
}
else
{ // an unexpected error has occured...
return E_UNEXPECTED;
}
AM_MEDIA_TYPE *pMediaType;
pSource->GetMediaType(&pMediaType);
pDest->SetMediaType(pMediaType);
DeleteMediaType(pMediaType);
hr = pSource->IsPreroll();
if(hr == S_OK)
{
pDest->SetPreroll(TRUE);
}
else if(hr == S_FALSE)
{
pDest->SetPreroll(FALSE);
}
else
{ // an unexpected error has occured...
return E_UNEXPECTED;
}
hr = pSource->IsDiscontinuity();

if(hr == S_OK)
{
pDest->SetDiscontinuity(TRUE);
}
else if(hr == S_FALSE)
{
pDest->SetDiscontinuity(FALSE);
}
else
{ // an unexpected error has occured...
return E_UNEXPECTED;
}
long lDataLength = pSource->GetActualDataLength();
pDest->SetActualDataLength(lDataLength);
return NOERROR;
} // Copy
HRESULT CContrast::Transform(IMediaSample *pMediaSample)
{
CheckPointer(pMediaSample,E_POINTER);

signed char ContrastLevel;
{
CAutoLock cAutoLock(&m_ContrastLock);
ContrastLevel = m_ContrastLevel;
}
return NOERROR;
}
HRESULT CContrast::CheckInputType(const CMediaType *mtIn)
{
CheckPointer(mtIn,E_POINTER);
if(*mtIn->FormatType() != FORMAT_VideoInfo)
{
return E_INVALIDARG;
}
if(CanChangeContrastLevel(mtIn))
{
return NOERROR;
}
return E_FAIL;
} // CheckInputType
HRESULT CContrast::CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut)
{
CheckPointer(mtIn,E_POINTER);
CheckPointer(mtOut,E_POINTER);
HRESULT hr;
if(FAILED(hr = CheckInputType(mtIn)))
{
return hr;
}
// format must be a VIDEOINFOHEADER
if(*mtOut->FormatType() != FORMAT_VideoInfo)
{
return E_INVALIDARG;
}
// formats must be big enough
if(mtIn->FormatLength() < sizeof(VIDEOINFOHEADER) ||
mtOut->FormatLength() < sizeof(VIDEOINFOHEADER))
{
return E_INVALIDARG;
}
VIDEOINFO *pInput = (VIDEOINFO *) mtIn->Format();
VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format();
if(memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0)
{
return NOERROR;
}
return E_INVALIDARG;
} // CheckTransform
HRESULT CContrast::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
CheckPointer(pAlloc,E_POINTER);
CheckPointer(pProperties,E_POINTER);
if(m_pInput->IsConnected() == FALSE)
{
return E_UNEXPECTED;
}
HRESULT hr = NOERROR;
pProperties->cBuffers = 1;
pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();
ASSERT(pProperties->cbBuffer);
if(!m_pInput->CurrentMediaType().bFixedSizeSamples)
{
if(pProperties->cbBuffer < 100000)
{
// nothing more than a guess!!
pProperties->cbBuffer = 100000;
}
}
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProperties,&Actual);
if(FAILED(hr))
{
return hr;
}
ASSERT(Actual.cBuffers == 1);
if(pProperties->cBuffers > Actual.cBuffers ||
pProperties->cbBuffer > Actual.cbBuffer)
{
return E_FAIL;
}
return NOERROR;
} // DecideBufferSize

HRESULT CContrast::GetMediaType(int iPosition, CMediaType *pMediaType)
{
if(m_pInput->IsConnected() == FALSE)
{
return E_UNEXPECTED;
}
if(iPosition < 0)
{
return E_INVALIDARG;
}
if(iPosition > 0)
{
return VFW_S_NO_MORE_ITEMS;
}

CheckPointer(pMediaType,E_POINTER);

*pMediaType = m_pInput->CurrentMediaType();
if(pMediaType->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER* hrIn = (VIDEOINFOHEADER*)pMediaType->pbFormat;
hrIn->bmiHeader.biWidth = hrIn->bmiHeader.biWidth / 2;
hrIn->bmiHeader.biHeight = hrIn->bmiHeader.biHeight * 2 ;
}
else if(pMediaType->formattype == FORMAT_VideoInfo2)
{
VIDEOINFOHEADER2* hrIn = (VIDEOINFOHEADER2*)pMediaType->pbFormat;
hrIn->bmiHeader.biWidth = hrIn->bmiHeader.biWidth / 2;
hrIn->bmiHeader.biHeight = hrIn->bmiHeader.biHeight * 2 ;
}
else
{
return E_INVALIDARG;
}
return NOERROR;

} // GetMediaType
STDMETHODIMP CContrast::get_ContrastLevel(signed char *pContrastLevel)
{
CheckPointer(pContrastLevel,E_POINTER);
CAutoLock cAutoLock(&m_ContrastLock);

*pContrastLevel = m_ContrastLevel;
return NOERROR;
} // get_ContrastLevel
STDMETHODIMP CContrast::put_ContrastLevel(signed char ContrastLevel)
{
CAutoLock cAutoLock(&m_ContrastLock);
m_ContrastLevel = ContrastLevel;
return NOERROR;
} // put_ContrastLevel
STDMETHODIMP CContrast::put_DefaultContrastLevel()
{
CAutoLock cAutoLock(&m_ContrastLock);
m_ContrastLevel = 2;
return NOERROR;
} // put_DefaultContrastLevel
STDMETHODIMP CContrast::put_UpStream(int nUpStream)
{
m_nUpStream = nUpStream;
return NOERROR;
}
BOOL CContrast::CanChangeContrastLevel(const CMediaType *pMediaType) const
{
CheckPointer(pMediaType,FALSE);

if((IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video)))
{
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB32))
{
VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)pMediaType->Format();
return (pvi->bmiHeader.biBitCount == 32);
}
else
{
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_YV12))
{
VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)pMediaType->Format();
return (pvi->bmiHeader.biBitCount == 12);
}
}
}
return FALSE;

} // CanChangeContrastLevel
HRESULT CContrast::Transform(AM_MEDIA_TYPE *pType, const signed char ContrastLevel) const
{
CheckPointer(pType,E_POINTER);
return NOERROR;
} // Transform
加载更多回复(6)

2,543

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧