在编码器中处理数据
按照编码器上的 媒体类型协商中所述,协商编码器 MFT 的输入类型和输出类型后,可以开始处理媒体数据示例。 数据以媒体样本的形式传递, (IMFSample 接口) 传递,并作为媒体样本从输出接收。
在将数据发送到编码器进行处理之前,必须分配媒体示例并添加包含需要编码的媒体数据的多个媒体缓冲区之一。 调用 IMFTransform::P rocessInput 并将指针传递到分配的媒体示例。 除了媒体示例, ProcessInput 还需要输入流标识符。 若要获取流标识符,请调用 IMFTransform::GetStreamIDs。 由于编码器设计为只有一个和一个输出,因此这些流标识符的值为 0。
若要从编码器获取数据,请调用 IMFTransform::P rocessOutput。 在调用 ProcessOutput 之前,需要确定编码器是分配输出媒体样本还是必须显式分配。 为此,请调用 IMFTransform::GetOutputStreamInfo。 这将返回 MFT_OUTPUT_STREAM_INFO 结构中的输出媒体示例信息。 如果编码器分配媒体样本,它将返回 dwFlags 成员中的 MFT_OUTPUT_STREAM_PROVIDES_SAMPLES 标志, cbSize 成员包含零。 如果编码器希望分配输出缓冲区,请根据 cbSize 中返回的大小创建输出媒体示例和关联的媒体缓冲区。 调用 ProcessSample 时,将指针传递到新创建的媒体示例。 在编码会话期间,编码器使用编码的数据填充由输出媒体示例指向的媒体缓冲区。
若要启动编码会话,请通过调用 ProcessInput 将输入媒体示例传递给编码器。 编码器开始处理数据,并生成一个或多个输出媒体样本,只要返回MF_E_TRANSFORM_NEED_MORE_INPUT, ProcessOutput 就必须检索这些样本。 如果调用 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;
};
相关主题