Cómo usan los descodificadores IAMVideoAccelerator
[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.
La interfaz IAMVideoAccelerator permite operaciones genéricas de aceleración de vídeo, incluida la aceleración de vídeo DirectX (VA). En el caso de la aceleración de VA que no sea DirectX, el descodificador y el controlador de vídeo deben cumplir un protocolo común.
En esta sección se describe el orden general de las operaciones que cualquier descodificador debe seguir al usar esta interfaz. Encontrará más información específica de los descodificadores basados en VA de DirectX en Mapping DirectX Video Acceleration to IAMVideoAccelerator (Asignación de aceleración de vídeo de DirectX a IAMVideoAccelerator).
Nota:
Esta interfaz está disponible en Windows 2000 y versiones posteriores.
La interfaz IAMVideoAccelerator se expone en el pin de entrada del mezclador de superposición o del representador de mezcla de vídeo (VMR). La interfaz IAMVideoAcceleratorNotify se expone en el pin de salida del descodificador. La secuencia de eventos para conectar los patillas de filtro es la siguiente:
Filter Graph Manager llama a IPin::Connect en el pin de salida del filtro de descodificador. Un AM_MEDIA_TYPE es un parámetro opcional.
- AM_MEDIA_TYPE es una estructura de datos que describe un tipo de medio. Contiene un GUID de tipo principal (que en nuestro caso debe ser MEDIATYPE_Video), un GUID de subtipo (que en nuestro caso debe ser un GUID de acelerador de vídeo) y una variedad de otras cosas. Una de estas cosas es un GUID de tipo de formato que contiene información sobre el medio, incluido en nuestro caso el ancho y el alto de una imagen de vídeo sin comprimir, lo más probable es en una estructura MPEG1VIDEOINFO, VIDEOINFOHEADER, MPEG2VIDEOINFO o VIDEOINFOHEADER2 .
- La estructura AM_MEDIA_TYPE , si está presente, indica al descodificador que funcione con el tipo de medio especificado, que puede ser "totalmente especificado" o "parcialmente especificado". Si se "especifica completamente", el descodificador normalmente simplemente intentaría funcionar con ese tipo de medio. Si se "especifica parcialmente", intentará encontrar un modo de operación compatible "totalmente especificado" que puede usar para conectarse de forma coherente con el tipo de medio "especificado parcialmente".
- La manera normal de intentar encontrar un tipo de medio "totalmente especificado" para usar para una conexión es simplemente ejecutar una lista de cada tipo de medio "completamente especificado" que el pin de salida admite, que es compatible con el tipo de medio "parcialmente especificado" e intentar conectarse con cada uno de ellos hasta que se realice correctamente. Normalmente, el proceso sería similar si no hay ningún AM_MEDIA_TYPE contenido en la llamada IPin::Connect , pero con el pin de salida que necesita comprobar todos sus tipos multimedia.
Si el descodificador quiere comprobar si un AM_MEDIA_TYPE específico (incluido un GUID del acelerador de vídeo) es compatible con el pin de entrada de bajada, puede llamar a IPin::QueryAccept (con el GUID del acelerador de vídeo como subtipo de la AM_MEDIA_TYPE) o simplemente puede intentar conectarse a ese pin, tal y como se describe en el elemento 5 siguiente.
Si el descodificador no sabe qué GUID del acelerador de vídeo admite el pin de entrada de bajada y no desea proponer solo un GUID de acelerador de vídeo candidato concreto llamando al IPin::QueryAccept del pin de entrada de bajada, el descodificador puede llamar a IAMVideoAcceleratorGUIDs para obtener una lista de los GUID del acelerador de vídeo que admite el pin.
Para algunos GUID de acelerador de vídeo concretos, el descodificador puede llamar al IAMVideoAccelerator del pin de entrada de bajada::GetUncompFormatsSupported para obtener una lista de los formatos de píxel DDPIXELFORMAT que se pueden usar para representar un GUID de acelerador de vídeo específico. La lista devuelta debe considerarse en orden de preferencia decreciente (es decir, con el formato más preferido enumerado primero).
El descodificador llama al IPin::ReceiveConnection del pin de entrada de bajada y lo pasa un AM_MEDIA_TYPE con el GUID del acelerador de vídeo adecuado como subtipo del tipo de medio. Esto configura la conexión para la operación, incluida la creación de las superficies de salida sin comprimir (que se asignan mediante el ancho y alto que se encuentra en AM_MEDIA_TYPE, y el número de superficies que se asignarán mediante una llamada descrita a continuación, y cualquier otra información que tenga disponible el acelerador de vídeo y desee usar para ese propósito, como el PROPIO GUID del acelerador de vídeo). Si el pin de entrada de bajada rechaza el GUID del acelerador de vídeo o algún otro aspecto de la conexión, esto puede hacer que se produzca un error en IPin::ReceiveConnection . Si se produce un error en IPin::ReceiveConnection , se indica en un VALOR HRESULT devuelto y el descodificador puede intentar volver a realizar la llamada, por ejemplo, con un nuevo GUID del acelerador de vídeo en la estructura AM_MEDIA_TYPE .
[!Nota]
Esta es otra manera (y la forma más definitiva) de que el descodificador determine lo que admite el pin de entrada de bajada, simplemente llamando a IPin::ReceiveConnection e intentando conectarse y, a continuación, comprobando si el intento de conexión se realizó correctamente.
Durante IPin::ReceiveConnection, el representador llama al IAMVideoAcceleratorNotify::GetUncompSurfacesInfo del codificador, pasando el GUID del acelerador de vídeo y una estructura AMVAUncompBufferInfo , para averiguar cuántas superficies sin comprimir se van a asignar. El descodificador rellena y devuelve la estructura , que contiene el número mínimo y máximo de superficies que se asignarán del tipo determinado, y una estructura DDPIXELFORMAT que describe el formato de píxel de las superficies que se van a asignar.
[!Nota]
En realidad, no se pasa nada al descodificador en la llamada a IAMVideoAcceleratorNotify::GetUncompSurfacesInfo que no sea el GUID del acelerador de vídeo.
El representador llama al IAMVideoAcceleratorNotify::SetUncompSurfacesInfo del descodificador, pasando al descodificador el número real de superficies sin comprimir que se asignaron.
El representador llama al IAMVideoAcceleratorNotify::GetCreateVideoAcceleratorData del descodificador para obtener los datos necesarios para inicializar el acelerador de vídeo.
El descodificador llama a IAMVideoAccelerator::GetCompBufferInfo, pasándole un GUID de acelerador de vídeo, una estructura AMVAUncompDataInfo y el número de tipos de búfer comprimidos, para obtener un conjunto de estructuras de datos AMVACompBufferInfo , una que corresponde a cada tipo de búfer de datos comprimido usado por el GUID del acelerador de vídeo.
- La estructura AMVAUncompDataInfo contiene el ancho y alto de los datos descodificados sin comprimir (en píxeles) y DDPIXELFORMAT de la imagen sin comprimir.
- Las estructuras de datos AMVACompBufferInfo devueltas contienen:
Número de búferes comprimidos necesarios para el tipo específico.
Ancho y alto de la superficie que se va a crear (campos que pueden o no tener ningún significado real).
Nota:
La operación de asignación de superficie de DirectDraw para los búferes comprimidos no proporciona actualmente el ancho o alto de estas superficies para que sea mayor o igual que 2^15, aunque es posible que la llamada de asignación de superficie no produzca un error excesivamente si se infringe este límite. Por lo tanto, el controlador podría estructurar sus solicitudes de memoria de búfer comprimida para evitar estos tamaños extremos. Por ejemplo, en lugar de solicitar un búfer con width="1" y height="65536", el controlador debe solicitar un búfer de width="1024" y height="64".
Número total de bytes que va a usar la superficie.
Estructura de tipo DDSCAPS2 que define un objeto DirectDrawSurface, que describe las funcionalidades para crear superficies para almacenar datos comprimidos.
DDPIXELFORMAT, que describe el formato de píxel utilizado para crear superficies para almacenar datos comprimidos (un campo que puede o no tener ningún significado real).
Nota:
Las llamadas del representador a algunos de los métodos de interfaz IAMVideoAcceleratorNotify del descodificador pueden producirse (y normalmente) dentro de la llamada del descodificador a la IPin::ReceiveConnection del representador. En concreto, esto se aplica a lo siguiente:
Nota:
Para admitir cambios de formato dinámico, el descodificador también puede llamar a IPin::ReceiveConnection y otros métodos por encima mientras los filtros están conectados y en ejecución. Esta funcionalidad se proporciona con el fin de admitir cambios dinámicos en el formato (aunque no en el H.263, anexo P, sentido), ya que todos los conjuntos de datos se inician de nuevo desde cero y, por tanto, se pierde cualquier información de imagen de referencia.
A continuación se muestra una descripción del uso de IAMVideoAccelerator durante la operación después de la inicialización:
Para cada superficie sin comprimir, el descodificador llama a IAMVideoAccelerator::BeginFrame para comenzar el procesamiento para crear la imagen de salida. Cuando lo hace, el descodificador envía una estructura AMVABeginFrameInfo .
La estructura AMVABeginFrameInfo contiene un índice para un búfer de destino, un puntero a algunos datos que se van a enviar de bajada y un puntero a un lugar donde el acelerador puede colocar algunos datos para que el descodificador pueda leer.
NOTA 1: El acelerador no recibe realmente el índice del búfer de destino, ya que se traduce por el representador antes de bajar.
NOTA 2: Se puede llamar a IAMVideoAccelerator::BeginFrame más de una vez entre llamadas a IAMVideoAccelerator::EndFrame.
NOTA 3: No hay ninguna suposición dentro de la operación de interfaz que IAMVideoAccelerator::BeginFrame e IAMVideoAccelerator::EndFrame deben llamarse para el procesamiento de cada imagen individual en la secuencia de bits.
Lo que hace IAMVideoAccelerator::BeginFrame , en lo que respecta a la interfaz, es crear una asociación dentro del representador entre un índice y una superficie sin comprimir. También proporciona un medio para llamar a una función específica en un controlador de dispositivo (con compatibilidad con un medio de pasar datos arbitrarios entre el descodificador y el controlador del dispositivo).
(Sin embargo, en la operación de VA de DirectX hay un requisito que se describe a continuación que IAMVideoAccelerator::BeginFrame e IAMVideoAccelerator::EndFrame deben llamarse para el procesamiento de cada imagen individual en la secuencia de bits).
Para enviar datos sin comprimir al acelerador, el descodificador llama a:
- IAMVideoAccelerator::QueryRenderStatus para determinar si un búfer es seguro para leer o escribir en.
- IAMVideoAccelerator::GetBuffer para bloquear y obtener acceso a un búfer especificado (si no lo ha llamado anteriormente para obtener ese acceso). GetBuffer también se puede usar para obtener una copia del contenido de la última imagen de salida sin comprimir para la que se llamó a IAMVideoAccelerator::BeginFrame , siempre que no se haya llamado a IAMVideoAccelerator::EndFrame para ese índice de búfer de destino. Si el DDI devuelve un estado de representación de DDERR_WASSTILLDRAWING para el búfer solicitado, se operará un bucle de suspensión en GetBuffer hasta que se borre esta condición. Para llamar a GetBuffer, el descodificador necesitará información de una estructura de datos AMVACompBufferInfo que se obtiene llamando a IAMVideoAccelerator::GetCompBufferInfo.
- IAMVideoAccelerator::Execute para indicar que se deben procesar los datos de un conjunto de búferes comprimidos como se indica en una matriz de estructuras de datos AMVABUFFERINFO . Un código de función dwFunction se pasa al controlador en esta llamada. Un puntero lpPrivateInputData también se pasa a algunos datos para enviar datos de bajada y se pasa un puntero lpPrivateOutputData a un lugar donde el proceso de bajada puede colocar algunos datos para que el descodificador pueda leer.
- IAMVideoAccelerator::ReleaseBuffer para indicar que el descodificador ha completado el uso de un búfer especificado por el momento y ya no necesita acceso bloqueado al búfer. (Si el descodificador desea seguir usando el búfer, simplemente no puede llamar a IAMVideoAccelerator::ReleaseBuffer por el momento, evitando así la necesidad de llamar a IAMVideoAccelerator::GetBuffer hasta que realmente tenga intención de no usar el búfer más). El descodificador no debe escribir en el búfer después de llamar a Execute hasta que QueryRenderStatus indica que el búfer es seguro para escribir.
Para completar el procesamiento de salida de un búfer de destino, el descodificador llama a IAMVideoAccelerator::EndFrame. Puede pasar algunos datos arbitrarios de bajada con esta llamada, y eso es básicamente todo lo que sucede como resultado de esta llamada. No envía un índice de búfer de destino en esta llamada, por lo que no puede indicar al acelerador con precisión qué búfer de destino se completa a menos que esta indicación esté contenida en los datos arbitrarios que se pasan.
Para mostrar un fotograma, el descodificador llama a IAMVideoAccelerator::D isplayFrame con el índice del marco que se va a mostrar y una estructura IMediaSample que contiene marcas de tiempo de inicio y detención y marcas relevantes, como dwTypeSpecificFlags en la estructura AM_SAMPLE2_PROPERTIES y dwInterlaceFlags en la estructura VIDEOINFOHEADER2 . El descodificador debe comprobar que todas las operaciones de descompresión que afectan al contenido del fotograma se han completado antes de llamar a DisplayFrame.
Por último, el descodificador debe, después de completar todo el procesamiento, indicar la finalización de todos los fotogramas de salida iniciados restantes mediante una llamada a IAMVideoAccelerator::EndFrame y liberar todos sus búferes bloqueados mediante una llamada a IAMVideoAccelerator::ReleaseBuffer para cada búfer no lanzado.
Temas relacionados