Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Para criar um tipo de saída válido para um codificador de vídeo do Windows Media (WMV), você deve ter as seguintes informações:
- O formato do vídeo não comprimido que irá codificar.
- O subtipo de vídeo que representa o formato WMV codificado. Consulte GUIDs de subtipo de vídeo.
- A taxa de bits alvo para o fluxo codificado.
- As propriedades de configuração a serem definidas no codificador.
As propriedades de configuração estão documentadas na documentação das APIs de Codec de Áudio e Vídeo do Windows Media e de DSP. Para obter mais informações, consulte "Video Stream Properties" em Encoding Properties.
Para obter um tipo de saída válido para o codificador, execute as etapas a seguir.
Use a função MFTEnum ou a função MFTEnumEx para criar uma instância do codificador.
Consulte o codificador para a interface IPropertyStore .
Utilize a interface IPropertyStore para configurar o codificador.
Chame IMFTransform::SetInputType para definir o tipo de vídeo não compactado no codificador.
Chame IMFTransform::GetOutputAvailableType para obter a lista de formatos de compactação do codificador. Os codificadores WMV não retornam um tipo de mídia completo desse método. Os tipos de mídia estão faltando duas informações:
- A taxa de bits desejada.
- Dados de codec privados do codificador.
Antes de definir o tipo de saída no codificador, você deve adicionar ambos os itens ao tipo de mídia.
Para especificar a taxa de bits de destino, defina o atributo MF_MT_AVG_BITRATE no tipo de mídia.
Adicione os dados do codec privado ao tipo de mídia, conforme explicado na próxima seção.
Chame IMFTransform::SetOutputType para definir o tipo de mídia de compactação no codificador.
Dados Codec Privados
Os dados de codec privado são uma estrutura de dados opaca que você deve obter do codificador WMV e adicionar ao tipo de compactação, antes de definir o tipo de compactação no codificador. Para obter os dados privados, tem de utilizar a interface IWMCodecPrivateData, documentada no SDK do Windows Media Format 11.
Para obter os dados do codec privado, execute as seguintes etapas:
- Chame IMFTransform::GetOutputAvailableType para obter um tipo de mídia do codificador. (Esta é a etapa 6 da seção anterior.)
- Especifique a taxa de bits de destino definindo o atributo MF_MT_AVG_BITRATE no tipo de mídia.
- Converta o tipo de mídia em uma estrutura DMO_MEDIA_TYPE chamando a função MFInitAMMediaTypeFromMFMediaType .
- Consulte o codificador para a interface IWMCodecPrivateData.
- Chame o método IWMCodecPrivateData::SetPartialOutputType, passando a estrutura DMO_MEDIA_TYPE convertida.
- Chame o método IWMCodecPrivateData::GetPrivateData duas vezes, uma para obter o tamanho do buffer para os dados privados e outra para copiar os dados para o buffer.
- Adicione os dados privados ao tipo de mídia definindo o atributo MF_MT_USER_DATA no tipo.
O exemplo estendido a seguir mostra como criar um formato de compactação WMV a partir de um tipo de vídeo não compactado:
#include <wmcodecdsp.h>
#include <Wmsdk.h>
#include <Dmo.h>
#include <mfapi.h>
#include <uuids.h>
#include <mfidl.h>
#include <mftransform.h>
#include <mferror.h>
#pragma comment(lib, "Msdmo")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfuuid")
#pragma comment(lib, "strmiids")
#pragma comment(lib, "propsys")
HRESULT GetEncodedVideoType(
IMFMediaType *pTypeIn,
REFGUID subtype,
UINT32 TargetBitrate,
IPropertyStore *pEncoderProps,
IMFMediaType **ppEncodingType,
DWORD mftEnumFlags = MFT_ENUM_FLAG_SYNCMFT
);
HRESULT CreateVideoEncoder(REFGUID subtype, DWORD mftEnumFlags, IMFTransform **ppMFT);
HRESULT AddPrivateData(IMFTransform *pMFT, IMFMediaType *pTypeOut);
HRESULT CopyPropertyStore(IPropertyStore *pSrc, IPropertyStore *pDest);
//
// GetEncodedVideoType
// Given an uncompressed video type, finds a suitable WMV type.
//
HRESULT GetEncodedVideoType(
IMFMediaType *pTypeIn, // Uncompressed format
REFGUID subtype, // Compression format
UINT32 TargetBitrate, // Target bit rate
IPropertyStore *pEncoderProps, // Encoder properties (can be NULL)
IMFMediaType **ppEncodingType, // Receives the WMV type.
DWORD mftEnumFlags // MFTEnumEx flags
)
{
HRESULT hr = S_OK;
IMFTransform *pMFT = NULL;
IPropertyStore *pPropStore = NULL;
IMFMediaType *pTypeOut = NULL;
// Instantiate the encoder
hr = CreateVideoEncoder(subtype, mftEnumFlags, &pMFT);
// Copy the properties to the encoder.
if (SUCCEEDED(hr))
{
if (pEncoderProps)
{
hr = pMFT->QueryInterface(IID_PPV_ARGS(&pPropStore));
if (SUCCEEDED(hr))
{
hr = CopyPropertyStore(pEncoderProps, pPropStore);
}
}
}
// Set the uncompressed type.
if (SUCCEEDED(hr))
{
hr = pMFT->SetInputType(0, pTypeIn, 0);
}
// Get the partial output type
if (SUCCEEDED(hr))
{
hr = pMFT->GetOutputAvailableType(0, 0, &pTypeOut);
}
// Set the bit rate.
// You must set this before getting the codec private data.
if (SUCCEEDED(hr))
{
hr = pTypeOut->SetUINT32(MF_MT_AVG_BITRATE, TargetBitrate);
}
if (SUCCEEDED(hr))
{
hr = AddPrivateData(pMFT, pTypeOut);
}
if (SUCCEEDED(hr))
{
hr = pMFT->SetOutputType(0, pTypeOut, 0);
}
if (SUCCEEDED(hr))
{
*ppEncodingType = pTypeOut;
(*ppEncodingType)->AddRef();
}
SafeRelease(&pMFT);
SafeRelease(&pPropStore);
SafeRelease(&pTypeOut);
return hr;
}
A função CreateVideoEncoder cria um codificador de vídeo para um subtipo de vídeo especificado, como MFVideoFormat_WMV3:
//
// CreateVideoEncoder
// Creates a video encoder for a specified video subtype.
//
HRESULT CreateVideoEncoder(
REFGUID subtype, // Encoding subtype.
DWORD mftEnumFlags, // Flags for MFTEnumEx
IMFTransform **ppMFT // Receives a pointer to the encoder.
)
{
HRESULT hr = S_OK;
IMFTransform *pMFT = NULL;
MFT_REGISTER_TYPE_INFO info;
info.guidMajorType = MFMediaType_Video;
info.guidSubtype = subtype;
IMFActivate **ppActivates = NULL;
UINT32 count = 0;
hr = MFTEnumEx(
MFT_CATEGORY_VIDEO_ENCODER,
mftEnumFlags | MFT_ENUM_FLAG_SORTANDFILTER,
NULL,
&info,
&ppActivates,
&count
);
if (count == 0)
{
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
hr = ppActivates[0]->ActivateObject(
__uuidof(IMFTransform),
(void**)&pMFT
);
}
if (SUCCEEDED(hr))
{
*ppMFT = pMFT;
(*ppMFT)->AddRef();
}
// Clean up
for (DWORD i = 0; i < count; i++)
{
ppActivates[i]->Release();
}
CoTaskMemFree(ppActivates);
SafeRelease(&pMFT);
return hr;
}
A função AddPrivateData adiciona os dados do codec privado ao tipo de compactação:
//
// AddPrivateData
// Appends the private codec data to a media type.
//
// pMFT: The video encoder
// pTypeOut: A video type from the encoder's type list.
//
// The function modifies pTypeOut by adding the codec data.
//
HRESULT AddPrivateData(IMFTransform *pMFT, IMFMediaType *pTypeOut)
{
HRESULT hr = S_OK;
ULONG cbData = 0;
BYTE *pData = NULL;
IWMCodecPrivateData *pPrivData = NULL;
DMO_MEDIA_TYPE mtOut = { 0 };
// Convert the type to a DMO type.
hr = MFInitAMMediaTypeFromMFMediaType(
pTypeOut,
FORMAT_VideoInfo,
(AM_MEDIA_TYPE*)&mtOut
);
if (SUCCEEDED(hr))
{
hr = pMFT->QueryInterface(IID_PPV_ARGS(&pPrivData));
}
if (SUCCEEDED(hr))
{
hr = pPrivData->SetPartialOutputType(&mtOut);
}
//
// Get the private codec data
//
// First get the buffer size.
if (SUCCEEDED(hr))
{
hr = pPrivData->GetPrivateData(NULL, &cbData);
}
if (SUCCEEDED(hr))
{
pData = new BYTE[cbData];
if (pData == NULL)
{
hr = E_OUTOFMEMORY;
}
}
// Now get the data.
if (SUCCEEDED(hr))
{
hr = pPrivData->GetPrivateData(pData, &cbData);
}
// Add the data to the media type.
if (SUCCEEDED(hr))
{
hr = pTypeOut->SetBlob(MF_MT_USER_DATA, pData, cbData);
}
delete [] pData;
MoFreeMediaType(&mtOut);
SafeRelease(&pPrivData);
return hr;
}
A função CopyPropertyStore é uma função auxiliar que copia propriedades de um repositório de propriedades para outro:
//
// CopyPropertyStore
// Helper function to copy properties from one property
// store to another property store.
//
HRESULT CopyPropertyStore(IPropertyStore *pSrc, IPropertyStore *pDest)
{
HRESULT hr = S_OK;
DWORD cProps = 0;
PROPERTYKEY key;
PROPVARIANT var;
PropVariantInit(&var);
hr = pSrc->GetCount(&cProps);
if (SUCCEEDED(hr))
{
for (DWORD i = 0; i < cProps; i++)
{
hr = pSrc->GetAt(i, &key);
if (FAILED(hr)) { break; }
hr = pSrc->GetValue(key, &var);
if (FAILED(hr)) { break; }
hr = pDest->SetValue(key, var);
if (FAILED(hr)) { break; }
PropVariantClear(&var);
}
}
PropVariantClear(&var);
return hr;
}
Tópicos relacionados