📄 videoenc.cpp
字号:
//*@@@+++@@@@******************************************************************
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//*@@@---@@@@******************************************************************
//
// Interlace encoding mode is disabled by default.
// Interlace WMV 9 (4cc WMV3) bit streams should not
// currently be created in AVI, because AVI does not
// provide the ability to specify top-field-first or
// bottom-field-first at frame level. However, the code
// is provided in case the user may want to wrap interlace
// WMV 9 streams in other file formats.
//
#include "stdafx.h"
#include <strmif.h>
#include "baseclasses/amvideo.h"
#include <uuids.h>
#include "baseclasses/dvdmedia.h"
#include <wmcodeciface.h>
#include "wmsbuffer.h"
#include "encappErr.h"
#include "videoenc.h"
#include "encode.h"
//////////////////////////////////////////////////////////////////////////////
HRESULT MakeVideoOutputType(IMediaObject *pDMO,
AM_MEDIA_TYPE *pmtIn,
VideoEncParams *pParams,
AM_MEDIA_TYPE *pmt )
{
HRESULT hr = S_OK;
VIDEOINFOHEADER2 *pvih2 = NULL;
VIDEOINFOHEADER vih;
IWMCodecPrivateData *pWMCodecPrivateData = NULL;
DWORD cbPrivateData = 0;
BYTE *pbPrivateData = NULL;
BYTE *pNewFormat = NULL;
if( NULL == pDMO ||
NULL == pmtIn ||
NULL == pParams ||
NULL == pmt )
{
return ( E_INVALIDARG );
}
if( NULL == pmtIn->pbFormat || pmtIn->cbFormat < sizeof( VIDEOINFOHEADER ) )
{
return ( E_INVALIDARG );
}
// make up a partial media type
pmt->majortype = MEDIATYPE_Video;
pmt->formattype = FORMAT_VideoInfo;
pmt->bFixedSizeSamples = FALSE;
pmt->bTemporalCompression = TRUE;
if( pmtIn->formattype == FORMAT_VideoInfo )
{
vih = *(VIDEOINFOHEADER*)pmtIn->pbFormat;
}
else if( pmtIn->formattype == FORMAT_VideoInfo2 )
{
pvih2 = (VIDEOINFOHEADER2*)pmtIn->pbFormat;
vih.rcSource = pvih2->rcSource;
vih.rcTarget = pvih2->rcTarget;
vih.AvgTimePerFrame = pvih2->AvgTimePerFrame;
vih.bmiHeader = pvih2->bmiHeader;
}
else
return ( E_VIDEO_INVALID_INPUT_TYPE );
vih.dwBitRate = (DWORD)pParams->nBitrate;
vih.dwBitErrorRate = 0;
vih.bmiHeader.biPlanes = 1;
vih.bmiHeader.biBitCount = 24;
pmt->subtype = WMCMEDIASUBTYPE_WMV1;
pmt->subtype.Data1=pParams->dwTag;
vih.bmiHeader.biCompression = pParams->dwTag;
//
//use the partial format above to get the private data
//
pmt->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof( VIDEOINFOHEADER));
memcpy( pmt->pbFormat , &vih, sizeof( VIDEOINFOHEADER));
pmt->cbFormat = sizeof( vih );
do
{
hr = pDMO->QueryInterface(IID_IWMCodecPrivateData, (void**)&pWMCodecPrivateData);
if( FAILED( hr ) )
{
hr = E_NO_PRIVATE_DATA;
break;
}
hr = pWMCodecPrivateData->SetPartialOutputType( pmt );
if( FAILED( hr ) )
{
hr = E_PARTIAL_TYPE_REJECTED;
break;
}
hr = pWMCodecPrivateData->GetPrivateData( NULL, &cbPrivateData );
if( FAILED( hr ) )
{
hr = E_NO_PRIVATE_DATA_COUNT;
break;
}
if( 0 == cbPrivateData )
{ // No private data
hr = S_OK;
break;
}
pbPrivateData = new BYTE[ cbPrivateData ];
if( pbPrivateData == NULL )
{
hr = E_OUTOFMEMORY;
break;
}
//
// get the private data
//
hr = pWMCodecPrivateData->GetPrivateData( pbPrivateData, &cbPrivateData );
if( FAILED( hr ) )
{
hr = E_PRIVATE_DATA_FAILED;
break;
}
//
//modify the media type accordingly
//
pNewFormat = (BYTE*)CoTaskMemAlloc( sizeof( VIDEOINFOHEADER) + cbPrivateData );
if( NULL == pNewFormat )
{
hr = E_OUTOFMEMORY;
break;
}
memcpy( pNewFormat, pmt->pbFormat, sizeof( VIDEOINFOHEADER));
CoTaskMemFree(pmt->pbFormat);
memcpy( pNewFormat + sizeof( VIDEOINFOHEADER), pbPrivateData, cbPrivateData);
pmt->pbFormat = pNewFormat;
pmt->cbFormat = sizeof( VIDEOINFOHEADER) + cbPrivateData;
((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biSize += cbPrivateData;
((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biClrUsed = 0;
((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biClrImportant = 0;
((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biXPelsPerMeter = 0;
((VIDEOINFOHEADER*)pmt->pbFormat)->bmiHeader.biYPelsPerMeter = 0;
}
while( FALSE );
SAFERELEASE( pWMCodecPrivateData );
SAFEDELETE( pbPrivateData );
return ( hr );
}
//////////////////////////////////////////////////////////////////////////////
HRESULT SetVideoTypes( IMediaObject *pDMO, \
AM_MEDIA_TYPE *pmtIn, \
VideoEncParams *pParams, \
AM_MEDIA_TYPE *pmtOut, \
DWORD *pcbIn, \
DWORD *pcbOut )
{
HRESULT hr;
DWORD dwDummy;
hr = pDMO->SetInputType(0, pmtIn, 0);
if( S_OK != hr )
{
return ( hr );
}
hr = MakeVideoOutputType( pDMO, pmtIn, pParams, pmtOut );
if( FAILED( hr ) )
{
return ( hr );
}
hr = pDMO->SetOutputType(0, pmtOut, 0);
if( S_OK != hr )
{
return ( hr );
}
hr = pDMO->GetInputSizeInfo( 0, pcbIn, &dwDummy, &dwDummy);
if( FAILED(hr) )
{
return ( hr );
}
hr = pDMO->GetOutputSizeInfo( 0, pcbOut, &dwDummy);
if( FAILED( hr ) )
{
return ( hr );
}
return ( hr == S_FALSE ? E_VIDEO_TYPE_NOT_SET: hr );
}
//////////////////////////////////////////////////////////////////////////////
HRESULT SetVideoParams( IMediaObject *pDMO, VideoEncParams *pParams )
{
HRESULT hr;
VARIANT varg;
IPropertyBag *pPropertyBag = NULL;
if( NULL == pDMO || NULL == pParams )
{
return ( E_INVALIDARG );
}
do
{
//
// Get the IPropertyBag IF and set the appropriate params
//
hr = pDMO->QueryInterface(IID_IPropertyBag, (void**)&pPropertyBag);
if( FAILED( hr ) )
{
break;
}
//
//set the encoder in VBR mode if required
//
if( pParams->fIsVBR == TRUE )
{
::VariantInit(&varg);
varg.vt = VT_BOOL;
varg.boolVal = TRUE;
hr = pPropertyBag->Write( g_wszWMVCVBREnabled, &varg );
if( FAILED( hr ) )
{
hr = E_VIDEO_VBR_NOT_SUPPORTED;
break;
}
//
// if it is 1 pass VBR set the Quality param
//
if( pParams->nPasses == 1 )
{
::VariantInit(&varg);
varg.vt = VT_I4;
varg.lVal = pParams->nVBRQuality;
hr = pPropertyBag->Write( g_wszWMVCVBRQuality, &varg );
if( FAILED( hr ) )
{
hr = E_VBR_QUALITY_REJECTED;
break;
}
}
}
//
//set the number of passes
//
if( pParams->nPasses > 1 )
{
::VariantInit(&varg);
varg.vt = VT_I4;
varg.lVal = pParams->nPasses;
hr = pPropertyBag->Write( g_wszWMVCPassesUsed, &varg );
if( FAILED( hr ) )
{
hr = E_VIDEO_NPASS_NOT_SUPPORTED;
break;
}
}
//
// set the bitrate for all the modes except 1 pass VBR
//
if( !( pParams->fIsVBR == TRUE && pParams->nPasses == 1 ) )
{
::VariantInit(&varg);
varg.vt = VT_I4;
varg.lVal = pParams->nBitrate;
hr = pPropertyBag->Write( g_wszWMVCAvgBitrate, &varg );
if( FAILED( hr ) )
{
hr = E_VIDEO_BITRATE_REJECTED;
break;
}
}
//
// set the buffer window
//
::VariantInit(&varg);
varg.vt = VT_I4;
varg.lVal = pParams->nBufferDelay;
hr = pPropertyBag->Write( g_wszWMVCVideoWindow, &varg );
if( FAILED( hr ) )
{
hr = E_VIDEO_BUFFER_REJECTED;
break;
}
if( pParams->fIsConstrained == TRUE )
{
::VariantInit(&varg);
varg.vt = VT_I4;
varg.lVal = pParams->nPeakBitrate;
hr = pPropertyBag->Write( g_wszWMVCMaxBitrate, &varg );
if( FAILED( hr ) )
{
hr = E_VIDEO_PEAK_BITRATE_REJECTED;
break;
}
::VariantInit(&varg);
varg.vt = VT_I4;
varg.lVal = pParams->nPeakBuffer;
hr = pPropertyBag->Write( g_wszWMVCBMax, &varg );
if( FAILED( hr ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -