IMFTransform::ProcessOutput 返回 E_INVALIDARG

Posted

技术标签:

【中文标题】IMFTransform::ProcessOutput 返回 E_INVALIDARG【英文标题】:IMFTransform::ProcessOutput returns E_INVALIDARG 【发布时间】:2017-02-01 15:22:52 【问题描述】:

问题

我正在尝试拨打电话ProcessOutput 以从我的解码器获取解码数据并收到以下错误:

E_INVALIDARG 一个或多个参数无效。

我尝试过的

由于ProcessOutput 有很多论据,我试图找出错误可能是什么。 Documentation for ProcessOutput 没有提到 E_INVALIDARG。然而,documentation for MFT_OUTPUT_DATA_BUFFER(其中一个参数的数据类型)在其备注部分提到:

任何其他组合无效并导致ProcessOutput 返回E_INVALIDARG

它谈论的是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

问题

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

【问题讨论】:

至少,pdwStatus 事情不妙。你应该有 DWORD dwStatus 变量和 &dwStatus 作为参数。 @Alex Telon 尝试在 pOutputSamples[0].pSample = pOutSample; 之前将 pOutputSample 归零称呼。你是否也检查过 pStreamInfo->cbSize 的值是否不为 0? @RomanR。是的,感谢您提到一个明显的错误!我不再收到 E_INVALIDARG 错误,但现在我必须深入研究 E_FAIL。但是你的回答解决了问题。如果您将其添加为答案,我可以接受。 谢谢@VuVirt 虽然罗曼的回答解决了这个问题,但我尝试了你的建议,以防我错过了更多。我试过ZeroMemory(pOutputSamples, sizeof(MFT_OUTPUT_DATA_BUFFER)),但行为没有改变。 pStreamInfo->cbSize 是0x0000c000,dwFlags 是MFT_OUTPUT_STREAM_WHOLE_SAMPLES,cbAlignment 是0 【参考方案1】:

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

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

没关系:

DWORD dwStatus;
pDecoder->lpVtbl->ProcessOutput(..., &dwStatus);

关于进一步E_FAIL - 你上面的发现,总的来说,看起来不错。并不是说我看到了什么明显的东西,而且错误代码也不表明问题出在 MFT 数据流上。也许它可能是错误数据或与媒体类型集不匹配的数据。

【讨论】:

以上是关于IMFTransform::ProcessOutput 返回 E_INVALIDARG的主要内容,如果未能解决你的问题,请参考以下文章