Escribir un proyecto en un archivo

[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.

[Esta API no se admite y puede modificarse o no estar disponible en el futuro].

En este artículo se describe cómo escribir un proyecto de DirectShow Editing Services en un archivo. En primer lugar se describe cómo escribir un archivo con el motor de representación básico. A continuación, describe la recompresión inteligente con el motor de representación inteligente.

Para obtener información general sobre cómo DirectShow Editing Services representa los proyectos, consulte Acerca de los motores de representación.

Uso del motor de representación básico

Empiece por compilar el front-end del grafo, como se indica a continuación:

  1. Cree el motor de representación.
  2. Especifique la escala de tiempo.
  3. Establezca el intervalo de representación. (Opcional)
  4. Compile el front-end del gráfico.

En el ejemplo de código siguiente se muestran estos pasos.

IRenderEngine *pRender = NULL; 
hr = CoCreateInstance(CLSID_RenderEngine, NULL, CLSCTX_INPROC,
    IID_IRenderEngine, (void**) &pRender);

hr = pRender->SetTimelineObject(pTL);
hr = pRender->ConnectFrontEnd( );

A continuación, agregue filtros de multiplexador y escritura de archivos al gráfico de filtros. La manera más fácil de hacerlo es con capture Graph Builder, un componente DirectShow para compilar gráficos de captura. El generador de gráficos de captura expone la interfaz ICaptureGraphBuilder2 . Lleve a cabo los siguiente pasos:

  1. Cree una instancia del generador de gráficos de captura.
  2. Obtenga un puntero al gráfico y páselo al generador de grafos.
  3. Especifique el nombre y el tipo de medio del archivo de salida. Este paso también obtiene un puntero al filtro mux, que es necesario más adelante.

En el ejemplo de código siguiente se muestran estos pasos.

CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, 
    IID_ICaptureGraphBuilder2, (void **)&pBuilder);

// Get a pointer to the graph front end.
IGraphBuilder *pGraph;
pRender->GetFilterGraph(&pGraph);
pBuilder->SetFiltergraph(pGraph);

// Create the file-writing section.
IBaseFilter *pMux;
pBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, 
    OLESTR("Output.avi"), &pMux, NULL);

Por último, conecte las patillas de salida del front-end al filtro mux.

  1. Recupere el número de grupos.
  2. Para cada patilla, obtenga un puntero al pin.
  3. Opcionalmente, cree una instancia de un filtro de compresión para comprimir la secuencia. El tipo de compresor dependerá del tipo de medio del grupo. Puede usar el enumerador de dispositivos del sistema para enumerar los filtros de compresión disponibles. Para obtener más información, vea Enumerar dispositivos y filtros.
  4. Opcionalmente, establezca parámetros de compresión, como la velocidad de fotograma clave. Este paso se describe en detalle más adelante en el artículo.
  5. Llame a ICaptureGraphBuilder2::RenderStream. Este método toma punteros al pin, el filtro de compresión (si existe) y el multiplexador.

En el ejemplo de código siguiente se muestra cómo conectar los pines de salida.

long NumGroups;
pTimeline->GetGroupCount(&NumGroups);

// Loop through the groups and get the output pins.
for (i = 0; i < NumGroups; i++)
{
    IPin *pPin;
    if (pRender->GetGroupOutputPin(i, &pPin) == S_OK) 
    {
        IBaseFilter *pCompressor;
        // Create a compressor filter. (Not shown.)
        // Set compression parameters. (Not shown.)

        // Connect the pin.
        pBuilder->RenderStream(NULL, NULL, pPin, pCompressor, pMux);
        pCompressor->Release();
        pPin->Release();
    }
}

Para establecer parámetros de compresión (paso 4, anteriormente), use la interfaz IAMVideoCompression . Esta interfaz se expone en los pines de salida de los filtros de compresión. Enumere las patillas del filtro de compresión y consulte cada pin de salida para IAMVideoCompression. (Para obtener información sobre la enumeración de patillas, vea Enumerar pins). Asegúrese de liberar todos los punteros de interfaz que obtuvo durante este paso.

Después de compilar el gráfico de filtros, llame al método IMediaControl::Run en el administrador de gráficos de filtros. A medida que se ejecuta el grafo de filtro, escribe los datos en un archivo. Use la notificación de eventos para esperar a que se complete la reproducción. (Consulte Responder a eventos). Cuando finalice la reproducción, debe llamar explícitamente a IMediaControl::Stop para detener el gráfico de filtros. De lo contrario, el archivo no se escribe correctamente.

Uso del motor de representación inteligente

Para obtener las ventajas de la recompresión inteligente, use el motor de representación inteligente en lugar del motor de representación básico. Los pasos para crear el grafo son casi los mismos. La principal diferencia es que la compresión se controla en el front-end del grafo, no en la sección de escritura de archivos.

Importante

No use el motor de representación inteligente para leer o escribir archivos de Windows Media.

 

Cada grupo de vídeo tiene una propiedad que especifica el formato de compresión de ese grupo. El formato de compresión debe coincidir exactamente con el formato sin comprimir del grupo en alto, ancho, profundidad de bits y velocidad de fotogramas. El motor de representación inteligente usa el formato de compresión cuando construye el gráfico. Antes de establecer el formato de compresión, asegúrese de establecer el formato sin comprimir para ese grupo llamando a IAMTimelineGroup::SetMediaType.

Para establecer el formato de compresión de un grupo, llame al método IAMTimelineGroup::SetSmartRecompressFormat . Este método toma un puntero a una estructura SCompFmt0 . La estructura SCompFmt0 tiene dos miembros: nFormatId, que debe ser cero y MediaType, que es una estructura AM_MEDIA_TYPE . Inicialice la estructura AM_MEDIA_TYPE con la información de formato.

Nota:

Si desea que el proyecto final tenga el mismo formato que uno de los archivos de origen, puede obtener la estructura de AM_MEDIA_TYPE directamente desde el archivo de origen, mediante el detector de medios. Consulte IMediaDet::get_StreamMediaType.

 

Convierta la variable SCompFmt0 en un puntero de tipo long, como se muestra en el ejemplo siguiente.

SCompFmt0 *pFormat = new SCompFmt0;
memset(pFormat, 0, sizeof(SCompFmt0));
pFormat->nFormatId = 0;

// Initialize pFormat->MediaType. (Not shown.)

pGroup->SetSmartRecompressFormat( (long*) pFormat );

El motor de representación inteligente busca automáticamente un filtro de compresión compatible. También puede especificar un filtro de compresión para un grupo llamando a ISmartRenderEngine::SetGroupCompressor.

Para compilar el grafo, siga los mismos pasos descritos para el motor de representación básico en la sección anterior. Las únicas diferencias son las siguientes:

  • Use el motor de representación inteligente, no el motor de representación básico. El identificador de clase es CLSID_SmartRenderEngine.
  • Establezca los parámetros de compresión después de compilar el front-end, pero antes de representar los pines de salida. Llame al método ISmartRenderEngine::GetGroupCompressor para obtener un puntero al filtro de compresión de un grupo. A continuación, consulte la interfaz IAMVideoCompression , como se ha descrito anteriormente.
  • Al representar los pines de salida, no es necesario insertar un filtro de compresión. La secuencia ya está comprimida.

Representación de un proyecto