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 count
BSTR bstr = ::SysAllocString(ltmmMEDIATYPE_Audio);
HRESULT hr = mgr->GetCodecInfoCount(bstr, &cCodecs);
::SysFreeString(bstr);
if (FAILED(hr))
return hr;
// search for matching codec
for (long i = 0; i < cCodecs; i++)
{
long cFormats;
// get MEDIATYPE_Audio codec format count
BSTR 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 interface
IltmmWMStreamConfig* format;
bstr = ::SysAllocString(ltmmMEDIATYPE_Audio);
hr = mgr->GetCodecFormat(bstr, i, j, &format);
::SysFreeString(bstr);
if (SUCCEEDED(hr))
{
// get this format's media type
IltmmMediaTypeDisp* pmt;
hr = format->GetMediaType(&pmt);
if (SUCCEEDED(hr))
{
hr = pmt->get_FormatType(&bstr);
if (SUCCEEDED(hr))
{
// only check FORMAT_WaveFormatEx formats
if (!_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 candidate
long 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 nBlockAlign
if (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 candidate
if (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 type
bstr = ::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 count
BSTR bstr = ::SysAllocString(ltmmMEDIATYPE_Video);
HRESULT hr = mgr->GetCodecInfoCount(bstr, &cCodecs);
::SysFreeString(bstr);
if (FAILED(hr))
return hr;
// search for matching codec
for (long i = 0; !stream && i < cCodecs; i++)
{
long cFormats;
// get MEDIATYPE_Video codec format count
BSTR 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 interface
bstr = ::SysAllocString(ltmmMEDIATYPE_Video);
hr = mgr->GetCodecFormat(bstr, i, j, &stream);
::SysFreeString(bstr);
if (SUCCEEDED(hr))
{
// get this format's media type
hr = stream->GetMediaType(&pmt);
if (SUCCEEDED(hr))
{
hr = pmt->get_FormatType(&bstr);
if (SUCCEEDED(hr))
{
// only check FORMAT_VideoInfo formats
if (!_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 candidate
if (!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 object
HRESULT hr = profile->CreateNewMutualExclusion(&excl);
if (FAILED(hr))
return hr;
// indicate that the streams differ by bit rate
// see CLSID_WMMUTEX_Bitrate in the WMSDK
BSTR 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 exclusion
for (UINT i = 0; i < nStreamCount; i++)
{
hr = excl->AddStream(nBaseStream + i);
if (FAILED(hr))
{
excl->Release();
return hr;
}
}
// assign the exclusion object to the profile
hr = 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
Your email has been sent to support! Someone should be in touch! If your matter is urgent please come back into chat.
Chat Hours:
Monday - Friday, 8:30am to 6pm ET
Thank you for your feedback!
Please fill out the form again to start a new chat.
All agents are currently offline.
Chat Hours:
Monday - Friday
8:30AM - 6PM EST
To contact us please fill out this form and we will contact you via email.