Udostępnij przez


Przetwarzanie danych w koderze

Po wynegocjowaniu typu danych wejściowych i wyjściowych dla kodera MFT, zgodnie z opisem w negocjacji typu danych na koderze, można rozpocząć przetwarzanie próbek danych multimedialnych. Dane są przekazywane w postaci próbek multimedialnych (interfejs IMFSample), a także odbierane z wyjścia jako próbki multimedialne.

Przed wysłaniem danych do koderze do przetwarzania, należy przydzielić próbkę nośnika i dodać jedną lub więcej buforów multimedialnych zawierających dane nośnika, które muszą być zakodowane. Wywołaj IMFTransform::ProcessInput i przekaż wskaźnik do przydzielonej próbki multimedialnej. Oprócz próbki multimediów, ProcessInput potrzebuje również identyfikatora strumienia wejściowego. Aby uzyskać identyfikator strumienia, wywołaj IMFTransform::GetStreamIDs. Ponieważ koder został zaprojektowany tak, aby miał tylko jedno i jedno dane wyjściowe, te identyfikatory strumienia zawsze mają wartość 0.

Aby pobrać dane z enkodera, wywołaj metodę IMFTransform::ProcessOutput. Przed wywołaniem ProcessOutputnależy dowiedzieć się, czy enkoder przydziela próbki multimedialne wyjściowe, czy należy to zrobić jawnie. W tym celu wywołaj IMFTransform::GetOutputStreamInfo. Zwraca informacje o próbce nośnika wyjściowego w strukturze MFT_OUTPUT_STREAM_INFO. Jeśli koder przydziela próbki multimediów, zwraca flagę MFT_OUTPUT_STREAM_PROVIDES_SAMPLES w dwFlags członka, a członek cbSize zawiera zero. Jeśli koder oczekuje przydzielenia buforu wyjściowego, utwórz próbkę nośnika wyjściowego i powiązany bufor multimediów na podstawie rozmiaru zwróconego w cbSize. Podczas wywoływania ProcessSampleprzekaż wskaźnik do nowo utworzonej próbki multimedialnej. Podczas sesji kodowania enkoder wypełnia bufory multimedialne, wskazywane przez próbkę wyjściową, zakodowanymi danymi.

Aby rozpocząć sesję kodowania, przekaż przykład nośnika wejściowego do kodera, wywołując ProcessInput. Koder rozpoczyna przetwarzanie danych i tworzy co najmniej jeden przykład nośnika wyjściowego, który musi zostać pozyskany przez ProcessOutput, dopóki zwraca MF_E_TRANSFORM_NEED_MORE_INPUT. Jeśli wywołasz ProcessInput, aby przekazać więcej danych wejściowych, gdy dostępne są dane wyjściowe do pobrania, ProcessInput zakończy się niepowodzeniem z MF_E_NOTACCEPTING. Koder nie akceptuje więcej danych wejściowych, dopóki klient nie wywoła ProcessOutput co najmniej raz.

Należy ustawić dokładne sygnatury czasowe i czasy trwania dla wszystkich przekazanych próbek wejściowych. Sygnatury czasowe nie są ściśle wymagane, ale pomagają zachować synchronizację audio/wideo. Jeśli nie masz sygnatur czasowych dla próbek, lepiej je pominąć niż używać niepewnych wartości.

Przykład przetwarzania kodera

Poniższy przykładowy kod pokazuje, jak wywołać IMFTransform::ProcessOutput w celu uzyskania zakodowanej próbki. Pełny kontekst tego przykładu można znaleźć w Koder przykładowy.

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;
};

multiplekser ASF

Utworzenie instancji kodera MFT

Koderów Windows Media