locked
How To Decode a frame mp4 from IMFSourceReader::ReadSample using CLSID_CMpeg4sDecMFT RRS feed

  • Question

  • Dear sir.

    I would like to extract a image frame from a MPEG-4 part 2 file.

    I have done on MPEG-4 file. but as MPEG-4 part 2 did not.

    Here's the source code.

    ----------------------------------


     TCHAR BASED_CODE szFilter[] = _T("MPEG-4 Files (*.mp4)|*.mp4|All Files (*.*)|*.*||");
     CFileDialog dialogOpenFile(TRUE, _T("mp4"), NULL, OFN_FILEMUSTEXIST, szFilter, this);
     if (IDCANCEL == dialogOpenFile.DoModal())
     {
      return;
     }

     CString strFileName = dialogOpenFile.GetPathName();

     CComPtr<IMFSourceReader> SourceReader;
     VERIFY(S_OK == MFCreateSourceReaderFromURL(strFileName, nullptr, &SourceReader));

     CComPtr<IMFTransform > pMpeg4sDecoder;
     VERIFY(S_OK == pMpeg4sDecoder.CoCreateInstance(CLSID_CMpeg4sDecMFT));


     UINT32 Width, Height;
     CComPtr <IMFMediaType>pInputType;
     CComPtr <IMFMediaType>pOutputType;


     for (DWORD MediaTypeIndex = 0;; MediaTypeIndex++)
     {
      CComPtr < IMFMediaType> pNativeType;
      if (S_OK != SourceReader->GetNativeMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,MediaTypeIndex, &pNativeType))
      {
       break;
      }
      MFGetAttributeSize(pNativeType, MF_MT_FRAME_SIZE, &Width,&Height);
      GUID majorType, subtype;
      pNativeType->GetGUID(MF_MT_MAJOR_TYPE, &majorType);
      if (majorType == MFMediaType_Video)
      {
       GUID NativeSubtype;
       pNativeType->GetGUID(MF_MT_SUBTYPE, &NativeSubtype);

       MFCreateMediaType(&pInputType);
       pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
       pInputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_MP4V);
       VERIFY(S_OK == SourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, nullptr, pInputType));
       VERIFY(S_OK == MFSetAttributeSize(pInputType, MF_MT_FRAME_SIZE, Width, Height));
       VERIFY(S_OK == pMpeg4sDecoder->SetInputType(0, pNativeType, 0));

      

       MFCreateMediaType(&pOutputType);
       pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
       pOutputType->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_YV12);
       VERIFY(S_OK == MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, Width, Height));
       VERIFY(S_OK == pMpeg4sDecoder->SetOutputType(0, pOutputType, 0));

      }
     }

     SourceReader->SetStreamSelection(MF_SOURCE_READER_ANY_STREAM, FALSE);
     SourceReader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE);
     DWORD StreamIndex, Flags;
     LONGLONG TimeStamp;
    CComPtr<IMFSample> Sample;
    SourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &StreamIndex, &Flags, &TimeStamp, &Sample);
      if (Flags & MF_SOURCE_READERF_ENDOFSTREAM)
      {
       return;
      }
      HRESULT hr;

      VERIFY(S_OK==(hr= pMpeg4sDecoder->ProcessInput(0, Sample, 0) ));

    -----------------

    The last line fails with E_UNEXPECTED Catastrophic failure.

    I think that  the pMpeg4sDecoder is correctly configured.but I don't have a resolution.

    I looked for the more infomation of CLSID_CMpeg4sDecMFT, but I found only a following page.

    https://msdn.microsoft.com/ja-jp/library/windows/desktop/ff819454%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

    Please tell me my wrong point.

    Sincerely yours.

    Wednesday, July 15, 2015 12:04 PM

Answers

  • I solved this problem by myself.

    I changed decoding way.In IMFSourceReader,the decoder is configured automatically by setting MF_MT_SUBTYPE attribute as MEDIASUBTYPE_NV12.Here's the Code.

     TCHAR BASED_CODE szFilter[] = _T("MPEG-4 Files (*.mp4)|*.mp4|All Files (*.*)|*.*||");
     CFileDialog dialogOpenFile(TRUE, _T("mp4"), NULL, OFN_FILEMUSTEXIST, szFilter, this);
     if (IDCANCEL == dialogOpenFile.DoModal())
     {
      return;
     }

     CComPtr<IMFAttributes> Attributes;
     MFCreateAttributes(&Attributes, 1);
     Attributes->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING,1);
     CString strFileName = dialogOpenFile.GetPathName();

     CComPtr<IMFSourceReader> SourceReader;
     VERIFY(S_OK == MFCreateSourceReaderFromURL(strFileName, nullptr, &SourceReader));

     UINT32 Width, Height;

     

     for (DWORD MediaTypeIndex = 0;; MediaTypeIndex++)
     {
      CComPtr < IMFMediaType> pNativeType;
      CComPtr <IMFMediaType>pInputType;
      if (S_OK != SourceReader->GetNativeMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, MediaTypeIndex, &pNativeType))
      {
       break;
      }
      MFGetAttributeSize(pNativeType, MF_MT_FRAME_SIZE, &Width,&Height);
      GUID majorType, subtype;
      pNativeType->GetGUID(MF_MT_MAJOR_TYPE, &majorType);
      if (majorType == MFMediaType_Video)
      {
       GUID NativeSubtype;
       pNativeType->GetGUID(MF_MT_SUBTYPE, &NativeSubtype);

       MFCreateMediaType(&pInputType);
       pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
       pInputType->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_NV12);
       VERIFY(S_OK == SourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, nullptr, pInputType));
       VERIFY(S_OK == MFSetAttributeSize(pInputType, MF_MT_FRAME_SIZE, Width, Height));
       break;
      }
      
     }
     
     CComPtr<IMFTransform > pMFTransform;
     VERIFY(S_OK == pMFTransform.CoCreateInstance(CLSID_CColorConvertDMO));
     CComPtr <IMFMediaType>pTransformInputType;
     MFCreateMediaType(&pTransformInputType);
     pTransformInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
     pTransformInputType->SetGUID(MF_MT_SUBTYPE, MEDIASUBTYPE_NV12);
     VERIFY(S_OK == MFSetAttributeSize(pTransformInputType, MF_MT_FRAME_SIZE, Width, Height));
     VERIFY(S_OK == pMFTransform->SetInputType(0, pTransformInputType, 0));

     CComPtr <IMFMediaType >pTransformOutputType;
     MFCreateMediaType(&pTransformOutputType);
     pTransformOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
     pTransformOutputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
     VERIFY(S_OK == MFSetAttributeSize(pTransformOutputType, MF_MT_FRAME_SIZE, Width, Height));
     VERIFY(S_OK == pMFTransform->SetOutputType(0, pTransformOutputType, 0));

     


     SourceReader->SetStreamSelection(MF_SOURCE_READER_ANY_STREAM, FALSE);
     SourceReader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE);
     DWORD StreamIndex, Flags;
     LONGLONG TimeStamp;

     CComPtr<IMFSample> Sample;
     SourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &StreamIndex, &Flags, &TimeStamp, &Sample);
     if (Flags & MF_SOURCE_READERF_ENDOFSTREAM)
     {
      return;
     }
     HRESULT hr;
     VERIFY(S_OK == (hr = pMFTransform->ProcessInput(0, Sample, 0)));
     CComPtr<IMFMediaBuffer>MediaBuffer;
     DWORD TotalLength;
     IMFMediaBuffer *pBuffer = NULL;
     IMFSample      *pOutputSample;
     IMFMediaBuffer *pOutputBuffer;
     MFCreateSample(&pOutputSample);
     MFCreateMemoryBuffer(Width * Height * 4, &pOutputBuffer);
     pOutputSample->AddBuffer(pOutputBuffer);
     MFT_OUTPUT_DATA_BUFFER RGBOutputDataBuffer;
     RGBOutputDataBuffer.dwStreamID = 0;
     RGBOutputDataBuffer.dwStatus = 0;
     RGBOutputDataBuffer.pEvents = NULL;
     RGBOutputDataBuffer.pSample = pOutputSample;
     DWORD ProcessStatus;
     DWORD OutputStatus;
     hr = pMFTransform->ProcessOutput(0, 1, &RGBOutputDataBuffer, &ProcessStatus);
     if (hr != S_OK)continue;
      DWORD BufferCount;
     RGBOutputDataBuffer.pSample->GetBufferCount(&BufferCount);
      m_Image.Create(Width, Height, 32, 0);
     BYTE *outData;
     DWORD outDataLen = 0;
     pOutputBuffer->Lock(&outData, NULL, &outDataLen);

     /* DO the Data to a Bitmap*/

     pOutputBuffer->Unlock();
     m_Picture.SetBitmap(m_Image);

    ---------------

    Thank you

    • Marked as answer by hiro_3 Wednesday, July 15, 2015 3:25 PM
    Wednesday, July 15, 2015 3:23 PM