The following code can be used to create a file with two audio streams that are mutually exclusive:
BSTR bstr;
CString fname;
HRESULT hr;
USES_CONVERSION;
if( m_pConvert == NULL )
return;
// Create the profile manager object:
hr = CoCreateInstance(CLSID_ltmmWMProfileManager, NULL, CLSCTX_INPROC_SERVER, IID_IltmmWMProfileManager, (void**) &m_pProfMan);
// create an empty profile:
hr = m_pProfMan->CreateEmptyProfile (ltmmWMT_VER_7_0, &m_pProf);
// Set the profile name and description
hr = m_pProf->put_Name (L"Mutex Stream_test");
hr = m_pProf->put_Description (L"Example code");
// add 2 audio streams with different bitrates
hr = AddAudioStream(mgr, profile, 1, CODEC_AUDIO_MSAUDIO, 8000, 8000, 1, FALSE);
hr = AddAudioStream(mgr, profile, 2, CODEC_AUDIO_MSAUDIO, 16000, 16000, 1, FALSE);
// make them mutually exclusive
hr = AddMutexObject(profile, 1, 2);
// add the profile to the convert object
hr = m_pConvert->put_WMProfile (m_pProf);
m_pProf->Release();
m_pProfMan->Release();
//set the target format
hr = m_pConvert->put_TargetFormat ( ltmmConvert_TargetFormat_Asf_Compressor_Mux );
// set the source file name; the source file contains multiple audio streams:
hr = m_pConvert->put_SourceFile (L"London.avi");
// set the output file name:
hr = m_pConvert->put_TargetFile ("London.asf");
// do the conversion
hr = m_pConvert->StartConvert ();
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);
// 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);
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 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);
// 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);
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);
// 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);
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);
hr = stream->SetMediaType (pmt);
hr = profile->AddStream (stream);
stream->Release();
pmt->Release();
SafeArrayUnaccessData(V_ARRAY(&varSave));
VariantClear(&varSave);
return S_OK;
}
HRESULT AddMutexObject(IltmmWMProfile *profile, UINT nBaseStream, UINT nStreamCount)
{
IltmmWMMutualExclusion *excl = NULL;
// create an exclusion object
HRESULT hr = profile->CreateNewMutualExclusion (&excl);
// mark all the streams for mutual exclusion
for(UINT i = 0; i < nStreamCount; i++)
{
hr = excl->AddStream (nBaseStream + i);
}
// indicate that the streams differ by Bitrate
// see CLSID_WMMUTEX_Bitrate in the WMSDK
BSTR bstr = ::SysAllocString(L"{D6E22A01-35DA-11D1-9034-00A0C90349BE}");
hr = excl->put_Type(bstr);
::SysFreeString(bstr);
// 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.