Create a File with 2 Audio Streams that are Mutually Exclusive

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 Version 21.0.2021.7.19
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2021 LEAD Technologies, Inc. All Rights Reserved.

LEADTOOLS Multimedia C API Help
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2021 LEAD Technologies, Inc. All Rights Reserved.