Обработка данных в кодировщике
После согласования типа ввода и выходного типа для кодировщика MFT, как описано в разделе Согласование типов мультимедиа в кодировщике, можно начать обработку примеров данных мультимедиа. Данные передаются в форме медиа-образцов (IMF образец интерфейс) и также принимаются на выходе в качестве медиа-образцов.
Перед отправкой данных кодировщику для обработки необходимо выделить образец носителя и добавить один из нескольких буферов мультимедиа, содержащих данные мультимедиа, которые необходимо закодировать. Вызовите IMFTransform::ProcessInput и передайте указатель на выделенный медиасемпл. Помимо примера носителя, для ProcessInput также требуется идентификатор входного потока. Чтобы получить идентификатор потока, вызовите IMFTransform::GetStreamIDs. Так как кодировщик предназначен только для одного и одного выходных данных, эти идентификаторы потока всегда имеют значение 0.
Чтобы получить данные из кодировщика, вызовите IMFTransform::ProcessOutput. Перед вызовом 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;
};
Связанные разделы