For complete code, refer to the CNVWM demo.
#include "amvideo.h" void CopyWaveFormatEx (WAVEFORMATEX *wfex, BYTE *pArrayData) { memcpy ( wfex, pArrayData, sizeof ( WAVEFORMATEX ) ) ; } void CopyVideoInfoHeader (VIDEOINFOHEADER *vih, BYTE *pArrayData) { memcpy ( vih, pArrayData, sizeof ( VIDEOINFOHEADER ) ) ; } 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 = {0}; 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, 353, L"%0 8X"); 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 ) { 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); 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 IltmmWMProfile_AddStream_Example (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); }