Поделиться через


Обработка данных в кодировщике

После согласования типа входных и выходных данных для кодировщика MFT, как описано в разделе Согласование типов мультимедиа в кодировщике, можно начать обработку примеров данных мультимедиа. Данные передаются в виде примеров носителей (интерфейс IMFSample ), а также поступают из выходных данных в виде примеров носителей.

Перед отправкой данных в кодировщик для обработки необходимо выделить образец носителя и добавить один из буферов мультимедиа, содержащих данные мультимедиа, которые необходимо закодировать. Вызовите IMFTransform::P rocessInput и передайте указатель на выделенный образец носителя. Помимо примера мультимедиа , ProcessInput также нуждается в идентификаторе входного потока. Чтобы получить идентификатор потока, вызовите IMFTransform::GetStreamIDs. Так как кодировщик предназначен для того, чтобы иметь только один и один выход, эти идентификаторы потоков всегда имеют значение 0.

Чтобы получить данные из кодировщика, вызовите IMFTransform::P rocessOutput. Прежде чем вызывать ProcessOutput, необходимо выяснить, выделяет ли кодировщик примеры выходных носителей или это необходимо сделать явно. Для этого вызовите IMFTransform::GetOutputStreamInfo. При этом возвращаются выходные сведения о образце носителя в структуре MFT_OUTPUT_STREAM_INFO . Если кодировщик выделяет примеры мультимедиа, он возвращает флаг MFT_OUTPUT_STREAM_PROVIDES_SAMPLES в члене dwFlags , а элемент cbSize содержит ноль. Если кодировщик ожидает выделения выходного буфера, создайте образец выходного носителя и связанный буфер мультимедиа на основе размера, возвращаемого в cbSize. При вызове ProcessSample передайте указатель на только что созданный пример мультимедиа. Во время сеанса кодирования кодировщик заполняет буферы мультимедиа, на которые указывает пример выходного носителя, закодированными данными.

Чтобы начать сеанс кодирования, передайте пример входного носителя кодировщику, вызвав ProcessInput. Кодировщик начинает обработку и данные и создает один или несколько примеров выходных носителей, которые должны быть извлечены ProcessOutput при условии, что он возвращает MF_E_TRANSFORM_NEED_MORE_INPUT. Если вы вызываете ProcessInput для передачи дополнительных входных данных при наличии выходных данных для извлечения, ProcessInput завершается сбоем с MF_E_NOTACCEPTING. Кодировщик не принимает больше входных данных, пока клиент не вызовет ProcessOutput хотя бы один раз.

Необходимо задать точные метки времени и длительность для всех пройденных входных примеров. Метки времени не являются обязательными, но помогают поддерживать синхронизацию звука и видео. Если у вас нет меток времени для ваших примеров, лучше оставить их, чем использовать неопределенные значения.

Пример обработки кодировщика

В следующем примере кода показано, как вызвать IMFTransform::P rocessOutput для получения закодированного примера. Полный контекст этого примера см. в разделе Кодировщик Пример кода.

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

Создание экземпляра кодировщика MFT

Кодировщики Windows Media