美菲特官方电商平台


美菲特淘宝店铺 美菲特京东店铺
美菲特京东店铺

技术知识

wmv 解码样例程序

2014-09-16 美菲特品牌 0

  最近有些客户在使用美菲特视频采集卡中遇到一个Windows Media SDK或者Wndows SDK 7A的WMV解码问题:

  在Win7 64bit下,interlacing 的wmv 片子decode出来的YUYV视频只有色度,没有亮度。

  奇怪的问题!

  在项目修改之后,又写了以下解码样例代码来验证,确认问题的存在。

  最后的解决办法是:

  1,确定修改逻辑只作用在64bit,32bit处理逻辑保持不变

  2,分析侦测影片是否为interlaced

  3,对于64bit interlaced的片子,设置为VYUY导出,其他则保持为YUYV导出

  4,将VYUY转换成YUYV

  是微软挖了个大坑,还是调用方法有误?

  聊以记之,以观后效。
// Date: 2014-9-16

// Target: Sample code to decode first frame as UYVY of WMV

#include "stdafx.h"

#include <wmsdk.h>

#include <atlbase.h>

#pragma comment(lib,"wmvcore.lib")

 

 

int _tmain(int argc, _TCHAR* argv[])

{

HRESULT hr = S_OK;

DWORD dwStreams = 0;

DWORD dwOutputNum;

GUID pguidStreamType;

ULONG cbType = 0;

WORD wStreamNumber = 0 ;

CComPtr<IWMSyncReader> m_pReader;

bool bInterlacedAllowedIsSet = FALSE;

WMVIDEOINFOHEADER head;

WORD wVideoStreamNum = 0;

_TCHAR* ptszFile = TEXT("c:\\test.wmv");

if (argc>1)

ptszFile = argv[1];

CoInitialize(NULL);

if ( !m_pReader )

{

hr = WMCreateSyncReader( NULL, 0, (IWMSyncReader**)&m_pReader.p );

}

if ( FAILED( hr ) )

{

CoUninitialize();

return( hr );

}

hr = m_pReader->Open( ptszFile );

if ( FAILED( hr ) )

{

CoUninitialize();

return( hr );

}

 

 

//

// Get the profile interface

//

CComPtr<IWMProfile> pProfile;

hr = m_pReader->QueryInterface( IID_IWMProfile, ( VOID ** )&pProfile.p);

if ( FAILED( hr ) )

{

CoUninitialize();

return( hr );

}

hr = pProfile->GetStreamCount( &dwStreams );

for ( DWORD ix = dwStreams; ix ; --ix )

{

DWORD i=ix-1;

CComPtr<IWMStreamConfig> pStream;

hr = pProfile->GetStream( i, &pStream );

if ( FAILED( hr ) )

{

continue;

}

wStreamNumber = 0;

//

// Get the stream number of the current stream

//

hr = pStream->GetStreamNumber( &wStreamNumber );

if ( FAILED( hr ) )

{

continue;

}

hr = pStream->GetStreamType( &pguidStreamType );

if ( FAILED( hr ) )

{

continue;

}

hr = m_pReader->GetOutputNumberForStream( wStreamNumber, &dwOutputNum);

if ( FAILED( hr ) )

{

continue ;

}

DWORD dwNrFormats=0;

if (SUCCEEDED(hr=m_pReader->GetOutputFormatCount(dwOutputNum,&dwNrFormats)))

{

 

//For each supported format, call IWMReader::GetOutputFormat to retrieve the IWMOutputMediaProps interface on the output media properties object.

CComPtr<IWMOutputMediaProps> pOutputMediaProps;

for (unsigned int f=0; f<dwNrFormats; f++)

{

//Call IWMMediaProps::GetMediaType to retrieve the media type.

m_pReader->GetOutputFormat(dwOutputNum,f,&pOutputMediaProps.p);

if (FAILED( pOutputMediaProps->GetMediaType( NULL, &cbType ) ))

continue;

WM_MEDIA_TYPE* pMediaType = ( WM_MEDIA_TYPE* ) _alloca(cbType);

if (pMediaType==NULL)

continue;

if (FAILED( pOutputMediaProps->GetMediaType( pMediaType, &cbType )))

continue;

//If the retrieved media type is the desired multichannel type, then set it by calling IWMReader::SetOutputProps.

if ( pMediaType->formattype == WMFORMAT_WaveFormatEx)

{

if (pMediaType->cbFormat >= sizeof(WAVEFORMATEX) ) // type actually is WAVEFORMATEXTENSIBLE for 6 channels

{

WAVEFORMATEX* pWaveEx = (WAVEFORMATEX*)pMediaType->pbFormat;

}

}

if ( pMediaType->formattype == WMFORMAT_VideoInfo)

{

if (pMediaType->cbFormat >= sizeof(WMVIDEOINFOHEADER) ) // type actually is WAVEFORMATEXTENSIBLE for 6 channels

{

WMVIDEOINFOHEADER* pWmvVideoInfo = (WMVIDEOINFOHEADER*)pMediaType->pbFormat;

DWORD biC = pWmvVideoInfo->bmiHeader.biCompression;

if (pWmvVideoInfo->bmiHeader.biCompression == MAKEFOURCC('U','Y','V','Y')) {

m_pReader->SetOutputProps(dwOutputNum,pOutputMediaProps);

memcpy(&head, pWmvVideoInfo, sizeof(WMVIDEOINFOHEADER));

wVideoStreamNum = wStreamNumber;

}

}

}

}

}

 

// get media info

CComPtr<IWMOutputMediaProps> pProps;

hr = m_pReader->GetOutputProps( dwOutputNum, &pProps );

if( FAILED( hr ) )

{

continue;

}

// Find out the space needed for pMediaType

hr = pProps->GetMediaType( NULL, &cbType );

if( FAILED( hr ) )

{

continue;

}

WM_MEDIA_TYPE* pMediaType = ( WM_MEDIA_TYPE* ) _alloca(cbType);

if( NULL == pMediaType )

{

hr = HRESULT_FROM_WIN32( GetLastError() ) ;

continue;

}

//

// Get the value for MediaType

//

hr = pProps->GetMediaType( pMediaType, &cbType );

if( FAILED( hr ) )

{

continue;

}

if( WMMEDIATYPE_Audio == pguidStreamType )

{

//

}

else if( WMMEDIATYPE_Video == pguidStreamType )

{

BYTE allowInterlaced[4]; *(DWORD*)allowInterlaced=1;

if( SUCCEEDED(hr=m_pReader->SetOutputSetting( dwOutputNum, g_wszAllowInterlacedOutput, WMT_TYPE_BOOL, allowInterlaced,sizeof(allowInterlaced) )) )

bInterlacedAllowedIsSet = TRUE;

}

}

CComPtr<INSSBuffer> pSample;

INSSBuffer** ppSample = &pSample.p;

WMT_STREAM_SELECTION wmtSS = WMT_ON;

QWORD cnsSampleTime = 0, cnsPrevSampleTime = 0;

QWORD cnsSampleDuration = 0;

DWORD dwFlags = 0;

WORD wStreamNum = 0;

DWORD dwVideoSamplesCnt = 0;

hr = m_pReader->GetNextSample( wVideoStreamNum, ppSample,

&cnsSampleTime,

ppSample?(&cnsSampleDuration):NULL,

ppSample?(&dwFlags):NULL,

&dwOutputNum,

&wStreamNum );

BOOL m_bInterlaced = FALSE;

if (*ppSample!=NULL) {

if (bInterlacedAllowedIsSet) {

CComQIPtr<INSSBuffer3> pMS3(pSample);

if( pMS3 )

{

BYTE bufContentType[16];

memset(bufContentType,0xff,sizeof(bufContentType));

DWORD dwSize = WM_SampleExtension_ContentType_Size;

hr = pMS3->GetProperty( WM_SampleExtensionGUID_ContentType, bufContentType, &dwSize ); // bug in WMFSDK9.5: ContentType is only set if buffer was allocated by Reader itself!

if (SUCCEEDED( hr ))

m_bInterlaced = ( ((*bufContentType)&WM_CT_INTERLACED) != 0 );

 

}

}

BYTE* pbBuffer = NULL;

DWORD dwLength=0;

hr = (*ppSample)->GetBufferAndLength( &pbBuffer, &dwLength);

if ( FAILED( hr ) )

{

pbBuffer = NULL; dwLength = 0;

}

(*ppSample)->Release();

(*ppSample) = NULL;

}

if( !!m_pReader )

{

hr = m_pReader->Close();

}

m_pReader.Release();

CoUninitialize();

return 0;

}

15311325956 服务时间 周一至周五 9:00-17:00