2011-11-12 3 views
1

J'ai une application DirectShow écrite en Delphi 6 en utilisant la bibliothèque de composants DSPACK. J'ai un problème étrange permettant une ligne d'entrée sur un filtre. Je recherche les broches jusqu'à ce que je trouve la ligne d'entrée, dans ce cas nommé «Microphone», et appelez put_Enable (true) pendant que le graphique de filtre est actif. Quand je fais cela, je reçois une erreur non spécifiée de 80004005 $ comme HRESULT.

Je règle le type de support audio de sortie pour le filtre avant d'activer la ligne d'entrée, mais quelque chose ne fonctionne pas correctement. L'exemple DirectShow original dont j'ai travaillé pour créer mon application fonctionne correctement. Je crois que je suis exactement les mêmes étapes de construction de mon graphique de filtre, et il est possible que j'ai raté quelque chose bien sûr. Est-ce que quelqu'un a des conseils ou des idées pour les choses que je peux essayer de résoudre ce problème? l'extrait de code ci-dessous montre partiellement ce que je fais, mais pas toutes les étapes qui y conduisent, car elles sont extrêmement longues. Le périphérique de capture que j'utilise pour tester est un casque VOIP avec une ligne d'entrée unique appelée «Microphone».

// 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; 

Répondre

1

Je suppose que sur le matériel Audio Capture Filter repose sous-jacente et le conducteur lors d'une tentative pour activer certaines broches pour le mélange dans l'enregistrement. Si le calque sous-jacent échoue avec une erreur, cette erreur vous est transmise.

En guise de supposition, le matériel de capture peut indiquer une erreur lorsque vous essayez d'activer une broche lorsqu'une autre broche est déjà activée, c'est-à-dire qu'elle est réellement incapable de faire le mélange des deux.

+0

C'était exactement ça. J'ai confirmé cela en allant dans Graph Edit et il ne permettrait pas plus d'une connexion sur la broche d'entrée d'un filtre en aval. Savez-vous si DirectShow s'appuie sur le retour d'appel CheckConnect() pour déterminer si un filtre accepte plus d'une connexion d'entrée ou de sortie, ou est-ce une autre méthode de filtrage qui détermine cela? –

+0

Un filtre est libre d'ajouter de nouvelles broches à tout moment. La même chose s'applique à la suppression des broches existantes non connectées. Chaque fois qu'une application ou un graphe de filtre doit vérifier les broches du filtre, il utilise l'énumérateur pour voir quelles broches sont disponibles. –

+0

Merci. Quelle (s) méthode (s) dois-je modifier pour indiquer au filtre graphique que ma broche de sortie singulière est déjà utilisée et que je n'accepte pas de nouvelles connexions de sortie? En d'autres termes, quels appels faits au filtre facilitent l'énumération des broches et quel champ/propriété dans la broche permet à l'appelant de savoir que la broche est indisponible? Ou quel drapeau je vérifie pendant le dénombrement pour décider si une épingle devrait ou non être incluse dans la liste retournée, si cela fonctionne à la place? –

Questions connexes