Creación de gráficos con Capture Graph Builder
[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.
A pesar de su nombre, Capture Graph Builder es útil para crear muchos tipos de gráficos de filtros personalizados, no solo capturar gráficos. En este artículo se proporciona información general sobre cómo usar este objeto.
Capture Graph Builder expone la interfaz ICaptureGraphBuilder2 . Para empezar, llame a CoCreateInstance para crear el Generador de gráficos de captura y el Administrador de gráficos de filtros. A continuación, inicialice Capture Graph Builder llamando a ICaptureGraphBuilder2::SetFiltergraph con un puntero al Administrador de gráficos de filtros, como se indica a continuación:
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;
// Create the Filter Graph Manager.
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
if (SUCCEEDED(hr))
{
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void **)&pBuilder);
if (SUCCEEDED(hr))
{
pBuilder->SetFiltergraph(pGraph);
}
};
Conectar filtros
El método ICaptureGraphBuilder2::RenderStream conecta dos o tres filtros juntos en una cadena. Por lo general, el método funciona mejor cuando cada filtro no tiene más de un pin de entrada o de salida del mismo tipo. Esta explicación comienza ignorando los dos primeros parámetros de RenderStream y centrándose en los tres últimos parámetros. El tercer parámetro es un puntero IUnknown , que puede especificar un filtro (como puntero de interfaz IBaseFilter ) o un pin de salida (como puntero de interfaz IPin ). Los parámetros cuarto y quinto especifican punteros IBaseFilter . El método RenderStream conecta los tres filtros de una cadena. Por ejemplo, supongamos que A, B y C son filtros. Supongamos por ahora que cada filtro tiene exactamente un pin de entrada y un pin de salida. La siguiente llamada conecta A a B y, a continuación, B a C:
- 'RenderStream(NULL, NULL, A, B, C)'
Todas las conexiones son "inteligentes", lo que significa que se agregan filtros adicionales al gráfico según sea necesario. Para obtener más información, consulte Intelligent Connect. Para conectar solo dos filtros, establezca el valor intermedio en NULL. Por ejemplo, esta llamada conecta A a C:
- 'RenderStream(NULL, NULL, A, NULL, C)'
Puede crear cadenas más largas llamando al método dos veces:
- 'RenderStream(NULL, NULL, A, B, C)' 'RenderStream(NULL, NULL, C, D, E)'
Si el último parámetro es NULL, el método busca automáticamente un representador predeterminado. Usa Video Renderer para vídeo y DirectSound Renderer para audio. Así:
- 'RenderStream(NULL, NULL, A, NULL, NULL)'
es equivalente a
- 'RenderStream(NULL, NULL, A, NULL, R)'
donde R es el representador adecuado. Sin embargo, para conectar el filtro Representador de mezcla de vídeos en lugar de Video Renderer, debe especificarlo explícitamente.
Si especifica un filtro en el tercer parámetro, en lugar de un pin, es posible que tenga que indicar qué pin de salida se debe usar para la conexión. Ese es el propósito de los dos primeros parámetros del método. El primer parámetro solo se aplica a los filtros de captura. Especifica un GUID que indica una categoría de anclaje. Para obtener una lista completa de categorías, vea Anclar conjunto de propiedades. Dos de las categorías son válidas para todos los filtros de captura:
- PIN_CATEGORY_CAPTURE
- PIN_CATEGORY_PREVIEW
Si un filtro de captura no proporciona patillas independientes para la captura y la vista previa, el método RenderStream inserta un filtro Smart Tee , que divide la secuencia en una secuencia de captura y una secuencia de vista previa. Desde el punto de vista de la aplicación, simplemente puede tratar todos los filtros de captura como tener patillas independientes e ignorar la topología subyacente del grafo.
Para la captura de archivos, conecte el pin de captura a un filtro mux. Para la vista previa en directo, conecte el pin de vista previa a un representador. Si cambia las dos categorías, el gráfico podría quitar un número excesivo de fotogramas durante la captura de archivos; pero si el grafo está conectado correctamente, quita los fotogramas de vista previa según sea necesario para mantener el rendimiento en la secuencia de captura.
En el ejemplo siguiente se muestra cómo conectar ambas secuencias:
// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, NULL, pCapFilter, NULL, pMux);
// Preview:
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, NULL, pCapFilter, NULL, NULL);
Algunos filtros de captura también admiten subtítulos, indicados por PIN_CATEGORY_VBI. Para capturar los subtítulos en un archivo, represente esta categoría en el filtro mux. Para ver los subtítulos en la ventana de vista previa, conéctese al representador:
// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, pMux);
// Preview on screen:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, NULL);
El segundo parámetro de RenderStream identifica el tipo de medio y normalmente es uno de los siguientes:
- MEDIATYPE_Audio
- MEDIATYPE_Video
- MEDIATYPE_Interleaved (DV)
Puede usar este parámetro siempre que las patillas de salida del filtro admitan la enumeración de tipos de medios preferidos. En el caso de los orígenes de archivos, Capture Graph Builder agrega automáticamente un filtro de analizador si es necesario y, a continuación, consulta los tipos de medios en el analizador. (Para obtener un ejemplo, vea Recompressing an AVI File).) Además, si el último filtro de la cadena tiene varios pines de entrada, el método intenta enumerar sus tipos de medios. Sin embargo, no todos los filtros admiten esta funcionalidad.
Buscar interfaces en filtros y patillas
Después de compilar un grafo, normalmente tendrá que buscar varias interfaces expuestas por filtros y patillas en el gráfico. Por ejemplo, un filtro de captura podría exponer la interfaz IAMDroppedFrames , mientras que las patillas de salida del filtro podrían exponer la interfaz IAMStreamConfig .
La manera más sencilla de encontrar una interfaz es usar el método ICaptureGraphBuilder2::FindInterface . Este método recorre el gráfico (filtros y patillas) hasta que localiza la interfaz deseada. Puede especificar el punto de partida de la búsqueda y puede limitar la búsqueda a filtros ascendentes o descendentes desde el punto inicial.
En el ejemplo siguiente se busca la interfaz IAMStreamConfig en un pin de vista previa de vídeo:
IAMStreamConfig *pConfig = NULL;
HRESULT hr = pBuild->FindInterface(
&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video,
pVCap,
IID_IAMStreamConfig,
(void**)&pConfig
);
if (SUCCESSFUL(hr))
{
/* ... */
pConfig->Release();
}
Nota:
El tema Buscar una interfaz en un filtro o pin muestra un enfoque alternativo que usa la interfaz IGraphBuilder en lugar de ICaptureGraphBuilder2. El enfoque que se debe usar depende de la aplicación. Si la aplicación ya usa ICaptureGraphBuilder2 para compilar el grafo, ICaptureGraphBuilder2::FindInterface es un buen enfoque. De lo contrario, considere la posibilidad de usar los métodos IGraphBuilder .
Buscar patillas
Con menos frecuencia, es posible que tenga que buscar un pin individual en un filtro, aunque en la mayoría de los casos los métodos RenderStream y FindInterface le ahorrarán el problema. Si necesita encontrar un pin determinado en un filtro, el método auxiliar ICaptureGraphBuilder2::FindPin es útil. Especifique la categoría, el tipo de medio (vídeo o audio), la dirección y si la patilla debe estar desconectada.
Por ejemplo, el código siguiente busca un pin de vista previa de vídeo no conectado en un filtro de captura:
IPin *pPin = NULL;
hr = pBuild->FindPin(
pCap, // Pointer to the filter to search.
PINDIR_OUTPUT, // Search for an output pin.
&PIN_CATEGORY_PREVIEW, // Search for a preview pin.
&MEDIATYPE_Video, // Search for a video pin.
TRUE, // The pin must be unconnected.
0, // Return the first matching pin (index 0).
&pPin); // This variable receives the IPin pointer.
if (SUCCESSFUL(hr))
{
/* ... */
pPin->Release();
}
Temas relacionados