Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
fw:dshow [2013/11/21 16:52] alfred [Formatos de captura y compresión] |
fw:dshow [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 85: | Línea 85: | ||
| Los datos son almacenados en buffers (simples arrays de bytes), están dentro de un objeto COM denominado media sample (implementa IMediaSample) y son creados por los allocators (IMemAllocator). Un allocator se asigna a una conexión entre pines (dos o más conexiones de pines pueden compartir el mismo allocator). \\ | Los datos son almacenados en buffers (simples arrays de bytes), están dentro de un objeto COM denominado media sample (implementa IMediaSample) y son creados por los allocators (IMemAllocator). Un allocator se asigna a una conexión entre pines (dos o más conexiones de pines pueden compartir el mismo allocator). \\ | ||
| Cuando un filtro necesita rellenar un buffer con datos le pide un sample al allocator llamando a IMemAllocator::GetBuffer. Si los samples están libres retornará un puntero a uno de ellos, si están en uso el método se bloqueará hasta que quede uno disponible. Un sample queda libre cuando el filtro downstream ha dejado de utilizarlo (p.ej. renderizandolo), de esa forma los samples no se sobreescriben. | Cuando un filtro necesita rellenar un buffer con datos le pide un sample al allocator llamando a IMemAllocator::GetBuffer. Si los samples están libres retornará un puntero a uno de ellos, si están en uso el método se bloqueará hasta que quede uno disponible. Un sample queda libre cuando el filtro downstream ha dejado de utilizarlo (p.ej. renderizandolo), de esa forma los samples no se sobreescriben. | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== Formato de los datos ==== | ||
| + | === Stride de la imagen === | ||
| + | El stride (o pitch) es el número de bytes de una fila de pixels que se reservan para agregar información adicional. Esto afecta al tamaño de la imagen en memoria pero no pero no a como esta se muestra. \\ | ||
| + | [[http://msdn.microsoft.com/en-us/library/windows/desktop/aa473780(v=vs.85).aspx|Artículo de MSDN]] | ||
| + | |||
| + | === Leer video no comprimido === | ||
| + | Video no comprimido es una secuencia de bitmaps mostrados en sucesión con ratio de unos 30 frames por segundo. Para descomprimir un frame se utilizará el método CTransformFilter::Transform; este recibe un puntero a IMediaSample donde están encapsulados los datos, IMediaSample::GetPointer retornará un puntero al primer byte de los datos. | ||
| + | |||
| + | === Producir video no comprimido === | ||
| + | |||
| + | Información sacada de la [[http://msdn.microsoft.com/en-us/library/windows/desktop/ff485865(v=vs.85).aspx|MSDN]], en ese artículo también hay ejemplos de... | ||
| + | * Función que asigna los valores para un vídeo sin comprimir. | ||
| + | * Descompresión de una imagen. | ||
| + | Cuando produzcamos vídeo no comprimido rellenaremos el IMFMediaType con los siguientes valores: | ||
| + | * MF_MT_MAJOR_TYPE: Asignarlo con MFMediaType_Video. | ||
| + | * MF_MT_SUBTYPE: [[http://msdn.microsoft.com/en-us/library/windows/desktop/aa370819(v=vs.85).aspx|Subtipos de video]]. | ||
| + | * MF_MT_DEFAULT_STRIDE: El número de bytes necesitado para ir de una fila de pixels a la siguiente (este valor se puede omitir si no es igual al ancho de la imagen en bytes). | ||
| + | * MF_MT_FRAME_RATE: Frame rate. | ||
| + | * MF_MT_FRAME_SIZE: Frame size. | ||
| + | * MF_MT_INTERLACE_MODE: Interlacing mode. | ||
| + | * MF_MT_ALL_SAMPLES_INDEPENDENT: Indica si cada sample es independiente (true en formato no comprimido). | ||
| + | * MF_MT_PIXEL_ASPECT_RATIO: Pixel aspect ratio. | ||
| + | Si se conocen se añadirán los siguientes valores: MF_MT_VIDEO_PRIMARIES, MF_MT_TRANSFER_FUNCTION, MF_MT_VIDEO_CHROMA_SITINGMF_MT_YUV_MATRIX y MF_MT_VIDEO_NOMINAL_RANGE. \\ | ||
| + | |||
| + | Existen las siguientes funciones que pueden ser de utilidad: | ||
| + | * MFAverageTimePerFrameToFrameRate: Calcula el frame rate a partir de la duración del frame. | ||
| + | * MFCalculateImageSize: Calcula el tamaño de la imagen para un video no comprimido. | ||
| + | * MFFrameRateToAverageTimePerFrame: Calcula la duracion de un video dando el frame rate. | ||
| + | * MFGetStrideForBitmapInfoHeader: Retorna el minimo valor de stride por formato de video. | ||
| + | * MFInitVideoFormat: Inicializa el MFVIDEOFORMAT para algunos formatos de video standard. | ||
| + | * MFIsFormatYUV: Indica si el formato es YUV. | ||
| + | |||
| + | |||
| + | === Cambio del formato de datos === | ||
| + | En el filtro upstream: | ||
| + | - El filtro downstream comprueba en la conexión quién debe ser propietario del allocator, si lo es el upstream no podrá cambiar el formato de los datos. | ||
| + | - El filtro downstream llama a IPin::QueryAccept del pin de output del upstream. | ||
| + | - Si QueryAccept retorna S_OK, entonce el filtro downstream llama al método privado del allocator para asignar el media type. Dentro de este método se llama a IMediaSample::SetMediaType. | ||
| + | - El filtro upstream llama a GetBuffer para tomar un nuevo sample y a IMediaSample::GetMediaType para obtener el media type. | ||
| + | - Cuando el filtro upstream deja el sample debe indicar el media type, de esa forma el filtro de downstream podrá conformar que el media type a cambiado. | ||
| + | |||
| + | === Explicación en MSDN === | ||
| + | * [[http://msdn.microsoft.com/en-us/library/windows/desktop/bb530104(v=vs.85).aspx|Conversion a YUV]] | ||
| + | * [[http://msdn.microsoft.com/en-us/library/windows/desktop/bb530115(v=vs.85).aspx|Crop, pan y aspect ratio]] | ||
| + | * [[http://msdn.microsoft.com/en-us/library/windows/desktop/dd407212(v=vs.85).aspx|Imagenes Top-Down y Bottom-Up]] | ||
| ==== Creación de un filtro ==== | ==== Creación de un filtro ==== | ||
| === CUnknown === | === CUnknown === | ||
| Línea 177: | Línea 227: | ||
| Para más información: [[http://msdn.microsoft.com/en-us/library/windows/desktop/dd389099(v=vs.85).aspx|How to Register DirectShow Filters]]. | Para más información: [[http://msdn.microsoft.com/en-us/library/windows/desktop/dd389099(v=vs.85).aspx|How to Register DirectShow Filters]]. | ||
| ==== Formatos de captura y compresión ==== | ==== Formatos de captura y compresión ==== | ||
| - | Para indicar los formatos de captura y compresión se utiliza el método IAMStreamConfig::GetStreamCaps. Este retorna un array de media type (estructura AM_MEDIA_TYPE) y structuras de capacidad (estructuras AUDIO_STREAM_CONFIG_CAPS o VIDEO_STREAM_CONFIG_CAPS). \\ | + | Para indicar los formatos de captura y compresión que el filtro produce se utiliza el método IAMStreamConfig::GetStreamCaps. Este retorna un array de media type (estructura AM_MEDIA_TYPE) y structuras de capacidad (estructuras AUDIO_STREAM_CONFIG_CAPS o [[http://msdn.microsoft.com/en-us/library/windows/desktop/dd407352(v=vs.85).aspx|VIDEO_STREAM_CONFIG_CAPS]]). De VIDEO_STREAM_CONFIG_CAPS sólo se utilizan los campos guid, VideoStandard, MinFrameInterval y MaxFrameInterval, estos dos últimos son necesarios para obtener el rango de los frame rates soportados por el dispositivo de captura (tiempo mínimo y máximo de duración de un frame). \\ |
| - | El método IAMStreamConfig::SetFormat devuelve el formato antes de la conexión entre pines. \\ | + | Por ejemplo podríamos tener los siguientes valores: |
| + | <code> | ||
| + | MinCroppingSize = (160, 120) | ||
| + | MaxCroppingSize = (320, 240) | ||
| + | CropGranularityX = 4 | ||
| + | CropGranularityY = 8 | ||
| + | CropAlignX = 2 | ||
| + | CropAlignY = 4 | ||
| + | </code> | ||
| + | Estos definen un grupo de rectángulos válidos para el rcSource del VIDEOINFOHEADER (o VIDEOINFOHEADER2). En este caso la estructura mínima es de 160x120 píxels. El tamaño en ancho puede incrementar en 4 hasta 320 y la altura en 8 hasta 240. CropAlignX y CropAlignY definen el crop para la ventana. Los siguientes valores serían válidos pues: | ||
| + | <code> | ||
| + | (0, 0, 160, 120) | ||
| + | (2, 0, 162, 120) | ||
| + | (2, 8, 162, 128) | ||
| + | </code> | ||
| + | |||
| + | |||
| + | El método IAMStreamConfig::SetFormat devuelve el formato antes de la conexión entre pines. \\ \\ | ||
| Supongamos que una captura se lleva a cabo en formato JPEG en todas las resoluciones entre 160x120 y 320x240; dicha diferencia entre las posibles resoluciones es denominada granularity. Si se permiten todas, la granularity es de 1, si por ejemplo fuese 8 las resoluciones serían: 160x120, 168x120, 168x128, 176x128... 312x232, 320x240. \\ | Supongamos que una captura se lleva a cabo en formato JPEG en todas las resoluciones entre 160x120 y 320x240; dicha diferencia entre las posibles resoluciones es denominada granularity. Si se permiten todas, la granularity es de 1, si por ejemplo fuese 8 las resoluciones serían: 160x120, 168x120, 168x128, 176x128... 312x232, 320x240. \\ | ||
| Se usará GetStreamCaps para indicar el formato de color (16b, 24b...), las resoluciones y la granularity (esta podría ser 0 también). Se utiliza la estructura VIDEOINFOHEADER, ésta contiene las siguientes propiedades: | Se usará GetStreamCaps para indicar el formato de color (16b, 24b...), las resoluciones y la granularity (esta podría ser 0 también). Se utiliza la estructura VIDEOINFOHEADER, ésta contiene las siguientes propiedades: | ||
| Línea 264: | Línea 331: | ||
| Los samples de un pin de preview, en cambio, no deberían contener time stamps. | Los samples de un pin de preview, en cambio, no deberían contener time stamps. | ||
| ==== Creación de un filtro source ==== | ==== Creación de un filtro source ==== | ||
| - | Una live-source toma los datos de una fuente externa (camara o stream de red) y no puede controlar el ratio de los datos. Si el filtro downstream (el siguiente) no consume los datos el filtro source tendrá que desacerse de ellos. \\ | + | Una live-source toma los datos de una fuente externa (camara o stream de red) y no puede controlar el ratio de los datos. Si el filtro downstream (el siguiente) no consume los datos el filtro source tendrá que desacerse de ellos. |
| - | Un source push no tiene por qué ser una live-source, también podría, por ejemplo, leer de un fichero local. En ese caso el downstream determinará cuan rápido lee los datos según el clock y los time stamps. \\ | + | |
| + | === Live-sources === | ||
| + | Una live-sorce devolverá AM_FILTER_MISC_FLAGS_IS_SOURCE en el método IAMFilterMiscFlags::GetMiscFlags y uno de sus pins deberá ser IAMPushSource. El filtro expondrá un IKsPropertySet y un pin de captura (PIN_CATEGORY_CAPTURE). \\ | ||
| + | La latencia del filtro es la cantidad de tiempo que le toma procesar un sample, en los live-source se determina por el tamaño del buffer. \\ | ||
| + | Los live-sources se sincronizarán por la interface IAMPushSource mediante el método IAMGraphStreams::SyncUsingStreamOffset. \\ | ||
| + | |||
| + | Un source push no será siempre una live-source, también podría, por ejemplo, leer de un fichero local. En ese caso el downstream determinará cuan rápido lee los datos según el clock y los time stamps. \\ | ||
| === Streaming de datos === | === Streaming de datos === | ||
| Línea 281: | Línea 354: | ||
| * CheckMediaType: que devuelve si acepta un tipo de datos (media type) concreto. Según implementes el GetMediaType será o no necesario sobreescribirlo. | * CheckMediaType: que devuelve si acepta un tipo de datos (media type) concreto. Según implementes el GetMediaType será o no necesario sobreescribirlo. | ||
| GetMediaType puede contener únicamente un puntero a CMediaType (cuando soporta un solo media type) o un puntero y una variable de índice (cuando soporta varios). Uno (y sólo uno) de los dos se ha de sobreescribir, en el caso de tener varios media types también deberá ser sobreescrito el CheckMediaType. \\ | GetMediaType puede contener únicamente un puntero a CMediaType (cuando soporta un solo media type) o un puntero y una variable de índice (cuando soporta varios). Uno (y sólo uno) de los dos se ha de sobreescribir, en el caso de tener varios media types también deberá ser sobreescrito el CheckMediaType. \\ | ||
| - | Para los formatos de video sin comprimir el filtro downstream podrá proponer cualquier stride value (valor de salto). \\ | + | Para los formatos de video sin comprimir el filtro downstream podrá proponer cualquier stride value (valor de salto, en cada fila de la imagen los valores adicionales que se añaden). \\ |
| También de deberá sobreescribir el método CBaseOutputPin::DecideBufferSize para indicar el tamaño de los buffers. \\ | También de deberá sobreescribir el método CBaseOutputPin::DecideBufferSize para indicar el tamaño de los buffers. \\ | ||
| ==== Definición de propiedades del filtro ==== | ==== Definición de propiedades del filtro ==== | ||
| Línea 299: | Línea 372: | ||
| - Si lo has hecho por COM, agrega otra CFactoryTemplate al array g_Templates que indica los objetos COM que tiene tu dll. | - Si lo has hecho por COM, agrega otra CFactoryTemplate al array g_Templates que indica los objetos COM que tiene tu dll. | ||
| ===== Notas ===== | ===== Notas ===== | ||
| + | * Flash Media Live Encoder reconocerá los filtros de captura en formatos sin procesar I420, YV12, YUY2, UYVY, RGB24 y RGB32. | ||
| + | * Script .bat para instalar un filtro: | ||
| + | <code> | ||
| + | @echo off | ||
| + | SET filterfile=VCamD.ax | ||
| + | AT > NUL | ||
| + | IF NOT %ERRORLEVEL% EQU 0 ( | ||
| + | ECHO Necesitas ser administrador para instalar el filtro | ||
| + | pause | ||
| + | EXIT /B 1 | ||
| + | ) | ||
| + | regsvr32 %~dp0%filterfile% | ||
| + | </code> | ||
| ==== Notas de programación COM ==== | ==== Notas de programación COM ==== | ||
| === Funciones de ayuda === | === Funciones de ayuda === | ||
| Línea 331: | Línea 416: | ||
| ==== Recursos ==== | ==== Recursos ==== | ||
| * {{:fw:dshow:com_in_plain_c_-_codeproject.pdf|Explicación del COM}} | * {{:fw:dshow:com_in_plain_c_-_codeproject.pdf|Explicación del COM}} | ||
| + | * {{:fw:dshow:graphstudio.zip|GraphStudio}}, aplicación para debugar los filtros y obtener info de ellos. | ||