Как отладить неопределенную ошибку ($ 80004005) во время вызова DirectShow put_Enable для фильтра Capture? - PullRequest
1 голос
/ 12 ноября 2011

У меня есть приложение DirectShow, написанное на Delphi 6 с использованием библиотеки компонентов DSPACK.У меня странная проблема с включением строки ввода в фильтре.Я ищу контакты до тех пор, пока не найду строку ввода, в данном случае называемую «Микрофон», и вызываю 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 Ответ

1 голос
/ 14 ноября 2011

Я бы предположил, что Audio Capture Filter опирается на базовое оборудование и драйвер при попытке включить определенный вывод для микширования в записи. Если нижележащий слой завершается с ошибкой, эта ошибка пересылается вам.

Как можно предположить, аппаратное обеспечение захвата может указывать на ошибку, когда вы пытаетесь включить вывод, когда другой вывод уже включен, то есть он фактически не может смешивать их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...