求教为什么我用directshow采集的视频预览时不能正常显示
我用directshow采集视频, 中间用了一个CTransformFilter来旋转90度视频, 取出来的是RBG565,然后我再把它转成YUV420保存, 但现在出现一个问题, 那个保存下来的视频是正常的, 但是在预览的时候就画面不正确了, 应该显示出来的图象变成了一杠一杠的宽斜杠, 中间的间隔全部是黑色的.
这个代码我在其它的型号手机上是完全正常的.
我不用CTransformFilter预览画面是正常的, 我现在有点想不明白, 如果我CTransformFilter旋转90度的数据出错, 那我最终保存下来的视频也应该是宽斜杠和黑色的呀, 但现在从保存下来的视频是正常的, 那我用CTransformFilter旋转90度的数据也就是正确了,但为什么预览时会不正常呢
HRESULT BuildGraph(HWND hWnd)
{
HRESULT hr;
hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGraph);
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void **)&m_pBuilder);
hr = m_pGraph->AddFilter(m_pCap, L"Video Capture Source");
m_pBuilder->SetFiltergraph(m_pGraph);
hr = CoCreateInstance(CLSID_VideoRenderer, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
(void **)&m_pRenderP);
hr = m_pGraph->AddFilter(m_pRenderP, L"Video Render");
hr = m_pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pCap, NULL, m_pRenderP);
//IAMStreamConfig *pConfig = NULL;
//hr = m_pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
//m_pRenderP, IID_IAMStreamConfig, (void**)&pConfig);
//if (SUCCEEDED(hr))
//{
//int iCount=0,iSize=0;
//hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
//AM_MEDIA_TYPE *pmt = NULL;
//hr = pConfig->GetFormat(&pmt);
// if (SUCCEEDED(hr))
// {
// pConfig-> SetFormat(pmt);
// }
//DeleteMediaType(pmt);
//pConfig-> Release();
//}
//////////////////////////////////////////////////////////////////////////
// 添加自定义Filter
CCRotateFilter *pRollTranc = new CCRotateFilter(NULL, &hr);
pRollTranc->SetCallback(&CallbackVideo);
IBaseFilter *pTrancFilter;
hr = pRollTranc->QueryInterface(__uuidof(IBaseFilter), (void**)&pTrancFilter);
if (FAILED(hr))
{
return S_FALSE;
}
hr = m_pGraph->AddFilter(pTrancFilter, L"My Filter");
if (FAILED(hr))
{
return S_FALSE;
}
IEnumFilters* pEnum;
hr = m_pGraph->EnumFilters(&pEnum);
if (FAILED(hr))
{
return S_FALSE;
}
// 查找Renderer Filter 输入pin
IPin* pPinIn = InputPinOf(m_pRenderP);
if (!pPinIn)
{
return S_FALSE;
}
// 查找连接在Renderer Filter输入pin上的输出pin
IPin* pPinOut = NULL;
hr = pPinIn->ConnectedTo(&pPinOut);
if (FAILED(hr))
{
return S_FALSE;
}
// 断开当前pin连接
hr = m_pGraph->Disconnect(pPinOut);
if (SUCCEEDED(hr))
{
hr = m_pGraph->Disconnect(pPinIn);
}
// 通过连接输入pin和输出pin连接我们自定的filter
if (SUCCEEDED(hr))
{
IPin* pPinInXfm = InputPinOf(pTrancFilter);
hr = m_pGraph->Connect(pPinOut, pPinInXfm);
pPinInXfm->Release();
}
if (SUCCEEDED(hr))
{
IPin* pPinOutXfm = OutputPinOf(pTrancFilter);
hr = m_pGraph->Connect(pPinOutXfm, pPinIn);
pPinOutXfm->Release();
}
pPinIn->Release();
pPinOut->Release();
//////////////////////////////////////////////////////////////////////////
// 用于调试,输出graph中所有的filter,以及各filter的所有pin及其连接
EnumFilters(m_pGraph);
hr = m_pRenderP->QueryInterface(IID_IVideoWindow, (void**)&m_pVideoWindow);
// 设置视频播放的WINDOWS窗口
m_pVideoWindow->put_MessageDrain((OAHWND)hWnd);
m_pVideoWindow->put_Owner((OAHWND)hWnd);
m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
//设置视频尺寸
m_pVideoWindow->SetWindowPosition(VIDEO_SRCCEN_LEFT, VIDEO_SRCCEN_TOP, VIDEO_SRCCEN_WIDTH, VIDEO_SRCCEN_HEIGHT);
m_pVideoWindow->put_Visible(OATRUE);
pEnum->Release();
pTrancFilter->Release();
pTrancFilter = NULL;
if (pRollTranc)
{
pRollTranc->Release();
}
return hr;
}
HRESULT CCRotateFilter::Transform(IMediaSample *pSource, IMediaSample *pDest)
{
HRESULT hr = S_OK;
BYTE *pBufferIn, *pBufferOut;
hr = pSource-> GetPointer(&pBufferIn);
if (FAILED(hr))
{
return hr;
}
hr = pDest-> GetPointer(&pBufferOut);
if (FAILED(hr))
{
return hr;
}
// 直接copy, 不做转换
//memcpy(pBufferOut, pBufferIn, 2*m_lHeight*m_lWidth);
// 图像数据旋转90°(不同的机器可能旋转的方向不同,请自行调整loop变量起始值)
// 这里只支持16bit的RGB颜色空间,如RGB565,RGB555
int k = 0;
for(int i = 0; i< m_lWidth; i++)
{
for(int j = 0; j < m_lHeight; j++)
{
pBufferOut[k] = pBufferIn[2*i + j*m_cbWidth];//16bits
k++;
pBufferOut[k] = pBufferIn[2*i + j*m_cbWidth + 1];
k++;
}
}
if (m_callback)
{
REFERENCE_TIME StartTime, StopTime;
pSource->GetTime( &StartTime, &StopTime);
//long lSize = pDest->GetActualDataLength();
HRESULT hr = m_callback(pBufferOut, &StartTime, &StopTime, m_lHeight, m_lWidth, k);
return hr;
}
return NOERROR;
}
[解决办法]
输出 Pin 的类型是不是 YUV420?
[解决办法]
应该是N或P制的原因吧,强制设置为N(320x240)试一下。
[解决办法]
GetMediaType中设置下面格式就是设置为YUV播放视频,
pvi->bmiHeader.biCompression = MAKEFOURCC('I','4','2','0');
pvi->bmiHeader.biBitCount = 16;
楼主试试