问题

我正在尝试调用ProcessOutput来从我的解码器获取解码数据并出现以下错误:



我尝试过的

由于ProcessOutput具有许多参数,因此我试图查明错误可能是什么。 Documentation for ProcessOutput 没有提到E_INVALIDARG。但是,documentation for MFT_OUTPUT_DATA_BUFFER (其中一个参数的数据类型)在其“备注”部分中提到:



它谈论的是如何设置MFT_OUTPUT_DATA_BUFFER结构。因此,错误设置的MFT_OUTPUT_DATA_BUFFER可能会导致该错误。但是,我尝试正确设置它。

通过调用GetOutputStreamInfo,我发现我需要分配发送给ProcessOutput的样本。我正在使用与ProcessInput几乎相同的方法,所以我不知道我在做什么错。

我还试图确保逻辑上也应该引起E_INVALIDARG的其他参数。它们对我来说看起来不错,而我无法找到其他导致我的ProcessOutput参数无效的线索。

编码

我试图仅在下面发布代码的相关部分。为了简洁起见,我已删除或简化了许多错误检查。请注意,我使用的是纯C。

“序幕”

...
hr = pDecoder->lpVtbl->SetOutputType(pDecoder, dwOutputStreamID, pMediaOut, dwFlags);
...
// Send input to decoder
hr = pDecoder->lpVtbl->ProcessInput(pDecoder, dwInputStreamID, pSample, dwFlags);
if (FAILED(hr)) { /* did not fail */ }

因此,在下面有趣的代码之前,我已经成功设置了东西(希望如此)并将它们发送到没有失败的ProcessInput。我有1个输入流和1个输出流,AAC输入,PCM输出。

代码直接导致错误

// Input has now been sent to the decoder
// To extract a sample from the decoder we need to create a strucure to hold the output
// First we ask the OutputStream for what type of output sample it will produce and who should allocate it
// Then we create both the sample in question (if we should allocate it that is) and the MFT_OUTPUT_DATA_BUFFER
// which holds the sample and some other information that the decoder will fill in.

#define SAMPLES_PER_BUFFER 1 // hardcoded here, should depend on GetStreamIDs results, which right now is 1

MFT_OUTPUT_DATA_BUFFER pOutputSamples[SAMPLES_PER_BUFFER];
DWORD *pdwStatus = NULL;

// There are different allocation models, find out which one is required here.
MFT_OUTPUT_STREAM_INFO streamInfo = { 0,0,0 };
MFT_OUTPUT_STREAM_INFO *pStreamInfo = &streamInfo;

hr = pDecoder->lpVtbl->GetOutputStreamInfo(pDecoder, dwOutputStreamID, pStreamInfo);
if (FAILED(hr)) { ... }

if (pStreamInfo->dwFlags == MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) { ... }
else if (pStreamInfo->dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) { ... }
else {
    // default, the client must allocate the output samples for the stream
    IMFSample *pOutSample = NULL;
    DWORD minimumSizeOfBuffer = pStreamInfo->cbSize;
    IMFMediaBuffer *pBuffer = NULL;

    // CreateMediaSample is explained further down.
    hr = CreateMediaSample(minimumSizeOfBuffer, sampleDuration, &pBuffer, &pOutSample);
        if (FAILED(hr)) {
            BGLOG_ERROR("error");
        }

    pOutputSamples[0].pSample = pOutSample;
}

// since GetStreamIDs return E_NOTIMPL then dwStreamID does not matter
// but its recomended that it is set to the array index, 0 in this case.
// dwOutputStreamID will be 0 when E_NOTIMPL is returned by GetStremIDs
pOutputSamples[0].dwStreamID = dwOutputStreamID; // = 0
pOutputSamples[0].dwStatus = 0;
pOutputSamples[0].pEvents = NULL; // have tried init this myself, but MFT_OUTPUT_DATA_BUFFER documentation says not to.

hr = pDecoder->lpVtbl->ProcessOutput(pDecoder, dwFlags, outputStreamCount, pOutputSamples, pdwStatus);
if (FAILED(hr)) {
    // here E_INVALIDARG is found.
}

代码中使用的CreateMediaSample是从官方文档的an example派生而来的,但已修改为调用SetSampleDuration和SetSampleTime。我通过不设置这两个来得到相同的错误,因此应该是引起问题的其他原因。

发送到ProcessOutput的一些实际数据

万一我可能错过了一些从实际数据中容易看到的东西:
hr = pDecoder->lpVtbl->ProcessOutput(
    pDecoder, // my decoder
    dwFlags, // 0
    outputStreamCount, // 1 (from GetStreamCount)
    pOutputSamples, // se comment below
    pdwStatus // NULL
);
// pOutputSamples[0] holds this struct:
// dwStreamID = 0,
// pSample = SampleDefinedBelow
// dwStatus = 0,
// pEvents = NULL

// SampleDefinedBelow:
// time = 0
// duration = 0.9523..
// buffer = with max length set correctly
// attributes[] = NULL



因此,有人对我做错了什么或如何进一步调试有任何想法吗?

最佳答案

ProcessOutput需要一个有效的指针作为最后一个参数,因此不起作用:

DWORD *pdwStatus = NULL;
pDecoder->lpVtbl->ProcessOutput(..., pdwStatus);

没关系:
DWORD dwStatus;
pDecoder->lpVtbl->ProcessOutput(..., &dwStatus);

关于进一步的E_FAIL-一般来说,您在上面的发现看起来不错。并不是我看到明显的东西,而且错误代码也没有表明问题出在MFT数据流上。可能是不良数据或与设置的媒体类型不匹配的数据。

关于c - IMFTransform::ProcessOutput返回E_INVALIDARG,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41983374/

10-10 18:16