locked
Calling H.264 Video Encoder's SetInputType(...) always return MF_E_INVALIDMEDIATYPE RRS feed

  • Question

  • Hi there,

    I've been trying to get MF H.264 encoder working, and all attempts were failed. The main problem is that calling on the encoder's SetInputType method always returns MF_E_INVALIDMEDIATYPE (0xc00d36b4). I believe that I've followed the instructions at http://msdn.microsoft.com/en-us/library/dd797816(v=VS.85).aspx, and call SetOutputType first and then SetInputType. The actual input type is I420 or IYUV, which is supported according to the doc. Can anyone help with the issue?  Thanks. 

      // Get the partial output type
      if (SUCCEEDED(hr))
      {
        hr = m_pEncoder->GetOutputAvailableType(0, 0, &pTypeOut);
      }
    
      
      // Set all required output type attributes
    	...
    
    	// set encoder's output type
      if (SUCCEEDED(hr))
      {
        hr = m_pEncoder->SetOutputType(0, pTypeOut, 0);
      }
    
      // Set the uncompressed type.
      IMFMediaType *pTypeIn = NULL;
      hr = MFCreateMediaType(&pTypeIn);
      if (SUCCEEDED(hr))
      {
    	  hr = MFInitMediaTypeFromVideoInfoHeader(pTypeIn, &srcVideoInfoHdr, sizeof(srcVideoInfoHdr),NULL);
      }
      hr = pTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video );
      hr = pTypeIn->SetGUID(MF_MT_SUBTYPE,MFVideoFormat_IYUV );
    
      // the following call always fails with MF_E_INVALIDMEDIATYPE 
      hr = m_pEncoder->SetInputType(0, pTypeIn, 0);
    

    Thursday, July 21, 2011 1:24 AM

Answers

  • Nobby,

    Thanks for your suggestion. Actually the attribute MF_MT_MPEG2_PROFILE  was set. I just omitted all the the attribute settings for output media type in my initial post as I don't have any problem with the output type.

    I just found out that the h.264 encoder doesn't like to be set with a foreign media type. That is, you have to call GetInputAvailableType() to retreive the input type you want from the H.264 encoder, make changes to its attributes, and then call SetInputType with the ORIGINAL reference to the type (see attached code). It will return S_OK. So far so good.

    However, I came across another issue. When calling the encoder's ProcessInput, the encoder throws an exception -  0xC0000005: Access violation reading location 0x00000000. The input sample provided to the call is valid which has valid data of 115200 bytes and its buffer size is 230400. I use one single buffer per sample, and use the same test application on WMV encoder without an issue. Anything I missed out?

      IMFMediaType *pSrcType = NULL;
      GUID srcGuid = GetAttributeGUID(pTypeIn, MF_MT_SUBTYPE );
      for (int i = 0; i< 8; i++)
      {
        hr = m_pEncoder->GetInputAvailableType(0, i, &pSrcType);
    
        if (hr == MF_E_NO_MORE_TYPES) 
        {
          break;
        }
        //ATLTRACE("\nPrint encoder source input %d Media type info\n", i);
        //PrintMediaAttributes(pSrcType);
        if ( GetAttributeGUID(pSrcType, MF_MT_SUBTYPE ) == srcGuid || 
          (GetAttributeGUID(pSrcType, MF_MT_SUBTYPE )== MFVideoFormat_IYUV && srcGuid ==MFVideoFormat_I420))
        {
          break;
        }
        SafeRelease(&pSrcType);
      }
    
      hr = pSrcType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, 1);
      hr = pSrcType->SetUINT32(MF_MT_DEFAULT_STRIDE, 320);
      hr = pSrcType->SetUINT32(MF_MT_SAMPLE_SIZE, 115200);
      hr = pSrcType->SetUINT32(MF_MT_AVG_BITRATE, 23040000);
    
      ATLTRACE("\nPrint encoder source input Media type info\n");
      PrintMediaAttributes(pSrcType);
    
      hr = m_pEncoder->SetInputType(0, pSrcType, 0);
      SafeRelease(&pSrcType);  


    jon
    • Marked as answer by jon4112 Tuesday, August 2, 2011 2:43 PM
    Wednesday, July 27, 2011 4:37 PM

All replies

  • From your example code there it looks like the issue is an incomplete Media Type. The H.264 Encoder MFT will not construct a full input media type, from a partial input media type, based on the current output media type. This is mostly to do with the encoder needing an input frame rate to be specified and possibly a target bitrate which would be required in advance to encoding.

    The behaviour is very different to say using an IMFSourceReader where you can provide a partial output media type and the Source Reader will build a full media type based on the Native Media Type.

    Friday, July 22, 2011 5:14 AM
  • Thank for your suggestion. I checked the media type, and it looks fine to me. The following is the attributes printed out from both input and output media types.The only thing that doesn't look right is the height attribute. Setting it through MFSetAttributeSize(..) wouldn't change its value. However, it doesn't have any effect on WMV encoder.

    //Print encoder output Media type info
    MF_MT_COMPRESSED : 0
    MF_MT_AM_FORMAT_TYPE : None Video info
    MF_MT_FIXED_SIZE_SAMPLES: 0
    MF_MT_SAMPLE_SIZE : 0
    MF_MT_MAJOR_TYPE : MFMediaType_Video
    MF_MT_SUBTYPE : MFVideoFormat_H264
    MF_MT_AVG_BIT_ERROR_RATE: 0
    MF_MT_AVG_BITRATE: 240000
    MF_MT_DEFAULT_STRIDE: 0
    MF_MT_FRAME_RATE: Numerator = 30000, Denominator = 1001
    MF_MT_FRAME_RATE_RANGE_MIN: Numerator = 30000, Denominator = 1001
    MF_MT_FRAME_RATE_RANGE_MAX: Numerator = 30000, Denominator = 1001
    MF_MT_FRAME_SIZE: width = 320, height = 1241588
    MF_MT_INTERLACE_MODE: 2
    
    //Print encoder intput Media type info
    MF_MT_COMPRESSED : 0
    MF_MT_AM_FORMAT_TYPE : None Video info
    MF_MT_FIXED_SIZE_SAMPLES: 1
    MF_MT_SAMPLE_SIZE : 115200
    MF_MT_MAJOR_TYPE : MFMediaType_Video
    MF_MT_SUBTYPE : MFVideoFormat_I420
    MF_MT_AVG_BIT_ERROR_RATE: 0
    MF_MT_AVG_BITRATE: 23040000
    MF_MT_DEFAULT_STRIDE: 320
    MF_MT_FRAME_RATE: Numerator = 30, Denominator = 1
    MF_MT_FRAME_RATE_RANGE_MIN: Numerator = 30, Denominator = 1
    MF_MT_FRAME_RATE_RANGE_MAX: Numerator = 30, Denominator = 1
    MF_MT_FRAME_SIZE: width = 320, height = 1241588
    MF_MT_INTERLACE_MODE: 2
    


    jon
    Friday, July 22, 2011 9:21 PM
  • Jon, try omitting the following attributes from both the input & output media types:

    MF_MT_AVG_BIT_ERROR, MF_MT_AM_FORMAT_TYPE, FRAME_RATE_RANGE_MIN & MAX

     

    How is your height value ending up like that? Are you using IMFAttribute->GetUINT64? If so, make sure you're masking the lower 32 bits for the height. Also, I haven't worked with interlaced encoding. Make sure that if you are defining MF_MT_INTERLACE_MODE in the input type that the input data is actually interlaced. Im also not sure if the H.264 encoder will accept uncompressed interlaced frames for input. It might be full frames only.

    Sometimes my problem has just been that i've defined too many attributes so try the first suggestion then work from there.

    Monday, July 25, 2011 12:28 PM
  • Thanks for your reply, Nobby.

    Just found out the weird number in height is due to my typo in my printing routine, which prints the address of height instead of its value. The value is 240 as expected. The MF_MT_INTERLACE_MODE attribute in the input type is correct, which is progressive (2). Actually, the input type is initialized by calling MFInitMediaTypeFromVideoInfoHeader(...). I assumed that it should be correct and did not touch anything in it. So the attributes you suggested to ignore were not touched. I really have no clue what went wrong with the setting to the input type. Any other ideas?


    jon
    Tuesday, July 26, 2011 6:09 PM
  • Hey Jon,

    I was about to write a list of attributes I use that I know to work for me and get you to test those. However, I noticed there's one attribute you don't define in the output type.  MF_MT_MPEG2_PROFILE which you need to tell the H.264 encoder to use Baseline or Main encoding schemes. Just try adding in a SetUINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Main) to your output type and see how that goes when you set your input type.

    I've found that you can actually set a "faulty" output type to the sink because no validation actually occurs until you attempt to set the input type. Try that and see how you go.

    Wednesday, July 27, 2011 12:10 AM
  • Nobby,

    Thanks for your suggestion. Actually the attribute MF_MT_MPEG2_PROFILE  was set. I just omitted all the the attribute settings for output media type in my initial post as I don't have any problem with the output type.

    I just found out that the h.264 encoder doesn't like to be set with a foreign media type. That is, you have to call GetInputAvailableType() to retreive the input type you want from the H.264 encoder, make changes to its attributes, and then call SetInputType with the ORIGINAL reference to the type (see attached code). It will return S_OK. So far so good.

    However, I came across another issue. When calling the encoder's ProcessInput, the encoder throws an exception -  0xC0000005: Access violation reading location 0x00000000. The input sample provided to the call is valid which has valid data of 115200 bytes and its buffer size is 230400. I use one single buffer per sample, and use the same test application on WMV encoder without an issue. Anything I missed out?

      IMFMediaType *pSrcType = NULL;
      GUID srcGuid = GetAttributeGUID(pTypeIn, MF_MT_SUBTYPE );
      for (int i = 0; i< 8; i++)
      {
        hr = m_pEncoder->GetInputAvailableType(0, i, &pSrcType);
    
        if (hr == MF_E_NO_MORE_TYPES) 
        {
          break;
        }
        //ATLTRACE("\nPrint encoder source input %d Media type info\n", i);
        //PrintMediaAttributes(pSrcType);
        if ( GetAttributeGUID(pSrcType, MF_MT_SUBTYPE ) == srcGuid || 
          (GetAttributeGUID(pSrcType, MF_MT_SUBTYPE )== MFVideoFormat_IYUV && srcGuid ==MFVideoFormat_I420))
        {
          break;
        }
        SafeRelease(&pSrcType);
      }
    
      hr = pSrcType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, 1);
      hr = pSrcType->SetUINT32(MF_MT_DEFAULT_STRIDE, 320);
      hr = pSrcType->SetUINT32(MF_MT_SAMPLE_SIZE, 115200);
      hr = pSrcType->SetUINT32(MF_MT_AVG_BITRATE, 23040000);
    
      ATLTRACE("\nPrint encoder source input Media type info\n");
      PrintMediaAttributes(pSrcType);
    
      hr = m_pEncoder->SetInputType(0, pSrcType, 0);
      SafeRelease(&pSrcType);  


    jon
    • Marked as answer by jon4112 Tuesday, August 2, 2011 2:43 PM
    Wednesday, July 27, 2011 4:37 PM
  • Hi Jon

    I'm facing a similar problem as yours. I'm unable to "SetInputType" on a decoder (always returns me MF_E_INVALIDMEDIATYPE) Please see question posted on:

    http://social.msdn.microsoft.com/Forums/en-US/mediafoundationdevelopment/thread/17d0925b-c716-4ebb-9450-71a2f54a5912

    Can you help me fix this. I'm not sure what attributes/parameters I'm missing on input media type.

     

    Thanks,

    Mots

    Tuesday, September 13, 2011 10:35 AM