📄 genprofile_lib.cpp
字号:
//*****************************************************************************
//
// Microsoft Windows Media
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// FileName: GenProfile_lib.cpp
//
// Abstract: The implementation for the GenProfile static library.
//
//*****************************************************************************
#include "stdafx.h"
#include <assert.h>
#include "GenProfile_lib.h"
#include "Twmv9dll.h"
#define SAFE_RELEASE( x ) \
if ( x ) \
{ \
x->Release(); \
x = NULL; \
}
#define SAFE_ADDREF( x ) \
if ( x ) \
{ \
x->AddRef(); \
}
#define SAFE_DELETE( x ) \
if ( x ) \
{ \
delete x; \
x = NULL; \
}
#define SAFE_ARRAYDELETE( x ) \
if ( x ) \
{ \
delete[] x; \
x = NULL; \
}
#define SAFE_SYSFREESTRING( x ) \
if ( x ) \
{ \
SysFreeString( x ); \
x = NULL; \
}
#define SAFE_CLOSEHANDLE( x ) \
if ( x && INVALID_HANDLE_VALUE != x ) \
{ \
CloseHandle( x ); \
x = NULL; \
}
struct PIXEL_FORMAT
{
const GUID* guidFormat;
DWORD dwFourCC;
WORD wBitsPerPixel;
};
PIXEL_FORMAT PixelFormats[] =
{
{ &WMMEDIASUBTYPE_RGB555, BI_RGB, 16 },
{ &WMMEDIASUBTYPE_RGB24, BI_RGB, 24 },
{ &WMMEDIASUBTYPE_RGB32, BI_RGB, 32 },
{ &WMMEDIASUBTYPE_I420, 0x30323449, 12 },
{ &WMMEDIASUBTYPE_IYUV, 0x56555949, 12 },
{ &WMMEDIASUBTYPE_YV12, 0x32315659, 12 },
{ &WMMEDIASUBTYPE_YUY2, 0x32595559, 16 },
{ &WMMEDIASUBTYPE_UYVY, 0x59565955, 16 },
{ &WMMEDIASUBTYPE_YVYU, 0x55595659, 16 }
};
DWORD WaveFrequency[] =
{
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
};
//------------------------------------------------------------------------------
// Name: CopyMediaType()
// Desc: Allocates memory for a WM_MEDIA_TYPE and its format data and
// copies an existing media type into it.
//------------------------------------------------------------------------------
STDMETHODIMP CopyMediaType( WM_MEDIA_TYPE** ppmtDestination,
WM_MEDIA_TYPE* pmtSource )
{
if ( !ppmtDestination )
{
return E_POINTER;
}
if ( !pmtSource )
{
return E_NOTIMPL;
}
//
// Create enough space for the media type and its format data
//
*ppmtDestination = (WM_MEDIA_TYPE*) new BYTE[ sizeof( WM_MEDIA_TYPE ) + pmtSource->cbFormat ];
if ( !*ppmtDestination)
{
return E_OUTOFMEMORY;
}
//
// Copy the media type and the format data
//
memcpy( *ppmtDestination, pmtSource, sizeof( WM_MEDIA_TYPE ) );
(*ppmtDestination)->pbFormat = ( ((BYTE*) *ppmtDestination) + sizeof( WM_MEDIA_TYPE ) ); // Format data is immediately after media type
memcpy( (*ppmtDestination)->pbFormat, pmtSource->pbFormat, pmtSource->cbFormat );
return S_OK;
}
//------------------------------------------------------------------------------
// Name: EnsureIWMCodecInfo3()
// Desc: Creates an IWMCodecInfo3 interface if none exists, and ensures
// an outstanding reference either way. This way the IWMCodecInfo3
// object is guaranteed to exist and isn't released too many times.
//------------------------------------------------------------------------------
STDMETHODIMP EnsureIWMCodecInfo3( Twmv9dll *dll,IWMCodecInfo3** ppCodecInfo3 )
{
HRESULT hr = S_OK;
if ( !ppCodecInfo3 )
{
return E_POINTER;
}
do
{
if ( !*ppCodecInfo3 )
{
//
// Create a new IWMCodecInfo3 object
//
IWMProfileManager* pProfileManager;
hr = dll->WMCreateProfileManager( &pProfileManager );
if ( FAILED( hr ) )
{
break;
}
assert( pProfileManager );
hr = pProfileManager->QueryInterface( IID_IWMCodecInfo3, (void**) ppCodecInfo3 );
SAFE_RELEASE( pProfileManager );
if ( FAILED( hr ) )
{
break;
}
}
else
{
//
// Add a reference to the existing object, so that it won't be destroyed during cleanup
//
SAFE_ADDREF( (*ppCodecInfo3) );
}
assert( *ppCodecInfo3 );
//
// It should now not matter if the IWMCodecInfo3 was just created or was passed in
//
}
while ( FALSE );
return hr;
}
//------------------------------------------------------------------------------
// Name: SetCodecVBRSettings()
// Desc: Enables VBR with the specified number of passes, or disables it.
//------------------------------------------------------------------------------
STDMETHODIMP SetCodecVBRSettings( IWMCodecInfo3* pCodecInfo3,
GUID guidCodecType,
DWORD dwCodecIndex,
BOOL fIsVBR,
DWORD dwVBRPasses )
{
HRESULT hr;
if ( !pCodecInfo3 )
{
return E_INVALIDARG;
}
do
{
//
// Configure the codec to use or not use VBR as requested
//
hr = pCodecInfo3->SetCodecEnumerationSetting( guidCodecType, dwCodecIndex, g_wszVBREnabled, WMT_TYPE_BOOL, (BYTE*) &fIsVBR, sizeof( BOOL ) );
if ( FAILED( hr ) )
{
//
// If VBR is requested, then it's a problem, but otherwise the codec may just not support VBR
//
if ( ( !fIsVBR ) && ( NS_E_UNSUPPORTED_PROPERTY == hr ) )
{
hr = S_OK;
}
else
{
break;
}
}
if ( fIsVBR )
{
hr = pCodecInfo3->SetCodecEnumerationSetting( guidCodecType, dwCodecIndex, g_wszNumPasses, WMT_TYPE_DWORD, (BYTE*) &dwVBRPasses, sizeof( DWORD ) );
if ( FAILED( hr ) )
{
break;
}
}
}
while ( FALSE );
return hr;
}
//------------------------------------------------------------------------------
// Name: SetStreamLanguage()
// Desc: Sets the language in the stream configuration.
//------------------------------------------------------------------------------
/*
STDMETHODIMP SetStreamLanguage( IWMStreamConfig * pStreamConfig, LCID dwLanguage )
{
HRESULT hr = S_OK;
IWMStreamConfig3 * pStreamConfig3 = NULL;
IMultiLanguage * pMLang = NULL;
BSTR bstrLanguage = NULL;
do
{
hr = CoCreateInstance( CLSID_CMultiLanguage,
NULL,
CLSCTX_ALL,
IID_IMultiLanguage,
(VOID **) &pMLang );
if( FAILED( hr ) )
{
break;
}
hr = pMLang->GetRfc1766FromLcid( dwLanguage, &bstrLanguage );
if( FAILED( hr ) )
{
break;
}
hr = pStreamConfig->QueryInterface( IID_IWMStreamConfig3, (void**)&pStreamConfig3 );
if( FAILED( hr ) )
{
break;
}
hr = pStreamConfig3->SetLanguage( bstrLanguage );
if( FAILED( hr ) )
{
break;
}
}
while (FALSE);
SAFE_RELEASE( pMLang );
SAFE_RELEASE( pStreamConfig3 );
if ( !bstrLanguage )
{
SysFreeString( bstrLanguage );
}
return hr;
}
*/
/*
** Functions that create media types for the various stream types
*/
//------------------------------------------------------------------------------
// Name: CreateUncompressedAudioMediaType()
// Desc: Initializes a WM_MEDIA_TYPE for uncompressed audio.
//------------------------------------------------------------------------------
STDMETHODIMP CreateUncompressedAudioMediaType( WM_MEDIA_TYPE** ppmtMediaType,
DWORD dwSamplesPerSecond,
WORD wNumChannels,
WORD wBitsPerSample )
{
HRESULT hr = S_OK;
WM_MEDIA_TYPE mtUncompressedAudio;
WAVEFORMATEX wfxUncompressedAudio;
if ( !ppmtMediaType )
{
return E_POINTER;
}
//
// pCodecInfo3 is allowed to be NULL, since CreateMediatypeForFormat calls EnsureIWMCodecInfo3
//
do
{
//
// Setup the local copy of the uncompressed media type
//
ZeroMemory( &mtUncompressedAudio, sizeof( mtUncompressedAudio ) );
mtUncompressedAudio.majortype = WMMEDIATYPE_Audio;
mtUncompressedAudio.subtype = WMMEDIASUBTYPE_PCM;
mtUncompressedAudio.bFixedSizeSamples = TRUE;
mtUncompressedAudio.bTemporalCompression = FALSE;
mtUncompressedAudio.lSampleSize = wNumChannels * wBitsPerSample / 8;
mtUncompressedAudio.formattype = WMFORMAT_WaveFormatEx;
mtUncompressedAudio.pUnk = NULL;
mtUncompressedAudio.cbFormat = sizeof( WAVEFORMATEX );
mtUncompressedAudio.pbFormat = (BYTE*) &wfxUncompressedAudio;
//
// Configure the WAVEFORMATEX structure for the uncompressed audio
//
ZeroMemory( &wfxUncompressedAudio, sizeof( wfxUncompressedAudio ) );
wfxUncompressedAudio.wFormatTag = 1;
wfxUncompressedAudio.nChannels = wNumChannels;
wfxUncompressedAudio.nSamplesPerSec = dwSamplesPerSecond;
wfxUncompressedAudio.nAvgBytesPerSec = dwSamplesPerSecond * ( wNumChannels * wBitsPerSample / 8 );
wfxUncompressedAudio.nBlockAlign = wNumChannels * wBitsPerSample / 8;
wfxUncompressedAudio.wBitsPerSample = wBitsPerSample;
wfxUncompressedAudio.cbSize = sizeof( WAVEFORMATEX );
//
// Return a copy of the media type to the caller, since the mediatype is on the stack
//
hr = CopyMediaType( ppmtMediaType, &mtUncompressedAudio );
if ( FAILED( hr ) )
{
break;
}
}
while( FALSE );
return( hr );
}
//------------------------------------------------------------------------------
// Name: CreateVideoMediaType()
// Desc: Initializes a WM_MEDIA_TYPE for video.
//------------------------------------------------------------------------------
STDMETHODIMP CreateVideoMediaType( Twmv9dll *dll,
WM_MEDIA_TYPE** ppmtMediaType,
IWMCodecInfo3* pCodecInfo3,
DWORD dwCodecIndex,
double dFPS,
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBitrate,
BOOL fIsVBR,
DWORD dwNumberOfPasses )
{
HRESULT hr = S_OK;
WM_MEDIA_TYPE *pMediaType = NULL;
WMVIDEOINFOHEADER *pVIH;
if ( !ppmtMediaType )
{
return E_POINTER;
}
//
// pCodecInfo3 is allowed to be NULL, since CreateMediatypeForFormat calls EnsureIWMCodecInfo3
//
do
{
//
// Get the mediatype for the codec
//
hr = CreateMediatypeForFormat( dll,
&pMediaType,
pCodecInfo3,
NULL,
WMMEDIATYPE_Video,
dwCodecIndex,
0,
fIsVBR,
dwNumberOfPasses );
if( FAILED( hr ) )
{
break;
}
assert( pMediaType );
//
// Configure the WMVIDEOINFOHEADER structure of the media type
//
pVIH = (WMVIDEOINFOHEADER*) pMediaType->pbFormat;
pVIH->dwBitRate = dwBitrate;
pVIH->rcSource.right = dwWidth;
pVIH->rcSource.bottom = dwHeight;
pVIH->rcTarget.right = dwWidth;
pVIH->rcTarget.bottom = dwHeight;
pVIH->bmiHeader.biWidth = dwWidth;
pVIH->bmiHeader.biHeight = dwHeight;
pVIH->AvgTimePerFrame = ( (LONGLONG) 10000000 ) / ( (LONGLONG) dFPS );
//
// Return a copy of the media type to the caller
//
hr = CopyMediaType( ppmtMediaType, pMediaType );
if ( FAILED( hr ) )
{
break;
}
}
while( FALSE );
SAFE_ARRAYDELETE( pMediaType );
return( hr );
}
//------------------------------------------------------------------------------
// Name: CreateUncompressedVideoMediaType()
// Desc: Initializes a WM_MEDIA_TYPE for uncompressed video.
//------------------------------------------------------------------------------
STDMETHODIMP CreateUncompressedVideoMediaType( WM_MEDIA_TYPE** ppmtMediaType,
GUID guidFormat,
DWORD dwFourCC,
WORD wBitsPerPixel,
BYTE* pbPaletteData,
DWORD cbPaletteDataSize,
DWORD dwFPS,
DWORD dwWidth,
DWORD dwHeight )
{
const DWORD BITFIELD_DATA_SIZE = sizeof( RGBQUAD ) * 3;
HRESULT hr;
WM_MEDIA_TYPE mtUncompressedVideo;
WMVIDEOINFOHEADER* pvihUncompressedVideo;
BYTE* pbFormatData = NULL;
DWORD dwFormatDataSize;
DWORD dwMaxColors;
BOOL fPalettePresent;
BYTE* pbPostVIHData;
DWORD cbExpectedPostVIHDataSize;
BOOL fBitfieldsPresent;
if ( !ppmtMediaType )
{
return E_POINTER;
}
//
// pCodecInfo3 is allowed to be NULL, since CreateMediatypeForFormat calls EnsureIWMCodecInfo3
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -