私は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;
。グラフ編集に行くと、下流のフィルタの入力ピンで複数の接続が許可されないことを確認しました。あなたはDirectShowのフィルタは、1つの入力または出力ピン接続よりも多くを受け入れ、またはそれがこれを決定し、いくつかの他のフィルタ方法であるかどうかを判断するためにCheckConnect()呼び出しの戻り値に依存しているかどうかを知ることが起こるのでしょうか? –
フィルタはいつでも新しいピンを自由に追加できます。接続されていない既存のピンを取り外す場合も同様です。アプリケーションまたはフィルタグラフでフィルタのピンをチェックする必要があるたびに、列挙子を使用して、使用可能なピンを確認します。 –
ありがとうございます。 Filter Graphに私の特異なOutputピンがすでに使用中で、新しいOutput接続を受け入れないようにするには、どのような方法を変更する必要がありますか?言い換えれば、フィルタへの呼び出しによってピン列挙が容易になり、ピンのどのフィールド/プロパティによって呼び出し元にピンが使用できないことが通知されるのですか?または、代わりにそのように動作する場合、返されたリストにピンを含めるべきかどうかを判断するために、列挙中にどのようなフラグをチェックしますか?ピンが接続され、その 'IPIN :: ConnectedTo'と' IPIN :: ConnectionMediaType'方法で接続を示しているWhebn –