Processing Data in the Encoder

After you have negotiated the input type and output type for the encoder MFT, as described in Media Type Negotiation on the Encoder, you can start processing media data samples. The data is passed in form of media samples (IMFSample interface) and also received from the output as media samples.

Before sending data to the encoder for processing, you must allocate a media sample and add one of more media buffers containing media data that needs to be encoded. Call IMFTransform::ProcessInput and pass a pointer to the allocated media sample. In addition to the media sample, ProcessInput also needs the input stream identifier. To get the stream identifier, call IMFTransform::GetStreamIDs. Because an encoder is designed to have only one and one output, these stream identifiers always have the value of 0.

To get data from the encoder, call IMFTransform::ProcessOutput. Before you call ProcessOutput, you need to find out whether the encoder allocates the output media samples or you must do so explicitly. To do this, call IMFTransform::GetOutputStreamInfo. This returns output media sample information in the MFT_OUTPUT_STREAM_INFO structure. If the encoder allocates media samples, it returns the MFT_OUTPUT_STREAM_PROVIDES_SAMPLES flag in the dwFlags member and the cbSize member contains zero. If the encoder expects you to allocate the output buffer, create the output media sample and the associated media buffer based on the size returned in cbSize. When you call ProcessSample, pass a pointer to the newly created media sample. During the encoding session, the encoder fills the media buffers, pointed by the output media sample, with the encoded data.

To start the encoding session, pass the input media sample to the encoder by calling ProcessInput. The encoder starts processing and the data and produces one or more output media samples that must be retrieved by ProcessOutput as long as it returns MF_E_TRANSFORM_NEED_MORE_INPUT. If you call ProcessInput to pass more input as long as there is output data to be retrieved, ProcessInput fails with MF_E_NOTACCEPTING. The encoder does not accept any more input until the client calls ProcessOutput at least once.

You should set accurate time stamps and durations for all input samples passed. Time stamps are not strictly required but help maintain audio/video synchronization. If you do not have the time stamps for your samples it is better to leave them out than to use uncertain values.

Encoder Processing Example

The following example code shows how to call IMFTransform::ProcessOutput to get an encoded sample. For the complete context of this example, see Encoder Example Code.

HRESULT CWmaEncoder::ProcessOutput(IMFSample **ppSample)
{
    if (m_pMFT == NULL)
    {
        return MF_E_NOT_INITIALIZED;
    }

    *ppSample = NULL;

    IMFMediaBuffer* pBufferOut = NULL;
    IMFSample* pSampleOut = NULL;

    DWORD dwStatus;
  
    MFT_OUTPUT_STREAM_INFO mftStreamInfo = { 0 };
    MFT_OUTPUT_DATA_BUFFER mftOutputData = { 0 };

    HRESULT hr = m_pMFT->GetOutputStreamInfo(m_dwOutputID, &mftStreamInfo);
    if (FAILED(hr))
    {
        goto done;
    }

    //create a buffer for the output sample
    hr = MFCreateMemoryBuffer(mftStreamInfo.cbSize, &pBufferOut);
    if (FAILED(hr))
    {
        goto done;
    }

    //Create the output sample
    hr = MFCreateSample(&pSampleOut);
    if (FAILED(hr))
    {
        goto done;
    }

    //Add the output buffer 
    hr = pSampleOut->AddBuffer(pBufferOut);
    if (FAILED(hr))
    {
        goto done;
    }
 
    //Set the output sample
    mftOutputData.pSample = pSampleOut;

    //Set the output id
    mftOutputData.dwStreamID = m_dwOutputID;

    //Generate the output sample
    hr = m_pMFT->ProcessOutput(0, 1, &mftOutputData, &dwStatus);
    if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
    {
        hr = S_OK;
        goto done;
    }

    // TODO: Handle MF_E_TRANSFORM_STREAM_CHANGE

    if (FAILED(hr))
    {
        goto done;
    }

    *ppSample = pSampleOut;
    (*ppSample)->AddRef();

done:
    SafeRelease(&pBufferOut);
    SafeRelease(&pSampleOut);
    return hr;
};

ASF Multiplexer

Instantiating an Encoder MFT

Windows Media Encoders