IltmmWMProfile::AddStream Example for C
For complete code, refer to the CNVWM demo.
#include "amvideo.h"
void AddAudioStream(IltmmWMProfileManager *pManager, IltmmWMProfile *pProfile, int nStreamNum, int nFormatTag, long lPrefBitrate, long lSamplesPerSec, int nChannels, BOOL bWithVideo)
{
IltmmWMStreamConfig *pCodecFormat = NULL;
IltmmMediaTypeDisp *pMediaType = NULL;
WAVEFORMATEX wfex ;
BOOL bCandidate;
WAVEFORMATEX candidatewfex;
IltmmMediaTypeDisp *pCandidatemt = NULL;
IltmmMediaTypeDisp *pMt = NULL;
IltmmWMStreamConfig *pStream = NULL;
long codecs;
long formats;
long lSize;
BYTE *pArrayData = NULL;
HRESULT hr;
int codecindex;
int formatindex;
BSTR bstrData;
long diff;
BSTR stringData;
BSTR stringData2;
bCandidate = FALSE;
// get the number of audio codecs
IltmmWMProfileManager__getCodecInfoCount(pManager, /*MEDIATYPE_Audio*/L"{73647561-0000-0010-8000-00AA00389B71}", &codecs);
// search for matching codec
for(codecindex = 0; codecindex < codecs; codecindex++)
{
IltmmWMProfileManager__getCodecFormatCount(pManager, /*MEDIATYPE_Audio*/L"{73647561-0000-0010-8000-00AA00389B71}", codecindex, &formats);
for(formatindex = 0; formatindex < formats; formatindex++)
{
if(pCodecFormat)
{
IltmmWMStreamConfig_Release(pCodecFormat);
pCodecFormat = NULL;
}
hr = IltmmWMProfileManager__getCodecFormat(pManager, /*MEDIATYPE_Audio*/L"{73647561-0000-0010-8000-00AA00389B71}", codecindex, formatindex, &pCodecFormat);
if(pMediaType)
{
IltmmMediaTypeDisp_Release(pMediaType);
pMediaType = NULL;
}
hr = IltmmWMStreamConfig__getMediaType(pCodecFormat, &pMediaType);
IltmmMediaTypeDisp__get_FormatType(pMediaType, &bstrData);
if (!wcscmp(_wcsupr(bstrData), /*FORMAT_WaveFormatEx*/L"{05589F81-C356-11CE-BF01-00AA0055595A}"))
{
VARIANT var;
IltmmMediaTypeDisp__get_Format (pMediaType, &var);
SafeArrayAccessData(V_ARRAY(&var), (void**) &pArrayData);
lSize = var.parray->cbElements * var.parray->rgsabound->cElements;
CopyWaveFormatEx(&wfex, pArrayData);
SafeArrayUnaccessData(V_ARRAY(&var));
VariantClear(&var);
diff = (wfex.nAvgBytesPerSec * 8 - lPrefBitrate);
if(diff < 250 &&
diff > -250 &&
wfex.nSamplesPerSec == (unsigned int)lSamplesPerSec &&
wfex.nChannels == nChannels &&
wfex.wFormatTag == nFormatTag)
{
if(bCandidate)
{
if(bWithVideo)
{
//
// For audio/video configurations,
// we want to
// find the smaller blockalign.
// In this case,
// the blockalign is larger, so we want to
// use the old format.
//
if (wfex.nBlockAlign <= candidatewfex.nBlockAlign)
{
memcpy(&candidatewfex, &wfex, sizeof(WAVEFORMATEX));
pCandidatemt = pMediaType;
}
}
else
{
if (wfex.nBlockAlign >= candidatewfex.nBlockAlign)
{
memcpy(&candidatewfex, &wfex, sizeof(WAVEFORMATEX));
pCandidatemt = pMediaType;
}
}
}
else
{
bCandidate = TRUE;
memcpy(&candidatewfex, &wfex, sizeof(WAVEFORMATEX));
pCandidatemt = pMediaType;
}
}
}
}
}
if(bCandidate)
{
VARIANT var;
// modify the selected codec to support this bitrate and format
CoCreateInstance(&CLSID_ltmmMediaType,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IltmmMediaTypeDisp,
(void**) &pMt);
IltmmMediaTypeDisp__put_Type(pMt, /*MEDIATYPE_Audio*/L"{73647561-0000-0010-8000-00AA00389B71}");
stringData = SysAllocStringLen(L"00000000", 150);
stringData2 = SysAllocStringLen(L"{", 150);
swprintf(stringData, L"%0 8X", 353);
wcscat(stringData2, stringData);
wcscat(stringData2, L"-0000-0010-8000-00AA00389B71}");
IltmmMediaTypeDisp__put_Subtype(pMt, stringData2);
IltmmMediaTypeDisp__put_FixedSizeSamples(pMt, TRUE);
IltmmMediaTypeDisp__put_TemporalCompression(pMt, FALSE);
IltmmMediaTypeDisp__put_SampleSize(pMt, candidatewfex.nBlockAlign);
IltmmMediaTypeDisp__put_FormatType(pMt, /*FORMAT_WaveFormatEx*/L"{05589F81-C356-11CE-BF01-00AA0055595A}");
IltmmMediaTypeDisp__get_Format (pCandidatemt, &var);
IltmmMediaTypeDisp_SetFormatData(pMt, -1, var);
IltmmWMProfile_CreateNewStream(pProfile, /*MEDIATYPE_Audio*/L"{73647561-0000-0010-8000-00AA00389B71}", &pStream);
IltmmWMStreamConfig__put_StreamNumber (pStream, nStreamNum);
IltmmWMStreamConfig__put_StreamName(pStream, L"Audio Stream");
IltmmWMStreamConfig__put_ConnectionName (pStream, L"Audio");
IltmmWMStreamConfig__put_Bitrate(pStream, candidatewfex.nAvgBytesPerSec * 8);
IltmmWMStreamConfig_SetMediaType (pStream, pMt);
IltmmWMProfile_AddStream(pProfile, pStream);
IltmmMediaTypeDisp_Release(pMt);
IltmmWMStreamConfig_Release(pStream);
IltmmMediaTypeDisp_Release(pCandidatemt);
}
if(pCodecFormat)
{
IltmmWMStreamConfig_Release(pCodecFormat);
pCodecFormat = NULL;
}
if(pMediaType)
{
IltmmMediaTypeDisp_Release(pMediaType);
pMediaType = NULL;
}
}
void AddVideoStream(IltmmWMProfileManager *pManager ,
IltmmWMProfile *pProfile,
int nStreamNum,
long lFourCC,
long lBitrate,
long lWidth,
long lHeight,
long lFps,
long lQuality,
long lSecperKey)
{
USES_CONVERSION;
IltmmWMStreamConfig *pCodecFormat = NULL;
IltmmMediaTypeDisp *pMediaType = NULL;
VIDEOINFOHEADER vih;
BOOL bCandidate;
VIDEOINFOHEADER candidatevih;
IltmmMediaTypeDisp *pCandidateMt = NULL;
IltmmWMStreamConfig *pCandidateStream = NULL;
long codecs;
long formats;
BSTR bstrData;
BYTE *pArrayData = NULL;
int codecindex;
int formatindex;
VARIANT var;
SAFEARRAY sa;
struct
{
LONG lowpart;
LONG highpart;
} Num64;
bCandidate = FALSE;
// get the number of video codecs
IltmmWMProfileManager__getCodecInfoCount(pManager, /*MEDIATYPE_Video*/ L"{73646976-0000-0010-8000-00AA00389B71}", &codecs);
// search for matching codec
for(codecindex = 0; codecindex < codecs; codecindex++)
{
IltmmWMProfileManager__getCodecFormatCount (pManager, /*MEDIATYPE_Video*/ L"{73646976-0000-0010-8000-00AA00389B71}", codecindex, &formats);
#ifdef DEBUG
IltmmWMProfileManager__getCodecName(pManager, /*MEDIATYPE_Video*/ L"{73646976-0000-0010-8000-00AA00389B71}", codecindex, &bstrData);
OutputDebugString(OLE2A(bstrData));
SysFreeString(bstrData);
#endif
for(formatindex = 0; formatindex < formats; formatindex++)
{
if(pCodecFormat)
{
IltmmWMStreamConfig_Release(pCodecFormat);
pCodecFormat = NULL;
}
IltmmWMProfileManager__getCodecFormat (pManager, /*MEDIATYPE_Video*/ L"{73646976-0000-0010-8000-00AA00389B71}", codecindex, formatindex, &pCodecFormat);
if(pMediaType)
{
IltmmMediaTypeDisp_Release(pMediaType);
pMediaType = NULL;
}
IltmmWMStreamConfig__getMediaType (pCodecFormat, &pMediaType);
#ifdef _DEBUG
IltmmWMProfileManager__getCodecFormatDesc(pManager, /*MEDIATYPE_Video*/ L"{73646976-0000-0010-8000-00AA00389B71}", codecindex, formatindex, &bstrData);
OutputDebugString(OLE2A(bstrData));
SysFreeString(bstrData);
#endif
IltmmMediaTypeDisp__get_FormatType (pMediaType, &bstrData);
if (!wcscmp(_wcsupr(bstrData), /*FORMAT_VideoInfo*/ L"{05589F80-C356-11CE-BF01-00AA0055595A}"))
{
VARIANT var;
IltmmMediaTypeDisp__get_Format(pMediaType, &var);
SafeArrayAccessData(V_ARRAY(&var), (void**) &pArrayData);
CopyVideoInfoHeader(&vih, pArrayData);
SafeArrayUnaccessData(V_ARRAY(&var));
VariantClear(&var);
if (vih.bmiHeader.biCompression == (unsigned long)lFourCC)
{
bCandidate = TRUE;
memcpy(&candidatevih, &vih, sizeof(VIDEOINFOHEADER));
pCandidateMt = pMediaType;
pCandidateStream = pCodecFormat;
}
}
}
}
if(bCandidate)
{
// modify the selected codec to support this bitrate and size
candidatevih.dwBitRate = lBitrate;
candidatevih.rcSource.right = lWidth;
candidatevih.rcSource.bottom = lHeight;
candidatevih.rcTarget.right = lWidth;
candidatevih.rcTarget.bottom = lHeight;
candidatevih.bmiHeader.biWidth = lWidth;
candidatevih.bmiHeader.biHeight = lHeight;
Num64.lowpart = (long)((long)(10000000.0 / lFps) % 0x10000);
Num64.highpart = (long)((10000000.0 / lFps) / 0x10000);
memcpy(&candidatevih.AvgTimePerFrame, &Num64, 8);
// pass the data to ltmmMediaType via SAFEARRAY
memset(&sa, 0, sizeof(sa));
sa.cbElements = sizeof(unsigned char);
sa.cDims = 1;
sa.fFeatures = (FADF_AUTO | FADF_FIXEDSIZE);
sa.pvData = (void*)&candidatevih;
sa.rgsabound[0].cElements = sizeof(VIDEOINFOHEADER);
VariantInit(&var);
V_VT(&var) = (VT_ARRAY | VT_UI1);
V_ARRAY(&var) = &sa;
IltmmMediaTypeDisp_SetFormatData(pCandidateMt, -1, var);
IltmmWMStreamConfig__put_Quality(pCandidateStream, lQuality);
IltmmWMStreamConfig__put_MaxKeyFrameSpacing(pCandidateStream, lSecperKey);
IltmmWMStreamConfig__put_StreamNumber(pCandidateStream, nStreamNum);
IltmmWMStreamConfig__put_StreamName(pCandidateStream, L"Video Stream");
IltmmWMStreamConfig__put_ConnectionName(pCandidateStream, L"Video");
IltmmWMStreamConfig__put_Bitrate (pCandidateStream, lBitrate);
IltmmWMStreamConfig__put_BufferWindow(pCandidateStream, -1);
IltmmWMStreamConfig_SetMediaType(pCandidateStream, pCandidateMt);
IltmmWMProfile_AddStream (pProfile, pCandidateStream);
IltmmWMProfile_ReconfigStream(pProfile, pCandidateStream);
IltmmMediaTypeDisp_Release(pCandidateMt);
IltmmWMStreamConfig_Release(pCandidateStream);
}
if(pCodecFormat)
{
IltmmWMStreamConfig_Release(pCodecFormat);
pCodecFormat = NULL;
}
if(pMediaType)
{
IltmmMediaTypeDisp_Release(pMediaType);
pMediaType = NULL;
}
}
void AddMutexObject(IltmmWMProfile *pProfile, int nBaseStream, int nStreamCount)
{
IltmmWMMutualExclusion *pExcl = NULL;
HRESULT hr;
int i;
// create an exclusion object
IltmmWMProfile_CreateNewMutualExclusion(pProfile, &pExcl);
// indicate that the streams differ by bit rate
// see CLSID_WMMUTEX_Bitrate in the WMSDK
IltmmWMMutualExclusion__put_Type(pExcl, L"{D6E22A01-35DA-11D1-9034-00A0C90349BE}");
// mark all the streams for mutual exclusion
for(i = 0; i < nStreamCount; i++)
{
hr = IltmmWMMutualExclusion_AddStream(pExcl, nBaseStream + i );
}
// assign the exclusion object to the profile
hr = IltmmWMProfile_AddMutualExclusion(pProfile, pExcl);
IltmmWMMutualExclusion_Release(pExcl);
}
void CreateCustomProfile(IltmmConvert *pConvert)
{
IltmmWMProfileManager *pManager = NULL;
IltmmWMProfile *pProfile = NULL;
int i;
// create an empty profile
CoCreateInstance(&CLSID_ltmmWMProfileManager, NULL, CLSCTX_INPROC_SERVER, &IID_IltmmWMProfileManager, (void**) &pManager);
IltmmWMProfileManager__put_SystemProfileVersion(pManager, ltmmWMT_VER_8_0);
IltmmWMProfileManager_CreateEmptyProfile(pManager, ltmmWMT_VER_7_0, &pProfile);
IltmmWMProfile__put_Name(pProfile, L"Custom Profile");
IltmmWMProfile__put_Description(pProfile, L"Custom Profile Description");
// add a single audio stream
AddAudioStream( pManager, pProfile, 1, /*CODEC_AUDIO_MSAUDIO*/353, 8000, 8000, 1, TRUE);
// add 5 video streams with different bit rates
for(i = 0 ; i < 5; i++)
{
AddVideoStream( pManager, pProfile, 2 + i, /*CODEC_VIDEO_WMV1*/0x31564D57,
(1024 * 20) + i * 1024,
320,
240,
5 * (i + 1),
0,
8);
}
// mark all the video streams for mutual exclusion
AddMutexObject(pProfile, 2, 5);
// Assign the pProfile to a convert object
IltmmConvert__put_WMProfile(pConvert, pProfile);
// Free…
IltmmWMProfileManager_Release(pManager);
}