locked
Unable to obtain WAVEFORMATEX for Windows Media codec format RRS feed

  • Question

  • The Windows Media Audio 9.2 codec (WMAC) supports a limited number of formats which can be used to encode/decode audio.     I am capturing audio/video with a webcam and therefore need to configure the webcam audio capture format so that it is the same (i.e. compatible) with the WMAC format.   I am not able to query correct WAVEFORMATEX information from the audio formats supported by WMAC.    I have provided sample code and am asking if someone can point out what I am doing wrong.

    The following shows the incorrect WAVEFORMATEX information I obtained for the first WMAC codec format when my test code was run 3 different times under different conditions.

    Run 1 - Codec format #1
      codec format description:   8 kbps,  8 kHz, mono CBR
      wave format:
       wFormatTag: 4
       nChannels: 0
       nSamplesPerSec: 2
       nAvgBytesPerSec: 1120
       nBlockAlign: 65021
       wBitsPerSample: 65021
       cbSize: 43936

    Run 2 - Codec format #1
      codec format description:   8 kbps,  8 kHz, mono CBR
      wave format:
       wFormatTag: 65262
       nChannels: 65262
       nSamplesPerSec: 4277075694
       nAvgBytesPerSec: 4277075694
       nBlockAlign: 65262
       wBitsPerSample: 65262
       cbSize: 65262

    Run 3 - Codec format #1
      codec format description:   8 kbps,  8 kHz, mono CBR
      wave format:
       wFormatTag: 0
       nChannels: 0
       nSamplesPerSec: 0
       nAvgBytesPerSec: 0
       nBlockAlign: 0
       wBitsPerSample: 0

    The sample code used to obtain the WAVEFORMATEX information (with error checking removed) is as follows:

    _COM_SMARTPTR_TYPEDEF( IWMCodecInfo, IID_IWMCodecInfo );
    _COM_SMARTPTR_TYPEDEF( IWMCodecInfo3, IID_IWMCodecInfo3 );
    _COM_SMARTPTR_TYPEDEF( IWMMediaProps, IID_IWMMediaProps );
    _COM_SMARTPTR_TYPEDEF( IWMProfileManager, IID_IWMProfileManager );
    _COM_SMARTPTR_TYPEDEF( IWMStreamConfig, IID_IWMStreamConfig );

    void test2( wchar_t* outputFilename )
    {
     HRESULT hr;
     GUID mediaType = WMMEDIATYPE_Audio;
     int xCodec = 2; // Windows Media Audio 9.2

     // ----------------------------------------------------------
     IWMProfileManagerPtr profileManager;
     hr = ::WMCreateProfileManager( &profileManager );

     IWMCodecInfo3Ptr codecInfo3;
     hr = profileManager->QueryInterface( IID_IWMCodecInfo3, (void**)&codecInfo3 );

     // ----------------------------------------------------------
     BOOL enableVariableBitrate = FALSE;
     DWORD numberOfCodecPasses = 1;
     hr = codecInfo3->SetCodecEnumerationSetting(
      mediaType, xCodec,
      g_wszVBREnabled, WMT_TYPE_BOOL, (BYTE*)&enableVariableBitrate, sizeof(BOOL)
     );
     if( FAILED(hr) ) {
      if( !enableVariableBitrate  &&  NS_E_UNSUPPORTED_PROPERTY == hr )
       hr = S_OK;
     }
     hr = codecInfo3->SetCodecEnumerationSetting(
      mediaType, xCodec, g_wszNumPasses, WMT_TYPE_DWORD, (BYTE*)&numberOfCodecPasses, sizeof(DWORD)
     );

     // ----------------------------------------------------------
     DWORD ctCodecFormats = 0;
     hr = codecInfo3->GetCodecFormatCount( mediaType, xCodec, &ctCodecFormats );

     // ----------------------------------------------------------
     std::wfstream file( outputFilename, std::ios_base::out | std::ios_base::trunc );
     for( DWORD xCodecFormat = 0;  xCodecFormat < ctCodecFormats;  ++xCodecFormat ) {
      IWMStreamConfigPtr formatConfig;
      hr = codecInfo3->GetCodecFormat( mediaType, xCodec, xCodecFormat, &formatConfig );

      // ----------------------------------------------------------
      std::wstring codecFormatDescription;
      { IWMStreamConfigPtr formatConfig2;
       DWORD ctCharacters = 0;
       hr = codecInfo3->GetCodecFormatDesc(
        mediaType, xCodec, xCodecFormat, &formatConfig2, NULL, &ctCharacters
       );

       std::vector< WCHAR > buffer( ctCharacters+1, 0 );
       hr = codecInfo3->GetCodecFormatDesc(
        mediaType, xCodec, xCodecFormat, &formatConfig2, &buffer[0], &ctCharacters
       );
       codecFormatDescription = (WCHAR*)&buffer[0];
      }

      // ----------------------------------------------------------
      WAVEFORMATEX* waveFormat = NULL;
      { IWMMediaPropsPtr mediaProps;
       hr = formatConfig->QueryInterface( IID_IWMMediaProps, (void**)&mediaProps );
       
       DWORD ctBytes;
       hr = mediaProps->GetMediaType( NULL, &ctBytes );
       //
       std::vector< BYTE > buffer( ctBytes, 0 );
       hr = mediaProps->GetMediaType( (WM_MEDIA_TYPE*)&buffer[0], &ctBytes );
       
       WM_MEDIA_TYPE* mediaType = (WM_MEDIA_TYPE*)&buffer[0];
       ASSERT( WMMEDIATYPE_Audio == mediaType->majortype );
       ASSERT( WMFORMAT_WaveFormatEx == mediaType->formattype );
       ASSERT( sizeof(WAVEFORMATEX) <= mediaType->cbFormat );
       waveFormat = (WAVEFORMATEX*)mediaType->pbFormat;
      }

      std::wostringstream os;
      os << L"Codec format #"   << xCodecFormat + 1 << std::endl
       << L"\t codec format description: " << codecFormatDescription << std::endl
       << L"\t wave format: "   << std::endl
       << L"\t\t wFormatTag: "   << waveFormat->wFormatTag << std::endl
       << L"\t\t nChannels: "   << waveFormat->nChannels << std::endl
       << L"\t\t nSamplesPerSec: "  << waveFormat->nSamplesPerSec << std::endl
       << L"\t\t nAvgBytesPerSec: " << waveFormat->nAvgBytesPerSec << std::endl
       << L"\t\t nBlockAlign: "  << waveFormat->nBlockAlign << std::endl
       << L"\t\t wBitsPerSample: "  << waveFormat->wBitsPerSample << std::endl
       << L"\t\t cbSize: "    << waveFormat->cbSize << std::endl
       << std::endl;

      file << os.str();
     } // for( DWORD xCodecFormat = 0 ...
    }

     

    Tuesday, February 14, 2012 9:41 PM

Answers

  • hr = IWMMediaProps::GetMediaType( (WM_MEDIA_TYPE*)&buffer[0], ctBytes );

    // &buffer[0] contains an instance of MW_MEDIA_TYPE but, for reasons not clear,
    // the contents of MW_MEDIA_TYPE::pbFormat are being over written soon
    // after 'GetMediaType' is called.
    // The solution is to make a copy of MW_MEDIA_TYPE using the CopyMediaType function
    // found Window Media Format SDK sample project WMGenProfile

    MW_MEDIA_TYPE mediaType;
    hr =CopyMediaType( &mediaType, (
    MW_MEDIA_TYPE*)&buffer[0] );

    • Marked as answer by IB00 Thursday, February 16, 2012 4:28 AM
    • Edited by IB00 Thursday, February 16, 2012 2:10 PM
    Thursday, February 16, 2012 4:26 AM