如何在捕获过滤器上的DirectShow put_Enable调用期间调试未指定的错误($ 80004005)?

时间:2011-11-12 06:16:21

标签: delphi filter directshow hresult dspack

我有一个使用DSPACK组件库在Delphi 6中编写的DirectShow应用程序。我有一个奇怪的问题,在过滤器上启用输入行。我搜索引脚,直到找到输入线,在本例中名为'Microphone',并在Filter Graph处于活动状态时调用put_Enable(true)。当我这样做时,我得到$ 80004005“未指定的错误”作为HRESULT。

我在启用输入行之前设置过滤器的输出音频媒体类型,但某些功能无法正常工作。我创建我的应用程序的原始DirectShow示例工作正常。我相信我正在遵循构建我的过滤器图表的完全相同的步骤,我当然可能错过了一些东西。对于我可以尝试解决这个问题的事情,有没有人有任何提示或想法?下面的代码片段部分显示了我正在做的事情,但不是所有导致它的步骤,因为它们非常冗长。我用于测试的捕获设备是一个VOIP耳机,带有一条名为“麦克风”的输入线。

// The function I call to find an enable the first input line I find in the filter.
function findAndEnableFirstInputLineFound(intfBaseFilter: IBaseFilter; out strInputLineUsed: string): boolean;
var
    thePinList: TPinList;
    i: integer;
    ABool: LongBool;
begin
    strInputLineUsed := '';

    if not Assigned(intfBaseFilter) then
        raise Exception.Create('(findAndEnableFirstInputLineFound) The base filter interface object is unassigned.');

    // Now enable the first input source we can find.
    Result := false;
    thePinList := TPinList.Create(intfBaseFilter);

    try
        if thePinList.Count > 0 then
        begin
            // Scan the pin list looking for an input pin.
            i := 0;

            while (i < thePinList.Count) and (not Result) do
            begin
                if thePinList.PinInfo[i].dir = PINDIR_INPUT then
                begin
                    // Found one.  Enable it.
                    with thePinList.Items[i] as IAMAudioInputMixer do
                    begin
                        CheckDSEror(put_Enable(true)); // $80004005 error occurs here.

                        // Return the name of the input line used.
                        strInputLineUsed := thePinList.PinInfo[i].achName;
                    end; // with thePinList.Items[i] as IAMAudioInputMixer do

                    Result := true;
                    break; // Stop looping.
                end; // if thePinList.PinInfo[i].dir = PINDIR_INPUT then

                Inc(i);
            end; // while()
        end; // if thePinList.Count > 0 then
    finally
        thePinList.Free;
    end; // try
end;


// The initialization procedure that calls the function above.  It is run after the
//  the Filter Graph is activated but before it is played.
procedure TDXChain_wavaudio.initializeCaptureFilter;
var
    theMediaType: TMediaType;
    intfCapturePin: IPin;
    aryEnabledInputLines: TDynamicStringArray;
begin
    theMediaType := nil;
    intfCapturePin := nil;
    aryEnabledInputLines := nil;

    if not FFilterGraph.Active then
        raise Exception.Create('(TDXChain_wavaudio.Create::initializeCaptureFilter) The Filter Graph is INACTIVE.');

    if Assigned(FCaptureFilter) then
    begin

        // Make sure the Capture Filter's output pins supports the
        //   configured WAV format.
        with FOwner.ati_WaveFormatEx do
        begin
            // if not Assigned(findAudioMediaTypeByFormat(FCaptureFilter_mediatypes, nSamplesPerSec, wBitsPerSample, nChannels)) then
            theMediaType := findAudioMediaTypeExt_outputs(FCaptureFilter as IBaseFilter, nSamplesPerSec, wBitsPerSample, nChannels);

            if not Assigned(theMediaType) then
                // The capture device does not directly support the desired
                //  WAV format.  This is not allowed currently.
                raise Exception.Create('(TDXChain_wavaudio.Create::initializeCaptureFilter) The audio input device''s output pins does not support the given WAV format: '
                        + CRLF
                        + Format('(Device name: %s, Sample Rate: %d, Bits Per Sample: %d, Number of Channels: %d)',
                                    [FOwner.FCaptureFilterConfigInfo.filterName, nSamplesPerSec, wBitsPerSample, nChannels])
                    );

            // -------------- SET OUTPUT PINS TO MEDIA TYPE -------------

            // Set the output pins to the desired format.
            setPinAudMediaType_outputs(FCaptureFilter, theMediaType.AMMediaType);

            // Don't need the media type anymore.
            FreeAndNil(theMediaType);
        end; // with FOwner.ati_WaveFormatEx do

        // Enable at least one input line.
        if FOwner.FCaptureFilterConfigInfo.inputPinName = '' then
        begin
            //  No input name was specified so use the first one found.
            if not findAndEnableFirstInputLineFound(FCaptureFilter as IBaseFilter, FOwner.FInputLineUsed) then
                raise Exception.Create(
                    '(TDXChain_wavaudio.Create::initializeCaptureFilter) Unable to find a suitable input line for the audio input device named: '
                    + FOwner.FCaptureFilterConfigInfo.filterName);
        end
        else
        begin
            // Now find the desired available input line and enable it.
            if not findAndEnableInputLineByName(FOwner.FCaptureFilterConfigInfo.inputPinName, FCaptureFilter as IBaseFilter, FOwner.FInputLineUsed) then
                raise Exception.Create(
                    '(TDXChain_wavaudio.Create::initializeCaptureFilter) Unable to find the input line named ('
                    + FOwner.FCaptureFilterConfigInfo.inputPinName
                    + ') for the audio input device named: '
                    + FOwner.FCaptureFilterConfigInfo.filterName);
        end; // else - if FOwner.FCaptureFilterConfigInfo.inputPinName = '' then

        aryEnabledInputLines := getEnabledInputLineNames(FCaptureFilter as IBaseFilter);

        if Length(aryEnabledInputLines) < 1 then
            raise Exception.Create('(TDXChain_wavaudio.Create::initializeCaptureFilter) No input lines are enabled..');

        // ------------------ BUFFER LATENCY --------------------

        // Get a reference to the output pin for audio the capture device.
        with FCaptureFilter as IBaseFilter do
            CheckDSError(findPin(StringToOleStr('Capture'), intfCapturePin));

        if not Assigned(intfCapturePin) then
            raise Exception.Create('(TDXChain_wavaudio.Create::initializeCaptureFilter) Unable to find the audio input device''s Capture output pin.');

        // Set the capture device buffer to 50 ms worth of audio data to
        //  reduce latency.  NOTE: This will fail if the device does not
        //  support the latency you desire so make sure you watch out for that.
        setBufferLatency(intfCapturePin as IAMBufferNegotiation, FOwner.ati_BufferLatency_ms, FOwner.FMediaType);
    end; // if Assigned(FCaptureFilter) then
end;

1 个答案:

答案 0 :(得分:1)

我认为Audio Capture Filter在尝试启用某些引脚以便混合到录制时依赖于底层硬件和驱动程序。如果基础层失败并显示错误,则会将此错误转发给您。

作为猜测,当您尝试在另一个引脚已启用时启用引脚时,捕获硬件可能会指示错误,即它实际上无法混合两者。