For complete code, refer to the CNVWM demo.
#include "amvideo.h"#include "Mmreg.h"HRESULT AddAudioStream(IltmmWMProfileManager* mgr, IltmmWMProfile* profile,UINT nStreamNum, UINT nFormatTag, ULONG nBitRate,ULONG nSamplesPerSec, UINT nChannels, BOOL bVideo){long cCodecs;VARIANT varSave;VariantInit(&varSave);// get MEDIATYPE_Audio codec countBSTR bstr = ::SysAllocString(ltmmMEDIATYPE_Audio);HRESULT hr = mgr->GetCodecInfoCount(bstr, &cCodecs);::SysFreeString(bstr);if (FAILED(hr))return hr;// search for matching codecfor (long i = 0; i < cCodecs; i++){long cFormats;// get MEDIATYPE_Audio codec format countBSTR bstr = ::SysAllocString(ltmmMEDIATYPE_Audio);HRESULT hr = mgr->GetCodecFormatCount(bstr, i, &cFormats);::SysFreeString(bstr);if(FAILED(hr))break;for (long j = 0; j < cFormats; j++){// get MEDIATYPE_Audio stream config interfaceIltmmWMStreamConfig* format;bstr = ::SysAllocString(ltmmMEDIATYPE_Audio);hr = mgr->GetCodecFormat(bstr, i, j, &format);::SysFreeString(bstr);if (SUCCEEDED(hr)){// get this format's media typeIltmmMediaTypeDisp* pmt;hr = format->GetMediaType(&pmt);if (SUCCEEDED(hr)){hr = pmt->get_FormatType(&bstr);if (SUCCEEDED(hr)){// only check FORMAT_WaveFormatEx formatsif (!_wcsicmp(bstr, ltmmFORMAT_WaveFormatEx)){VARIANT var;VariantInit(&var);pmt->get_Format(&var);WAVEFORMATEX *pWfx;SafeArrayAccessData(V_ARRAY(&var), (void**) &pWfx);// does this format look like a good candidatelong nDiff = (long) (pWfx->nAvgBytesPerSec * 8 - nBitRate);if (nDiff < 250 &&nDiff > -250 &&pWfx->nSamplesPerSec == nSamplesPerSec &&pWfx->nChannels == nChannels &&pWfx->wFormatTag == nFormatTag){if (V_VT(&varSave) != VT_EMPTY){WAVEFORMATEX *pSaveWFX;SafeArrayAccessData(V_ARRAY(&varSave), (void**) &pSaveWFX);if (bVideo){// For audio/video configurations, we want to// find the smaller nBlockAlign. In this case,// the nBlockAlign is larger, so we want to// use the old format.if (pWfx->nBlockAlign <= pSaveWFX->nBlockAlign){SafeArrayUnaccessData(V_ARRAY(&varSave));VariantClear(&varSave);VariantCopy(&varSave, &var);}}else{// otherwise, we want the larger nBlockAlignif (pWfx->nBlockAlign >= pSaveWFX->nBlockAlign){SafeArrayUnaccessData(V_ARRAY(&varSave));VariantClear(&varSave);VariantCopy(&varSave, &var);}}}else{VariantClear(&varSave);VariantCopy(&varSave, &var);}}SafeArrayUnaccessData(V_ARRAY(&var));VariantClear(&var);}::SysFreeString(bstr);}pmt->Release();}format->Release();}}}// return an error, if we didn't find a good candidateif (V_VT(&varSave) == VT_EMPTY)return E_FAIL;WAVEFORMATEX *pSaveWFX;SafeArrayAccessData(V_ARRAY(&varSave), (void**) &pSaveWFX);IltmmMediaTypeDisp* pmt;hr = CoCreateInstance(CLSID_ltmmMediaType, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMediaTypeDisp, (void**) &pmt);if (FAILED(hr)){SafeArrayUnaccessData(V_ARRAY(&varSave));VariantClear(&varSave);return hr;}// setup the new stream's media typebstr = ::SysAllocString(ltmmMEDIATYPE_Audio);pmt->put_Type(bstr);::SysFreeString(bstr);CString s;s.Format(_T("{%.8X-0000-0010-8000-00AA00389B71}"), (UINT) pSaveWFX->wFormatTag);bstr = s.AllocSysString();pmt->put_Subtype(bstr);::SysFreeString(bstr);pmt->put_FixedSizeSamples(VARIANT_TRUE);pmt->put_TemporalCompression(VARIANT_FALSE);pmt->put_SampleSize(pSaveWFX->nBlockAlign);bstr = ::SysAllocString(ltmmFORMAT_WaveFormatEx);pmt->put_FormatType(bstr);::SysFreeString(bstr);pmt->SetFormatData(-1L, varSave);IltmmWMStreamConfig* stream;bstr = ::SysAllocString(ltmmMEDIATYPE_Audio);hr = profile->CreateNewStream(bstr, &stream);::SysFreeString(bstr);if (FAILED(hr)){SafeArrayUnaccessData(V_ARRAY(&varSave));VariantClear(&varSave);pmt->Release();return hr;}stream->put_StreamNumber(nStreamNum);bstr = ::SysAllocString(L"Audio Stream");stream->put_StreamName(bstr);::SysFreeString(bstr);bstr = ::SysAllocString(L"Audio");stream->put_ConnectionName(bstr);::SysFreeString(bstr);stream->put_Bitrate(pSaveWFX->nAvgBytesPerSec * 8);stream->SetMediaType(pmt);profile->AddStream(stream);stream->Release();pmt->Release();SafeArrayUnaccessData(V_ARRAY(&varSave));VariantClear(&varSave);return S_OK;}HRESULT AddVideoStream(IltmmWMProfileManager* mgr, IltmmWMProfile* profile,UINT nStreamNum, DWORD dwFourCC, ULONG nBitRate, ULONG nWidth, ULONG nHeight,ULONG nFPS, ULONG nQuality, ULONG nSecPerKey){long cCodecs;IltmmWMStreamConfig* stream = NULL;IltmmMediaTypeDisp* pmt = NULL;VIDEOINFOHEADER *pVIH = NULL;VARIANT varFormat;VariantInit(&varFormat);// get MEDIATYPE_Video codec countBSTR bstr = ::SysAllocString(ltmmMEDIATYPE_Video);HRESULT hr = mgr->GetCodecInfoCount(bstr, &cCodecs);::SysFreeString(bstr);if (FAILED(hr))return hr;// search for matching codecfor (long i = 0; !stream && i < cCodecs; i++){long cFormats;// get MEDIATYPE_Video codec format countBSTR bstr = ::SysAllocString(ltmmMEDIATYPE_Video);HRESULT hr = mgr->GetCodecFormatCount(bstr, i, &cFormats);::SysFreeString(bstr);if (FAILED(hr))break;for (long j = 0; j < cFormats; j++){// get MEDIATYPE_Video stream config interfacebstr = ::SysAllocString(ltmmMEDIATYPE_Video);hr = mgr->GetCodecFormat(bstr, i, j, &stream);::SysFreeString(bstr);if (SUCCEEDED(hr)){// get this format's media typehr = stream->GetMediaType(&pmt);if (SUCCEEDED(hr)){hr = pmt->get_FormatType(&bstr);if (SUCCEEDED(hr)){// only check FORMAT_VideoInfo formatsif (!_wcsicmp(bstr, ltmmFORMAT_VideoInfo)){pmt->GetFormatData(-1, &varFormat);SafeArrayAccessData(V_ARRAY(&varFormat), (void**) &pVIH);if (pVIH->bmiHeader.biCompression == dwFourCC){::SysFreeString(bstr);break;}SafeArrayUnaccessData(V_ARRAY(&varFormat));VariantClear(&varFormat);}::SysFreeString(bstr);}pmt->Release();pmt = NULL;}stream->Release();stream = NULL;}}}// return an error, if we didn't find a good candidateif (!stream)return E_FAIL;pVIH->dwBitRate = nBitRate;pVIH->rcSource.right = nWidth;pVIH->rcSource.bottom = nHeight;pVIH->rcTarget.right = nWidth;pVIH->rcTarget.bottom = nHeight;pVIH->bmiHeader.biWidth = nWidth;pVIH->bmiHeader.biHeight = nHeight;pVIH->AvgTimePerFrame = ((LONGLONG) 10000000 ) / ((LONGLONG) nFPS );pmt->SetFormatData(-1, varFormat);hr = stream->put_Quality( nQuality );hr = stream->put_MaxKeyFrameSpacing((double) nSecPerKey);stream->put_StreamNumber(nStreamNum);bstr = ::SysAllocString(L"Video Stream");stream->put_StreamName(bstr);::SysFreeString(bstr);bstr = ::SysAllocString(L"Video");stream->put_ConnectionName(bstr);::SysFreeString(bstr);stream->put_Bitrate(nBitRate);stream->SetMediaType(pmt);profile->AddStream(stream);stream->Release();pmt->Release();SafeArrayUnaccessData(V_ARRAY(&varFormat));VariantClear(&varFormat);return S_OK;}HRESULT AddMutexObject(IltmmWMProfile *profile, UINT nBaseStream, UINT nStreamCount){IltmmWMMutualExclusion *excl = NULL;// create an exclusion objectHRESULT hr = profile->CreateNewMutualExclusion(&excl);if (FAILED(hr))return hr;// indicate that the streams differ by bit rate// see CLSID_WMMUTEX_Bitrate in the WMSDKBSTR bstr = ::SysAllocString(L"{D6E22A01-35DA-11D1-9034-00A0C90349BE}");hr = excl->put_Type(bstr);::SysFreeString(bstr);if (FAILED(hr)){excl->Release();return hr;}// mark all the streams for mutual exclusionfor (UINT i = 0; i < nStreamCount; i++){hr = excl->AddStream(nBaseStream + i);if (FAILED(hr)){excl->Release();return hr;}}// assign the exclusion object to the profilehr = profile->AddMutualExclusion(excl);excl->Release();return hr;}
Help Collections
Raster .NET | C API | C++ Class Library | HTML5 JavaScript
Document .NET | C API | C++ Class Library | HTML5 JavaScript
Medical .NET | C API | C++ Class Library | HTML5 JavaScript
Medical Web Viewer .NET
Multimedia
Direct Show .NET | C API | Filters
Media Foundation .NET | C API | Transforms
Supported Platforms
.NET, Java, Android, and iOS/macOS Assemblies
Imaging, Medical, and Document
C API/C++ Class Libraries
Imaging, Medical, and Document
HTML5 JavaScript Libraries
Imaging, Medical, and Document
