2011-11-12 9 views
1

私はDSPACKコンポーネントライブラリを使用してデルファイ6で記述されたDirectShowのアプリケーションを持っています。私は奇妙な問題をフィルタ上の入力行を有効にしています。入力ライン(この場合は「Microphone」)が見つかるまで、ピンを検索し、フィルタグラフがアクティブな間にput_Enable(true)を呼び出します。私がこれをすると、HRESULTとして$ 80004005の "不特定のエラー"が出ます。

Iは入力行を有効にする前に、フィルタの出力オーディオメディアタイプを設定しています、まだ何かが右に機能していません。私のアプリケーションを作成するために取り組んだオリジナルのDirectShowサンプルは正常に動作します。私は私のフィルタグラフを構築する全く同じステップを踏襲していると信じています。誰にも私はこの問題を解決しようとすることができるもののためのヒントやアイデアを持っていますか?以下のコードスニペットは、私がやっていることを部分的に示していますが、極端に長いので、それに至るすべてのステップを示すわけではありません。私がテストに使用しているキャプチャデバイスは、「Microphone」という名前の単一の入力ラインを持つ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

私は記録に混合するための特定のピンを有効にしようとしたときAudio Capture Filterは、基盤となるハードウェアとドライバに依存していると仮定します。下層にエラーが発生した場合は、このエラーが転送されます。推測として

、あなたは別のピンがすでに有効になっている場合、ピンを有効にしようとしているときに、ハードウェアのエラーを示す可能性がありますキャプチャし、それは実際には二つの混合を行うことができないです。まさにそれだった

+0

。グラフ編集に行くと、下流のフィルタの入力ピンで複数の接続が許可されないことを確認しました。あなたはDirectShowのフィルタは、1つの入力または出力ピン接続よりも多くを受け入れ、またはそれがこれを決定し、いくつかの他のフィルタ方法であるかどうかを判断するためにCheckConnect()呼び出しの戻り値に依存しているかどうかを知ることが起こるのでしょうか? –

+0

フィルタはいつでも新しいピンを自由に追加できます。接続されていない既存のピンを取り外す場合も同様です。アプリケーションまたはフィルタグラフでフィルタのピンをチェックする必要があるたびに、列挙子を使用して、使用可能なピンを確認します。 –

+0

ありがとうございます。 Filter Graphに私の特異なOutputピンがすでに使用中で、新しいOutput接続を受け入れないようにするには、どのような方法を変更する必要がありますか?言い換えれば、フィルタへの呼び出しによってピン列挙が容易になり、ピンのどのフィールド/プロパティによって呼び出し元にピンが使用できないことが通知されるのですか?または、代わりにそのように動作する場合、返されたリストにピンを含めるべきかどうかを判断するために、列挙中にどのようなフラグをチェックしますか?ピンが接続され、その 'IPIN :: ConnectedTo'と' IPIN :: ConnectionMediaType'方法で接続を示しているWhebn –

関連する問題