PROYECTO FINAL DE CARRERA Estudio de viabilidad técnica e implementación de un sistema de transmisión de video adaptativo H264/SVC sobre TCP Estudios: INGENIERIA SUPERIOR DE TELECOMUNICACIONES Autor: MANEL GRAU GRACIA Tutor: DR. JORGE MATA DÍAZ JUNIO 2014 Sistema de video adaptativo H264/SVC sobre TCP 2 3 Sistema de video adaptativo H264/SVC sobre TCP Índice general Agradecimientos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Resum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 1.1. 1.2. 1.3. 1.4. JSVM y OpenSVCDecoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Proyectos similares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Medidas objetivas de calidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Introducción a H264 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 1.4.1. Predicción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.4.2. Transformación y cuantificación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 1.4.3. Codificación entrópica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2. H264/SVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.1. Conceptos de escalabilidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.1.1. Escalabilidad temporal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.1.2. Escalabilidad espacial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.1.3. Escalabilidad de calidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.1.4. Escalabilidad híbrida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.2. Cabecera de las unidades NAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.3. Sintaxis de las unidades NAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 2.3.1. Unidades NAL non-VCL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 2.3.1.1. Supplemental Enhancement Information . . . . . . . . . . . . . . . . . 34 2.3.1.2. Sequence Parameter Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 2.3.1.3. Picture Parameter Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 2.3.2. Unidades NAL VCL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 2.3.2.1. Coded Slice of non-IDR Picture . . . . . . . . . . . . . . . . . . . . . . . . . . 36 2.3.2.2. Coded Slice of an IDR Picture . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 2.3.2.3. Coded Slice Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3. Filtrado adaptativo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.1. Filtrado de unidades NAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.1.1. Reglas de dependencia en el filtrado de unidades NAL . . . . . . . . . . . . . 38 3.1.1.1. Reglas con escalabilidad espacial y temporal . . . . . . . . . . . . . . 39 3.1.1.2. Reglas con escalabilidad de SNR y uso de MGS . . . . . . . . . . . . . 39 3.1.2. Algoritmo de filtrado de unidades NAL . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.1.2.1. Algoritmo de extracción sin usar MGS . . . . . . . . . . . . . . . . . . . . 40 Sistema de video adaptativo H264/SVC sobre TCP 4 3.1.2.2. Algoritmo de extracción usando MGS . . . . . . . . . . . . . . . . . . . . 42 3.2. Filtrado adaptativo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.2.1. Orden de transmisión de flujo de datos H264/AVC . . . . . . . . . . . . . . . . 46 3.2.2. Orden de transmisión de flujo de datos H264/SVC . . . . . . . . . . . . . . . . 50 3.2.3. Parámetros de diseño del filtrado adaptativo . . . . . . . . . . . . . . . . . . . . 52 4. Estimación del ancho de banda de transmisión . . . . . . . . . . . . . . . . . . 55 4.1. Protocolo de control de Transporte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.1.1. Cabecera TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.1.2. Control de congestión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 4.2. Estimación del ancho de banda de transmisión . . . . . . . . . . . . . . . . . . . . . . 61 4.2.1. Tamaño de las capas de extracción en tiempo real . . . . . . . . . . . . . . . . 61 4.2.2. Velocidad de reproducción del video . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 4.2.3. Implementación de la estimación en tiempo real del ancho de banda de transmisión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 4.2.3.1. Detalles de la implementación . . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.2.3.2. Función estimación ancho de banda . . . . . . . . . . . . . . . . . . . . . 68 4.2.4. Estrategias temporales en la estimación del ancho de banda . . . . . . . 69 4.2.4.1. Implementación del uso de iteraciones . . . . . . . . . . . . . . . . . . . 70 5. Transmisor y receptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 5.1. Implementación del transmisor adaptativo . . . . . . . . . . . . . . . . . . . . . . . . . 72 5.1.1. Justificación uso de dos hilos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 5.1.2. Clase H264BitStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 5.1.3. Justificación de semáforos en la cola circular . . . . . . . . . . . . . . . . . . . . 79 5.1.4. Solución de semáforos en la aplicación . . . . . . . . . . . . . . . . . . . . . . . . 81 5.1.5. Solución de ancho de banda adaptativo . . . . . . . . . . . . . . . . . . . . . . . . . 85 5.1.6. Medidas para reducir el alto número de intercambios entre capas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 5.2. Criterios de diseño del receptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 5.2.1. Relación entre tiempo de reproducción y tiempo de transmisión . . . . 88 5.2.2. Estrategia de filtrado en recepción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 5.2.3. Solución de semáforos de la aplicación . . . . . . . . . . . . . . . . . . . . . . . . . 95 6. Evaluación del sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 6.1 Características de codificación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 6.1.1 Elección de los parámetros de cuantificación . . . . . . . . . . . . . . . . . . . . 99 6.2 Resultados al aplicar el algoritmo de filtrado . . . . . . . . . . . . . . . . . . . . . . . . 99 6.3 Perfiles de ancho de banda de transmisión . . . . . . . . . . . . . . . . . . . . . . . . 101 6.4 Puesta en escena . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 6.4.1 Prueba 1 - Ancho de banda límite de 300 Kbit/s . . . . . . . . . . . . . . . . . 107 6.4.2 Prueba 2 - Ancho de banda límite de 600 Kbit/s . . . . . . . . . . . . . . . . . 111 6.4.3 Prueba 3 - Ancho de banda límite de 1,3 Mbit/s . . . . . . . . . . . . . . . . . 115 5 Sistema de video adaptativo H264/SVC sobre TCP 6.4.4 Prueba 4 - Ancho de banda variable de 1,3 Mbit/s y 600 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 6.4.5 Prueba 5 - Ancho de banda de 1,3 Mbit/s compartido . . . . . . . . . . . . 120 7. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 7.1 Líneas futuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 APÉNDICES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 A. Ficheros de configuración del codificador de JSVM utilizados en las simulaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 B. Sintaxis H264/SVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 C. Manual de utilidades del proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 C.1. C.2. C.3. Utilidades de vídeo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Utilidades de compilación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Utilidades desarrolladas en el proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Bibliografía . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Sistema de video adaptativo H264/SVC sobre TCP 6 Lista de Figuras 1.1. Esquema de codificación H264/AVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.2. Esquema intra-predicción de bloques 4x4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.3. Esquema intra-predicción de bloques 16x16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.4. Esquema inter-predicción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.1. Esquema de codificación H264/SVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.2. Estructura de bipredicción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.3. Estructura diádica y no diádica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.4. Escalabilidad espacial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.5. Estructuras de dependencia de calidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.6. Estructura del primer byte de la cabecera de las unidades NAL . . . . . . . . . . . . 30 2.7. Tipos de unidad NAL H264/AVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.8. Tipos de unidad NAL H264/SVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.9. Estructura de los tres últimos bytes de la cabecera de las unidades NAL en H264/SVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.1. Estructura de la codificación, con capa base, capa de calidad mejorada y capa de resolución superior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.2. Estructura de la codificación, con capa base, capa de calidad mejorada con uso de MGS y capa de resolución superior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 3.3. Flujo de inicio con tamaño de GOP igual a 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.4. Flujo de inicio con tamaño de GOP igual a 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.5. Flujo de inicio con tamaño de GOP igual a 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.6. Flujo normal con tamaño de GOP igual a 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.7. Flujo normal con tamaño de GOP igual a 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.8. Flujo normal con tamaño de GOP igual a 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.9. Flujo en IDR múltiple periodo intra-predicción con tamaño de GOP igual a 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.10. Flujo en IDR múltiple periodo intra-predicción con tamaño de GOP igual a 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.11. Flujo en IDR múltiple periodo intra-predicción con tamaño de GOP igual a 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.12. Flujo en IDR no múltiple periodo intra-predicción con tamaño de GOP igual a 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.13. Flujo en IDR no múltiple periodo intra-predicción con tamaño de GOP igual a 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.14. Flujo en IDR no múltiple periodo intra-predicción con tamaño de GOP igual a 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.15. Flujo inicio codificación con tres capas, capa base, capa calidad mejorada y capa de resolución superior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 7 Sistema de video adaptativo H264/SVC sobre TCP 3.16. Flujo normal codificación con tres capas, capa base, capa calidad mejorada y capa de resolución superior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 3.17. Flujo en IDR múltiple periodo intra-predicción codificación con tres capas, capa base, capa calidad mejorada y capa de resolución superior . . . . . . . . . . . . . . . . . . 51 3.18. Flujo en IDR no múltiple periodo intra-predicción codificación con tres capas, capa base, capa calidad mejorada y capa de resolución superior . . . . . . . . . . . . . . 52 3.19. Intercambio entre capas 110 y 011 en flujo normal. Caso 1 . . . . . . . . . . . . . . . 53 3.20. Intercambio entre capas 110 y 011 en flujo normal. Caso 2 . . . . . . . . . . . . . . . 53 3.21. Intercambio entre capas 110 y 011 en flujo IDR múltiple periodo intrapredicción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 3.22. Intercambio entre capas 110 y 011 en flujo IDR no múltiple periodo intrapredicción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 4.1. Fases de establecimiento y finalización de conexión . . . . . . . . . . . . . . . . . . . . . 56 4.2. Casos de transmisión: Paquete enviado y reconocido, retransmisión y paquete duplicado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.3. Ejemplo de control de flujo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.4. Cabecera TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.5. Fase “slow start” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 4.6. Ejemplo control de congestión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 5.1. Ciclo de histéresis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 6.1. Algoritmo extracción hasta la capa 000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.2. Algoritmo extracción hasta la capa 001 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.3. Algoritmo extracción hasta la capa 100 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.4. Algoritmo extracción hasta la capa 010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.5. Algoritmo extracción hasta la capa 011 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 6.6. Algoritmo extracción hasta la capa 110 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 6.7. Perfil de ancho de banda: Capa 000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 6.8. Perfil de ancho de banda: Capa 010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 6.9. Perfil de ancho de banda: Capa 001 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 6.10. Perfil de ancho de banda: Capa 011 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 6.11. Perfil de ancho de banda: Capa 100 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 6.12. Perfil de ancho de banda: Capa 110 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 6.13. Escenario de red para las pruebas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 6.14. Flujo transmitido: Prueba 300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 6.15. Perfil de transmisión según opciones del socket: Prueba 300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 6.16. Intercambio entre capas: Prueba 300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 6.17. Flujo transmitido: Prueba 300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 6.18. Perfil de transmisión según opciones del socket: Prueba 300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 6.19. Intercambio entre capas: Prueba 300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Sistema de video adaptativo H264/SVC sobre TCP 8 6.20. Flujo transmitido: Prueba 600 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 6.21. Perfil de transmisión según opciones del socket: Prueba 600 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 6.22. Intercambio entre capas: Prueba 600 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 6.23. Flujo transmitido: Prueba 1,3 Mbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 6.24. Perfil de transmisión según opciones del socket: Prueba 1,3 Mbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 6.25. Intercambio entre capas: Prueba 1300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . 117 6.26. Flujo transmitido: Prueba 1300-600-1300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . 118 6.27. Perfil de transmisión según opciones del socket: Prueba 1300-600-1300 Kbit/s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 6.28. Intercambio entre capas: Prueba 1300-600-1300 Kbit/s . . . . . . . . . . . . . . . . . 120 6.29. Perfil de transmisión según opciones del socket: Prueba 1,3 Mbit/s compartido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 6.30. Intercambio entre capas: 1,3 Mbit/s compartido . . . . . . . . . . . . . . . . . . . . . . . 121 9 Sistema de video adaptativo H264/SVC sobre TCP Lista de Tablas 2.1. 3.1. 3.2. 6.1. 6.2. 6.3. Lista de ejemplos de codificación Exp-Golomb . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Resultados algoritmo de extracción para el ejemplo 1 . . . . . . . . . . . . . . . . . . . . 41 Resultados algoritmo de extracción para el ejemplo 2 . . . . . . . . . . . . . . . . . . . . 44 Parámetros de cuantificación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 PSNR obtenidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Medias y desviaciones típicas del ancho de banda de transmisión . . . . . . . . . 105 Sistema de video adaptativo H264/SVC sobre TCP 10 Agradecimientos Les doy las gracias y le dedico este proyecto a mi familia por su apoyo y comprensión durante el largo trayecto universitario así, como el de realización del PFC. También, le doy las gracias al director de mi proyecto, Jorge Mata Díaz por su ayuda y tutelaje en el desarrollo del PFC, en el que gran parte de haberlo llevado a buen puerto es gracias a él. 11 Sistema de video adaptativo H264/SVC sobre TCP Resum Durant els últims 20 anys, la comunitat científica ha estat estudiant la possibilitat de desenvolupar un sistema de video escalable. Es va intentar desenvolupar als anys 90 a l’estàndard MPEG2, però no va arribar a desenvolupar-se lo suficientment per a poder convertir-lo en un projecte comercial. L’any 2003, va aparèixer l’estàndard H264, amb el que es va aconseguir una millora important en la taxa de compressió de video respecte al seu antecessor MPEG2. Es va aconseguir mantenir la qualitat de la seqüencia de video amb taxes de compressió fins a un 50% més grans que a l’estàndard anterior. Amb el pas dels anys, s’han anat afegint annexos a l’estàndard H264, essent el més important l’annex G, “Scalable Video Coding”, corresponent a l’ús de video escalable. Un flux escalable, es defineix com aquell flux de dades, que pot ser descodificat i conformant amb l’estàndard al filtrar fins a uns determinats atributs, eliminant part del flux de dades. H264/SVC consta de tres atributs de dependència, els identificadors temporals, se resolució i de qualitat. D’aquesta manera, SVC permet codificar una mateixa seqüencia de video amb capes de millora de PSNR objectiva, i de millora de resolució. Per exemple, una seqüencia de video codificada amb tres capes, capa base, capa de millora de qualitat i capa amb més resolució, donarà lloc a diferents possibilitats de filtratge. És a dir, serà possible la extracció de fluxos conformants amb resolució més alta i més baixa, diferents velocitats de reproducció, y diferents PSNR. L’objectiu d’aquest projecte, és el desenvolupament d’una aplicació de video escalable sota demanda funcionant sobre el protocol de transport TCP. L’adequació al tipus de video i a les condicions de xarxa són els paràmetres de disseny principals de l’aplicació. Concretament, el principal objectiu ha obtenir, és que les transmissions de video siguin adaptatives a la connexió de xarxa. Actualment, existeixen molts sistemes de video sota demanda que utilitzen solucions propietàries, com en el cas de “Flash Media Server”, i unes altres que utilitzen H264/SVC (“Advanced Video Coding”), l’annex A de l’estàndard. Les dues més importants són sistemes de video sota demanda i punt a punt a Internet, com per exemple, Youtube; i la Televisió Digital Terrestre (TDT). Ambdós sistemes son susceptibles a l’aparició d’errors, i cadacún els combat de forma diferent. Als sistemes de video per Internet, quan es perd un paquet utilitzant TCP, es reenvia, en canvi, a la TDT s’utilitza OFDM per minimitzar els errors. Els paràmetres principals de la connexió de xarxa que s’utilitzaran per a fer el sistema adaptatiu, són l’ample de banda disponible, i el temps d’anada i tornada del paquets. El paràmetre d’ample de banda disponible serà estimat pels “sockets” a partir de la grandària de la finestra de congestió i el RTT de la connexió. D’aquesta manera, l’estratègia a seguir, serà l’estimació a temps real dels amples de banda necessaris per transmetre fins una determinada capa, i transmissions amb l’ample de banda més gran que sigui menor al disponible. Per aconseguir-ho, es fa l’estimació de les longituds incloses a cada extracció (per a capes Sistema de video adaptativo H264/SVC sobre TCP 12 superiors a la capa base, s’inclouran unitats NAL amb diferents atributs), i es rectifica l’ample de banda amb la velocitat de reproducció, per a obtenir les estimacions en temps real. Els instants d’estimació, vindran limitats per l’algoritme de filtrat adaptatiu. No serà possible fer estimacions després de cada unitat NAL, perquè els fluxos amb canvis temporals de nivells d’extracció, estaran limitats pel fet que cada tira B depèn de les dos tires I, P o B anteriors. Això, fa que només es puguin elegir com a punts de tall les tires I amb DTQ igual a 000. A més, les extraccions adaptatives seran d’alguna de les dues formes següents: 1. Canviar d’identificadors al punt de tall i filtrar les tires B següents. 2. Filtrar les tires I del canvi amb els identificadors anteriors i posteriors, incloent totes les tires I que compleixin algun del dos requisits, i filtrar les tires B posteriors amb els identificadors anteriors en temps, ja que depenen de les dos tires I, P o B anteriors. L’altre paràmetre de la connexió de xarxa, és el temps de recepció. Per al cas d’un receptor en temps real, es defineixen les següents estratègies de filtratge. Quan una unitat NAL es rebuda més tard que l’instant de reproducció, es filtra automàticament. A més, s’ha de tornar a filtrar al final de cadascuna de les iteracions (entre tira I amb DTQ igual a 000 i la següent amb els mateixos atributs) amb els nous atributs límit obtinguts després de filtrar les tires que no han arribat a temps, per a que el flux segueixi sent conformant. En aquest projecte, s’han realitzat probes de xarxa en un entorn real, per a provar la utilitat del sistema desenvolupat. Concretament, s’ha codificar el video BigBuckBunny amb tres capes, capa base, capa de millora de qualitat i capa amb més resolució; i s’ha provat el sistema amb dos routers entremitjos. Els resultat indiquen que realment es tracta d’un sistema que pot ser l’alternativa als sistemes actual, sempre que es disposi d’una connexió de banda ampla. 13 Sistema de video adaptativo H264/SVC sobre TCP Resumen Durante los últimos 20 años, la comunidad científica ha estado estudiando la posibilidad de desarrollar un sistema de video escalable. Se intentó desarrollar en los años 90 en el estándar MPEG2, pero no llego a desarrollarse lo suficientemente para poder convertirlo en un proyecto comercial. En el año 2003, apareció el estándar H264, que conseguía una mejora importante en tasa de compresión de video respecto a su antecesor MPEG2. Se consiguió mantener la calidad de la secuencia de video con tasas de comprensión un 50% mayores al anterior estándar. Con el paso de los años, se han ido añadiendo anexos al estándar H264, siendo el más importante el anexo G, “Scalable Video Coding”, correspondiente al uso de video escalable. Se define un flujo escalable, como aquel flujo de datos, que puede ser decodificable y conformante con el estándar al filtrar hasta unos determinados atributos, eliminando parte del flujo de datos. H264/SVC consta de tres atributos de dependencia, los identificadores temporales, de resolución y de calidad. De esta forma, SVC permite codificar una misma secuencia de video con capas de mejora de PSNR objetiva, y de mejora de resolución. Por ejemplo, una secuencia de video codificada con tres capas, capa base, capa de mejora de calidad y capa con más resolución, dará lugar a varias posibilidades de filtrado. Es decir, será posible la extracción de flujos conformantes con mayor y menor resolución, distintas velocidades de reproducción, y PSNR diferentes. El objetivo del presente proyecto, es el desarrollo de una aplicación de video escalable bajo demanda sobre el protocolo de transporte TCP. La adecuación al tipo de video y a las condiciones de red son los parámetros de diseño principales de la aplicación. En concreto, el principal objetivo a alcanzar es que las transmisiones de video sean adaptativas a la conexión de red. Actualmente, existen muchos sistemas de video bajo demanda que utilizan soluciones propietarias como es el caso de “Flash Media Server” de Adobe, y otras que utilizan H264/AVC (“Advanced Video Coding”), el anexo A del estándar. Las dos más importantes son sistemas de video bajo demanda punto a punto en Internet como Youtube; y la Televisión Digital Terrestre (TDT). Ambos sistemas son susceptibles de la aparición de errores, y cada uno de ellos lo combate de forma distinta. En los sistemas de video por Internet, cuando se pierde un paquete utilizando TCP, se reenvía, mientras que en la TDT se utiliza OFDM para minimizar los errores. Los parámetros principales de la conexión de red que se van a utilizar para hacer el sistema adaptativo son el ancho de banda disponible, y el tiempo de ida y vuelta de los paquetes. El parámetro de ancho de banda disponible va a ser estimado por los “sockets” a partir del tamaño de la ventana de congestión y el RTT de la conexión. De esta forma, la estrategia a seguir será la estimación en tiempo real de los anchos de banda necesarios para transmitir hasta una determinada capa y transmisiones con el ancho de banda mayor que sea menor al disponible. Para lograrlo, se hace la estimación de los tamaños incluidos en cada extracción Sistema de video adaptativo H264/SVC sobre TCP 14 (para capas superiores a la base, se incluirán unidades NAL con diferentes atributos), y se rectifica el ancho de banda con la velocidad de reproducción, para obtener las estimaciones en tiempo real. Los instantes de estimación vendrán limitados por el algoritmo de filtrado adaptativo. No será posible hacer estimaciones detrás de cada unidad NAL, porque los flujos con cambios temporales de niveles de extracción, vendrán limitados por el hecho de que cada tira B depende de las dos tiras I, P o B anteriores. Esto hace que solo pueda cogerse como punto de corte las tiras I con DTQ igual a 000. Además, las extracciones adaptativas van a ser de una de las dos formas siguientes: 1. Cambiar de identificadores en el punto de corte y filtrar las tiras B siguientes 2. Filtrar las tiras I del cambio con los identificadores anteriores y posteriores, incluyendo todas las tiras que cumplan uno de los dos requisitos, y filtrar las tiras B posteriores según los identificadores anteriores en tiempo, debido a que dependen de las dos tiras I, P o B anteriores. El otro parámetro de la conexión de red, es el tiempo de recepción. En el caso de un receptor para trabajar a tiempo real, se definen las siguientes estrategias de filtrado. Cuando una unidad NAL es recibida en un instante temporal mayor al instante de reproducción, se desecha automáticamente. Además, se debe volver a filtrar al final de cada iteración entre I con DTQ igual a 000 y la siguiente, con los nuevos atributos limite obtenidos después de filtrar las tiras que no han llegado a tiempo, para que el flujo resultante siga siendo conformante. En el presente proyecto, se han realizado pruebas de red en un entorno real, para probar la utilidad real del sistema desarrollado. En concreto, se ha codificado el video BigBuckBunny con tres capas, capa base, capa de mejora de calidad y capa con más resolución; y se ha probado el sistema con el uso de dos routers intermedios. Los resultados indican que realmente se trata de una alternativa válida a los sistemas actuales, siempre que se disponga de una conexión de ancha banda. 15 Sistema de video adaptativo H264/SVC sobre TCP Abstract During last 20 years, scientific community has been studying scalable video coding developing possibility. In nineties, they try to develop it in MPEG2 standard, but it was not enough developed in order to become a commercial project. In year 2003, it appears H264 standard, getting a significant improvement of video compression tax against his predecessor MPEG2. They got maintain quality video sequence achieving 50% major video compression taxes. During years, H264 annex has been appeared. The most important annex is G annex, “Scalable Video Coding”, which corresponds to scalable video use. An scalable bit stream is defined as that bit stream which could be decoded and standard confortable when it is filtered with specific attributes, deleting part of bit stream. H264/SVC standard has three dependency attributes, temporal, resolution and quality identifiers. Thus, SVC allows to code the same video sequence with PSNR and resolution improvement layers. For example, a coded video sequence of three layers, base layer, improvement quality layer and improvement resolution layer, become in different filtering possibilities. Therefore, it could be possible conformant extractions with different PSNR, resolution and playing velocity. The project objective is develop an scalable video on demand application over TCP protocol. Principal application parameters are video type and net conditions adequacy. Specifically, achieved principal objective is that video transmissions become network connection adaptive. Actually, it exists a lot of video on demand systems, which use proprietary solutions such as “Flash Media Server”, or they use H264/AVC (“Advanced Video Coding”), A annex of H264 standard. Two most important applications are point to point Internet video on demand systems and Digital Television (TDT). Both systems are susceptible of error appearance but each one fight differently errors. In Internet video systems, when a packet is lost using TCP, it is forwarded, while in TDT it is used OFDM in order to minimize transmission errors. Principal network connection parameters, which will be used in order to become and adaptive system, are available network bandwidth and packet round trip time. Available bandwidth parameter will be estimated by sockets from congestion window size and connection RTT. Thus, the strategy will be real time estimation of necessary bandwidth in order to transmit up to a certain layer, and transmit with maximum bandwidth less than available bandwidth. In order to achieve this, extraction included sizes are estimated (for superior layers than base layer, it will be included NAL units with different attributes), and it is rectified bandwidth with playing velocity, in order to obtain real time estimations. Estimation moments are limited by adaptive filter algorithm. It could not be possible to estimate after every NAL unit, because bit streams with temporal changes, will be limited by the fact that every B slice depends on last two I, P or B slices. Therefore, it could only catch cutoff point in I slices with DTQ equal to 000. Furthermore, adaptive extractions will be of one of the two following: Sistema de video adaptativo H264/SVC sobre TCP 16 1. Change identifiers in cutoff point and filter following B slices. 2. Filter change I slices with both identifiers, previous and posterior, including all slices which comply one of both requisites, and filter posterior B slices by previous time identifiers, due to, they depend on last two I, P or B slices. The other network connection parameter is receiver time. In real time applications, there are defined the following filtering strategies. When a NAL unit is received after its playing moment, it is filtered. Furthermore, it has to be filtered another time after every iteration between I slice with DTQ equal 000 and following next I slice with DTQ equal 000, with new limit attributes obtained after filtering slices which had not arrived at time, in order to obtain a H264 conformant resultant bit stream. In this project, there have been made network test in a real environment, in order to check developed system real utility. Specifically, it has been coded BigBuckBunny video sequence with three layers, base layer, PSNR quality improvement layer, and resolution improvement layer; and it has been checked the system by the use of a network environment which contain two intermediate routers. Obtained results indicate that it is really a valid alternative to actual systems, if we have a broadband connection. 17 Sistema de video adaptativo H264/SVC sobre TCP Sistema de video adaptativo H264/SVC sobre TCP 18 Capítulo 1: Introducción: En los últimos años se han desarrollado un gran conjunto de sistemas de video bajo demanda en diferentes entornos, desde sistemas de televisión por pago, hasta sistemas de videos bajo demanda en Internet, como por ejemplo “Youtube” o “Vimeo”. El objetivo del presente proyecto, es el desarrollo de otro sistema de video bajo demanda, que sea adaptativo a las condiciones de red, y que tome provecho de las diferentes características del video transmitido. Así, la principal innovación del presente proyecto es el hecho de trabajar con H264/SVC, la extensión del estándar H264 en su anexo G. El estándar es el documento “ITU-T H.264 Advanced video coding for generic audiovisual services (2012). Hasta ahora, la mayoría de sistemas bajo demanda habían sido implementados con los protocolos RTP (“Real Time Transport Protocol”), o sus versiones con mejoras de seguridad RTSP (“Real Time Streaming Protocol”) y RTCP. También en versiones comerciales como el caso de Adobe con “Flash Media Server” junto con toda la tecnología “Flash”, “ActionScript” y “Flex”, que mediante el uso de códec propietarios (“VP6 Sorenson” en el video) permitía el desarrollo de sistemas de video bajo demanda sobre HTTP y TCP. El principal reto que se nos plantea en el presente proyecto, es el del desarrollo de un sistema que sea fiable extremo a extremo independientemente de cual sea su sistema de acceso (“Wifi”, “ADSL”, “WiMAX”, “FTTH”, …), razón por la cual se va a trabajar sobre TCP, protocolo orientado a conexión, fiable y con control de errores extremo a extremo. Se tendrá que tratar con todos los problemas asociados a su uso, como es el caso que al inicio de la conexión, en la etapa de “slow start” las transmisiones no van a ser lo suficientemente rápidas como para que se pueda recibir el contenido en tiempo de reproducción, razón por la que se van a utilizar búferes en recepción para controlar el flujo transmitido. En concreto, con el uso de H264/SVC, que define los flujos de datos con diferentes atributos de escalabilidad nos permitirá transmitir hasta una determinada capa durante un cierto tiempo, y hasta otra determinada capa durante otro cierto tiempo. La idea principal es la de codificar con diferentes capas con atributos de velocidad de reproducción, resolución y PSNR diferentes, combinándolos todos en un flujo de datos único. De esta manera será posible filtrar con unos determinados atributos de los comentados anteriormente, para transmitir con condiciones del video cambiantes, que se adapten a las condiciones de red existentes. 19 Sistema de video adaptativo H264/SVC sobre TCP Así, la conexión de red vendrá principalmente caracterizada por el ancho de banda disponible para transmisión y el tiempo de transmisión extremo a extremo, parámetros de los que se va a sacar provecho en la búsqueda de un algoritmo de transmisión que sea adaptativo a estas condiciones de red. En concreto, se van a controlar los tamaños de transmisión de las diferentes capas en busca de la capa con mayor calidad posible para ser transmitida, que cumpla la restricción que el tamaño transmitido se pueda recibir y decodificar en tiempo real. El proyecto constara de los capítulos siguientes: 1. Presentación de H264 y del software disponible para H264/SVC. 2. Descripción detallada de H264/SVC. 3. Descripción detallada de los algoritmos de filtrado y de filtrado adaptativo de flujos de datos H264/SVC. 4. Descripción detallada de TCP y de la estimación del ancho de banda de transmisión. 5. Descripción detallada de la implementación del sistema transmisor y de los criterios de diseño del receptor en caso de buscar un sistema en tiempo real. 6. Resultados obtenidos y líneas futuras. 1.1. JSVM y OpenSVCDecoder: Actualmente, existen un codificador y dos decodificadores de H264/SVC. El software correspondiente es “Join Scalable Video Model” (JSVM) y “OpenSVCDecoder”. JSVM, es un software desarrollado por el “Joint Video Team” del ISO/IEC “Moving Pictures Experts Group” (MPEG) y el ITU-T “Video Coding Experts Group” (VCEG), capaz de codificar y decodificar flujos de video en el estándar H264/SVC. “OpenSVCDecoder” es una librería desarrollada por el IETR/INSA de la ciudad de Rennes, que implementa un decodificador de flujos H264/SVC en tiempo real. “OpenSVCDecoder” se usa conjuntamente con el reproductor “Mplayer” y permite visualizar flujos de datos codificados en SVC. 1.2. Proyectos similares: El proyecto más similar al que se presenta en este documento, es el “MPEG DASH (Dynamic Adaptive Streaming over HTTP)”, el cual a diferencia del actual que trabaja con SVC, trabaja con la transmisión de flujos H264/AVC. El parámetro de diseño principal de “MPEG Dash” es que concentra flujos de diferentes calidades (parámetro de cuantificación diferente), y los transmite Sistema de video adaptativo H264/SVC sobre TCP 20 adaptativamente a las condiciones de red, seleccionando las unidades NAL de un flujo o de otro en función de las condiciones de red. El funcionamiento es inverso al proyecto actual, en este caso la estimación se hace en recepción, donde a partir del tamaño de ocupación del buffer se hace una estimación del ancho de banda al que se va a solicitar la recepción. Se entiende que cuando se llena se puede pedir más velocidad de transmisión porque la velocidad de red es mayor a la de reproducción, y que cuando se vacía se debe reducir la velocidad de transmisión. Los perfiles de los proyectos son muy similares, pero la diferencia principal es que en “MPEG Dash” se transmite flujo AVC, y en el presente proyecto se transmiten flujos SVC, con las ventajas asociadas a este estándar. 1.3. Medidas objetivas de calidad: Para medir objetivamente una secuencia de video utilizamos el PSNR (“Peak Signal to Noise Ratio”) en dB. Se define como el coeficiente entre el valor máximo que puede tener una secuencia al cuadrado y el error cuadrático medio de la secuencia. Se considera como una medida de calidad objetiva, ya que cuantifica el error producido en el tratamiento de la secuencia de video. En general, cuanto mayor sea la PSNR en dB mayor será la calidad de la secuencia de video reconstruida. 1.4. Introducción a H264: H264 es un estándar de codificación digital de video que introduce muchas mejoras de compresión respecto a sus predecesores MPEG2 y MPEG4 Visual, de los que hereda muchas de sus características de codificación. H264 está desarrollado por “Joint Video Team”, formado a su vez por los equipos del ITU-T VCEG y el ISO/IEC MPEG. El documento estándar publicado en 2003, no define como codificar el video, pero sí define toda la implementación del decodificador, con lo que para codificar se puede llevar a cabo el procedimiento inverso. 21 Sistema de video adaptativo H264/SVC sobre TCP A continuación se van a ver las principales características del proceso de codificación y decodificación. El proceso de codificación consta de tres etapas principales: 1. Predicción: Ya sea intra-predicción o inter-predicción, en función de si se predice desde el propio a anteriores fotogramas. 2. Transformación y cuantificación: Se pasa la información al dominio transformado y se cuantifica. 3. Codificación entrópica: Codificación en palabras de longitud variable del resultado. Figura 1.1: Esquema de codificación H264/AVC 1.4.1. Predicción: El codificador procesa todo el contenido del fotograma en macro-bloques que van de 16x16 a 4x4 en muestras de luminancia y de 8x8 a 2x2 en muestras de crominancia, debido al submuetreo 4:2:0 del video. Durante este proceso se realizan predicciones a partir de los bloques ya codificados. Se conoce como Intra-predicción cuando los macro-bloques proviene del mismo fotograma, y como Inter-predicción cuando los macro-bloques proviene de otro fotograma previamente codificado. La predicción será necesaria en función del error cuadrático medio, en los Intrapredecidos habrá casos en que será más eficiente enviar su información directamente. En los casos en que sí sea necesario realizar la predicción, se obtiene el residual entre la predicción hecha y los valores del macro-bloque actual. La inter-predicción se conoce como estimación de los vectores de movimiento, mientras que la compensación de movimiento es el proceso de la obtención de los residuales a partir de la Inter-predicción. Sistema de video adaptativo H264/SVC sobre TCP 22 La Intra-predicción utiliza bloques de 16x16 hasta 4x4 píxeles para realizar la predicción a partir de los macro-bloques contiguos. Las formas de extrapolar para los casos de 4x4 muestras son las siguientes: Figura 1.2: Esquema intra-predicción de bloques 4x4 Como se puede ver en la figura 1.2, las formas de extrapolar en el caso de 4x4 muestras son de arriba abajo, prediciendo las muestras inferiores a partir de las superiores; de izquierda a derecha, promediando las muestras de arriba y de la izquierda; y varias combinaciones en diagonal dando más peso a muestras de dos de los lados del macro-bloque. Y en el caso de 16x16 muestras: Figura 1.3: Esquema intra-predicción de bloques 16x16 Como se puede ver en la figura 1.3, las formas de extrapolar en el caso de 16x16 muestras son de arriba abajo, de izquierda a derecha, promediando las muestras de arriba y de la izquierda y en combinaciones diagonales de las muestras de abajo a la izquierda y arriba a la derecha. La inter-predicción se hace con bloques de 16x16 píxeles a 4x4 píxeles, y se utiliza para sacar provecho de las regiones similares entre diferentes fotogramas. Tal como se puede ver en la figura 1.4 se predicen regiones del fotograma predicho a partir de macro-bloques de los fotogramas de referencia, cogiendo tamaños variables con bloques de 16x16 a 4x4 muestras, en función del error cuadrático medio de la predicción. 23 Sistema de video adaptativo H264/SVC sobre TCP Figura 1.4: Esquema inter-predicción 1.4.2. Transformación y cuantificación: En H264, se transforma a partir de la “Transformada Discreta del Coseno” (DCT), para obtener un conjunto de coeficientes prácticamente incorrelados y en los que la energía se concentra en un poco número de ellos. La DCT se basa en multiplicar por delante y por detrás por una matriz A y A transpuesta respectivamente, a la matriz que contiene los coeficientes. Los coeficientes de la matriz son: Para el caso de 4x4 muestras, la matriz A es la siguiente: A la salida de la transformación, tendremos un bloque de coeficientes transformados, en los que la energía se va a concentrar en pocos de ellos. Una vez se ha transformado se pasa al proceso de cuantificación, en el que a partir de un parámetro de cuantificación (QP) se van dividiendo por el parámetro de cuantificación los coeficientes resultantes, dando lugar a muchos ceros. De esta forma, cuando mayor sea el parámetro de cuantificación, mayor será el número de ceros y más información se perderá, y cuanto menor sea más información se conservará y, por lo tanto, mejor calidad tendrá el video reconstruido. 1.4.3. Codificación entrópica: Sistema de video adaptativo H264/SVC sobre TCP 24 El resultado de la transformación y cuantificación en forma de coeficientes transformados o de residuales de la predicción deben ser estructurados de alguna forma para la posterior transmisión en forma de flujo. En H264 se utilizan dos codificaciones entrópicas con palabras de longitud variable. Estas codificaciones son “Context Adaptive Variable Length Coding” (CAVLC) y “Context Adaptive Binary Arithmetic Coding” (CABAC). La diferencia principal entre las dos codificaciones es que con CABAC se consiguen compresiones mayores aunque su complejidad algorítmica es mucho mayor que en CAVLC, lo que se traduce en la necesidad de más recursos computacionales para poder llevar a cabo las codificaciones. En este proyecto, se ha elegido el uso de CAVLC, y se va a ver como realmente se consiguen altas tasas de compresión, a pesar de ser el algoritmo con tasas de compresión menores entre los dos a elegir. 25 Sistema de video adaptativo H264/SVC sobre TCP Capítulo 2: H264/SVC: En este capítulo vamos a ver todos los conceptos necesarios sobre el anexo G del estándar H264, para facilitar la correcta comprensión del proyecto en desarrollo. Partiendo de la definición de flujo decodificable en H264/AVC, se generaliza en H264/SVC el concepto de flujo de datos escalable, como el flujo tal que se pueden extraer sub-flujos decodificables, dividiendo el flujo de datos en distintas capas. Se muestra a continuación el esquema general de codificación del H264/SVC. Figura 2.1: Esquema de codificación H264/SVC 2.1. Conceptos de escalabilidad: En H264/SVC se definen tres tipos de escalabilidad, escalabilidad temporal, ya propia de H264/AVC, escalabilidad espacial, que consiste en diferentes capas con resolución espacial diferente, y escalabilidad de calidad, que consiste en diferentes pasos de cuantificación (QP), dando lugar a capas de mayor o menor PSNR. 2.1.1. Escalabilidad temporal: Sistema de video adaptativo H264/SVC sobre TCP 26 Se define la escalabilidad temporal como la capacidad de partir en tiempo una capa en diferentes casos de identificador de dependencia temporal (T0, …, Ti). La escalabilidad temporal, ya es propia del estándar H264/AVC, de forma que funciona igual en AVC que en SVC. Se entiende por escalabilidad temporal los niveles de dependencia entre tiras B, de forma que cada nueva capa que se añade se traduce en doblar el número de tiras B de la estructura del orden de reproducción. Las tiras B se forman de la forma siguiente. Figura 2.2: Estructura de bipredicción En las tiras B se realiza un proceso de bipredicción, a partir de las listas cero y uno de tiras I, P o B anteriores y posteriores al orden de reproducción. En el uso de escalabilidad temporal se utilizan estructuras de predicción jerárquicas y diádicas. En general en el caso de estructuras diádicas se obtiene un número de capas correspondiente al logaritmo en base dos del tamaño de GOP más uno. número de capas = log(GOP_size) + 1 Existen tres casos a contemplar, como se verá en la figura siguiente, estructura diádica, no diádica y el caso de solo usar tiras P inter-predichas. La estructura diádica es cuando se multiplica por dos el número de tiras B al incrementar el número de identificadores de escalabilidad temporal. En concreto, cuando se pone la primera B se añade una entre tiras I y P, y a partir de la primera B con cada identificador temporal que se añade se añaden el doble de tiras I de las que había. De esta forma se genera una estructura en la que las tiras B que se añaden se van intercalando a derecha e izquierda de las otras tiras I, P o B anteriores en tiempo de transmisión formando la estructura que se muestra en el caso a) de la figura 2.3. Este caso se corresponde con una estructura diádica con un tamaño de GOP igual a ocho, dando lugar a la capa base más tres capas de mejora. 27 Sistema de video adaptativo H264/SVC sobre TCP El caso b) muestra la estructura de GOP no diádica para un tamaño de GOP igual a nueve. Como se puede ver en la figura a partir de las tiras I se predicen las dos tiras P siguientes, y a partir de las tiras I y P se hace la bi-predicción de dos tiras B intermedias. La estructura es no diádica porque no respeta que se vayan añadiendo tiras B multiplicando por dos e intercalándolas secuencialmente, tal como sucede en la figura del caso a). El caso c) muestra una estructura diádica para el caso de solo usar tiras P. En este caso, a partir de la tira I inicial se predicen tres tiras P intermedias, y a partir de las tiras P intermedias se predicen más tiras P posteriores en tiempo de reproducción. Normalmente, cuando nos encontremos con una estructura de este tipo se va a tratar de un tamaño de GOP igual a uno en el que cada tira P posterior en tiempo va a depender de la tira I o P anterior en tiempo. Figura 2.3: Estructura diádica y no diádica 2.1.2. Escalabilidad espacial: La escalabilidad espacial, está basada en la capacidad de escalar en tamaño la resolución del video de menor a mayor tamaño. Así, las capas superiores dependen de las inferiores. En este caso aparte de las predicciones inter e intra, se añade el caso de la predicción entre capas. Se muestra a continuación un ejemplo con dos capas de escalabilidad espacial. Sistema de video adaptativo H264/SVC sobre TCP 28 Figura 2.4: Escalabilidad espacial La predicción entre capas se realiza de tal forma que se utiliza información propia de la capa y de las capas inferiores. En concreto hay tres tipos de predicción entre capas: 1. Predicción de los vectores de movimiento (Inter-Layer Motion Prediction, M): Consiste en sacar versiones interpoladas de los vectores de movimiento de la capa inferior. 2. Predicción a partir del residual (Inter-Layer Residual Prediction, R): Se interpola el residual de la capa inferior. 3. Predicción de macro-bloques intra-predecidos (Inter-Layer Intra Prediction): Se interpola la intra-predicción realizada en la capa inferior. La diferencia principal entre usar M y R, es que cuando se trabaja con la interpolación de los vectores de movimiento, en la siguiente tira se sigue prediciendo desde la capa base, mientras que cuando se trabaja con R, en las tiras siguientes se sigue trabajando con inter-predicción en la capa superior. 2.1.3. Escalabilidad de calidad: La escalabilidad de calidad se basa en el uso de dos o más capas con la misma resolución pero con diferente parámetro de cuantificación a la hora de obtener el valor de los coeficientes transformados. En H264/SVC se utiliza “Medium-Grain Scalability Coding” (MGS), que permite predecir desde la propia capa y desde las capas inferiores los valores de los residuales en cada caso. Se caracteriza por el hecho de permitir partir los coeficientes transformados en diferentes capas de mejora, asegurándose que se va a poder reconstruir usando los coeficientes de las capas inferiores en caso de que no se disponga de todos los coeficientes transformados en la capa superior. La ventaja principal de usar MGS respecto a sus antecesores, es que nos permite el intercambio entre capas en cualquier momento. En MPEG4 se utilizaba “Fine-Grain Scalability Coding”, que a diferencia de la escalabilidad de SNR, predecía todas las 29 Sistema de video adaptativo H264/SVC sobre TCP capas de mejora a partir de la capa base. En el otro extremo esta lo que se planteo en MPEG2, que consistía en predecir todas las capas a partir de la de mejora. El problema principal que apareció es que no se obtenía unas buenas tasas de codificación comparado con el caso de transmitir varios flujos codificados con AVC, a diferencia del caso de MGS que si se consiguió. En MGS se utilizan fotogramas clave, que sirven para re-sincronizar la capa base con las capas de mejora. De esta forma, se almacenan los fotogramas clave para no tener que recodificar los fotogramas clave en las capas de mejora. En la figura siguiente se muestran las diferentes estrategias de codificación en escalabilidad de SNR. Figura 2.5: Estructuras de dependencia de calidad El caso a) es el correspondiente a FGS, b) es el extremo opuesto propuesto en MPEG2, c) es un caso intermedio y d) es el caso de MGS. 2.1.4. Escalabilidad híbrida: El concepto general de escalabilidad en el estándar H264/SVC, se basa en las posibles combinaciones de los tres tipos de escalabilidad, dando lugar a flujos de datos conformantes con diferentes combinaciones de los tres tipos de escalabilidad. Así se podría generar secuencias de video codificadas con varias capas de escalabilidad temporal y de SNR dentro de cada capa con una resolución diferente. 2.2. Cabecera de las unidades NAL: En H264 hay tres tipos de unidades NAL: 1. VCL NALU: son propiamente las unidades NAL que contienen la información codificada de la secuencia de video. 2. Non-VCL NALU: Contienen conjuntos de parámetros de codificación,… Sistema de video adaptativo H264/SVC sobre TCP 30 3. Cabeceras NALU del flujo de datos. En este apartado vamos a analizar las cabeceras de las VCL NALU en H264/SVC. En H264/AVC las cabeceras de la unidad NAL son de un byte de longitud, en cambio las SVC contienen cuatro bytes de longitud, teniendo el primer byte el mismo contenido que en AVC. En SVC se utilizan las unidades NAL de tipo 20, que son las unidades NAL de tiras codificadas de extensión escalable. Figura 2.6: Estructura del primer byte de la cabecera de las unidades NAL F: 1 bit forbidden_zero_bit: Se define que cuando valga uno indica un error en la sintaxis. NRI: 2 bits nal_ref_idc: Un valor de 00 indica que la unidad NAL no será necesaria para reconstruir fotogramas de referencia en predicciones futuras. Se puede descartar la unidad NAL siempre que su valor sea de 00 pudiendo seguir decodificando sin su existencia. Las tiras B de las que dependen otras tiras B según la estructura diádica nunca tendrán un valor de 00, mientras que serán las tiras B de las que no depende ninguna unidad NAL las que tendrán un valor de 00. TYPE: 5 bits nal_unit_type: Indica el tipo de unidad NAL en cuestión. Los valores posibles en H264/AVC son los siguientes: Figura 2.7: Tipos de unidad NAL H264/AVC En SVC los valores posibles son los siguientes: 31 Sistema de video adaptativo H264/SVC sobre TCP Figura 2.8: Tipos de unidad NAL H264/SVC Los principales tipos de unidad NAL son las unidades NAL VCL (tipos 1, 2, 3, 4 y 5), correspondientes en H264/AVC a la codificación parcial o total de una tira en instante de refresco instantáneo, o sin instante de refresco instantáneo, y las non-VCL (tipos 6, 7 y 8) correspondientes al envió de información sobre la secuencia (SPS), sobre los fotogramas (PPS), o de información suplementaria para la decodificación (SEI). En H264/SVC, se añaden las unidades NAL correspondientes a la información codificada para las capas superiores, llamadas de extensión de tira escalable (tipo 20), las de información de capa a nivel de secuencia (SSPS, tipo 15) y las Prefix NAL Unit (tipo 14), para contener información de compatibilidad con H264/AVC. En H264/SVC además se añaden otros tres bytes que contienen la información de capa superior para las unidades NAL de tipo 14 y 20. Figura 2.9: Estructura de los tres últimos bytes de la cabecera de las unidades NAL en H264/SVC R: 1 bit reserved_one_bit: Bit reservado para extensiones futuras. I: 1 bit idr_flag: Indica si se trata de una unidad NAL de IDR (vale 1), o no. Las tiras IDR, tienen la peculiaridad que permiten resetear los errores propagados, ya que se decodifican por si solas. PRID: 6 bits priority_id: Indica la prioridad de la unidad NAL. Cuanto menor es su valor, más prioridad tiene la unidad NAL. Básicamente, los valores introducidos se ciñen a los niveles de dependencia, de forma que una unidad NAL de una tira I en la primera capa Sistema de video adaptativo H264/SVC sobre TCP 32 de mejora será la más prioritaria de todas y a medida que se suben capas hasta llegar a la capa superior en las tiras B sin que otras tiras B dependan de la bi-predicción se asignara los valores más altos. N: 1 bit no_inter_layer_pred_flag: Indica que se debe usar predicción entre capas para decodificar la tira (vale 1) o no. DID: 3 bits dependency_id: Identifica el nivel de dependencia espacial de la unidad NAL. Un valor de cero indica capa base, y a medida que aumenta se va pasando a las capas superiores. Existen ocho resoluciones posibles. QID: 4 bits quality_id: Identifica el nivel de dependencia de calidad de las capas MGS. Para una capa (Di, Ti, Qi) existe una capa (Di, Ti, (Qi – 1)) a partir de la que se hace predicción entre capas. Existen diez y seis niveles de escalabilidad de calidad por nivel de resolución. TID: 3 bits temporal_id: Identifica el nivel de dependencia temporal de la capa. Una capa con un determinado identificador temporal depende siempre de los identificadores temporales inferiores pero nunca superiores. Existen ocho niveles de dependencia temporal por cada capa de calidad y/o resolución. U: 1 bit use_ref_base_pic_flag: Indica que se utilizan fotogramas base de referencia para la inter-predicción (vale 1) o no (vale 0). D: 1 bit discartable_flag: Cuando vale uno indica que la unidad NAL actual no se utiliza para decodificar otras unidades NAL con valores superiores de dependency_id, ni en esta unidad de acceso ni en ninguna otra AU. Estas unidades NAL pueden ser descartadas sin comprometer la integridad de las capas con identificador de dependencia superior. O: 1 bit output_flag: Cuando vale uno indica que esta unidad NAL se utilizará para el proceso de decodificación de otras tiras posteriores en tiempo de transmisión. 33 Sistema de video adaptativo H264/SVC sobre TCP RR: 2 bits reserved_three_2_bits: Bits reservados para extensiones futuras. Debe valer “11”. 2.3. Sintaxis de las unidades NAL: En el estándar H264 se proponen varios tipos de lectura, en función de cómo están estructurados los datos de las unidades NAL. En concreto se propone: u(n): Leer n bits y devolver su valor como natural (unsigned). u(v): Leer v bits que son función de otros parámetros y devolver su valor como natural (unsigned). ue(v): Leer un código Exp-Golomb y devolver su valor como natural (unsigned). se(v): Leer un código Exp-Golomb y devolver su valor como entero (signed). El signo positivo va con los números pares. Los códigos Exp-Golomb son una codificación entrópica caracterizada por palabras de longitud variable. Estos códigos se generan de la forma siguiente: [sucesión de zeros][1][información] número_ceros_sucesión = floor(log2(número_codigo + 1); información = número_codigo + 1 – exp(2, número_ceros_sucesión); Tabla 2.1: Lista de ejemplos de codificación Exp-Golomb Y se decodifican de la forma siguiente: número_ceros_sucesión = read(ceros); información = read(número_ceros_sucesión después de uno); Sistema de video adaptativo H264/SVC sobre TCP 34 número_codigo = información + exp(2, número_ceros_sucesión) – 1; En H264 hay tres tipos de unidades NAL tal y como se ha comentado antes, las unidades NAL VCL, las non-VCL y las cabeceras. Vamos a ver a continuación los parámetros más importantes de los distintos tipos de unidad NAL. 2.3.1. Unidades NAL non-VCL: Son las unidades NAL, que nos aportan información a nivel de secuencia o de fotograma, para la posterior correcta decodificación. Las comunes en AVC y SVC son: Supplemental Enhancement Information (SEI). Sequence Parameter Set (SPS). Picture Parameter Set (PPS). Además en H264/SVC se añaden las siguientes: Prefix NAL Unit. Subset Sequence Parameter Set (SSPS). 2.3.1.1. Supplemental Enhancement Information: Los SEI aportan información acerca de la secuencia de video y su organización. Hay alrededor de 40 tipos de mensaje SEI pero nos vamos a centrar en el “Scalability_Information_SEI”, que solo se utiliza en SVC, y proporciona toda la información de cómo está estructurada la secuencia de video. Los elementos sintácticos más importantes que forman parte de este tipo de mensaje SEI son: num_layers_minus1: Indica el número de combinaciones diferentes de los parámetros DTQ que forman la secuencia de video, es decir indica el número de capas de la codificación. layer_id: Asigna un identificador a cada capa. El identificador de capa es único, y es un parámetro intercambiable por los tres siguientes. dependency_id: Identificador de dependencia espacial de cada capa. quality_id: Identificador de dependencia de calidad de cada capa. temporal_id: Identificador de dependencia temporal de cada capa. frame_height_in_mbs_minus1: Indica la altura en macro-bloques de los fotogramas. 35 Sistema de video adaptativo H264/SVC sobre TCP 2.3.1.2. Sequence Parameter Set: El “Sequence Parameter Set” contiene información acerca de los parámetros de codificación usados en origen, y se debe transmitir para que el decodificador pueda realizar la función inversa en recepción. Solo puede haber uno en todo el flujo de datos y se corresponde con la capa base. Para las demás capas están los “Subset Sequence Parameter Set” que contiene el SPS. Los elementos sintácticos más importantes en el SPS son: seq_parameter_set_id: Un identificador para que los PPS puedan referenciar de que SPS dependen. pic_order_cnt_type: Un valor de cero indica que en la cabecera de la tira tendremos su orden dentro del GOP. Los demás valores están sin definir. Siempre a cero. pic_width_in_mbs_minus1: Indica la anchura en macro-bloques del fotograma. 2.3.1.3. Picture Parameter Set: Los PPS contiene información para decodificar, principalmente sobre la capa de cuantificación. Puede haber uno para cada capa de las que forman el flujo de datos, y llevan asociado un SPS para la capa 000, y un SSPS para las demás. Los elementos sintácticos más importantes en el PPS son: pic_parameter_set_id: Un identificador del conjunto de parámetros a nivel de fotograma para poder referenciarlo desde la cabecera de la tira. seq_parameter_set_id: Identificador del SPS o SSPS del cual depende. entropy_coding_mode_flag: Nos indica si la codificación de datos de la secuencia de video se ha realizado con CAVLC (0) o CABAC (1). Ambos tipos de codificación son codificadores entrópicos con longitud de las palabras variables, y se aplican a los coeficientes transformados en forma de codificación. 2.3.2. Unidades NAL VCL: Las unidades NAL VCL son las que contienen la información útil del video. En función del tipo de unidad NAL se pueden clasificar en “Coded Slice of a non-IDR Picture”, “Coded Slice of an IDR Picture” y las “Coded Slice Extension” propias de SVC. Por tipo de tira se pueden clasificar en tiras I (Intra-predecidas), tiras P (inter-Predecidas) y tiras B (Bipredecidas). Todas las unidades NAL VCL, constan de la cabecera de la unidad NAL ya analizada en apartados anteriores y de la cabecera de la tira, que nos dará toda la información para Sistema de video adaptativo H264/SVC sobre TCP 36 decodificar, ya que referencia al “Picture Parameter Set” que a su vez referencia al “Sequence Parameter Set” o “Subset Sequence Parameter Set” correspondiente. 2.3.2.1. Coded Slice of non-IDR Picture: Las tiras codificadas de una imagen que no son de instante de refresco instantáneo, son aquellas que forman parte de la capa base, y que además de poder ser tiras I, como en el caso IDR, pueden ser tiras P o B. Se caracterizan por ser iguales en H264/AVC que en H264/SVC. Los elementos sintácticos más importantes de la cabecera de las tiras no IDR son: first_mb_in_slice: Indica la posición del primer macro-bloque en la tira. En principio vale cero, pero si la tira fuera demasiado grande para caber en una unidad NAL, se utiliza para indicar la posición relativa en número de macro-bloques. slice_type: Indica el tipo de tira. Las tiras I son el número 2, las P el número 0 y las B el número 1. pic_parameter_set_id: Indica de que “Picture Parameter Set” depende. pic_order_cnt_lsb: Nos indica cual sera el orden de decodificación, el cual va a seguir la estructura del GOP. direct_spatial_mv_pred_flag: Indica si esta activa (1) o desactiva (0) la predicción directa entre capas. Un valor de cero indica que se pueden coger las tiras anterior y posterior para la decodificación temporal. Los elementos sintácticos más importantes de la parte de datos de las tiras son: mb_skip_run: Se utiliza en CAVLC, e indica el número de macro-bloques no codificados o perdidos. mb_skip_flag: Se utiliza en CABAC, e indica si el macro-bloque presente se reconstruye con datos de la propia tira o de otras. 2.3.2.2. Coded Slice of an IDR Picture: Las tiras codificadas de una imagen de refresco instantáneo de decodificación, solo pueden ser tiras I, y nunca tendrán ningún mb_skip_flag igual a uno, ni ningún mb_skip_run diferente de cero. Se utilizan como punto de recuperación de errores, ya que dichas unidades NAL no dependen de ninguna otra. Los elementos sintácticos de estas unidades NAL son los mismos de las no IDR, con lo que la cabecera de la tira contiene los mismos campos. 2.3.2.3. Coded Slice Extension: 37 Sistema de video adaptativo H264/SVC sobre TCP Son las tiras propias de las capas superiores según H264/SVC. Mantienen mucha similitud con la sintaxis de H264/AVC (la parte de datos es igual). Sin embargo, se añaden algunos campos importantes para la caracterización de la escalabilidad. Los elementos sintácticos más importantes que se añaden respecto a las de AVC son: store_ref_base_pic_flag: Indica si se debe tener en cuenta la tira inmediatamente inferior, según niveles de dependencia, en el proceso de predicción de los vectores de movimiento de los macro-bloques de los datos de tira. ref_layer_dq_id: Indica el valor de los parámetros DQ de la capa que se utiliza como referencia. El parámetro DQ se establece según la expresión: DQ_id = (dependency_id << 4) + quality_id slice_skip_flag: Un valor de uno indica que no hay datos de tira. num_mbs_in_slice_minus1: Indica el número de macro-bloques que se van a predecir directamente. Sistema de video adaptativo H264/SVC sobre TCP 38 Capítulo 3: Filtrado adaptativo: 3.1. Filtrado de unidades NAL: Hasta este capítulo, se ha introducido la teoría necesaria para la correcta comprensión de los puntos que se introducirán a continuación. En concreto, se puede considerar como el capítulo central del proyecto, ya que es aquí donde se introducirá, la forma de filtrar las unidades NAL, de tal forma que con el resultado obtenido pasado el filtrado sea posible obtener una secuencia de video decodificable con los paquetes de software JSVM y OpenSVCDecoder. En primer lugar, vamos a definir como se entiende la palabra filtrar en este contexto. Entendemos como filtro de unidades NAL, el filtro que es capaz de extraer sub-flujos decodificables a partir del flujo general con distintos parámetros máximos de “dependency_id”, “quality_id” y “temporal_id”. De esta forma se extraerán capas con atributos menores a los máximos que serán a su vez conformantes con el estándar, y por lo tanto decodificables y reproducibles. En segundo lugar, cabe destacar que en el algoritmo desarrollado se ha buscado, la máxima adaptación a todas las codificaciones posibles, pero en el transcurso del desarrollo, he decidido acotar algunas limitaciones, contemplando aspectos como el de implementabilidad de la lógica interna en tiempo real equiparablemente inferior al tiempo de reproducción. Razón, por la que se han impuesto las siguientes restricciones en el proceso de codificación: El nivel de dependencia entre capas siempre respecto a la inferior. Máximo 2 capas de escalabilidad de SNR por cada capa. Para tratar el tema con detalle, se van a tomar en consideración las distintas implicaciones en el proceso de filtrado, teniendo en cuenta que las reglas expuestas a continuación, van acotadas a las restricciones anteriores. De esta forma, el planteamiento elegido es empezar de abajo a arriba añadiendo nuevas reglas impuestas según el nivel de opciones utilizado. 3.1.1. Reglas de dependencia en el filtrado de unidades NAL: Se empezará desde una primera versión en la que se verán las reglas impuestas por el uso de diferentes capas con escalabilidad espacial, conjuntamente con el uso de escalabilidad temporal. Una vez vistas las reglas de dependencia en el filtrado de 39 Sistema de video adaptativo H264/SVC sobre TCP unidades NAL para la reproducción en este caso, se pasara a evaluar las reglas introducidas por el uso de escalabilidad de SNR, y la introducción de “Medium Grain Scalability”. SINTAXIS: Si se desea extraer (Di, Ti, Qi) se debe extraer (Dj, Tj, Qj) Equivalente a: (Di, Ti, Qi) (Dj, Tj, Qj) Si se desea extraer (Di , Ti, Qi) no se debe extraer (Dj, Tj, Qj) Equivalente a: (Di, Ti, Qi) -/-> (Dj, Tj, Qj) 3.1.1.1. Reglas con escalabilidad espacial y temporal: En general, las reglas de dependencia cumplen: Escalabilidad temporal: (D, T + 1, 0) (D, T, 0) Escalabilidad espacial: (D + 1, T, 0) (D, T, 0) En particular, se deben añadir las siguientes reglas: Reglas combinadas: Si existe (Di, TMAX + 1, 0): (DMAX, TMAX, QMAX) -/-> (Di, TMAX + 1, 0) Esta regla básicamente indica que cuando existan más tiras B en alguna capa inferior que en la capa que se va a extraer (es decir, que se utilice una velocidad de reproducción mayor en capas inferiores), al extraer la capa superior a velocidad de reproducción menor que la capa inferior, esas tiras B de las capas inferiores van a ser filtradas en la extracción de la capa superior porque no habrán sido utilizadas para las predicciones entre capas, y consecuentemente no serán necesarias para la decodificación. 3.1.1.2. Reglas con escalabilidad de SNR y uso de MGS: Sistema de video adaptativo H264/SVC sobre TCP 40 En general las reglas de dependencia cumplen: Escalabilidad de SNR y uso de MGS: (D, T, Q + 1) (D, T, Q) Con el uso de MGS se añade una nueva regla general, que implica que cuando se utilizan niveles temporales con escalabilidad de SNR que en la capa superior no incluyen todos los coeficientes DCT de la codificación, en caso de existir alguna capa con la misma resolución y nivel temporal inferior, se deben incluir todas las capas MGS de esos niveles que contengan coeficientes DCT. Si existe (DMAX , Ti, QMAX + 1) Ti < TMAX (DMAX, TMAX, QMAX) (DMAX, Ti, QMAX + 1) Reglas combinadas con escalabilidad espacial y temporal: Para el correcto funcionamiento del algoritmo que se expondrá en el siguiente apartado, es importante remarcar que en un video codificado con H.264 SVC, se deben aplicar todas las reglas que se han ido desglosando en varios apartados, para obtener un archivo SVC filtrado que sea conformante con el estándar. 3.1.2. Algoritmo de filtrado de unidades NAL: A través de las reglas expuestas anteriormente, se ha procedido a la obtención del algoritmo en lenguaje de programación que llevara a cabo el acometido de extraer según los límites impuestos por dichas reglas. Se distinguen los dos casos según se trate de un video codificado que utilice MGS, o en ausencia de su uso. 3.1.2.1. Algoritmo de extracción sin usar MGS: Para una mejor comprensión del código que se muestra a continuación, vamos a ver un ejemplo del funcionamiento del algoritmo de filtrado explicado detalladamente. En este caso, no se contempla el uso de MGS, por lo que el ejemplo elegido, ha sido pensado para contener los tres tipos de escalabilidad, es decir una codificación con tres capas, la capa base, una capa de mejora de calidad, y otra con más resolución. Así, se estaría utilizando escalabilidad de resolución y de SNR. Por esto, se elige un tamaño de GOP igual a 2 generando así dos capas temporales por capa de resolución y calidad. En este caso particular, dispondremos de seis capas, que según el valor de sus identificadores DTQ, serán las capas 000, 001, 100, 010, 011 y 110. La generación del flujo se hace según la imagen de la figura 3.1. 41 Sistema de video adaptativo H264/SVC sobre TCP Figura 3.1: Estructura de la codificación, con capa base, capa de calidad mejorada y capa de resolución superior Partiendo de la capa base (000) se generan las capas superiores en niveles de dependencia de resolución (100), de calidad (001) y temporal (010), y a partir de las capas superiores se generan las capas temporales superiores en resolución (110) y calidad (011). Estas últimas capas dependen a su vez de la capa base y de las capas de mejora. El algoritmo de filtrado, se encarga de obtener la extracción con un DTQ_th máximo, encargándose de cumplir todos los niveles de dependencia, es decir, hacer que en cada extracción se cumplan todas las reglas descritas en el apartado anterior. Por ejemplo, para conseguir la extracción del flujo con máxima resolución a la máxima velocidad de reproducción se deben incluir las unidades NAL correspondientes a las capas 000, 010, 100 y 110, porque para cumplir las reglas, la extracción hasta 110 debe incluir todas sus dependencias, la capa 100 según dependencia temporal y las capas 000 y 010 porque la capa base de la que se predice entre capas es esta. Es importante darse cuenta que no depende de las capas de calidad mejorada, ya que se parte de una codificación, en la que se debe haber utilizado como capa base de la de resolución mayor, la capa base. En este caso también se podría añadir las capas de mejora de calidad, pero no se obtendría el mínimo flujo de transmisión. Para completar el ejemplo, se ve en la tabla siguiente para cada DTQ_th de extracción, las capas que va a incluir una vez analizado según el algoritmo de extracción que se mostrará más adelante. DTQ_th 000 001 100 010 011 110 Capas incluidas 000 001 100 010 011 Sí No No No No Sí Sí No No No Sí No Sí No No Sí No No Sí No Sí Sí No Sí Sí Si No Sí Sí No Tabla 3.1: Resultados algoritmo de extracción para el ejemplo 1 110 No No No No No Sí Sistema de video adaptativo H264/SVC sobre TCP 42 A continuación, vemos el código correspondiente al algoritmo de filtrado para el caso sin uso de MGS, el cual se encarga de realizar el proceso descrito en el ejemplo, y en el que los atributos “dependency_id”, “quality_id” y “temporal_id” se corresponden con los atributos de cada unidad NAL analizada. //PARAMETROS LIMITE EN LA EXTRACCIÓN int dependency_id_th, quality_id_th, temporal_id_th; int extract = 0; //1: NALU se debe extraer //0: No se debe extraer //Parametros auxiliares para manejar los limites en las distintas capas int quality_id_tmp; … extract = 0; quality_id_tmp = quality_id_th; for(int i=dependency_id_th; i>-1; i--){ for(int j=temporal_id_th; j>-1; j--){ for(int k=quality_id_tmp; k>-1; k--){ if(dependency_id == i && temporal_id == j && quality_id == k){ extract = 1; break; } } if(extract == 1) break; } if(extract ==1) break; quality_id_tmp = 0; } if(extract == 1){ //ALMACENAR o TRANSMITIR } 3.1.2.2. Algoritmo de extracción usando MGS: De la misma forma, que en el caso sin MGS, vamos a ver un ejemplo, que permita la correcta comprensión del código que se añade al algoritmo de extracción para el caso en que se va a usar MGS. La codificación de video elegida es la misma que en el ejemplo anterior, pero usando MGS en la capa de calidad mejorada. En concreto, se van a generar dos capas de calidad mejorada, que contendrán cuatro de los ocho coeficientes transformados cada 43 Sistema de video adaptativo H264/SVC sobre TCP una. De esta forma, se generan las ocho capas 000, 001, 002, 100, 010, 011, 012 y 110, tal y como se ve en la figura 3.2. Figura 3.2: Estructura de la codificación, con capa base, capa de calidad mejorada con uso de MGS y capa de resolución superior Aunque, en la imagen se muestra, la capa añadida (Q=2) como si fuera predicha a partir de la capa de mejora (Q=1), en realidad se trata de una codificación con MGS, por lo que se trata de la misma capa pero en este caso se parten los coeficientes transformados en dos capas. En la práctica, se van a dividir las unidades NAL de la misma forma que si se estuvieran utilizando varias capas de mejora. La principal diferencia, con el algoritmo de extracción sin el uso de MGS, es que se va a cumplir la última regla general expuesta, que consiste en incluir las capas con identificador de calidad mayor, nivel temporal inferior y misma resolución que el de la extracción, en los casos en que se va extraer con identificador de calidad menor e identificador temporal más grande. Este es el caso, que sucede cuando se quiere extraer hasta la capa 011, en que según el algoritmo de filtrado sin MGS, cumpliendo todas las dependencias se iban a extraer las capas 000, 001, 010 y 011. Lo que sucede, es que al usar MGS, los coeficientes transformados quedan divididos en las capas con Q igual a uno y dos, razón por la que si se quiere extraer hasta 011 se debe incluir la capa 002 para que se incluyan todos los coeficientes transformados de la capa DT igual a 00. Es importante tener en cuenta, que en el caso de haber utilizado dos capas de calidad mejorada el algoritmo de extracción funciona correctamente sin el uso de MGS. Por esto, ya se ha expuesto al inicio del capítulo que se limita a dos capas con diferentes calidades por capa de resolución, y posibilidad de usar MGS en la capa de mejora. Para completar el ejemplo, se ve en la tabla siguiente para cada DTQ_th de extracción, las capas que va a incluir una vez analizado según el algoritmo de extracción que se mostrará más adelante. DTQ_th 000 001 002 Capas incluidas 100 010 011 012 110 Sistema de video adaptativo H264/SVC sobre TCP 000 001 002 100 010 011 012 110 Sí No No No No No No Sí Sí No No No No No Sí Sí Sí No No No No Sí No No Sí No No No Sí No No No Sí No No Sí Sí Sí No Sí Sí No Sí Sí Sí No Sí Sí Sí Si No No Sí Sí No No Tabla 3.2: Resultados algoritmo de extracción para el ejemplo 2 44 No No No No No No No Sí A continuación, se muestra el código correspondiente al algoritmo de filtrado para el caso con uso de MGS. Los atributos “dependency_id”, “quality_id” y “temporal_id” se corresponden con los atributos de cada unidad NAL analizada. A continuación, vemos el código correspondiente al algoritmo de filtrado para el caso sin uso de MGS, el cual se encarga de realizar el proceso descrito en el ejemplo, y en el que los atributos “dependency_id”, “quality_id” y “temporal_id” se corresponden con los atributos de cada unidad NAL analizada. //PARAMETROS LIMITE EN LA EXTRACCIÓN int dependency_id_th, quality_id_th, temporal_id_th; int extract = 0; //1: NALU se debe extraer //0: No se debe extraer //Parametros auxiliares para manejar los limites en las distintas capas int quality_id_tmp; //Parametros que contendran las capas a las que se les da acceso int D_array[NUM_LAYER], T_array[NUM_LAYER], Q_array[NUM_LAYER]; int pos_array = 0; … extract = 0; quality_id_tmp = quality_id_th; for(int i=dependency_id_th; i>-1; i--){ for(int j=temporal_id_th; j>-1; j--){ for(int k=quality_id_tmp; k>-1; k--){ if(dependency_id == i && temporal_id == j && quality_id == k){ extract = 1; break; } } if(extract == 1) break; } if(extract ==1) break; 45 Sistema de video adaptativo H264/SVC sobre TCP quality_id_tmp = 0; } //Comprobar que en caso de (D,T,Q) almacenado con ((D < dependency_id_th || T < temporal_id_th)&&Q>=1) // Se incluyan también (D,T,Qi) con Qi>Q int i = 0; if(quality_id > 0 && extract == 0){ while(!(D_array[i] == -1 && T_array[i] == -1 && Q_array[i] == -1) == true){ if((D_array[i] < dependency_id_th || (T_array[i] < temporal_id_th)) && Q_array[i] > 0){ if(dependency_id == D_array[i] && temporal_id == T_array[i] && quality_id > Q_array[i]){ extract = 1; } } i++; } } //Comprobar si existe (D, T, Q) introducido en los arrays i = 0; int DTQ_exists_in_array = 0; while(!(D_array[i] == -1 && T_array[i] == -1 && Q_array[i] == -1)){ if(dependency_id == D_array[i] && quality_id == Q_array[i] && temporal_id == T_array[i]){ DTQ_exists_in_array = 1; break; } i++; } //Almacenar capas a las que se les da acceso y que no han sido introducidas antes (DTQ_exists_in_array == 0) if(extract == 1 && DTQ_exists_in_array == 0){ D_array[pos_array] = dependency_id; Q_array[pos_array] = quality_id; T_array[pos_array] = temporal_id; pos_array++; } if(extract == 1){ //ALMACENAR o TRANSMITIR } 3.2. Filtrado adaptativo: Sistema de video adaptativo H264/SVC sobre TCP 46 Se define el filtrado adaptativo, como la capacidad de extracción de distintas capas máximas a través del tiempo, de forma que durante un intervalo de tiempo se extraerá a un DTQ_th y durante otro intervalo de tiempo a otro DTQ_th distinto del primero y así, sucesivamente. Las reglas del filtrado adaptativo, vendrán limitadas por las líneas de dependencia entre unidades NAL propias del estándar H264. De esta manera empezaremos por ver como se conforman los flujos de transmisión en el estándar H264/AVC, para seguir con la conformación del estándar H264/SVC, para a posteriori poder obtener los posibles puntos de corte en que se pueda realizar un intercambio de capa. 3.2.1. Orden de transmisión de flujo de datos H264/AVC: Hay tres casos a contemplar, el flujo inicial en que se transmite una I seguida de una P, porque I y P, siempre van transmitidas antes que las B que se reproducen antes de la I o P en cuestión, contemplado como flujo en inicio; flujo normal y flujo cuando se encuentra una unidad NAL de refresco instantáneo de decodificación (IDR). Vamos a ver unos cuantos ejemplos con valores variables de tamaño de GOP. Flujo de inicio: GOP size = 2: Figura 3.3: Flujo de inicio con tamaño de GOP igual a 2 GOP_size = 4: Figura 3.4: Flujo de inicio con tamaño de GOP igual a 4 GOP size = 8: 47 Sistema de video adaptativo H264/SVC sobre TCP Figura 3.5: Flujo de inicio con tamaño de GOP igual a 8 Flujo normal: GOP size = 2: Figura 3.6: Flujo normal con tamaño de GOP igual a 2 GOP_size = 4: Figura 3.7: Flujo normal con tamaño de GOP igual a 4 GOP size = 8: Figura 3.8: Flujo normal con tamaño de GOP igual a 8 Sistema de video adaptativo H264/SVC sobre TCP 48 Como se puede ver, el orden de dependencia es tal que se van añadiendo tiras B, hasta llegar al máximo identificador de dependencia, y a partir de ahí se van repartiendo de dos en dos formando la estructura que se puede ver en las imágenes. La diferencia entre el flujo de origen y el normal es tal que en el origen se transmiten primero las tiras I y P para que las B que se transmiten a posteriori sean anteriores en orden de reproducción. En el caso de intercambio por tira I de refresco de decodificación se deben contemplar dos casos. En primer lugar, el caso en que el periodo de IDR es múltiple del periodo de tiras intra-predecidas, caso en el que cuando se pone la tira IDR le toca a una tira I. Y el segundo es el caso contrario, caso en el que debido a que el periodo IDR debe ser múltiple del tamaño de GOP, le corresponderá la posición de una P. Flujo en IDR: IDR_period = M * Intra_period (M entero): GOP size = 2: Figura 3.9: Flujo en IDR múltiple periodo intra-predicción con tamaño de GOP igual a 2 GOP size = 4: Figura 3.10: Flujo en IDR múltiple periodo intra-predicción con tamaño de GOP igual a 4 GOP size = 8: 49 Sistema de video adaptativo H264/SVC sobre TCP Figura 3.11: Flujo en IDR múltiple periodo intra-predicción con tamaño de GOP igual a 8 IDR_period != M * Intra_period (M entero): GOP size = 2: Figura 3.12: Flujo en IDR no múltiple periodo intra-predicción con tamaño de GOP igual a 2 GOP size = 4: Figura 3.13: Flujo en IDR no múltiple periodo intra-predicción con tamaño de GOP igual a 4 GOP size = 8: Sistema de video adaptativo H264/SVC sobre TCP 50 Figura 3.14: Flujo en IDR no múltiple periodo intra-predicción con tamaño de GOP igual a 8 El detalle más importante en que hay que fijarse es el hecho que cuando aparece una tira I de refresco instantáneo de decodificación, las tiras B siguientes no tienen dos tiras para ser inter-predichas y consecuentemente se transforman en tiras P en las que el segundo subíndice indica la posición relativa. Para el filtrado adaptativo en H264/AVC tendremos combinaciones con diferentes identificadores de dependencia temporal, como por ejemplo 010 y 020. Al tener siempre dependencia hacía atrás en tiempo de reproducción respecto al tiempo de transmisión será posible cortar por cualquier sitio obteniendo como resultado flujos conformantes con el estándar, independientemente de si los intercambios son de identificador temporal mayor a menor, o menor a mayor. 3.2.2. Orden de transmisión de flujo de datos H264/SVC: Para el caso del estándar H264/SVC se elige una codificación que contiene los tres tipos de escalabilidad a modo de ejemplo para detectar las características que deben cumplir los puntos de corte para obtener flujos de datos conformantes con el estándar. En concreto, se elige una codificación de tres capas, capa base, capa de calidad de SNR mejorada y capa con resolución superior a las dos capas anteriores, con un tamaño de GOP en cada capa de dos. Se va a ver para esta codificación el orden de transmisión del flujo de datos para cada uno de los cuatro casos. Los subíndices indican la capa correspondiente a la que pertenecen las unidades NAL, siendo cero la capa base, 1 la capa de escalabilidad de SNR y 2 la capa de escalabilidad de resolución. Se muestra a continuación, los flujos generados. Flujo de inicio: Figura 3.15: Flujo inicio codificación con tres capas, capa base, capa calidad mejorada y capa de resolución superior 51 Sistema de video adaptativo H264/SVC sobre TCP Flujo normal: Figura 3.16: Flujo normal codificación con tres capas, capa base, capa calidad mejorada y capa de resolución superior Flujo en IDR: IDR_period = M * Intra_period (M entero): Figura 3.17: Flujo en IDR múltiple periodo intra-predicción codificación con tres capas, capa base, capa calidad mejorada y capa de resolución superior IDR_period != M * Intra_period (M entero): Sistema de video adaptativo H264/SVC sobre TCP 52 Figura 3.18: Flujo en IDR no múltiple periodo intra-predicción codificación con tres capas, capa base, capa calidad mejorada y capa de resolución superior De forma general, igual que en el caso analizado, el orden de transmisión cuando se transmite más de una capa, sigue el orden temporal de H264/AVC, fijando el orden entre capas correspondiente a la codificación. En este caso, se transmiten primero las unidades NAL de la capa base, seguidas por las de escalabilidad de SNR, y finalmente las de escalabilidad de resolución. 3.2.3. Parámetros de diseño del filtrado adaptativo: Vamos a analizar a continuación la posibilidad de transmitir flujos filtrados adaptativamente que puedan contener cualquier combinación entre las seis capas generadas (000, 001, 100, 010, 011 y 110). En primer lugar es importante darse cuenta que en los flujos resultantes se deberá cumplir todas las restricciones de dependencia propias del estándar. Así, si se fuera a cortar por tiras P o tiras B, ya se ve enseguida que dependerían de las tiras I anteriores, por lo que podría dar lugar a flujos de datos no conformantes. De esta forma, se ve la necesidad de que los puntos de corte se localicen en las tiras I de la capa base. Entonces, teniendo en cuenta que las tiras B que siguen al punto de corte son dependientes de las dos tiras I y/o P anteriores se llega a dos posibilidades en el filtrado realizado en el flujo normal: 1. Cambiar de DTQ_th en la tira I con DTQ igual a 000, y filtrar las tiras B siguientes, de forma que se consigue un flujo de datos decodificable porque las siguientes tiras B que aparecen ya disponen de dos tiras I y/o P para poder ser decodificadas correctamente. 2. La segunda opción, es no filtrar las tiras B que se transmiten después del punto de corte. En este caso, estas tiras B dependerán del DTQ_th inicial porque para 53 Sistema de video adaptativo H264/SVC sobre TCP poder ser decodificadas, deberá ser filtrado en el DTQ_th que se dispongan las dos tiras I y/o P anteriores, y como antes del filtrado la tira I y/o P anterior será extraída en el primer DTQ, las tiras B que siguen al punto de corte se van a filtrar con el DTQ_th que había antes del corte. De forma similar las siguientes tiras B que aparezcan dependerán de las dos tiras I y/o P anteriores, razón por la cual dependerán de las tiras I siguientes al punto de corte incluidas en la extracción. Se ve así la necesidad de extraer las tiras I siguientes al corte para que se incluya las necesarias para decodificar las dos tiras B siguientes. Es decir, debe incluir las tiras I según los dos DTQ_th, el anterior y el posterior al punto de corte. Así, el funcionamiento es el siguiente, intercambio a DTQ_th2 cuando se detecte tira I con DTQ igual a 000, cambio a DTQ_th cuando se detecte dependencia temporal más grande que uno y intercambio a DTQ_th2 cuando se vuelva a detectar tira con nivel de dependencia temporal igual a 0. En el caso de intercambio de capa por un punto de corte IDR, que también cumple que la tira del intercambio es una I con DTQ igual a 000, al ser las tiras siguientes dependientes solamente de la unidad NAL IDR, van a poder realizar el intercambio sin tener que filtrar ni tener en cuenta consideraciones adicionales. Se muestra el ejemplo de un intercambio entre 110 y 011 para cada uno de los casos. Flujo normal: Figura 3.19: Intercambio entre capas 110 y 011 en flujo normal. Caso 1 Figura 3.20: Intercambio entre capas 110 y 011 en flujo normal. Caso 2 Flujo en intercambio IDR: IDR_period = M * Intra_period (M entero): Figura 3.21: Intercambio entre capas 110 y 011 en flujo IDR múltiple Sistema de video adaptativo H264/SVC sobre TCP periodo intra-predicción IDR_period != M * Intra_period (M entero): Figura 3.22: Intercambio entre capas 110 y 011 en flujo IDR no múltiple periodo intra-predicción 54 55 Sistema de video adaptativo H264/SVC sobre TCP Capítulo 4: Estimación del ancho de banda de transmisión: Una vez visto el algoritmo de filtrado de unidades NAL, el siguiente paso para desarrollar el sistema de transmisión de video adaptativo sobre TCP, es plantearse cuál será él, o los parámetros que nos permitirán transmitir adaptativamente a la conexión un determinado número de capas durante un cierto tiempo y otro determinado número de capas durante otro cierto tiempo, y así sucesivamente. De esta forma, es en el protocolo TCP, donde vamos a buscar los parámetros característicos de la conexión, razón por la cual en primer lugar se verá una breve descripción de los parámetros de funcionamiento del protocolo de transporte TCP. 4.1. Protocolo de control de Transporte: TCP es un protocolo de transporte orientado a conexión, fiable y con control de errores extremo a extremo. Es orientado a conexión porque antes de iniciar la conexión se pasa por la fase de establecimiento y al finalizar la conexión se pasa por la fase de cierre de conexión. Es fiable porque se encarga de comprobar y asegurar que los paquetes se reciban y que sea en orden correcto, mediante el uso de control de errores, basados en el uso de paquetes de reconocimiento de recepción por parte del extremo receptor. En primer lugar, cuando aparece una conexión usando TCP, se pasa por la fase de establecimiento, que es un proceso de tres pasos, el extremo que inicia la apertura activa envía un paquete SYN, al extremo que debe estar escuchando en un puerto de recepción, para que cuando reciba un paquete SYN, responda con un SYN-ACK, que le indica al extremo inicial que se va a establecer conexión, y este finalmente envía un paquete de reconocimiento de recepción del paquete de establecimiento de conexión, momento en que la conexión queda establecida, y ya se puede iniciar la transmisión de paquetes de datos. La fase de cierre funciona exactamente igual, pero en este caso los paquetes enviados son FIN, FIN-ACK y ACK. Vemos a continuación una imagen que muestra ambas fases de conexión. Sistema de video adaptativo H264/SVC sobre TCP 56 Figura 4.1: Fases de establecimiento y finalización de conexión Una conexión TCP queda caracterizada por dos direcciones IP y dos puertos, los correspondientes al origen y al destino de la conexión. De esta forma se llama establecimiento activo a la parte que fija la dirección y el puerto de destino y transmite desde dirección y puerto origen, y establecimiento pasivo al extremo que fija su dirección y puerto de destino y pone un socket en escucha a la espera de que se establezcan conexiones. En una conexión TCP, se define el control de errores como la capacidad de detectar cuando se produce un error en las transmisiones. De esta forma, se utilizan paquetes ACK, de reconocimiento que se encargan de asegurar cuando se reciben en el extremo transmisor que los paquetes enviados hasta el reconocido han sido recibidos correctamente. Así, existen tres posibilidades cuando se envía un paquete, primero que se reciba y se reconozca correctamente, segundo que el paquete se pierda y tercero que haya un reenvió del paquete debido a la pérdida del reconocimiento. Es por esta razón, que se define el tiempo de retransmisión (RTO) antes de que se reenvíe el paquete. El valor de este tiempo viene determinado por medidas del tiempo de transporte extremo a extremo (“Round Trip Time”), y se utiliza con un algoritmo de backoff exponencial que va multiplicando por 2 (RTO(n) = 2 * RTO(n – 1)), a medida que se van perdiendo paquetes porque se asume que cuando se pierden es un indicativo de una situación de congestión. Las tres situaciones citadas son las siguientes. 57 Sistema de video adaptativo H264/SVC sobre TCP Figura 4.2: Casos de transmisión: Paquete enviado y reconocido, retransmisión y paquete duplicado Además, TCP dispone de control de flujo, en que mediante el mecanismo de ventana deslizante se controla que el flujo en red sin haber sido procesado por parte del extremo receptor no exceda el límite fijado por el tamaño de la ventana deslizante. El funcionamiento es tal que cada vez que se transmite un determinado paquete de tamaño N bytes, se reduce el tamaño de la ventana en dicho tamaño, llegando como mínimo al tamaño de ventana igual a 0 bytes, caso en que se detendrá la transmisión a la espera de que el nodo receptor envíe otro paquete indicando que el tamaño de la ventana ha aumentado. Se muestra a continuación una imagen que contiene un ejemplo de funcionamiento del control de flujo. Sistema de video adaptativo H264/SVC sobre TCP Figura 4.3: Ejemplo de control de flujo 4.1.1. Cabecera TCP: La cabecera del protocolo de control de transporte es la siguiente: Figura 4.4: Cabecera TCP Los campos por los que está formado son los siguientes: Puerto de origen. Puerto de destino. 58 59 Sistema de video adaptativo H264/SVC sobre TCP Número de secuencia: Número del paquete transmitido. Sigue orden secuencial. Número de ACK: Número de secuencia de reconocimiento hasta el que se reconoce paquetes anteriores recibidos correctamente. Tamaño de la cabecera: Se expresa en palabras de 4 bytes. Code bits: Bits para enviar mensajes especiales. o FIN: Finalizar conexión o SYN: Establecer conexión. o RTS: Resetear la conexión. o PSH: Petición de envió de datos. o ACK: Reconocimiento de paquetes. o URG: Campo de puntero urgente valido. Tamaño de la ventana deslizante. Checksum: Función resumen obtenida a partir de las direcciones IP y otros atributos. Opciones: MSS, Window Scale y Timestamp. A parte de los campos descritos en TCP también es posible añadir opciones en la cabecera, se puede modificar el tamaño de segmento mediante la opción MSS, o el escalado de ventana, y ponerle etiquetas temporales a los paquetes marcando los tiempos de envío y recepción para poder por ejemplo obtener una estimación de RTO. 4.1.2. Control de congestión: El control de congestión en TCP es el que se encarga de controlar las situaciones con alto tráfico en red que conlleven reenvíos de paquetes. Consta de tres mecanismos, inicio lento, evitar congestión y ser conservativo después de eventos de retransmisión. Al iniciar la transmisión se empieza con “slow start”, se fija la ventana de congestión a que solo se pueda transmitir un segmento, y cada vez que se recibe un ACK, se multiplica por dos de forma exponencial el número de segmentos que se pueden transmitir. Una vez se detecta que ha habido alguna perdida, se pasa a trabajar con uno de los otros dos métodos. Sistema de video adaptativo H264/SVC sobre TCP 60 Figura 4.5: Fase “slow start” Si se detectan tres ACK duplicados, se pasa a trabajar con el mecanismo “Congestion Avoidance”, que se basa en incremento aditivo, y decremento multiplicativo, de forma que cuando se detectan los tres ACK duplicados se reduce la ventana de congestión a la mitad y a partir de ese momento, con la situación de congestión detectada se pasa a aumentar el tamaño de uno en uno. Se puede ver a continuación un ejemplo de este mecanismo. Figura 4.6: Ejemplo control de congestión Por último, en el caso de que se detecte una retransmisión, se reduce el tamaño a uno y se empieza otra vez los aumentos de forma exponencial hasta un límite fijado normalmente en la mitad de tamaño que tenía antes de detectar la situación de congestión. 61 4.2. Sistema de video adaptativo H264/SVC sobre TCP Estimación del ancho de banda de transmisión: Una vez vistas las principales características del protocolo de transporte TCP, vamos a pasar a evaluar con que parámetros será posible controlar a nivel de aplicación que la transmisión sea adaptativa al protocolo TCP. Básicamente, los parámetros principales son el ancho de banda disponible, y el tiempo de transmisión extremo a extremo. Es importante darse cuenta que se pueden definir varias estrategias a nivel de capa de aplicación, como por ejemplo añadir comunicación entre los extremos transmisor y receptor, para mediante la definición de un protocolo a nivel de aplicación conseguir evitar transmisiones en ciertas circunstancias. En este proyecto, a diferencia del concepto anterior se ha optado por evitar definir un protocolo a nivel de aplicación y en su lugar, se ha elegido que mediante las medidas estimadas por parte del sistema operativo se consiga saber aproximadamente cuál es el ancho de banda disponible, y acotar la transmisión de forma adaptativa a las condiciones de red existentes. A nivel de socket el ancho de banda disponible podrá ser estimado por la siguiente expresión: BW(bits/s) = cwnd(bits) / RTT(s) Es por esta razón que el siguiente paso lógico de la operación es tratar de obtener en tiempo real la estimación del ancho de banda a transmitir por parte de cada una de las posibles combinaciones de parámetros de escalabilidad del video codificado. 4.2.1. Tamaño de las capas de extracción en tiempo real: El primer paso para poder obtener una estimación en tiempo real que nos permita comparar el ancho de banda disponible con el ancho de banda necesario para transmitir hasta una capa determinada, es obtener en tiempo real el tamaño de cada unidad NAL con una determinada combinación de DTQ, para así mediante el conocimiento de la velocidad de transmisión del video poder estimar para cada capa el ancho de banda necesario para su transmisión. Con un fotograma: BW(bits/s) = L(bits/frame)*Fps(frame/s) Con N fotogramas: BW(bits/s) = L(bits en N frames)*Fps(frames/s)/N(frames) Sistema de video adaptativo H264/SVC sobre TCP 62 El primer punto importante, es darse cuenta, que no basta con obtener el tamaño de una determinada unidad NAL de la DTQ, sino que en su lugar el tamaño que se tiene que obtener en tiempo real, es el agregado, de todas las capas incluidas que habría en la extracción de un determinado DTQ. De esta forma, se ve la necesidad de disponer una vez analizada cada una de las unidades NAL de una estimación del ancho de banda a transmitir para cada una de las posibles combinaciones DTQ del video codificado. En segundo lugar, es importante ver que será necesario aplicar el algoritmo de extracción de unidades NAL cada vez que se analice una de dichas unidades para poder obtener la estimación de todas y cada una de las capas. Así, el algoritmo con el que se obtendrá el tamaño de las unidades NAL en tiempo real, básicamente lo que realizara será un incremento del tamaño de cada una de las capas en las que la unidad NAL deba ser incluida. 4.2.2. Velocidad de reproducción del video: El siguiente parámetro para la estimación del ancho de banda necesario para la transmisión, es la velocidad de reproducción del video. La obtención de dicho parámetro es totalmente dependiente del identificador de escalabilidad temporal, parámetro ya propio de H.264 en su versión AVC. A pesar de tener una dependencia directa con este parámetro, es importante remarcar que el parseado entre “dependency_id” y la velocidad de reproducción necesaria para la estimación del ancho de banda, será dependiente del tipo de video. En general se cumple que si se aumenta el parámetro de escalabilidad temporal se multiplica por dos la velocidad de reproducción, pero la velocidad mínima de reproducción es dependiente de la codificación empleada, concretamente se determina a partir de los parámetros “Frame Rate” y “GOP_size”. Por ejemplo para un “GOP_size” de 4 con orden de reproducción IbBbPbBbI… y un “Frame Rate” máximo de 50 frames/s, la velocidad de transmisión con “temporal_id” de 0 es de 12,5 frames/s. 4.2.3. Implementación de la estimación en tiempo real del ancho de banda de transmisión: El objetivo de la implementación es conseguir que en tiempo real se vayan obteniendo los tamaños agregados, y a partir de su velocidad de reproducción y del número de unidades NAL incluidas con el DTQ máximo de la capa se deduzca el ancho de banda de transmisión durante los distintos tramos del video codificado. 63 Sistema de video adaptativo H264/SVC sobre TCP El punto más importante a tener en cuenta es la necesidad de aplicar el algoritmo de extracción cada vez que se analiza una unidad NAL, debido a la necesidad de incrementar el tamaño de cada una de las combinaciones que incluyen el DTQ de la capa analizada. De esta forma, se valoró el desarrollo del mismo algoritmo de extracción en orden inverso, porque se adecuaría mucho mejor al hecho de comprobar de abajo arriba en niveles de dependencia, el hecho de si se debe añadir o no el tamaño de una unidad NAL a una capa de extracción. Sin embargo, no se logró llegar a un algoritmo cerrado que se adaptara al máximo número de unidades NAL. A causa, de no encontrar dicho algoritmo cerrado que evaluara en orden inverso, se pasó a contemplar otra opción igual de valida. Básicamente, se trata que una vez analizada una iteración en las que se presentaran todas las combinaciones de DTQ existentes en la secuencia de video (entre una tira I con DTQ igual a 000 a otra con las mismas características), se aplicara el algoritmo con todas las posibles combinaciones y se almacenaran los datos dentro de un objeto de tipo “extraction_layer” que básicamente contendrá la información de la capa que contiene, especificada como DTQ máximo de la extracción, y un conjunto de vectores conteniendo los DTQ que incluye la extracción. El “struct” correspondiente a los objetos de tipo “extraction_layer” es el siguiente: #define NUM_LAYER N struct extraction_layer { int dependency_id_th; int quality_id_th; int temporal_id_th; int limitD[NUM_LAYER]; que contiene el STRUCT. int limitQ[NUM_LAYER]; int limitT[NUM_LAYER]; int real_time_size; última iteración. int size_aggregated; iteración. int total_size; int num_NALU_included; size_aggregated. int total_num_NALU; //DTQ de la capa que contiene el STRUCT. //Conjunto de DTQ incluidos en la extracción de la capa //Tamaño de la capa superior aislada obtenido en la //Tamaño agregado de todas las capas en la última //Tamaño total. //Número de unidades NAL con DTQ_max incluidas en //Número total de unidades NAL incluidas. Sistema de video adaptativo H264/SVC sobre TCP float bandwidth; 64 //Ancho de banda estimado }; Como, se puede observar, además de contener las capas tal como se ha descrito anteriormente, el mismo objeto almacenará los tamaños, y el número de unidades NAL con el DTQ máximo de la capa en tiempo real. Además, mediante la fórmula expuesta anteriormente, se va a computar en tiempo real el ancho de banda asociado a las medidas realizadas. Siguiendo, con la explicación de cómo se aplicará el algoritmo, una vez almacenadas todas las combinaciones de extracción en las demás iteraciones, solo será necesario evaluar que este contenida en alguna de las capas almacenadas. 4.2.3.1. Detalles de la implementación: A continuación se muestra parte del código para llevar a cabo las iteraciones anteriores. En primer lugar, se especifica el código necesario para conseguir que una vez almacenadas todas las capas superiores en el vector de objetos “extraction_layer”, se analice en todos los casos que capas debe incluir, y se incluyan en las capas correctas (código que sólo será necesario incluir en la primera iteración). Este código, básicamente aplica el algoritmo de filtrado para obtener como resultado en los vectores “limitT”, “limitQ” y “limitD” de cada objeto “extraction_layer”, todas las capas incluidas según el algoritmo de filtrado. Para conseguirlo, se fija un DTQ_th máximo, y se analizan todos los DTQ_th que se hayan detectado en la evaluación entre la primera y segunda tira I con DTQ igual a 000, comprobando para cada caso si se debe incluir la capa en el objeto “extraction_layer”. La decisión se toma aplicando el algoritmo de filtrado, y en los casos que la extracción sea positiva, se contabiliza el tamaño en la capa y se añade la capa a evaluar en los vectores “limitT”, “limitQ” y “limitD”. De esta forma, se consigue que mediante la evaluación de todas las capas para cada uno de los DTQ_th, lo cual se traduce en el uso de dos bucles que recorrerán todas las capas, una vez finalizada la iteración se consigue que cada objeto “extraction_layer” tenga las capas incluidas según el algoritmo de extracción en sus vectores “limitT”, “limitQ” y “limitD”. for(int l=0; l<num_layer; l++){ pos_escritura = 0; 65 Sistema de video adaptativo H264/SVC sobre TCP for(int m=0; m<num_layer; m++){ extract = 0; quality_id_tmp = extract_layer[l].quality_id_th; for(int i=extract_layer[l].dependency_id_th; i>-1; i--){ for(int j=extract_layer[l].temporal_id_th; j>-1; j--){ for(int k=quality_id_tmp; k>-1; k--){ if(extract_layer[m].dependency_id_th == i extract_layer[m].temporal_id_th == j && extract_layer[m].quality_id_th == k){ extract = 1; break; } } if(extract == 1) break; } if(extract ==1) break; quality_id_tmp = 0; } && //Comprobar que en caso de (D,T,Q) almacenado con ((D < dependency_id_th || T < dependency_id_th)&&Q>=1) // Se incluyan también (D,T,Qi) con Qi>Q int o = 0; if(extract_layer[m].quality_id_th > 0 && extract == 0){ while(!(extract_layer[l].limitD[o] == -1 && extract_layer[l].limitT[o] == -1 && extract_layer[l].limitQ[o] == -1) == true){ if((extract_layer[l].limitD[o] < extract_layer[l].dependency_id_th || (extract_layer[l].limitT[o] < extract_layer[l].temporal_id_th)) && extract_layer[l].limitQ[o] > 0){ if(extract_layer[m].dependency_id_th == extract_layer[l].limitD[o] && extract_layer[m].temporal_id_th == extract_layer[l].limitT[o] && extract_layer[m].quality_id_th > extract_layer[l].limitQ[o]){ extract = 1; break; } } o++; } } //Introducir el tamaño de las NAL Units que se deben extraer en el tamaño agregado. if(extract == 1){ if(l!=m){ extract_layer[l].size_aggregated += extract_layer[m].real_time_size; } //Introducir los DTQ que se van a extraer en "extract_layer[l]" Sistema de video adaptativo H264/SVC sobre TCP 66 //Obtener posición en la que se debe escribir extract_layer[l].limitD[pos_escritura] = extract_layer[m].dependency_id_th; extract_layer[l].limitT[pos_escritura] = extract_layer[m].temporal_id_th; extract_layer[l].limitQ[pos_escritura] = extract_layer[m].quality_id_th; pos_escritura++; } } } Por otra parte, una vez ya están almacenadas las capas extraídas, el algoritmo para incluir el tamaño en todas las capas donde se introduce, así como el número de unidades NAL que se han incluido en el “struct” de cada capa, es el que se muestra a continuación. Este código básicamente comprueba para cada unidad NAL si pertenece a alguno de los DTQ incluidos en la extracción de cada DTQ_th, es decir recorre dos bucles, uno con todos los DTQ_th (objetos “extraction_layer”) y el otro con todas las capas incluidas en la extracción. De esta forma, si la unidad NAL analizada pertenece a la extracción, se incrementan los tamaños agregados de la capa, ya que cada capa debe contener en tiempo real el tamaño de todas las capas incluidas en la extracción. A parte, se deben contabilizar el número de fotogramas incluidos en la extracción, en este caso sólo se va a contabilizar las unidades NAL que tengan los mismos atributos que la capa analizada. Se consigue como resultado que se vayan actualizando en tiempo real los tamaños agregados de cada capa, así como el número de fotogramas incluidos, parámetros necesarios para la correcta estimación. for(int i=0; i<num_layer; i++){ //Para todas las capas. for(int j=0; j<num_layer; j++){ //Para todas las capas que están incluidas en la extracción. if(dependency_id == extract_layer[i].limitD[j] && temporal_id == extract_layer[i].limitT[j] && quality_id == extract_layer[i].limitQ[j]){ //Incrementar número de unidades NAL almacenadas y tamaños almacenados if(pos_final != -1){ extract_layer[i].real_time_size = (pos_final - pos); extract_layer[i].size_aggregated += (pos_final - pos); extract_layer[i].total_size += (pos_final - pos); } else{ extract_layer[i].real_time_size = (size - pos + 3); extract_layer[i].size_aggregated += (size - pos + 3); 67 Sistema de video adaptativo H264/SVC sobre TCP extract_layer[i].total_size += (size - pos + 3); } break; } } if(dependency_id == extract_layer[i].dependency_id_th && temporal_id == extract_layer[i].temporal_id_th && quality_id == extract_layer[i].quality_id_th){ if(NALU_type == 1 || NALU_type == 5 || NALU_type == 20){ if(dependency_id != last_dependency_id || temporal_id != last_temporal_id || quality_id != last_quality_id){ extract_layer[i].num_NALU_included++; extract_layer[i].total_num_NALU++; } } } } Es importante fijarse en dos puntualizaciones de la implementación. La primera de ellas es que a veces existen tiras codificadas que ocupan más de una unidad NAL, razón por la cual es necesario mantener en memoria el DTQ de la unidad NAL anterior (variables “last_dependency_id”, “last_temporal_id” y “last_quality_id”). De esta forma se comprueba que sólo se añada una unidad NAL en el cómputo del ancho de banda estimado cuando estas son consecutivas. En segundo lugar, en el mismo caso, el ancho de banda estimado sólo debe ser calculado al sumarse la última unidad NAL del mismo tipo cuando aparece una tira codificada que contiene varias unidades NAL. Para lograrlo, se pasa a obtener el ancho de banda estimado una vez analizada la unidad NAL siguiente. El código correspondiente se muestra a continuación: if((dependency_id != last_dependency_id || quality_id != last_quality_id || temporal_id != last_temporal_id) && (NALU_type == 1 || NALU_type == 5 || NALU_type == 20)){ int extract_layer_pos = array_position_of_DTQ_th(extract_layer, last_dependency_id, last_temporal_id, last_quality_id, num_layer); extract_layer[extract_layer_pos].bandwidth = bandwidth(extract_layer[extract_layer_pos]); } } Sistema de video adaptativo H264/SVC sobre TCP 68 Este código, se encarga de que el ancho de banda estimado incluya todas las unidades NAL que formen parte del fotograma. Se realiza una vez analizada la siguiente unidad NAL para evitar que se trate de un fotograma formado por varias unidades NAL. Se consigue así, que la estimación sea realizada con todo el tamaño incluido. El método “array_position_of_DTQ_th” se encarga de devolver la posición del vector de objetos “extraction_layer” en que se encuentran los identificadores “last_temporal_id”, “last_quality_id” y “last_dependency_id” como DTQ_th del objeto. Así, una vez seleccionado el objeto “extraction_layer” se pasa a utilizar el método “bandwidth” para obtener la estimación del ancho de banda de transmisión de la capa en tiempo real, método que se verá en el siguiente apartado. 4.2.3.2. Función estimación ancho de banda: Vamos a ver a continuación, el método que se encarga de calcular el ancho de banda estimado para una capa en concreto. Se muestra a continuación el código de la función y una breve descripción sobre su funcionamiento. float bandwidth(extraction_layer& extract_layer){ float fps, bandwidth; if(extract_layer.num_NALU_included == 0) return 0; if(extract_layer.temporal_id_th == 0){ fps = 12.5; } else if(extract_layer.temporal_id_th == 1){ fps = 12.5; } else if(extract_layer.temporal_id_th == 2){ fps = 25; } bandwidth = (float)((float)extract_layer.size_aggregated (float)extract_layer.num_NALU_included); //Reinicializar variables extract_layer.real_time_size = 0; extract_layer.size_aggregated = 0; extract_layer.num_NALU_included = 0; return bandwidth; } * fps / 69 Sistema de video adaptativo H264/SVC sobre TCP Esta función se encarga de obtener el ancho de banda estimado en tiempo real, a partir de las estimaciones de tamaño y del número de fotogramas incluidos, mediante la rectificación según la velocidad de reproducción, para determinar que ancho de banda será necesario para la extracción hasta cada una de las diferentes capas. Los detalles importantes a destacar son dos, en primer lugar, al trabajar con la acumulación de unidades NAL incluidas de la capa superior en lugar que de todas las capas incluidas, la velocidad de reproducción en la estimación debe ser la mitad para todos los casos que la velocidad de reproducción real. En segundo lugar, se ha añadido el código que reinicia el algoritmo cada vez que se obtiene el ancho de banda estimado, concretamente, reinicializando tamaños y número de unidades NAL incluidas. Por último, y no menos importante, se debe tener en cuenta que esta función deberá ser redefinida para otra codificación que no cumpla una velocidad de reproducción de 12,5 frames/s con “temporal_id” igual a 0. 4.2.4. Estrategias temporales en la estimación del ancho de banda: Una vez vista la implementación de la estimación del ancho de banda adaptativo, vamos a ver las distintas estrategias temporales en cuanto a instantes de estimación y obtención de ancho de banda de transmisión, para poder tratar con dicha estimación a nivel de aplicación a través del tiempo. Las diferentes estrategias serán o bien secuencialmente, en que se estima y se transmite secuencialmente cada vez, provocando un retardo a nivel de aplicación entre transmisiones, o concurrentemente, con el uso de dos hilos, cada uno de los cuales se encarga de una de las dos tareas. Viendo, en primer lugar que la estrategia secuencial, puede provocar retardos a nivel de aplicación, la elección tomada es su ejecución concurrente, lo cual ya de entrada pasa a justificar el uso de dos hilos a nivel de aplicación, tal y como se verá en el capítulo siguiente. Los instantes en que se va a realizar la estimación del ancho de banda necesario para la transmisión de una determinada capa, vendrán limitados por el filtrado adaptativo. El hecho de que sólo sea posible un intercambio entre capas cada vez que aparezca una tira I con DTQ igual a 000, hace que realizar estimaciones después de cada fotograma no sea interesante, porque el algoritmo de filtrado adaptativo limita los instantes en que se puede cambiar el DTQ_th. Como se ha visto en el capítulo 3 si se cogieran instantes arbitrarios, la extracción daría lugar a flujos no conformantes con el estándar. Sistema de video adaptativo H264/SVC sobre TCP 70 De esta forma, se genera el concepto de iteraciones de diferencia entre los dos hilos, entendiendo iteración, como cada instante de estimación que se avance el primer hilo en las estimaciones al segundo hilo. Se define, cada iteración según la limitación propia del filtrado adaptativo, es decir cada vez que se llega a una tira I con DTQ igual a 000 se realizará la estimación del ancho de banda, y consecuentemente se avanzará una iteración. Es por esto que será un punto clave definir cuantas iteraciones se podrá avanzar el primer hilo haciendo estimaciones al siguiente. 4.2.4.1. Implementación del uso de iteraciones: Para poder tratar con el uso de iteraciones se definen unas variables extras en la estructura “extraction_layer”, tal y como se puede ver a continuación. struct extraction_layer { … int num_iterations; //Número de veces que se ha recorrido desde 000-I hasta 000-I. float aggregated_bandwidth; //Suma de los anchos de banda de todas las iteraciones presentes hasta el momento. }; Las variables que han añadido son el número de iteraciones que se avanza la estimación a la obtención del ancho de banda para transmitir, y el ancho de banda agregado, que se define de forma que se vayan sumando los anchos de banda a medida que se avancen iteraciones para obtener los resultados como el promediado entre el ancho de banda agregado y el número de iteraciones. void actualizate_bandwidth(extraction_layer& extract_layer){ extract_layer.bandwidth = bandwidth(extract_layer); extract_layer.num_iterations++; extract_layer.aggregated_bandwidth = extract_layer.aggregated_bandwidth + extract_layer.bandwidth; } El método “actualízate_bandwidth” se encarga de obtener el ancho de banda según lo expuesto anteriormente, con el único método dependiente del video en cuestión (“bandwidth”), incrementa el número de iteraciones y suma el ancho de banda 71 Sistema de video adaptativo H264/SVC sobre TCP obtenido al agregado, de forma que si es la primera iteración que se avanza el valor agregado será exactamente el valor del ancho de banda de la iteración. float read_bandwidth(extraction_layer& extract_layer, sem_t* s1, sem_t* s3){ float bandwidth_aux = extract_layer.aggregated_bandwidth / extract_layer.num_iterations; extract_layer.bandwidth = 0; if(extract_layer.num_iterations > 1){ extract_layer.aggregated_bandwidth = extract_layer.aggregated_bandwidth * (extract_layer.num_iterations - 1) / extract_layer.num_iterations; } else extract_layer.aggregated_bandwidth = 0; extract_layer.num_iterations--; return bandwidth_aux; } En cambio, el método “read_bandwidth” hace un promediado entre el número de iteraciones del ancho de banda agregado, de forma que se consigue, que si se deja una sola iteración de diferencia como mucho, los valores estimados en tiempo real sean los correctos. Es importante darse cuenta, que el acceso a estos métodos deberá definir control de acceso ya que se accederá por dos hilos a direcciones de memoria compartida. El control de acceso se verá en el capítulo siguiente, y se realiza mediante el uso de semáforos. Además, se ha de notar que mediante este control de acceso, se va a controlar cuántas iteraciones se puede avanzar la estimación a la obtención del ancho de banda a transmitir. Por otra parte, aunque se ha definido un control con promediados, también sería posible definirlo permitiendo que el primer hilo se avance más de una iteración y que los tamaños de ancho de banda fueran los valores obtenidos en la estimación mediante el uso de vectores que contengan todas las estimaciones en lugar de una variable agregada de ancho de banda. Aunque, obviamente, se iba a complicar bastante más la implementación en código. Sistema de video adaptativo H264/SVC sobre TCP 72 Capítulo 5: Transmisor y receptor: En este capítulo, vamos a ver el desarrollo del transmisor adaptativo, con cada una de sus peculiaridades a nivel de programación de la aplicación, tales como semáforos de control de acceso, y uso de varios hilos ejecutados concurrentemente. A parte, también se verán los criterios de diseño del receptor, que a diferencia del transmisor no ha sido desarrollado en el presente proyecto. 5.1. Implementación del transmisor adaptativo: En este capítulo, se va a tratar la solución práctica empleada para diseñar la aplicación de transmisión de flujo de video H264/SVC de forma adaptativa sobre el protocolo de transporte TCP. 5.1.1. Justificación uso de dos hilos: Con el objetivo de desarrollar la aplicación capaz de adaptarse a las condiciones de red en la transmisión del flujo de datos de video codificados en H264/SVC, se ve la necesidad de utilizar hilos ejecutados concurrentemente en el hecho que las diferentes interacciones deben permitir estar transmitiendo continuamente para no crear retardos secuenciales en las transmisiones de red. Así, las tareas a llevar a cabo por parte del ejecutable final serán: 1. La estimación del ancho de banda de transmisión de cada una de las diferentes capas, a través de computar el número de bytes a transmitir y las capas incluidas rectificadas por la velocidad de reproducción. 2. La transmisión de las unidades NAL correspondientes a la capa con máximo ancho de banda de transmisión inferior al ancho de banda de red disponible en cada momento. De esta forma, se genera la necesidad, de utilizar dos hilos ejecutados concurrentemente y una clase intermedia compartida con todos los atributos de caracterización del flujo de datos, el primero de los dos se encargará de analizar el contenido, obtener el ancho de banda estimado de la forma expuesta en el capítulo 4, y almacenarlo en el objeto compartido por los dos hilos. En cambio, el segundo se encargará de extraer según el algoritmo de filtrado los datos y la obtención de la estimación de red en origen del ancho de banda disponibles, para posteriormente transmitir las unidades NAL correspondientes por red obtenidas desde el objeto compartido por los dos hilos. 73 Sistema de video adaptativo H264/SVC sobre TCP 5.1.2. Clase H264BitStream: Para poder llevar a cabo el desarrollo, se ha empezado por diseñar una clase intermedia compartida entre los diferentes hilos, la clase se ha bautizado como H264BitStream. Se ha decidido desarrollarla como una cola circular con muchos campos para cada una de las posiciones de la cola, de forma que cada unidad NAL quede caracterizada por sus atributos facilitando así el reconocimiento por parte del segundo hilo en la extracción adaptativa. Los atributos propios de la cola circular son: int capacity; //Capacidad de la cola circular int numNALUnit; //Número de elementos introducidos en la cola circular (Número de unidades NAL) int pos_set; //Posición en la que debe ser introducido el siguiente elemento int pos_get; //Posición en la que toca extraer el siguiente elemento Se utilizan estos atributos para controlar los casos de cola llena y cola vacía que en el acceso concurrente de los hilos implican el uso de semáforos de control de acceso, para evitar situaciones en las que se produzcan problemas de concurrencia en la consulta o modificación de los atributos de la cola circular, tal y como se verá en este capítulo más adelante. Los otros atributos propios del flujo de datos de video H264/SVC son: char** array_NALU; //Vector de punteros de unidades NAL int size_H264BitStream; //Tamaño de H264BitStream almacenado en la cola circular int* size_NALU; //Vector con los tamaños de cada unidad NAL int* NALU_type; //Vector con los valores de tipo de unidad NAL int* dependency_id; //Vector con los valores de escalabilidad espacial int* quality_id; //Vector con los valores de escalabilidad de SNR int* temporal_id; //Vector con los valores de escalabilidad temporal int* slice_type; //Vector con los valores de tipo de tira (En el caso de no ser unidades NAL VCL tendrá valor de -1) int max_sizeNALU; //Tamaño máximo de todas las unidades NAL del H264BitStream Sistema de video adaptativo H264/SVC sobre TCP 74 Se utilizan vectores correspondientes a cada uno de los atributos que permiten clasificar si la unidad NAL se incluye en la extracción de una capa y/u otra en función del algoritmo de extracción. Además se inicializa un doble puntero, para convertirse en matriz correspondiente a la variable “array_NALU”, se diseña de esta forma para asegurar que en cada uno de los índices se va a introducir el contenido de datos de cada unidad NAL analizada, para posteriormente tener acceso a la transmisión por red a través de la cola circular intermedia. Se diseñan dos constructores, uno el por defecto, que se encarga de reservar el espacio de memoria correspondiente a los vectores y la matriz que contendrá el contenido del flujo de datos, y otro, que inicializa el contenido de la cola circular con un determinado número de unidades NAL que se pasan como variable buffer directamente como atributo del constructor. Para el primer caso, se puede inicializar el contenido de la cola circular mediante el método init(). H264BitStream::H264BitStream(const int max_capacity, const int max_NALUsize) { //Inicialización parámetros cola circular pos_set = 0; pos_get = 0; capacity = max_capacity; numNALUnit = 0; size_H264BitStream = 0; max_sizeNALU = max_NALUsize; //Reserva del espacio de memoria necesario para almacenar el contenido de todas las unidades NAL array_NALU = new char* [capacity]; for(int i=0; i<capacity; i++) array_NALU[i] = new char[max_sizeNALU]; size_NALU = new int[capacity]; NALU_type = new int[capacity]; dependency_id = new int[capacity]; quality_id = new int[capacity]; temporal_id = new int[capacity]; slice_type = new int[capacity]; } H264BitStream::H264BitStream(const int max_capacity, const char* buffer, const int numNALU, int* pos_inicio_NALU, const int max_NALUsize); 75 Sistema de video adaptativo H264/SVC sobre TCP void H264BitStream::init(const char* buffer, const int numNALU, int* pos_inicio_NALU); En el segundo caso o en la combinación del primer y el tercer caso, se inicializa el contenido de la cola circular intermedia, pasándole como parámetros un vector de caracteres con el contenido de las unidades NAL a introducir en la cola circular, y un vector de posiciones iniciales para identificar los puestos en que están situados los inicios de cada unidad NAL. Las posiciones de inicio de unidad NAL que se pasan como parámetro en los casos con inicialización apuntan a la posición del byte ‘\1’, correspondiente al cuarto byte del conjunto de bytes que indican el inicio de una unidad NAL (“\0\0\0\1”). De esta forma la inicialización de los tamaños se hace restando dos posiciones de inicio consecutivas, ya que identifican el inicio de dos unidades NAL consecutivas, y la segunda posición es a su vez la posición final de la primera unidad NAL de las dos. A parte, se restan cuatro bytes porque se contabiliza en la cola circular el tamaño de datos codificados sin incluir la identificación del inicio de unidad NAL. La inicialización del contenido de la unidad NAL en la cola circular, se hace copiando el contenido del buffer que se pasa como parámetro entre las posiciones de inicio y final de cada unidad NAL. De esta forma, se empieza a copiar en la posición inicial más uno, para apuntar al primer byte de la unidad NAL, y se termina de copiar en la posición inicial de la siguiente unidad NAL menos tres. //Inicialización de los tamaños de las unidades NAL correspondientes a las unidades NAL que se van a introducir for(int i=0; i<capacity; i++){ if(i < numNALUnit){ size_NALU[i] = pos_inicio_NALU[i+1]-pos_inicio_NALU[i]-4; } else size_NALU[i] = 0; } //Inicialización de la matriz que contendrá las unidades NAL for(int i=0; i<numNALUnit; i++){ pos = pos_inicio_NALU[i]+1; for(int j=0;j<size_NALU[i];j++){ array_NALU[i][j]=buffer[pos]; pos++; } pos_set = (pos_set + 1) % capacity; } Sistema de video adaptativo H264/SVC sobre TCP 76 A parte, de los métodos constructores de la clase, también se han diseñado métodos para la introducción y extracción de unidades NAL en la cola circular de forma individual, y también métodos para la obtención de los atributos correspondientes a cada unidad NAL. Vamos a ver en primer lugar los métodos para la introducción (“put_NALU”) y para la extracción (“get_NALU”) de unidades NAL, que como se puede ver modifican las variables propias de la cola circular, de forma que en cada utilización de por ejemplo, el método “get_NALU” se incrementa el “pos_get”. En el método “put_NALU”, se introduce una unidad NAL en la cola circular. Los parámetros que se pasan a la función son un vector de caracteres que contiene el contenido del flujo de datos H264/SVC, y las posiciones inicial y final del vector en las que está contenida la unidad NAL. El funcionamiento del método es tal que se inicializa en primer lugar el contenido de la unidad NAL de la cola circular copiando el contenido del “buffer” entre las posiciones inicial y final. Acto seguido, se inicializan los atributos de la unidad NAL, sacando el contenido de las cabeceras de la unidad NAL y de la cabecera de la tira. Los métodos “obtain_lenght_exp_Golomb” y “decod_exp_Golomb” utilizados en la obtención del tipo de tira, se encargan de tratar con palabras codificadas con el algoritmo Exp-Golomb. El primero de los dos obtiene el tamaño de la palabra ExpGolomb y el segundo se encarga de decodificar una palabra codificada según ExpGolomb. Los atributos que se pasan a la función son: el byte dentro del vector de caracteres y el bit inicial de la palabra Exp-Golomb dentro del byte. En este caso se utiliza primero la obtención de la longitud para saltarse la primera palabra Exp-Golomb de la cabecera de la tira y se obtiene la decodificación de la segunda palabra que es la correspondiente al tipo de tira. //Introducción de una unidad NAL en la cola circular intermedia void H264BitStream::put_NALU(const char* buffer, const int pos_inicial, const int pos_final) { int eg_length, eg_byte_inicial; //Introducir NAL Unit en la posición "pos_set" for(int i=0; i<(pos_final-pos_inicial); i++){ array_NALU[pos_set][i] = buffer[pos_inicial + i]; } size_NALU[pos_set] = pos_final - pos_inicial; size_H264BitStream += size_NALU[pos_set]; 77 Sistema de video adaptativo H264/SVC sobre TCP //Obtener NALU type, DTQ y Slice_type NALU_type[pos_set] = (int)((array_NALU[pos_set][0])&0x1F); if(NALU_type[pos_set] == 14 || NALU_type[pos_set] == 20){ dependency_id[pos_set] = (int)(((array_NALU[pos_set][2])&0x70)>>4); quality_id[pos_set] = (int)((array_NALU[pos_set][2])&0x0F); temporal_id[pos_set] = (int)(((array_NALU[pos_set][3])&0xE0)>>5); } else if(NALU_type[pos_set] == 1 || NALU_type[pos_set] == 2 || NALU_type[pos_set] == 3 || NALU_type[pos_set] == 4 || NALU_type[pos_set] == 5 || NALU_type[pos_set] == 6 || NALU_type[pos_set] == 7 || NALU_type[pos_set] == 8 || NALU_type[pos_set] == 15){ dependency_id[pos_set] = 0; quality_id[pos_set] = 0; temporal_id[pos_set] = 0; } if(NALU_type[pos_set] == 1 || NALU_type[pos_set] == 5){ eg_length = obtain_length_exp_Golomb(array_NALU[pos_set],1,0); eg_byte_inicial = eg_length/8; eg_byte_inicial += 1; eg_length = eg_length % 8; slice_type[pos_set] = decod_exp_Golomb(array_NALU[pos_set], eg_byte_inicial, eg_length, &eg_length); } else slice_type[pos_set] = -1; numNALUnit++; pos_set = (pos_set + 1) % capacity; } El método “get_NALU” extrae una unidad NAL de la cola circular. En concreto copia la información de la posición “pos_get”, en los parámetros pasados como atributos, es decir, copia el contenido de la unidad en el atributo “NALU” y de los atributos de caracterización de la unidad NAL en los demás atributos de la función. void H264BitStream::get_NALU(char* NALU, int& NALU_size, int& d_id, int& t_id, int& q_id); void H264BitStream::get_NALU(char* NALU, int& NALU_size, int& d_id, int& t_id, int& q_id, int& type_slice); void H264BitStream::get_NALU(char* NALU, int& NALU_size, int& d_id, int& t_id, int& q_id, int& type_slice, int& type_NALU) Sistema de video adaptativo H264/SVC sobre TCP 78 { //Copiar el contenido de la unidad NAL en la posición "pos_get" for(int i=0; i<size_NALU[pos_get]; i++){ NALU[i] = array_NALU[pos_get][i]; } type_NALU = NALU_type[pos_get]; NALU_size = size_NALU[pos_get]; d_id = dependency_id[pos_get]; t_id = temporal_id[pos_get]; q_id = quality_id[pos_get]; type_slice = slice_type[pos_get]; type_NALU = NALU_type[pos_get]; numNALUnit--; pos_get = (pos_get + 1) % capacity; } Vamos a ver a continuación los demás métodos utilizados en la clase H264BitStream, usados para obtener externamente los atributos de una determinada unidad NAL, se muestran las cabeceras de los métodos debido a la simpleza de dichos métodos. //Obtención de atributos //Obtener tamaño total de las unidades NAL almacenadas en la cola circular int H264BitStream::get_size_H264BitStream(); //Obtener el número de unidades NAL almacenadas en la cola circular int H264BitStream::get_numNALU(); //Obtener el tamaño maximo en unidades NAL para almacenar en la cola circular int H264BitStream::get_capacity(); //Obtener el tamaño de la unidad NAL en la posición numNALU int H264BitStream::get_sizeNALU(const int numNALU); //Obtener "array_NALU[numNALU][pos]" char H264BitStream::get_content(const int numNALU,const int pos); //Obtener contenido de la unidad NAL número numNALU void H264BitStream::get_content(char *buffer, const int numNALU); //Obtener NALU_type en la posición numNALU int H264BitStream::get_NALU_type(const int numNALU); //Obtener dependency_id en la posición numNALU 79 Sistema de video adaptativo H264/SVC sobre TCP int H264BitStream::get_dependency_id(const int numNALU); //Obtener quality_id en la posición numNALU int H264BitStream::get_quality_id(const int numNALU); //Obtener temporal_id en la posición numNALU int H264BitStream::get_temporal_id(const int numNALU); //Obtener slice_type en la posición numNALU int H264BitStream::get_slice_type(const int numNALU); //Obtener tamaño maximo de unidades NAL int H264BitStream::get_max_sizeNALU(); //Obtener la siguiente posición en la que se va a introducir una unidad NAL int H264BitStream::get_pos_set(); //Obtener la siguiente posición de la que se va a extraer una unidad NAL int H264BitStream::get_pos_get(); 5.1.3. Justificación de semáforos en la cola circular: Como se ha comentado antes, el uso de dos hilos con acceso concurrente a la cola circular intermedia implica la necesidad de combatir las situaciones de contorno en la modificación de variables compartidas. Por esta razón, aunque se hayan mostrado los métodos sin control de acceso mediante semáforos, realmente se ha trabajado con semáforos para solucionar los problemas. De esta forma, se va a mostrar la solución elegida para tratar con la clase H264BitStream. Al ser una cola circular compartida, y haber accesos por parte de dos hilos, uno para introducir y el otro para extraer el contenido de una posición de la cola circular, se ha tenido que definir el control de acceso en los métodos “get_NALU” y “put_NALU”. La solución utilizada consta de dos semáforos, uno de acceso a zona crítica y el otro de control de las situaciones en que el hilo que accede concurrentemente debe ser detenido, casos de cola bacía para extraer unidades NAL y cola llena para introducirlas. La solución utilizada en el método “put_NALU” es la siguiente: void H264BitStream::put_NALU(const char* buffer, const int pos_inicial, const int pos_final, const int is_last_NALU) { Sistema de video adaptativo H264/SVC sobre TCP 80 //Coger Exclusión Mutua sem_wait(&s1); if(numNALUnit == capacity && pos_set == pos_get){ num_wait_s2++; sem_post(&s1); sem_wait(&s2); sem_wait(&s1); } //Introducir unidad NAL //Liberar exclusión mutua if(numNALUnit == 1 && num_wait_s2 > 0){ num_wait_s2--; sem_post(&s2); } sem_post(&s1); } Como se puede observar en el código anterior se controla el acceso a la zona crítica controlando el caso en que no se puede introducir ninguna unidad NAL, que se corresponde con que la cola este llena en el momento de ir a introducir una nueva unidad NAL. Para controlar entre los dos extremos que haya algún hilo detenido en la cola se utiliza la variable número de hilos en espera en el segundo semáforo, que cuando tenga un valor superior a cero, indicara o que se encuentra en caso de cola llena o de cola bacía con hilos en espera a que cambie la situación actual. De esta forma, en el caso del método “put_NALU” se controla al final del método si se sale de una situación de cola bacía con hilos detenidos en el método “get_NALU” debido a que la cola este bacía, comprobando que haya hilos detenidos en el segundo semáforo y que el número de unidades NAL introducidas en la cola al salir sea de una, la que se acaba de introducir, y en tal caso se pone un recurso para los hilos detenidos. La solución utilizada en el método “get_NALU” es la siguiente: void H264BitStream::get_NALU(char* NALU, int& NALU_size, int& d_id, int& t_id, int& q_id, int& type_slice, int& type_NALU) { //Coger Exclusión Mutua sem_wait(&s1); if(numNALUnit == 0 && pos_set == pos_get){ 81 Sistema de video adaptativo H264/SVC sobre TCP num_wait_s2++; sem_post(&s1); sem_wait(&s2); sem_wait(&s1); } //Obtener unidad NAL //Liberar exclusión mutua if(numNALUnit == (capacity-1) && num_wait_s2 > 0){ num_wait_s2--; sem_post(&s2); } sem_post(&s1); } En el método “get_NALU”, la situación en que se tiene que detener la ejecución del hilo concurrente es en el caso de que al ir a extraer la cola circular esta bacía. Se implementa la misma solución que antes, se utiliza el primer semáforo para entrar en exclusión mutua a la zona donde comprobar si se trata del caso cola bacía, y detener el hilo en dicho caso. En la salida del método debe comprobarse que no se salga de la situación de cola llena con algún hilo en espera para poner un recurso en el semáforo dos en tal caso. La solución compatibiliza el uso de dos semáforos tratando los dos casos extremos, ya que en el segundo semáforo que es donde realmente se detienen los hilos, solo puede encontrarse uno de los dos casos a la vez, es decir en ningún caso puede haber hilos detenidos en cola bacía y llena a la vez. Se consigue así, el funcionamiento deseado de la cola circular en que los accesos concurrentes al mismo recurso compartido (misma posición en la cola circular) se controla mediante semáforos como control de acceso. Además, en los demás métodos de acceso a atributos de la cola circular o de una determinada unidad NAL, se implementa un control de acceso mediante el primer semáforo de entrada y salida de la zona critica. //Los demás métodos sem_wait(&s1) //Metodo Sem_post(&s1); 5.1.4. Solución de semáforos en la aplicación: Sistema de video adaptativo H264/SVC sobre TCP 82 Tal y como se ha comentado en el último apartado del capítulo 4, también se utilizaran semáforos para controlar los instantes de actualización del ancho de banda estimado de transmisión por parte del primer hilo concurrente, y en los instantes de lectura de la estimación del ancho de banda de transmisión de cada una de las posibles capas a transmitir. En el capítulo 4 se han visto las diferentes estrategias que se pueden seguir en la diferencia en el número de iteraciones entre lectura por parte del primer hilo y transmisión por parte del segundo, pudiendo dejar un mínimo de una iteración entre actualización y un máximo indeterminado de iteraciones de diferencia, teniendo en cuenta que con la solución utilizada cuando hay más de una iteración de diferencia entre los dos hilos se realizan promediados del ancho del ancho de banda de transmisión de las diferentes capas entre el número de iteraciones avanzadas. A pesar, de haber expuesto las diferentes estrategias, no se ha presentado la solución con semáforos correspondiente, solución que se va a ver a continuación. Los métodos en los que se va a utilizar semáforos son “actualizate_bandwidth” y “read_bandwidth” de la forma que se muestra en los párrafos siguientes: void actualizate_bandwidth(extraction_layer& extract_layer, sem_t* s1, sem_t* s3){ sem_wait(s1); //Actualizar ancho de banda de transmisión de la capa if(num_wait_s3 > 0){ sem_post(s3); } sem_post(s1); } float read_bandwidth(extraction_layer& extract_layer, sem_t* s1, sem_t* s3){ sem_wait(s1); if(extract_layer.num_iterations == 0){ num_wait_s3++; sem_post(s1); sem_wait(s3); sem_wait(s1); } //Leer ancho de banda estimado de la capa sem_post(s1); return bandwidth_aux; 83 Sistema de video adaptativo H264/SVC sobre TCP } Como se puede ver en las actualizaciones solo se coge el semáforo de exclusión mutua, mientras que en la lectura de los valores estimados se detiene al hilo en caso que el número de iteraciones de diferencia entre los dos hilos sea de cero debido a que cuando este valor es cero no hay lecturas posibles del ancho de banda estimado, situación que se corresponde cuando los dos hilos se sincronizan. De esta forma, en el “actualízate_bandwidth”, cuando se detectan hilos en espera (variable “num_wait_s3” más grande que cero), se ponen recursos para que los hilos en espera sean despertados. El funcionamiento, es tal que en la actualización del ancho de banda sólo se va a despertar hilos en la lectura, cuando la lectura se avance a la actualización, es decir el caso en que se hayan quedado detenidos. Para que no haya problemas de concurrencia el primer semáforo debe ser compartido con el primero de la clase H264BitStream razón por la que se añade el siguiente método a dicha clase. //Obtener la dirección de memoria sem_t* H264BitStream::get_s1_memdir() { sem_t* sem; sem_wait(&s1); sem = &s1; sem_post(&s1); return sem; } Así, el control de acceso a los métodos de actualización y lectura de la estimación del ancho de banda de transmisión solo permite detener el caso de lectura del valor almacenado por parte de la actualización pero no limita el número de iteraciones que se puede avanzar el hilo de actualización. Se ha diseñado así para a posteriori controlar a nivel de aplicación el número de iteraciones de diferencia a nivel de aplicación. La solución final por la que se ha optado es la de dejar una sola iteración de diferencia entre actualizaciones y lecturas, lo que se traduce en un máximo de dos iteraciones en el análisis de unidades NAL por parte del primer hilo antes de que sean analizadas por parte del segundo. Es por esta razón que teniendo en cuenta la limitación propia del filtrado adaptativo en los instantes de actualización del ancho de banda que se producen al final de una Sistema de video adaptativo H264/SVC sobre TCP 84 iteración, entendiendo una iteración como el número de unidades NAL entre una tira I con DTQ igual a 000 y la siguiente con las mismas características; el tamaño de la cola circular para evitar que la aplicación se detenga debe cumplir la siguiente restricción, debido a que al inicio de la ejecución debe haber estimado como mínimo una iteración sin que haya comenzado a transmitir: CAPACIDAD COLA CIRCULAR > NUMERO DE UNIDADES NAL EN UNA ITERACIÓN Además en el caso de una iteración como máximo se debe cumplir que: CC_CAPACITY <= NUM_NALU_IN_1_ITER * (NUM_ITER + 1) Vamos a ver a continuación la solución de semáforos a nivel de aplicación con la restricción de un máximo de una iteración entre actualizaciones y lecturas del ancho de banda estimado, y a analizar si podría aparecer algún problema de concurrencia o de detención de la aplicación debido a los posibles entrelazados. HILO 1{ 1_iter_to_circular_queue(); actualizate_BW(); while(!end_of_execution){ 1_iter_to_circular_queue(); sem_wait(&s4); actualizate_BW(); } } HILO 2{ while(!end_of_execution){ read_BW(); obtain_DTQ_th(); tx_1_iter_with_DTQ_th(); sem_post(&s4); } } Esta solución, permite cumplir los criterios de diseño debido a que con el semáforo que se ha añadido se asegura que la ejecución concurrente nunca se avance más de una iteración de actualizar a leer, o dos en el análisis del contenido. Los casos críticos serán: 85 Sistema de video adaptativo H264/SVC sobre TCP 1. La combinación de cola bacía con que se detenga el primer hilo en el semáforo cuatro, lo cual no sucederá nunca debido a que cuando se detiene en el semáforo el primer hilo, va con dos iteraciones de diferencia. 2. Cola llena y que se detenga en “read_BW”, que tampoco sucederá porque con la cola llena cumpliendo la restricción antes impuesta habrá como mínimo un recurso para leer el ancho de banda estimado. Por otro, lado tampoco se produce ningún caso en que ambos hilos queden detenidos a la vez, razón por la que la solución propuesta es correcta. 5.1.5. Solución de ancho de banda adaptativo: Para conseguir que la solución final sea adaptativa al protocolo de red, se hacen estimaciones del ancho de banda disponible para poder transmitir, ancho de banda que vendrá limitado por el protocolo TCP, y se compara cogiendo el valor máximo menor que el disponible con los anchos de banda de transmisión de las capas, de forma que siempre se va a transmitir a la máxima velocidad posible. De esta forma el método del hilo 2 “obtain_DTQ_th”, en el que se obtiene el DTQ_th tal que el ancho de banda de transmisión sea el máximo menor que el disponible, queda de la forma siguiente. void obtain_DTQ_th(int d_th, int t_th, int q_th, const float* read_BW, const extraction_layer* extract_layer) { int bandwidth_th = obtain_BW_th_from_socket_options(); int BW_pos = 0; for(int i=1; i<num_layer; i++){ if(read_BW[i] < bandwidth_th && read_BW[i] > read_BW[BW_pos]) BW_pos = i; } d_th = extract_layer[BW_pos].dependency_id_th; t_th = extract_layer[BW_pos].temporal_id_th; q_th = extract_layer[BW_pos].quality_id_th; } Se consigue así, que en cada iteración se trabaje con la extracción de la capa de tamaño máximo con la que el ancho de banda de red disponible permite extraer a tiempo real. Sistema de video adaptativo H264/SVC sobre TCP 86 En esta versión, se ha hecho que en caso que el ancho de banda no fuera suficiente para poder transmitir la capa 000, la transmita igualmente, caso que se controlara mediante el uso de un buffer de recepción, que se encargara de almacenar cuando no se transmita a tiempo real. De igual forma, se podría definir un valor de menos uno de inicio que a la postre se interpretara en caso de ser el valor elegido, como que en esta iteración no se transmitiera. 5.1.6. Medidas para reducir el alto número de intercambios entre capas: Durante el transcurso del desarrollo de las pruebas de red (ver capítulo 6) se ha detectado que existe en las pruebas un gran número de intercambios entre capas debido a la alta variabilidad del video codificado. Esto puede llegar a ser un poco desquiciante ya que durante la reproducción del video, en caso de no indicarle una resolución fija para el video, se va a redimensionar el video constantemente. Por esta razón, se buscan estrategias que permitan reducir el número de intercambios entre capas, para conseguir una reproducción más suave de la secuencia de video. La primera estrategia que se va a utilizar es utilizar un segundo estimador de ancho de banda que suavice los saltos que existen con el estimador a partir de las opciones del “socket”. El estimador hará un seguimiento del tamaño transmitido hasta un determinado momento rectificado por el tiempo de ejecución. Así, el ancho de banda disponible vendrá determinada por la siguiente expresión: BW(n) = a * BW_socket + (1 - a) * BW(n – 1) donde: BW(n – 1) = tamaño_transmitido (bit) / tiempo_ejecución (s) Con esta estrategia, se consigue una variabilidad del ancho de banda disponible más suave que con el primer estimador. Esto podría provocar que haya casos de congestión en que se transmita por encima del ancho de banda disponible, pero estos posibles errores van a ser resueltos en el buffer de entrada de los “socket”, haciendo que se precargue el buffer sin llegar a transmitir, porque vendrá controlado por el control de congestión de TCP. La segunda estrategia para evitar este problema, será utilizar un ciclo de histéresis en el intercambio entre capas. Hacer que para subir de capa necesite el ancho de banda necesario para hacerlo más un umbral extra, y para bajar el necesario menos un umbral extra. Se muestra en la siguiente figura un ejemplo, en el que el ancho de banda necesario para cambiar de capa es de 700 Kbit/s, se sube con 800 Kbit/s y se baja con 600 kbit/s. 87 Sistema de video adaptativo H264/SVC sobre TCP Figura 5.1: Ciclo de histéresis Finalmente, el ciclo de histéresis solo se aplicara a los casos en que se suba de capa, porque en el caso de intercambios entre capas hacia abajo, podría provocar problemas de transmitir más de lo disponible. En concreto, solo se va a aplicar en el caso de cambio de resolución de inferior a mayor, porque en los demás casos no habrá cambio de resolución del video. Sistema de video adaptativo H264/SVC sobre TCP 5.2. 88 Criterios de diseño del receptor: La parte del receptor a diferencia del transmisor se va a tratar con un marco de trabajo en el que se adaptara el transmisor, en concreto se va a utilizar un receptor de TCP, que solo se encargara de recibir el contenido transmitido sin tener en cuenta las características del video transmitido. Se deben diferenciar dos aplicaciones objetivo, en primer lugar la transmisión de video con buffers de recepción, que son el caso principal, y en segundo lugar las aplicaciones orientadas a reproducción en tiempo real. El primer caso se contempla mediante el uso de un receptor estándar al que se le añade la peculiaridad de utilizar un buffer de recepción en el destino, para poder almacenar parte del video antes de reproducirlo, y como se verá en el capítulo siguiente será el caso analizado. Para el segundo caso se van a mostrar los criterios de diseño pertinentes pero no se va a desarrollar dejándolo como posible mejora al presente proyecto. 5.2.1. Relación entre tiempo de reproducción y tiempo de transmisión: El parámetro más crítico en el receptor orientado a funcionar en tiempo real, serán los tiempos de transmisión extremo a extremo. Así, en características del video esto se traduce en la diferencia entre los tiempos de transmisión y los tiempos de reproducción, ya que la naturaleza del estándar hace que se transmitan antes algunas tiras que otras que se reproducen antes debido a los niveles de dependencia temporal propios del H264. Es por esta razón que en primer lugar se deberá hacer una conmutación entre tiempos de transmisión y tiempos de reproducción, para a posteriori controlando el tiempo de reproducción en el receptor poder hacer comparaciones de tiempo y en caso de que alguna unidad NAL llegara fuera del intervalo de reproducción descartar el contenido recibido. Vamos a ver a continuación como relacionar los tiempos de reproducción con los de transmisión, para así poder hacer a posteriori dichas comparaciones. Es importante darse cuenta que las relaciones serán dependientes del parámetro “GOP_size” elegido y de los identificadores de dependencia temporal asociados a cada tamaño de GOP. Así, en primer lugar se va a mostrar el código para determinar los identificadores de dependencia temporal, a partir del tamaño de GOP. void obtain_B_structure(const int GOP_size, int* B_t_id_structure){ int num_B_t_max = 0; int num_slice = 0; int dist_B = 0; 89 Sistema de video adaptativo H264/SVC sobre TCP num_t = log2(GOP_size); for(int i=0 ; i<(GOP_size - 1); i++){ B_t_id_structure[i] = 0; } for(int i=0; i<num_t; i++) B_t_id_structure[i] = i + 1; num_slice += num_t; for(int i=0; i<num_t; i++){ if((dist_B = obtain_dist_B(B_t_id_structure[i], num_t)) == -1){ std::cout << "Internal error while computing dist_B\n"; return; } if(B_t_id_structure[i] == num_t) num_B_t_max ++; if(dist_B == 0 && (B_t_id_structure[i] != num_t || num_B_t_max == 2)){ if(num_B_t_max == 2) num_B_t_max = 0; } else if((i + dist_B + 2 < GOP_size)){ B_t_id_structure[i + dist_B + 1] = B_t_id_structure[i]; num_slice ++; } } num_B_t_max = 0; int i = 0; while(num_slice < (GOP_size - 1)){ int aux; while(B_t_id_structure[i] != 0){ i++; } i--; aux = i; while(B_t_id_structure[i] < num_t){ B_t_id_structure[i+1] = B_t_id_structure[i] + 1; num_slice ++; /*DEBUG std::cout << "t[" << (i + 1) << "] = " << t[i + 1] << '\n'; //END DEBUG*/ i++; } i = aux; Sistema de video adaptativo H264/SVC sobre TCP 90 while(B_t_id_structure[i] != 0){ if((dist_B = obtain_dist_B(B_t_id_structure[i], num_t)) == -1){ std::cout << "Internal error while computing dist_B\n"; return; } if(B_t_id_structure[i] == num_t) num_B_t_max ++; if(dist_B == 0 && (B_t_id_structure[i] != num_t || num_B_t_max == 2)){ if(num_B_t_max == 2) num_B_t_max = 0; } else if((i + dist_B + 2) < GOP_size){ int j = 0; while(B_t_id_structure[i + j + dist_B + 1] != 0 && B_t_id_structure[i] != B_t_id_structure[i + j + dist_B + 1]){ j++; } if(B_t_id_structure[i] != B_t_id_structure[i + j + dist_B + 1]){ B_t_id_structure[i + j + dist_B + 1] = B_t_id_structure[i]; num_slice ++; if(num_slice == (GOP_size - 1)) break; } } i++; } } return; } Lo que hace este código es obtener los identificadores de dependencia temporal para todos los casos con identificador mayor que uno y durante un tamaño de GOP. Está basado en la estructura diádica de los GOP, y consigue pasándole como parámetro el tamaño de GOP, devolver un vector que contiene en orden secuencial los valores de los identificadores de dependencia temporal según su orden de transmisión. Como se puede observar en el código se utiliza el método “obtain_dist_B”, que básicamente lo que hace es calcular en qué posición se va a repetir el siguiente identificador temporal, aunque a medida que avanzan las posiciones hay que añadir rectificaciones para que cada valor se ponga en la posición correcta. El código de la función es el siguiente: int obtain_dist_B(const int t_id, const int num_t){ 91 Sistema de video adaptativo H264/SVC sobre TCP int dist_B = 0; for(int i=1; i<(num_t - t_id + 1); i++){ int aux; if((aux = exp2(2,i)) == -1) return -1; dist_B += aux; } return dist_B; } Como se puede apreciar, las distancias entre la repetición de los mismos identificadores temporales vienen determinados por la suma de las exponenciales de dos elevado a cada valor entre uno y el número de identificadores temporales menos el valor del identificador temporal. De forma que se generan distancias de 2, 6, 14, … Por ejemplo para el caso de un tamaño de GOP igual a 8, en el que los identificadores temporales según su orden de transmisión es: 1, 2, 3, 3, 2, 3, 3; para el caso con identificador temporal igual a dos se obtiene una distancia 2, lo que colocaría el segundo dos en la cuarta posición. El el código general, la estructura obtenida se genera llenando las posiciones y cuando se detecta que una posición relativa está ocupada se desplaza la posición a la derecha. En este caso como se habría generado la estructura 1, 2, 3, 3, al obtener la distancia de 2 se pondría en la quinta posición. La estructura se genera analizando en primer lugar los identificadores temporales menores y subiendo hasta los mayores, de forma que las rectificaciones van saliendo en orden correcto para que el resultado sea el esperado. Una vez visto cómo obtener el orden de identificadores de dependencia temporal, vamos a pasar a ver el código que permite obtener la relación buscada entre instantes de transmisión, los que tenemos actualmente, e instantes de reproducción. Para esto vamos a distinguir de igual forma que antes los valores con identificador temporal superior a cero, para obtener la relación directa entre unos y otros. Es importante darse cuenta que los valores que se buscan son el de las B, por lo que siempre serán valores negativos respecto al valor de una I o una P anteriores en tiempo de transmisión. Vamos a ver a continuación, el código correspondiente a la obtención de los retardos de reproducción respecto al orden de transmisión. void obtain_num_frames_in_tr(int* n_frames, cons tint* temporal_id, cons tint GOP_size) Sistema de video adaptativo H264/SVC sobre TCP 92 { Int* array_pos = new int[2]; Int adding_size; n_frames[0] = -GOP_size / 2; for(int i=1; i<GOP_size; i++){ //Buscar las siguientes dos posiciones con mismo temporal_id search_next_2_positions(temporal_id, array_pos, i); adding_size = obtain_adding_size(GOP_size, temporal_id[i]); n_frames[array_pos[0]] = n_frames[i-1] – adding_size; n_frames[array_pos[1]] = n_frames[i-1] + adding_size; } return; } Este código, se encarga de encontrar la relación entre identificadores temporales e instantes de reproducción. Para ello se inicializa la primera posición correspondiente a “temporal_id” igual a uno a la mitad del tamaño de GOP. Esto, será siempre así, según la estructura diádica. A partir de la primera posición, lo que sucede es que para cada repetición del identificador temporal, se obtiene una posición relativa que se suma y se resta respecto a la posición anterior en tiempo para obtener su posición de orden de reproducción. Para realizar estas dos funcionalidades, se utilizan los métodos “search_next_2_positions”, que se encarga de encontrar las dos posiciones siguientes con el mismo identificador temporal; y “obtain_adding_size”, para obtener la posición relativa que se debe sumar y restar en las dos nuevas posiciones obtenidas. El código de estos dos métodos se muestra a continuación: void search_next_2_positions(const int* temporal_id, int* array_pos, cons tint pos_inicial) { int tmp = pos_inicial + 1; array_pos[0] = pos_inicial; array_pos[1] = 0; while(array_pos[1] == 0){ if(temporal_id[tmp] == temporal_id[pos_inicial]){ array_pos[1] = tmp; } tmp ++; } return; 93 Sistema de video adaptativo H264/SVC sobre TCP } El método “obtain_adding_size” devuelve la diferencia relativa de la posición de la tira en orden de reproducción respecto a la tira anterior, y está basada en la estructura diádica. En concreto se obtiene la exponencial de dos elevado al número de identificadores temporales menos el identificador temporal, dando lugar a resultados, para por ejemplo un tamaño de GOP igual a 8, de 2 y de 1 para los identificadores temporales de 2 y de 3. Su funcionamiento es tal que teniendo como parámetro de entrada los identificadores temporales: 1, 2, 3, 3, 2, 3, 3; las posiciones con “temporal_id” igual a 2 obtendrán unas diferencias relativas de +/- 2, que respecto a la posición -4 del “temporal_id” igual a 1, darán lugar a las posiciones -2 y -6. Lo mismo sucede con los “temporal_id” igual a 3, que dan lugar a +/-1. Finalmente se obtiene un orden de reproducción: -4, -2, -1, -3, -6, -5, -7. Int obtain_adding_size(cons tint GOP_size, const int t_id) { Int dif = log2(GOP_size) – t_id; return (exp(2, dif)); } El concepto sobre el que se ha trabajado es la correlación existente entre los diferentes retardos relativos, que se basa en que a medida que se incrementa el identificador temporal se va dividiendo por dos el tamaño que hay que añadir entre retardos relativos. Finalmente, el paso de número de tiras relativas a retardo relativo se obtiene mediante la velocidad de reproducción. Tiempo de reproducción = Número de fotogramas / fps 5.2.2. Estrategia de filtrado en recepción: Una vez visto cómo obtener el vector de diferencias relativas entre tiempo de reproducción y tiempo de transmisión se debe comprobar si el instante de recepción de una unidad NAL es anterior o posterior al instante de entrega para reproducción, para que en caso de que sea posterior dicha unidad NAL sea filtrada en recepción. Sistema de video adaptativo H264/SVC sobre TCP 94 De esta forma, debido al comportamiento del filtrado de unidades NAL, el hecho de filtrar en función de los tiempos de recepción podría provocar la conformación de flujos de datos que no fueran decodificables. Por esta razón, se van a usar dos hilos, el primero de los cuales se encargara de comprobar los instantes de tiempo de recepción y en caso de que alguna unidad NAL llegara fuera de tiempo, de redefinir el DTQ máximo de la extracción en función de que capa se descarte en una determinada iteración. Así, el segundo hilo, se encargara de aplicar el algoritmo de filtrado al flujo resultante de la extracción hecha por el primer hilo en la cola circular intermedia, fijando como DTQ máximo el obtenido en dicha iteración por parte del primer hilo, para que el flujo resultante sea conformante con el estándar H264/SVC. Así, en primer lugar se muestra, como se va a tratar por parte del primer hilo el descartar las unidades NAL en función de los tiempos de recepción, partiendo de que se conoce previamente el vector de diferencias relativas “n_frames” y el vector de identificadores temporales “t_id”. HILO 1{ while(receive_NALU()){ if(temporal_id == 0){ num_frames[DQ] += GOP_size; num_frame = num_frames[DQ]; position = 0; } else if(temporal_id > 0){ position = search_next_temporal_id_position(temporal_id, t_id, position, GOP_size); num_frame = num_frames[DQ] + n_frames[position]; } If((num_frame / fps) < tiempo_recepcion){ discart(); obtain_new_DTQ_th(dependency_id, temporal_id, quality_id, dependency_id_th, temporal_id_th, quality_id_th); } else NAL_UNIT_to_cc(); } } En el filtrado se distingue entre identificadores temporales iguales a cero y mayores que cero. Esto se hace porque para el caso de iguales a cero, se va a añadir 95 Sistema de video adaptativo H264/SVC sobre TCP exactamente un tamaño de GOP al número de fotogramas, mientras que en el caso de identificadores temporales mayores que cero, se va a obtener la posición en orden de reproducción a partir del vector que contiene las diferencias relativas en orden de reproducción. Funciona de forma, que en primer lugar se obtiene la siguiente posición con ese identificador temporal (método “search_next_temporal_id_position”), para localizar la posición en que está situada la diferencia relativa, para posteriormente sumarla al número de fotograma absoluto. A continuación, se muestra el método “search_next_temporal_id_position”: El funcionamiento, es tal que todas las unidades NAL en que el tiempo de recepción sea mayor que el tiempo de reproducciónvan a ser filtradas. Para conseguirlo se usa el método “search_next_temporal_id_position” que se muestra a continuación. Int search_next_temporal_id_position(cons tint temporal_id, cons tint* t_id, cons tint initial_position, cons tint GOP_size) { for(int i=initial_position; i<GOP_size; i++){ if(t_id[i] == temporal_id) return i; } } Así, una vez obtenida la posición absoluta en orden de reproducción, todas las unidades NAL en que su tiempo de recepción sea mayor que el tiempo de reproducción van a ser filtradas. En cambio, siempre que se llegue a tiempo para la correcta reproducción las unidades NAL son almacenadas en la cola circular intermedia (objeto de la clase H264BitStream). En el caso, en que se filtra además de descartar la unidad NAL, se va a redefinir la capa máxima a la que se podrá filtrar para que el segundo hilo, usando este dato pueda filtrar el flujo entero de una iteración según el DTQ_th resultante de dicha iteración. 5.2.3. Solución de semáforos de la aplicación: Finalmente, la aplicación constara de dos hilos, tal y como se ha descrito anteriormente. De esta forma las variables compartidas serán el objeto de la clase H264BitStream y el valor máximo de la extracción. El pseudocódigo correspondiente a cada uno de los dos hilos en los que se deberá definir una solución de control de acceso mediante semáforos es el siguiente. HILO 1{ Sistema de video adaptativo H264/SVC sobre TCP 96 while(!end_of_execution){ receive_1_iter_filter_and_modify_DTQ_th(); modify_DTQ_th2(dependency_id_th, temporal_id_th, quality_id_th); } } HILO2{ while(!end_of_execution){ obtain_DTQ_th2(dependency_id_th, temporal_id_th, quality_id_th); filter_1_iter_and_send_to_play(); } } Como se había comentado antes, el primer hilo se encarga de llevar a cabo el filtrado de unidades NAL según los tiempos de recepción y la actualización en cada iteración del DTQ_th. El segundo hilo, se encarga de filtrar al DTQ_th obtenido por el primer hilo y enviar a reproducir el video. En esta solución se implementa de forma que cada hilo tiene su valor de DTQ_th, y la aplicación comparte las variables globales DTQ_th2. En los accesos a los métodos de actualización y modificación de dicha variable, se define control de acceso mediante semáforos, para evitar situaciones conflictivas en tiempo de ejecución. En cada uno de los métodos se accede en primer lugar mediante el semáforo principal de la aplicación que es el correspondiente a la cola circular intermedia, de igual forma que se hacía en el transmisor. Una vez introducido el control de acceso, los métodos quedan de la forma siguiente. void_modify_DTQ_th2(const int dependency_id_th, const int temporal_id_th, const int quality_id_th, sem_t* s1, sem_t* s3) { sem_wait(s1); if(actualized){ nw_sem3 ++; sem_post(s1); sem_wait(s3); sem_wait(s1); } actualized = true; dependency_id_th2 = dependency_id_th; temporal_id_th2 = temporal_id_th; quality_id_th2 = quality_id_th; if(nw_sem3 > 0) 97 Sistema de video adaptativo H264/SVC sobre TCP sem_post(s3); sem_post(s1); } void obtain_DTQ_th2(int dependency_id_th, int temporal_id_th, int quality_id_th) { sem_wait(s1); if(!actualized){ nw_sem3 ++; sem_post(s1); sem_wait(s3); sem_wait(s1); } actualized = false; dependency_id_th = dependency_id_th2; temporal_id_th = temporal_id_th2; quality_id_th = quality_id_th2; if(nw_sem3 > 0) sem_post(s3); sem_post(s1); } La solución propuesta, usa la variable “actualized” como método de control de acceso, variable que sólo se modifica dentro de los métodos y siempre en exclusión mutua. La variable indica si se ha actualizado el DTQ_th. De esta forma, se quedara detenido en el segundo hilo cuando su valor sea falso, porque indicara que no ha sido actualizado, y en primer hilo cuando sea cierto. Así, en el primer hilo lo actualiza a cierto y en el segundo lo actualiza a falso. El funcionamiento de los semáforos es el mismo, se entra a zona crítica y en caso que deba detenerse lo hace en el segundo semáforo. Al salir de los métodos se da recursos para el semáforo detenido, en caso que haya algún hilo detenido y en espera. Esta solución permite que la ejecución sea concurrente entre los dos hilos con un máximo de una iteración de diferencia entre actualizaciones de DTQ_th2 y con un máximo de dos iteraciones entre los dos hilos, aunque el primero quedándose detenido en el semáforo de espera. Además, no hay ninguna interacción que haga que los dos hilos se queden parados y entre ellos se van abriendo la puerta en los casos de detención de uno de ellos con lo que se considera una buena solución. Sistema de video adaptativo H264/SVC sobre TCP 98 Capítulo 6: Evaluación del sistema: Para la evaluación del sistema se ha elegido la secuencia de video BigBuckBunny con una duración de 9 minutos y 56 segundos. En concreto se va a hacer una codificación de tres capas con resoluciones de 640x360 en la capa superior y su versión diezmada de 360x180 en la capa base y en la capa de mejora de calidad, con una velocidad de reproducción de 24 fotogramas por segundo cada una de ellas. Se verán a continuación la elección de las principales características de codificación. 6.1. Características de la codificación: En JSVM se utilizan unos ficheros de codificación en los que se especifica diferentes atributos de codificación. En concreto, se eligen el número de capas, el tamaño de GOP, el periodo de intra-predicción, que indica cada cuantos fotogramas aparece una tira I, el periodo IDR, que indica cada cuantos fotogramas aparece una tira de IDR, la capa base a partir de la que se predice entre capas, … Sin embargo, el parámetro más importante que se elige es el parámetro de cuantificación, que será el principal determinante de la PSNR obtenida. Se puede demostrar que una PSNR de 40 dB proporciona una secuencia decodificable visualmente aceptable para el ojo humano. En primer lugar vamos a centrarnos en la elección de la estructura diádica. Se elige un tamaño de GOP igual a 2 y un periodo de intra-predicción igual a 4, para cada una de las tres capas. La elección ha sido tomada porque cuanto mayor es el tamaño de GOP, cuando hay cambios repentinos de escena, se va a bi-predecir de fotogramas que no se van a parecer en nada. Es por esto que se eligen valores pequeños que permitan obtener una secuencia reconstruida con mejor PSNR. Esta combinación da lugar a la secuencia de tiras en orden de reproducción siguiente: IBPBIBP… En cuanto a la elección del periodo de tiras de instante de refresco instantáneo, se ha optado por un periodo de 16 tiras, de forma que cada cuatro tiras I una de ellas sea de decodificación instantánea. La elección ha sido tomada para que los errores propagados, sean reseteados cada un número razonable de tiras. De esta forma la codificación da lugar a una secuencia de video codificado con seis capas de extracción posible, dos capas de escalabilidad temporal por cada una de las tres capas principales, de forma que habrán seis resultados posibles al aplicar el algoritmo de filtrado. 99 Sistema de video adaptativo H264/SVC sobre TCP En cuanto a la capa de la que predicen, se ha optado por hacer predecir tanto la capa de resolución superior como la de mejora de la capa base. La elección de la capa base en el caso de la capa de mejora de resolución, ha sido tomada porque con el algoritmo de filtrado se consigue una mejor relación PSNR a ancho de banda de transmisión, ya que se filtrara la capa de mejora de calidad al filtrar hasta la capa superior. 6.1.1. Elección de los parámetros de cuantificación: Para la elección de los parámetros de cuantificación se ha tenido en cuenta la PSNR de la secuencia reconstruida. De esta forma buscando unas PSNR similares a 40 dB se han obtenido los siguientes parámetros de cuantificación: D Q T QP 0 0 0 32 0 0 1 33 0 1 0 25 0 1 1 26 1 0 0 27 1 0 1 28 Tabla 6.1: Parámetros de cuantificación Como se puede observar, se han elegido los parámetros de cuantificación de 32, 25 y 27 para cada una de las tres capas. En cuanto a las capas temporales superiores se ha utilizado el mismo parámetro de cuantificación más uno. Por último, en las componentes de crominancia, se les ha aplicado una rectificación de más dos en el parámetro de cuantificación debido a la naturaleza del ojo humano a reconocer con más precisión la componente de luminancia. Se considera una buena elección de los parámetros de cuantificación porque se obtienen las siguientes PSNR en la secuencia reconstruida: CAPA 0 1 2 PSNR (Y) PSNR (Cr) 36.2303 dB 42.9990 dB 41.0125 dB 45.2626 dB 41.2202 dB 45.8067 dB Tabla 6.2: PSNR obtenidas PSNR (Cv) 41.7011 dB 44.4091 dB 45.1039 dB Como se puede ver se consiguen PSNR superiores a los 40 dB en todos los casos menos en la capa base que es de 36 dB. Se considera aceptable, por el hecho de que existe una capa de mejora de PSNR para esta capa. 6.2. Resultados al aplicar el algoritmo de filtrado: Sistema de video adaptativo H264/SVC sobre TCP 100 A continuación, se muestran los flujos de datos resultantes una vez aplicado el algoritmo de filtrado, donde se pueden observar las capas incluidas en cada extracción, tal y como se ha explicado en el ejemplo del capítulo 3: Hasta capa 000: Figura 6.1: Algoritmo extracción hasta la capa 000 Hasta 001: Figura 6.2: Algoritmo extracción hasta la capa 001 Hasta 100: Figura 6.3: Algoritmo extracción hasta la capa 100 Hasta 010: 101 Sistema de video adaptativo H264/SVC sobre TCP Figura 6.4: Algoritmo extracción hasta la capa 010 Hasta 011: Figura 6.5: Algoritmo extracción hasta la capa 011 Hasta 110: Figura 6.6: Algoritmo extracción hasta la capa 110 6.3. Perfiles de ancho de banda de transmisión: A continuación, se verán los perfiles de ancho de banda de transmisión de las diferentes extracciones posibles, es decir con cada una de las diferentes combinaciones de identificadores de dependencia. Lo que se muestra en las figuras es el ancho de banda necesario para transmitir hasta una determinada capa a través del tiempo. El resultado ha sido obtenido a través de la estimación de ancho de banda en tiempo real. Por lo tanto, se verá para cada capa cual sería la velocidad de transmisión necesaria para transmitir hasta esa capa en cada instante temporal de la duración del video. Hasta capa 000: Sistema de video adaptativo H264/SVC sobre TCP Figura 6.7: Perfil de ancho de banda: Capa 000 Hasta capa 010: Figura 6.8: Perfil de ancho de banda: Capa 010 Hasta capa 001: 102 103 Sistema de video adaptativo H264/SVC sobre TCP Figura 6.9: Perfil de ancho de banda: Capa 001 Hasta capa 011: Figura 6.10: Perfil de ancho de banda: Capa 011 Hasta capa 100: Sistema de video adaptativo H264/SVC sobre TCP 104 Figura 6.11: Perfil de ancho de banda: Capa 100 Hasta capa 110: Figura 6.12: Perfil de ancho de banda: Capa 110 Como era de esperar, las capas superiores necesitan un ancho de banda mayor que las inferiores. Vamos a ver a continuación los anchos de banda de transmisión medios, así como sus desviaciones típicas para poder valorar objetivamente la variación del video a través del tiempo, aunque ya podemos ver en las gráficas que se trata de una secuencia de video que contiene escenas con mucho y con poco movimiento porque las desviaciones típicas serán de un valor considerablemente grande. Capa Ancho de banda medio Desviación típica (Kbit/s) 105 Sistema de video adaptativo H264/SVC sobre TCP (Kbit/s) 000 202,87 100,13 010 298,86 184,88 001 533,16 237,12 011 576,51 278,39 100 1195,90 743,28 110 1294,00 846,80 Tabla 6.3: Medias y desviaciones típicas del ancho de banda de transmisión Como se puede ver en la tabla 6.3, se obtienen unas desviaciones típicas desde el 45 por ciento al 66 por ciento. Esto indica que la variabilidad del video es grande, es decir, que existen escenas con poco y con mucho movimiento, lo que provoca que el tamaño del video codificado sea tan variante. A parte, las medias obtenidas de aproximadamente 300 Kbit/s, 600 Kbit/s y 1,3 Mbit/s para cada una de las tres capas principales, se consideran un buen ejemplo de las capacidades del estándar H264/SVC, ya que para el objetivo del presente proyecto que es la transmisión de la secuencia de video, permiten una estrategia que divida las capas de forma clara y concisa. 6.4. Puesta en escena: El último apartado del capítulo 6, será la puesta en escena del sistema de comunicaciones diseñado en un escenario real. Se va a emular una red con un transmisor (“sender”), dos routers intermedios (“routerA” y “routerB”) y un destinatario (“sink”) usando la herramienta de emulación “Simtools”. A parte, el dispositivo “host” tendrá acceso a las tres interfaces de red generadas. El esquema de red es el siguiente: Figura 6.13: Escenario de red para las pruebas Sistema de video adaptativo H264/SVC sobre TCP 106 En el primer router se configura el ancho de banda máximo que puede aceptar la transmisión, así como su RTT. En cambio, en el segundo router se configura el tamaño máximo de la cola de espera y su retardo de transmisión, obteniendo el ancho de banda disponible como el producto del tamaño de la cola por dos veces el retardo introducido, que se corresponde con tamaño de la cola por RTT. Las pruebas de red que se van a realizar son las cinco siguientes: 1. Transmisión de la secuencia BigBuckBunny con una limitación de ancho de banda que permita extraer hasta la capa base, es decir un ancho de banda disponible de 300 Kbit/s. 2. Transmisión de la secuencia BigBuckBunny con una limitación de ancho de banda que permita extraer hasta la capa de mejora de calidad, es decir un ancho de banda disponible de 600 Kbit/s. 3. Transmisión de la secuencia BigBuckBunny con una limitación de ancho de banda que permita extraer hasta la capa de mejora de resolución, es decir un ancho de banda disponible de 1,3 Mbit/s. 4. Transmisión de la secuencia BigBuckBunny con una limitación de ancho de banda variable. La elección tomada es de 1,3 Mbit/s durante los primeros 200 segundos, 600 Kbit/s durante los siguientes 200 segundos y 1,3 Mbit/s hasta el final. 5. Transmisión simultánea de dos flujos de datos, por un lado la secuencia BigBuckBunny, y por otro lado una secuencia de video codificada según H264/SVC. Se va a utilizar una limitación de ancho de banda de 1,3 Mbit/s, y el objetivo de esta prueba será observar cómo se adapta la transmisión en un entorno en el que se comparte el ancho de banda. Para poder realizar las pruebas, se debe configurar en primer lugar el dispositivo “host” para recepción de flujo en la tercera interfaz, ya que las transmisiones van a ser realizadas por parte del dispositivo “sender” y recibidas por parte del “host” en dicha interfaz. Se muestra a continuación, los comandos de configuración que se ejecutan en el “host”: host$ifconfig tap0 0 host$ifconfig tap2 172.16.5.2/24 host$route add -net 192.168.1.0/24 gw 172.16.5.1 De esta forma, queda configurado el dispositivo “host” con una dirección IP de la tercera interfaz de red, y como pasarela para llegar a la primera interfaz se utiliza el “routerB”. 107 Sistema de video adaptativo H264/SVC sobre TCP Para la prueba cinco, se va a transmitir simultáneamente hacia el “host” (secuencia BigBuckBunny), y hacia el “sink” (secuencia H264/AVC). 6.4.1. Prueba 1 - Ancho de banda límite de 300 Kbit/s: Se configura el primer router con un ancho de banda límite de 300 Kbit/s para obtener un perfil de transmisión que se adecue a la transmisión de la capa base. Viendo el perfil de las capas 000 y 010 ya se puede observar que la variabilidad en tamaño del video puede que provoque que no haya suficiente ancho de banda para poder transmitir en la capa base durante todo el tiempo. A continuación se muestra el flujo transmitido capturado con la herramienta de red “Wireshark”: Figura 6.14: Flujo transmitido: Prueba 300 Kbit/s Como se puede observar la transmisión se detiene a los 220 segundos. Esto se debe al hecho que no puede asumir en tiempo real la transmisión del flujo de datos, lo que provoca que “mplayer” se congele y no se consiga el objetivo de poder reproducir la secuencia en tiempo real. A continuación, vemos el perfil generado de transmisión a partir de los valores estimados de ancho de banda por parte del “socket” y la figura correspondiente al intercambio entre capas realizado durante los 220 segundos de transmisión. Sistema de video adaptativo H264/SVC sobre TCP Figura 6.15: Perfil de transmisión según opciones del socket: Prueba 300 Kbit/s Leyenda Valor Capa 1 000 2 010 3 001 4 011 5 100 6 110 108 109 Sistema de video adaptativo H264/SVC sobre TCP Figura 6.16: Intercambio entre capas: Prueba 300 Kbit/s La diferencia de duración entre la simulación y las otras dos figuras se debe a los instantes temporales en que se transmite con una capa con identificador temporal menor al máximo, ya que en estos casos se reduce la duración del video. Esta diferencia podría deberse al hecho que siempre se transmite con un ancho de banda menor al disponible y por lo tanto las transmisiones se avanzan al instante de reproducción. Sin embargo, este no es el caso, porque si se debiera a esta segunda razón el video no se detendría. Como puede verse en la figura 6.16, la mayor parte del tiempo se transmite hasta las capas 000 y 010, por lo que se obtiene el resultado esperado para la prueba realizada. Sin embargo, como no puede llegar a transmitir todo el flujo, se llega a la conclusión que será necesario introducir un buffer de entrada en recepción que cargue parte del video antes de empezar a reproducir, porque en caso contrario la reproducción se detiene. Se ha repetido la prueba introduciendo el uso del buffer, y se ha obtenido el flujo de transmisión siguiente: Sistema de video adaptativo H264/SVC sobre TCP 110 Figura 6.17: Flujo transmitido: Prueba 300 Kbit/s Como puede esperarse se obtiene un flujo aproximado de 300 Kbit/s durante toda la transmisión. La duración de 515 segundos queda justificada porque como se verá durante gran parte de la transmisión se extrae hasta la capa 000, razón por la que se reduce la duración del video. El buffer intermedio que se ha elegido en este caso es de 3 Mbyte, de forma que antes de empezar a transmitir se ponen 3 Mbyte en el buffer, haciendo que se inicie aproximadamente un minuto después de empezar a transmitir. Esto nos indica que la duración del video es de 465 segundos, por lo que se deduce, que aproximadamente el 25 % del tiempo se transmite con identificador temporal menor al máximo. A continuación, se muestran las figuras correspondientes al perfil generado por las estimaciones del “socket” y el intercambio entre capas realizado en la transmisión. 111 Sistema de video adaptativo H264/SVC sobre TCP Figura 6.18: Perfil de transmisión según opciones del socket: Prueba 300 Kbit/s Figura 6.19: Intercambio entre capas: Prueba 300 Kbit/s Como puede observarse la mayor parte del tiempo se transmite hasta las capas 000 y 010. 6.4.2. Prueba 2 - Ancho de banda límite de 600 Kbit/s: La segunda prueba realizada, está orientada a la reproducción de la secuencia de video hasta la capa de mejora de PSNR, razón por la que se limita la transmisión a 600 Kbit/s. En esta, y en las siguientes pruebas se ha decidido poner otra limitación al ancho de banda para quede limitado por la velocidad de reproducción del video, aparte de por Sistema de video adaptativo H264/SVC sobre TCP 112 el propio ancho de banda disponible. Para conseguirlo, se ha utilizado la opción “nocache” en el reproductor multimedia, para que no utilice un buffer interno de almacenamiento. La razón de esta elección, es para evitar que la duración de la transmisión sea mucho más reducida que la duración del video. Se considera una buena estrategia, porque existe suficiente ancho de banda disponible para poder reproducir como mínimo la capa base en tiempo real y se evita así que se avance demasiado la transmisión. Esta estrategia se convierte en una limitación porque la cola de espera hasta nivel de aplicación será la ventana de control de flujo de TCP, y habrá instantes en que esta quedara bacía, y por lo tanto limitara las transmisiones. A continuación, se muestra el flujo transmitido de la segunda prueba capturado con “Wireshark”: 113 Sistema de video adaptativo H264/SVC sobre TCP Figura 6.20: Flujo transmitido: Prueba 600 Kbit/s Como puede observarse se consigue un flujo de duración de 530 segundos. La razón por la que termina antes es los instantes temporales en que se transmite con identificador temporal menor al máximo. Además, como puede observarse, se obtiene un flujo que en la mayor parte del tiempo está cerca de los 600 Kbit/s tal y como se esperaba. Las razones por las que hay instantes de tiempo con menor ancho de banda son el hecho de no utilizar buffer interno en el reproductor o situaciones de congestión. A continuación, se muestran las figuras correspondientes al perfil generado de flujo máximo que se puede transmitir según las estimaciones obtenidas del “socket” y el intercambio entre capas realizado en la transmisión: Sistema de video adaptativo H264/SVC sobre TCP 114 Figura 6.21: Perfil de transmisión según opciones del socket: Prueba 600 Kbit/s Figura 6.22: Intercambio entre capas: Prueba Como puede observarse en el perfil el ancho de banda medio disponible es aproximadamente de 600 Kbit/s, tal y como se esperaba. Los casos en que este disminuye significativamente son casos de perdida de paquetes, razón por la que se activa el control de congestión. Como se ha podido ver en la reproducción de la secuencia el sistema a 600 Kbit/s se adapta correctamente a las fases de inicio y de control de congestión. 115 Sistema de video adaptativo H264/SVC sobre TCP A parte, como puede observarse en la figura 6.22, la mayor parte del tiempo se transmite hasta las capas 000, 010, 001 y 011, lo cual se corresponde con al ancho de banda necesario para transmitir dichas capas. 6.4.3. Prueba 3 - Ancho de banda límite de 1,3 Mbit/s: La tercera prueba tiene como objetivo la transmisión del flujo a la máxima resolución durante la mayor parte del tiempo, ya que como se ha visto en los perfiles de transmisión de las capas la variabilidad en los tamaños hace que no pueda ser transmitido a la máxima capa durante todo el tiempo. A continuación, se muestra el flujo transmitido en esta prueba (capturado con “Wireshark”): Sistema de video adaptativo H264/SVC sobre TCP 116 Figura 6.23: Flujo transmitido: Prueba 1,3 Mbit/s Como puede observarse se consigue un flujo de duración de 560 segundos. La razón por la que termina antes es la misma que en la segunda prueba, ya que no se utiliza buffer en el reproductor. Además, como puede observarse, se obtiene un flujo que en la mayor parte del tiempo está cerca de los 1,3 Mbit/s tal y como se esperaba. Se detectan casos con pérdida de paquetes como a los 460 segundos, pero al seguir reproduciendo a tiempo real se observa que el sistema se adapta bien a los errores debido al hecho que siempre transmite por debajo del ancho de banda disponible. A continuación, se muestran las figuras correspondientes al perfil generado de flujo máximo que se puede transmitir según las estimaciones obtenidas del “socket” y el intercambio entre capas realizado en la transmisión: 117 Sistema de video adaptativo H264/SVC sobre TCP Figura 6.24: Perfil de transmisión según opciones del socket: Prueba 1,3 Mbit/s Figura 6.25: Intercambio entre capas: Prueba 1300 Kbit/s En la figura 6.25, se observan varias situaciones con pérdida de paquetes, pero como puede observarse el sistema reacciona a gran velocidad a la bajada de ancho de banda disponible. Sin embargo, es importante darse cuenta que se deben a pérdidas de la propia transmisión, razón por la que se recupera con gran velocidad, y en ninguno de los tres casos analizados hasta ahora ha habido ancho de banda compartido con otras transmisiones, caso que se verá en la prueba cinco. A parte, como puede observarse en la figura 6.25, la transmisión ha estado principalmente concentrada en las capas 100 y 110, tal y como se esperaba. 6.4.4. Prueba 4 - Ancho de banda variable de 1,3 Mbit/s y 600 Kbit/s: Sistema de video adaptativo H264/SVC sobre TCP 118 Esta prueba, será evaluado con ancho de banda variable, los primeros 200 segundos se dispondrá de 1,3 Mbit/s, los siguientes 200 segundos de 600 Kbit/s y hasta el final de la secuencia 1,3 Mbit/s. A continuación, se puede ver la figura correspondiente al flujo transmitido capturada con “Wireshark”: 119 Sistema de video adaptativo H264/SVC sobre TCP Figura 6.26: Flujo transmitido: Prueba 1300-600-1300 Kbit/s Como se puede observar, se obtiene el perfil deseado de 1,3 Mbit/s, 600 Kbit/s y 1,3 Mbit/s con intercambios de flujo en los instantes indicados. Se obtiene una duración de 540 segundos, como en los anteriores casos debido al acortamiento del video al filtrar con identificadores temporales menores que el máximo. A continuación, se muestran las figuras correspondientes al perfil de transmisión según las estimaciones realizadas por el “socket” y el intercambio entre capas realizado en la transmisión: Figura 6.27: Perfil de transmisión según opciones del socket: Prueba 1300-600-1300 Kbit/s Sistema de video adaptativo H264/SVC sobre TCP 120 Figura 6.28: Intercambio entre capas: Prueba 1300-600-1300 Kbit/s Como puede observarse en la figura 6.28, se extrae mayormente a las capas 100 y 110 cuando el ancho de banda disponible es de 1,3 Mbit/s, y a las capas 000, 010, 001 y 011 cuando el ancho de banda disponible es de 600 Kbit/s. 6.4.5. Prueba 5 - Ancho de banda de 1,3 Mbit/s compartido: En esta prueba, se han realizado dos transmisiones simultáneas desde el dispositivo “sender”, una dirigida al dispositivo “host” con la secuencia codificada según H264/SVC, y la otra dirigida al dispositivo “sink” con una secuencia codificada según H264/AVC. El objetivo de esta prueba es observar cómo se reparte el ancho de banda disponible (1,3 Mbit/s) entre las dos transmisión. Es una prueba más similar a los entornos reales en que simultáneamente se comparte el ancho de banda con otras aplicaciones. En esta prueba, se ha prescindido de mostrar el flujo capturado con “Wireshark” porque es el agregado por las dos transmisiones y se va a trabajar con el perfil de transmisión obtenido a través de las estimaciones por parte del “socket”. A continuación, se muestran las figuras correspondientes al perfil de transmisión y al intercambio entre capas de esta prueba: 121 Sistema de video adaptativo H264/SVC sobre TCP Figura 6.29: Perfil de transmisión según opciones del socket: Prueba 1,3 Mbit/s compartido Figura 6.30: Intercambio entre capas: 1,3 Mbit/s compartido Como puede observase en la figura 6.29, se obtiene un ancho de banda disponible de entre 300 y 900 Kbit/s, lo que nos indica que ambos flujos luchan por el ancho de banda disponible durante todo el tiempo repartiéndoselo entre ambos. Es importante darse cuenta de que existen situaciones con pérdidas en la transmisión como se puede observar, y el sistema es capaz de restablecerse incluso en el caso de flujo compartido con otras transmisiones, lo que indica una cierta robustez a las situaciones de “congestion avoidance” por parte del sistema desarrollado. Sin, embargo, es igual de importante percatarse que habrán situaciones de congestión límite para todos los caos que harán que la transmisión se detenga debido a las colisiones. Sistema de video adaptativo H264/SVC sobre TCP 122 Por último, debido al flujo disponible, principalmente se extrae a las capas 000, 010, 001 y 011. 123 Sistema de video adaptativo H264/SVC sobre TCP Capítulo 7: Conclusiones: Después de analizar la evaluación del sistema se llega a las conclusiones siguientes: 1. El algoritmo de filtrado desarrollado da lugar a flujos de datos conformantes con el estándar H264/SVC. 2. Los resultados de aplicar las estrategias de filtrado adaptativo planteadas aunque no dan lugar a flujos de datos conformantes estrictamente hablando, son reproducibles por parte de “OpenSVCDecoder”, con cambios de resolución, calidad y velocidad apreciables a simple vista. Por lo que se puede considerar los flujos resultantes como conformantes con H264/SVC. 3. Las pruebas de red sin compartir el ancho de banda disponible reaccionan correctamente a las pérdidas de paquetes permitiendo reproducir la secuencia de video en tiempo real, siempre que se disponga del ancho de banda necesario para transmitir como mínimo hasta la capa base. 4. En los casos en que no se dispone del ancho de banda necesario para transmitir hasta la capa base, el uso de un buffer que almacene parte del flujo antes de reproducir garantiza la correcta reproducción del video, con el retardo introducido por el buffer. Cuanto menor sea el ancho de banda disponible, más retardo se deberá introducir. 5. Las pruebas de red compartiendo el ancho de banda disponible reaccionan correctamente a las pérdidas de paquetes permitiendo reproducir la secuencia de video en tiempo real, siempre que se disponga de “n” veces” el ancho de banda necesario para transmitir como mínimo hasta la capa base, donde “n” es el número de transmisiones simultáneas, ya que tienden a repartirse el ancho de banda a partes iguales, a menos que se definan los anchos de banda limite por aplicación. 6. Obviamente, con situaciones de alta congestión, las transmisiones a tiempo real no serán posible debido a las colisiones. 7. El sistema desarrollado es una alternativa real a los sistemas de video bajo demanda existentes siempre que se disponga de una conexión de banda ancha. 7.1. Líneas futuras: Existen muchas mejoras que se podrían llevar a cabo para mejorar el sistema desarrollado. A continuación, se muestran tanto posibles mejoras para el sistema como proyectos futuros continuación del presente proyecto: Sistema de video adaptativo H264/SVC sobre TCP 124 1. Desarrollar el receptor orientado a aplicaciones a tiempo real, diseñado en el apartado 2 del capítulo 5. 2. Desarrollar un codificador H264/SVC a tiempo real, lo cual sería condición necesaria para poder desarrollar sistemas de videoconferencia que trabajaran con el estándar H264/SVC, ya que actualmente con “JSVM” las codificaciones no son a tiempo real. 3. Modificar “OpenSVCDecoder” para que detecte cuando se transmite con identificador temporal menor que el máximo, y conseguir que adapte la velocidad de reproducción. 4. Desarrollar “plugins” para los principales navegadores web que permitan incorporar el códec H264/SVC para poder reproducir las secuencias H264/SVC en el navegador web. 5. Incorporar el sistema de comunicaciones trabajando sobre HTTP, ya sea en forma de aplicación programada con PHP, o con “servlets” de JAVA, o incluyéndolo de forma nativa en el estándar HTML5. 125 Sistema de video adaptativo H264/SVC sobre TCP APÉNDICES Sistema de video adaptativo H264/SVC sobre TCP 126 Apéndice A: Ficheros de configuración del codificador de JSVM utilizados en las simulaciones: Los siguientes ficheros han sido utilizados para la configuración de la codificación hecha en la secuencia de video “BigBuckBunny”. Concretamente, se han codificado dos capas de escalabilidad temporal para cada una de las capas, siendo las capas: capa base, capa de calidad mejorada (ambas con resolución 320x180) y capa de resolución superior a 640x320. El archivo principal, “confSVC.cfg” es el siguiente: # JSVM Main Configuration File #========================GENERAL================================ OutputFile stream.264 # Bitstream file FrameRate 24.0 # Maximum frame rate [Hz] FramesToBeEncoded 14000 # Number of frames (at input frame rate) NonRequiredEnable 0 # NonRequiredSEI enable (0:disable, 1:enable) CgsSnrRefinement 1 # SNR refinement as 1: MGS; 0: CGS EncodeKeyPictures 1 # Key pics at T=0 (0:none, 1:MGS, 2:all) MGSControl 1 # ME/MC for non-key pictures in MGS layers # (0:std, 1:ME with EL, 2:ME+MC with EL) #===================== CODING STRUCTURE ======================== GOPSize 2 # GOP Size (at maximum frame rate) IntraPeriod 4 # Intra Period NumberReferenceFrames 1 # Number of reference pictures BaseLayerMode 0 #Base layer mode (0,1: AVC compatible, 2: AVC w subseq SEI) ConstrainedIntraUps 0 # constrained intra upsampling #======================= MOTION SEARCH ========================= SearchMode 4 # Search mode (0:BlockSearch, 4:FastSearch) SearchFuncFullPel 3 # Search function full pel # (0:SAD, 1:SSE, 2:HADAMARD, 3:SAD-YUV) SearchFuncSubPel 2 # Search function sub pel # (0:SAD, 1:SSE, 2:HADAMARD) SearchRange 32 # Search range (Full Pel) ELSearchRange 4 # Enh. layer search range FastBiSearch 1 # Fast bi-directional search (0:off, 1:on) 127 Sistema de video adaptativo H264/SVC sobre TCP BiPredIter 4 # Max iterations for bi-pred search IterSearchRange 8 # Search range for iterations (0: normal) #========?================ LOOP FILTER ========================= LoopFilterDisable 0 # Loop filter idc (0: on, 1: off, 2: on except for slice boundarieS, 3: Se aplica 2 etapas de filtrado (limite bloques y limite tiras) # 4: Luma on but Chroma off in enh. layer # (w.r.t. idc=0) # 5: Luma on except on slice boundaries but Chroma off in enh. layer # (w.r.t. idc=2) # 6: Como 3 en las muestras luma y sin filtrado croma # Loop filter idc (0: on, 1: off, 2: # on except for slice boundaries, # 3: Luma on but Chroma off in enh. layer # (w.r.t. idc=0) # 4: Luma on except on slice boundaries. # but Chroma off in enh. layer # (w.r.t. idc=2) LoopFilterAlphaC0Offset 0 # AlphaOffset(-6..+6): valid range LoopFilterBetaOffset 0 # BetaOffset (-6..+6): valid range InterLayerLoopFilterDisable 0 # filter idc for inter-layer deblocking InterLayerLoopFilterBetaOffset 0 # BetaOffset for inter-layer deblocking #======================= LAYER DEFINITION ====================== NumLayers 3 # Number of layers LayerCfg confSVC_layer0.cfg # Layer configuration file LayerCfg confSVC_layer1.cfg # Layer configuration file LayerCfg confSVC_layer2.cfg # Layer configuration file #====================== WEIGHTED PREDICTION ==================== WeightedPrediction 0 # Weighting IP Slice (0:disable, 1:enable) WeightedBiprediction 1 # Weighting B Slice (0:disable, 1:explicit, # 2:implicit) #===================== LOSS-AWARE RDO ========================== LARDO 0 # Loss-aware RDO (0:disable, 1:enable) #========================= HRD ================================= EnableVclHRD 0 # Type I HRD (default 0:Off, 1:on) EnableNalHRD 0 # Type II HRD (default 0:Off, 1:on) #======================= RATE CONTROL ========================== RateControlEnable 0 # Enable base-layer rate control (0=off, 1=on) #====================== FRAME-COMPATIBLE ======================= MuxMethod 0 # Enable 3D mux method (0: none, 1: SbS, 2: TaB) Sistema de video adaptativo H264/SVC sobre TCP MuxFilter 15 # # # # # # # # # # # # # 128 # 3D Muxing/DOwnsampling Filter 0: decimate, 1: average 2: [-1 2 6 2 -1]/8 3: [-1 2 -1] 4: [-1 4 26 4 -1]/32 5: [ 1 -2 5 56 5 -2 1]/64 6: HF1 7: HF0 8: SVC 9: CDF9 10: CDF7 11: "1024"• 12: low-pass (fractional-pixel offset) # 13: JVT-R006 (fractional-pixel offset) # 14: JVT-R070 (fractional-pixel offset) # 15: SVC (fractional-pixel offset) MuxOffset0 1 (view 0) MuxOffset1 1 Layer1; # 16: HF0 (fractional-pixel offset) # offset for input to layer 0 # is not zero; offset for Los archivos de configuración de las tres capas son los siguientes. A continuación se muestra “confSVC_layer0.cfg”: # JSVM Layer Configuration File #=========================== INPUT ============================ SourceWidth 320 # Input frame width SourceHeight 180 # Input frame height FrameRateIn 24 # Input frame rate [Hz] FrameRateOut 24 # Output frame rate [Hz] InputFile BigBuckBunny_320x180@24_000-000s.yuv # Input file SymbolMode 0 # 0=CAVLC, 1=CABAC IDRPeriod 16 # IDR period (should be (GOP size)*N) IntraPeriod 4 # Intra period (should be (GOP size)*N) #=========================== CODING =========================== ProfileIdc 77 # value of profile_idc (or 0 for auto detection) MinLevelIdc 10 # minimum level (level_idc * 10 ) CbQPIndexOffset 2 # QP index offset for the Cb component CrQPIndexOffset 2 # QP index offset for the Cr 129 Sistema de video adaptativo H264/SVC sobre TCP component MaxDeltaQP 1 # Max. absolute delta QP QP 32.0 # Quantization parameters #========================= CONTROL ============================ InterLayerPred 0 # Inter-layer Pred. (0:no, 1:yes, 2:adap.) ILModePred 0 # Inter-layer mode pred. (0:no, 1:yes, 2:adap.) ILMotionPred 0 # Inter-layer motion pred. (0:no, 1:yes, 2:adap.) ILResidualPred 0 # Inter-layer residual pred. (0:no, 1:yes, 2:adap.) #================ EXTENDED SPATIAL SCALABILITY ================ UseESS 0 # ESS mode #============================= MGS ============================ MGSVectorMode 0 # MGS vector usage selection #====================== QP Cascading ========================== ExplicitQPCascading 1 # QP Cascading (0:auto, 1:explicit) DQP4TLevel0 0 # Delta QP for temporal level 0 DQP4TLevel1 1 # Delta QP for temporal level 1 #=================== SVC TO AVC REWRITE ======================= AvcRewriteFlag 0 # Enable SVC to AVC rewrite (0: no, 1: yes) El archivo “confSVC_layer1.cfg” es el siguiente: # JSVM Layer Configuration File #==================== INPUT / OUTPUT ========================== SourceWidth 320 # Input frame width SourceHeight 180 # Input frame height FrameRateIn 24 # Input frame rate [Hz] FrameRateOut 24 # Output frame rate [Hz] InputFile BigBuckBunny_320x180@24_000-000s.yuv # Input file SymbolMode 0 # 0=CAVLC, 1=CABAC IDRPeriod 16 # IDR period (should be (GOP size)*N) IntraPeriod 4 # Intra period (should be (GOP size)*N) #======================== CODING ============================== ProfileIdc 86 # value of profile_idc (or 0 for auto detection) MinLevelIdc 10 # minimum level (level_idc * 10 ) CbQPIndexOffset 2 # QP index offset for the Cb component CrQPIndexOffset 2 # QP index offset for the Cr component MaxDeltaQP 1 # Max. absolute delta QP QP 25.0 # Quantization parameters Sistema de video adaptativo H264/SVC sobre TCP 130 BaseLayerId 0 # Layerd ID for the base layer #======================== CONTROL ============================= InterLayerPred 2 # Inter-layer Pred. (0:no, 1:yes, 2:adap.) ILModePred 2 # Inter-layer mode pred. (0:no, 1:yes, 2:adap.) ILMotionPred 2 # Inter-layer motion pred. (0:no, 1:yes, 2:adap.) ILResidualPred 2 # Inter-layer residual pred. (0:no, 1:yes, 2:adap.) #================ EXTENDED SPATIAL SCALABILITY ================ UseESS 1 # ESS mode ESSCropWidth 320 # base layer upsampled frame width ESSCropHeight 180 # base layer upsampled frame height ESSOriginX 0 # base layer upsampled frame xpos ESSOriginY 0 # base layer upsampled frame ypos #=========================== MGS ============================== MGSVectorMode 0 # MGS vector usage selection #====================== QP Cascading ========================== ExplicitQPCascading 1 # QP Cascading (0:auto, 1:explicit) DQP4TLevel0 0 # Delta QP for temporal level 0 DQP4TLevel1 1 # Delta QP for temporal level 1 #=================== SVC TO AVC REWRITE ======================= AvcRewriteFlag 0 # Enable SVC to AVC rewrite (0: no, 1: yes) El archivo “confSVC_layer2.cfg” es el siguiente: # JSVM Layer Configuration File #===================== INPUT / OUTPUT ========================= SourceWidth 640 # Input frame width SourceHeight 360 # Input frame height FrameRateIn 24 # Input frame rate [Hz] FrameRateOut 24 # Output frame rate [Hz] InputFile [email protected] # Input file SymbolMode 0 # 0=CAVLC, 1=CABAC IDRPeriod 16 # IDR period (should be (GOP size)*N) IntraPeriod 4 # Intra period (should be (GOP size)*N) #========================= CODING ============================= ProfileIdc 86 # value of profile_idc (or 0 for auto detection) MinLevelIdc 10 # minimum level (level_idc * 10 ) 131 Sistema de video adaptativo H264/SVC sobre TCP CbQPIndexOffset 2 # QP index offset for the Cb component CrQPIndexOffset 2 # QP index offset for the Cr component MaxDeltaQP 1 # Max. absolute delta QP QP 27.0 # Quantization parameters BaseLayerId 0 # Layerd ID for the base layer #======================= CONTROL ============================== InterLayerPred 2 # Inter-layer Pred. (0:no, 1:yes, 2:adap.) ILModePred 2 # Inter-layer mode pred. (0:no, 1:yes, 2:adap.) ILMotionPred 2 # Inter-layer motion pred. (0:no, 1:yes, 2:adap.) ILResidualPred 2 # Inter-layer residual pred. (0:no, 1:yes, 2:adap.) #=============== EXTENDED SPATIAL SCALABILITY ================= UseESS 1 # ESS mode ESSCropWidth 640 # base layer upsampled frame width ESSCropHeight 360 # base layer upsampled frame height ESSOriginX 0 # base layer upsampled frame xpos ESSOriginY 0 # base layer upsampled frame ypos #========================== MGS =============================== MGSVectorMode 0 # MGS vector usage selection #===================== QP Cascading =========================== ExplicitQPCascading 1 # QP Cascading (0:auto, 1:explicit) DQP4TLevel0 0 # Delta QP for temporal level 0 DQP4TLevel1 1 # Delta QP for temporal level 1 #================= SVC TO AVC REWRITE ========================= AvcRewriteFlag 0 # Enable SVC to AVC rewrite (0: no, 1: yes) Sistema de video adaptativo H264/SVC sobre TCP Apéndice B: Sintaxis H264/SVC: 132 133 Sistema de video adaptativo H264/SVC sobre TCP Sistema de video adaptativo H264/SVC sobre TCP 134 135 Sistema de video adaptativo H264/SVC sobre TCP Sistema de video adaptativo H264/SVC sobre TCP 136 137 Sistema de video adaptativo H264/SVC sobre TCP Sistema de video adaptativo H264/SVC sobre TCP 138 139 0 Sistema de video adaptativo H264/SVC sobre TCP Sistema de video adaptativo H264/SVC sobre TCP 140 141 Sistema de video adaptativo H264/SVC sobre TCP Sistema de video adaptativo H264/SVC sobre TCP 142 143 Sistema de video adaptativo H264/SVC sobre TCP Sistema de video adaptativo H264/SVC sobre TCP 144 Apéndice C: Manual de utilidades del proyecto: C.1. Utilidades de video: Reproducción de una secuencia YUV en Mplayer: Una secuencia YUV, es aquella secuencia de video que está representado por las tres componentes de representación de imagen YUV, es decir, una secuencia de video decodificada. La forma de indicarle a Mplayer que se va a reproducir una secuencia YUV es la siguiente: mplayer -demuxer rawvideo -rawvideo fps=FPS_IN:w=W_IN:h=H_IN in.yuv En primer lugar se le indica que el formato de la secuencia de video no está codificado (“rawvideo”), acto seguido para que Mplayer pueda reproducirlo se le indican la velocidad de reproducción y su resolución. Mplayer con estos atributos es capaz de detectar las diferentes combinaciones en número de bits para la representación de todas sus componentes. Reproducción de una secuencia codificada con H264: Mplayer detecta automáticamente cuando se inicia la reproducción de una secuencia de video codificada con H264, aunque para conseguir una respuesta más rápida por parte de Mplayer es útil utilizar la extensión “.264”. El único parámetro que se le debe indicar es la velocidad de reproducción. Vemos a continuación el comando a ejecutar para reproducir una secuencia H264: mplayer –fps FPS_IN in.264 Para la reproducción de un archivo codificado con SVC se utiliza exactamente el mismo comando, y Mplayer ya se encarga de detectar que esta codificado con SVC. Para que Mplayer detecte las codificaciones de SVC se debe compilar configurando el código para que utilice este decodificador. Para más información sobre como realizar la compilación, ver [4]. Descomprimir un fichero codificado: Vamos a ver a continuación, el comando para obtener un fichero descomprimido en formato YUV a partir de un fichero de entrada que use una de las siguientes 145 Sistema de video adaptativo H264/SVC sobre TCP codificaciones o multiplexores de video y audio: AVI, MP4, H264; MPEG2, MPEG4. La utilidad utilizada es “ffmpeg” y el comado correspondiente es el siguiente: ffmpeg -i in.avi -v FPS_IN -s W_INxH_IN –pix-fmt yuv420p out.yuv Los parámetros que se le indican son el fichero de entrada (“in.avi”), la velocidad de reproducción de la secuencia de entrada, su resolución (se indica con un carácter “x” en el medio) y el formato de codificación del archivo no comprimido de la salida. Se elige por defecto “yuv420p”. Obtención de versiones sub-muestreadas y sobre-muestreadas de una secuencia YUV: Para la obtención de versiones sub-muestreadas y sobre-muestreadas de una secuencia YUV utilizaremos la utilidad “DownConvertStatic” del paquete de software JSVM. El comando a utilizar es el siguiente: DownConvertStatic W_IN H_IN in.yuv W_OUT H_OUT out.yuv NUM_METHOD En los parámetros se indica las secuencias de entrada y de salida, y sus resoluciones. Es decir, se indica la resolución del archivo de entrada, y la resolución deseada para el archivo de salida. Además, se indica el o los filtros que se utilizaran para el submuestreo o el sobre-muestreo, mediante el parámetro “NUM_METHOD. Existen otros parámetros, para aprender a utilizarlos o ver los distintos tipos de filtrado se recomienda la lectura de [3]. El resultado de ejecutar esta utilidad será la versión sub o sobre-muestreada de la entrada utilizando el método indicado. Codificación de una secuencia H264/SVC: El siguiente paso lógico, en las funcionalidades sobre utilidades de video, es la codificación de una secuencia utilizando el estándar H264/SVC. Para codificar con AVC se cogerá el caso particular de la siguiente explicación, en que solo se incluye una capa. El proceso de codificación se realiza con la siguiente instrucción: H264AVCEncoderLibTestStatic –pf confSVC.cfg Existen muchos parámetros adicionales que se le pueden indicar, pero estos serán equivalentes a los parámetros que se indicaran en el fichero de configuración. De esta forma el único parámetro que se pasa es el archivo de configuración, donde se inicializan todas las variables necesarias para la codificación. Vemos a continuación las principales variables de codificación. No se van a presentar todas las posibilidades del codificador “H264AVCEncoderLibTestStatic”. Para obtener más información se recomienda la lectura de [3]. Sistema de video adaptativo H264/SVC sobre TCP 146 La codificación consta de varios ficheros de configuración, el principal (“confSVC.cfg”) y uno por cada capa de las que conste la codificación (“confSVC_layer*i+”). Empezamos presentando las opciones de configuración más importantes del archivo principal. En ellas veremos la identificación del flujo de salida, su estructura de codificación, los métodos utilizados en la búsqueda de muestras realizada en intra e inter-predicción y la identificación de los ficheros correspondientes a las distintas capas que forman parte de la codificación. Empezamos, viendo la identificación del fichero de salida. Los parámetros que deberán especificarse son los siguientes: #============================ GENERAL ================================ OutputFile path/stream.264 # Bitstream file FrameRate 24.0 # Maximum frame rate [Hz] FramesToBeEncoded 14000 # Number of frames (at input frame rate) Especificamos el nombre del fichero de salida, su velocidad de reproducción, y el número de fotogramas de la secuencia de entrada que van a ser codificados. Como punto importante, remarcar que para que no haya errores en la codificación el número de fotogramas a codificar debe ser múltiplo del tamaño de GOP especificado en los atributos que veremos a continuación. En segundo lugar, se especifica la estructura de codificación, para conseguirlo debemos fijar el tamaño de GOP de la secuencia y el periodo entre fotogramas intrapredecidos. La estructura en SVC se genera siguiendo los principios de funcionamiento de la estructura diádica, de forma que con el tamaño de GOP determinaremos el número de tiras B que habrá entre las tiras I y P. #======================== CODING STRUCTURE =========================== GOPSize 2 # GOP Size (at maximum frame rate) IntraPeriod 4 # Intra Period Seguimos en tercer lugar viendo las principales opciones en cuanto a los algoritmos de búsqueda de muestras y el tamaño máximo sobre el que se van a realizar las búsquedas. Es importante darse cuenta, que la velocidad de la codificación dependerá bastante de la elección de estos parámetros. #========================== MOTION SEARCH ============================ 147 SearchMode 4 SearchFuncFullPel 3 SearchFuncSubPel 2 SearchRange 32 ELSearchRange 4 FastBiSearch 1 BiPredIter 4 IterSearchRange 8 Sistema de video adaptativo H264/SVC sobre TCP # Search mode (0:BlockSearch, 4:FastSearch) # Search function full pel # (0:SAD, 1:SSE, 2:HADAMARD, 3:SAD-YUV) # Search function sub pel # (0:SAD, 1:SSE, 2:HADAMARD) # Search range (Full Pel) # Enh. layer search range # Fast bi-directional search (0:off, 1:on) # Max iterations for bi-pred search # Search range for iterations (0: normal) Con estos atributos, decidimos si utilizamos búsqueda rápida o por bloques, el tipo de algoritmo utilizado para búsqueda a nivel de muestra o de sub-muestra, el tamaño máximo de distancias en las búsquedas, así, como otros atributos más. Por último, en el archivo de configuración principal, tenemos unos atributos que nos permiten identificar donde encontrar los archivos de configuración de cada una de las capas. Habrá una variable por cada capa de las que conste la codificación. #========================== LAYER DEFINITION =========================== NumLayers 3 # Number of layers LayerCfg confSVC_layer0.cfg # Layer configuration file LayerCfg confSVC_layer1.cfg # Layer configuration file LayerCfg confSVC_layer2.cfg # Layer configuration file Pasamos a ver a continuación los principales atributos que se deben definir en los archivos de configuración de cada una de las capas. En concreto veremos la identificación de la secuencia de entrada en formato YUV, las características de la estructura, las características de la codificación, si se utiliza predicción entre capas y si se utiliza escalabilidad de resolución. En primer lugar vamos a ver, la identificación de la secuencia YUV de entrada, su resolución y su velocidad de reproducción de entrada. Además podemos fijar el valor de la velocidad de reproducción de salida, con lo que en caso de que sean valores distintos aumentaría o disminuiría el número de fotogramas codificados. Esta opción nos permite por ejemplo fijar una secuencia de entrada a 50 fotogramas por segundo, y en la capa base solo codificar la mitad de estos fotogramas fijando la velocidad de salida a 25 fotogramas por segundo. #==================== INPUT / OUTPUT ========================== Sistema de video adaptativo H264/SVC sobre TCP 148 SourceWidth 320 # Input frame width SourceHeight 180 # Input frame height FrameRateIn 24 # Input frame rate [Hz] FrameRateOut 24 # Output frame rate [Hz] InputFile BigBuckBunny_320x180@24_000-000s.yuv # Input file Se verá a continuación, los parámetros correspondientes el periodo de tiras intrapredecidas, que indica para cada capa la periodicidad de las tiras I; y el periodo de tiras IDR, que nos indicara la periodicidad en instantes de refresco, que seran tiras decodificables por sí mismas, y como consecuencia instantes en los que se dejaran de propagar errores. #======================== CODING STRUCTURE =========================== IDRPeriod 16 IntraPeriod 4 # IDR period (should be (GOP size)*N) # Intra period (should be (GOP size)*N) En tercer lugar, se verán los atributos que fijaran si se utilizara predicción entre capas en la capa actual, y en caso que sea así, a partir de que capa se va a predecir. #======================== CODING ============================== BaseLayerId 0 # Layerd ID for the base layer #======================== CONTROL ============================= InterLayerPred 2 # Inter-layer Pred. (0:no, 1:yes, 2:adap.) ILModePred 2 # Inter-layer mode pred. (0:no, 1:yes, 2:adap.) ILMotionPred 2 # Inter-layer motion pred. (0:no, 1:yes, 2:adap.) ILResidualPred 2 # Inter-layer residual pred. (0:no, 1:yes, 2:adap.) En este caso, decidimos para cada capa de mejora la capa sobre la que se realizaran las predicciones, normalmente la inferior; aunque existen casos como cuando se utiliza una capa intermedia con calidad mejorada, en que la capa de resolución superior se hace predecir sobre la capa base por temas de eficiencia entre tamaños de extracción utilizando el algoritmo de filtrado y calidad visual obtenida. En el caso de la capa base este atributo no se utiliza ya que no va a predecir de ninguna capa. Además, se especifica el tipo de predicciones entre capas que se va a utilizar, pudiendo elegir un tipo para todas las predicciones entre capas (primer atributo), o un tipo para 149 Sistema de video adaptativo H264/SVC sobre TCP cada uno de los tres tipos de predicción entre capas. En las capas superiores se deberá especificar un valor de 1 o de 2, mientras que en la capa base se elegirá el valor de 0, ya que no existe predicción entre capas. Pasamos a ver, los atributos correspondientes al parámetro de cuantificación que vamos a utilizar. En primer lugar veremos la forma de fijar el parámetro de cuantificación que vamos a utilizar. Además vamos a ver como fijar parámetros de cuantificación diferentes en las componentes de crominancia, y en las distintas capas temporales que se generan. #======================== CODING ============================== MaxDeltaQP 1 # Max. absolute delta QP QP 25.0 # Quantization parameters Con estos dos parámetros fijamos el parámetro de cuantificación para la capa, y la máxima desviación absoluta que se permitirá respecto al valor fijado, en este caso el parámetro de cuantificación quedaría entre 24 y 26. #======================== CODING ============================== CbQPIndexOffset 2 # QP index offset for the Cb component CrQPIndexOffset 2 # QP index offset for the Cr component Con estos dos parámetros fijamos la diferencia relativa de cada una de las dos componentes de crominancia respecto al valor de la capa. Normalmente se utilizara estos atributos con diferencias positivas ya que el ojo humano es más sensible a la componente de luminancia, y consecuentemente nos podremos permitir normalmente el hecho de que no se obtengan unas PSNR tan altas en las componentes de crominancia. Para conseguir, diferentes parámetros de cuantificación en las distintas capas temporales generadas dentro de cada capa utilizamos “QPCascading”, en el que definimos de la misma forma que antes las diferencias relativas respecto al valor de la capa, para cada una de las capas de escalabilidad temporal. Es necesario especificar un valor para cada capa en caso de especificarse su uso. #======================= QP Cascading ========================= ExplicitQPCascading 1 # QP Cascading (0:auto, 1:explicit) DQP4TLevel0 0 # Delta QP for temporal level 0 DQP4TLevel1 1 # Delta QP for temporal level 1 Sistema de video adaptativo H264/SVC sobre TCP 150 En quinto lugar, veremos como determinar si vamos a utilizar escalabilidad espacial. Tendremos un atributo que nos permitirá activar su uso, y deberemos indicar la resolución de la capa en la que estamos trabajando. Este atributo se deberá activar tanto cuando estemos utilizando una capa con resolución superior, como cuando estemos generando una capa de calidad mejorada con el uso de MGS. Se muestran a continuación estos atributos: #================ EXTENDED SPATIAL SCALABILITY ================ UseESS 1 # ESS mode ESSCropWidth 320 # base layer upsampled frame width ESSCropHeight 180 # base layer upsampled frame height ESSOriginX 0 # base layer upsampled frame x-pos ESSOriginY 0 # base layer upsampled frame y-pos En penúltimo lugar se va a explicar cómo se debe hacer para realizar una codificación usando MGS y generando varias capas de mejora con partición de los coeficientes. Para ello, disponemos de un atributo que se encarga de permitir activar el uso de MGS con partición de coeficiente, y posteriormente asignaremos valores para cada capa de mejora, la suma de los cuales debe ser 8, correspondientes al número de coeficientes disponibles. Se muestran a continuación estos atributos: #=========================== MGS ============================== MGSVectorMode 1 # MGS vector usage selection MGSVector0 4 # Specifies 0th position of the vector MGSVector1 2 # Specifies 1st position of the vector MGSVector2 2 # Specifies 2nd position of the vector Decodificación de una secuencia H264/SVC: La utilidad para decodificar una secuencia H264, tanto AVC como SVC, es “H264AVCDecoderLibTestStatic”. Esta utilidad convierte una secuencia codificada según H264 en una secuencia de video no comprimida en formato YUV. A continuación se muestra el comando para decodificar, donde sus atributos son la secuencia H264 de entrada, y el fichero en el que almacenar el flujo decodificado: H264AVCDecoderLibTestStatic in.264 out.yuv C.2. Utilidades de compilación: 151 Sistema de video adaptativo H264/SVC sobre TCP Compilación con make: Para realizar la compilación del código que se haya desarrollado utilizaremos el compilador de GNU: GCC. Veremos a continuación la plantilla de un Makefile que utilizara este compilador. En concreto, el ejemplo que se propone trabaja con la utilidad c++, que se corresponde con el compilador del lenguaje de programación c++ del conjunto de compiladores GCC. Para compilar vamos a utilizar el siguiente comando. Este debe ejecutarse en el directorio raíz en que se encuentran los archivo de código fuente. cd project_dir make Vemos a continuación el conjunto de instrucciones que forman parte del Makefile: EXEC := application_name DIRSRC := src/ DIROBJ := obj/ DIRHDR := include/ CXXFLAGS := -I $(DIRHDR) OBJS := $(subst $(DIRSRC), $(wildcard $(DIRSRC)*.cpp))) $(DIROBJ),$(patsubst %.cpp, %.o, .PHONY: all clean all: info $EXEC $(EXEC): $(OBJS) $(CXX) -o $@ $^ $(DIROBJ) %.o: $(DIRSRC) %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@ clean: rm -f *.log $(EXEC) *~ $(DIROBJ)* $(DIRSRC)*~ $(DIRHEA)*~ El Makefile anterior se encarga de realizar la compilación del fichero por etapas. En primer lugar a partir los ficheros de código fuente obtiene los ficheros objeto resultantes y los almacena en el directorio “obs/”. Acto seguido, se realiza el proceso de enlazado para obtener el ejecutable resultante. Además hemos definido el comportamiento cuando se ejecute “make clean”, para que elimine todos los ficheros temporales. Sistema de video adaptativo H264/SVC sobre TCP 152 El siguiente comando realiza la misma funcionalidad. En él se deben especificar todas las cabeceras y ficheros de código fuente necesarios para la compilación. c++ -o application_name hdr1.h … hdrN.h src1.cpp … srcN.cpp Compilación con KDevelop4: En el programa KDevelop4, se trabaja con Makefiles que van a ser compilados utilizando CMake. Para compilar en KDevelop solo es necesario incluir todos los ficheros en el proyecto y sus nombres, tanto de cabecera como de código fuente en el archivo “CMakeLists.txt”. Así, es el propio programa el que se encarga de generar los ficheros de compilación. En concreto deben ponerse utilizando la siguiente línea de texto: add_executable(application_name hdr1.h … hdrN.h src1.cpp … srcN.cpp) C.3. Utilidades desarrolladas en el proyecto: Obtener los atributos de una secuencia H264/SVC: La primera utilidad desarrollad, se encarga de mostrar por pantalla los atributos de cada una de sus unidades NAL. En concreto muestra tipo de unidad NAL, capa a la que pertenece y en caso de ser una tira codificada, tipo de tira (I, P o B). Además, en todos los casos muestra el número de unidad NAL, y su tamaño en bytes. El comando correspondiente es el siguiente: obtain_NALU_parameters in.264 El único parámetro que tiene es el flujo de entrada. Filtrado hasta una capa máxima: La segunda utilidad desarrollada en el proyecto se encarga de obtener una versión filtrada de la secuencia de video H264/SVC de entrada. De esta forma, eligiendo en la línea de comandos el DTQ máximo de la extracción obtenemos a la salida otra secuencia H264/SVC, que es a su vez conformante con el estándar, es decir, la secuencia resultante será decodificable y reproducible. El comando correspondiente para esta utilidad es el siguiente: extract_DTQ in.264 out.264 D_th T_th Q_th Como se puede observar se fijan los atributos máximos de la extracción, el archivo de entrada, y el archivo de salida en que será almacenada la versión filtrada. 153 Sistema de video adaptativo H264/SVC sobre TCP Extracción con ancho de banda fijo: Esta utilidad, se encarga de extraer según el algoritmo de filtrado siempre hasta la capa con ancho de banda necesario para transmitir hasta esa capa máximo pero menor al disponible, que en este caso será fijo y será uno de los atributos que se le pasaran al ejecutable. El comando correspondiente es el siguiente: fixedBW_extraction in.264 out.264 max_BW(KB/s) Como se puede observar los atributos que se le van a pasar son el archivo de entrada, el de salida y el ancho de banda disponible. Este ancho de banda limite será comparado con las estimaciones del ancho de banda necesario para transmitir hasta cada una de las posibles capas, y servirá para limitar la extracción. Se ve así, que cuanto mayor sea el ancho de banda disponible, más calidad tendrá la secuencia extraída. Extracción con ancho de banda variable: Este caso, será igual que el anterior pero utilizando intercambios de ancho de banda disponible a través del tiempo. Para conseguirlo se ha utilizado un fichero auxiliar en el que se indicaran los diferentes anchos de banda y se pasa como atributo el periodo de actualización entre cambios de ancho de banda máximo (se indica en segundos). El comando correspondiente es el siguiente: variableBW_extraction in.264 out.264 BW.txt time(s) Sus atributos son la secuencia de entrada, el fichero donde almacenar la secuencia de salida, el fichero auxiliar en el que se almacena un valor de ancho de banda (KB/s) por línea y el intervalo de actualización. Este ejecutable funciona de tal forma que cuando transcurre el tiempo indicado, se actualiza el ancho de banda disponible. Conseguimos así, emular el funcionamiento de situaciones en que el ancho de banda disponible es variante. Extracción por red: Finalmente, se va a explicar el funcionamiento del sistema de transmisión diseñado. Esta vez al trabajar a través de redes, ha sido necesario definir dos utilidades distintas, el transmisor se encargara de enviar el flujo de dato filtrado según el ancho de banda disponible y el receptor de enviarlo al reproductor. El comando correspondiente a la transmisión del flujo de datos es el siguiente: network_extraction in.264 @dst_IP dst_PORT Sistema de video adaptativo H264/SVC sobre TCP 154 Los parámetros son los correspondientes al fichero de entrada y la identificación del servidor formada por su dirección IP y su puerto. De esta forma fijamos el destino de la transmisión y vamos extrayendo hasta la capa con mayor ancho de banda inferior al disponible, que obtenemos con la estimación de TCP, es decir, tamaño de la ventana de congestión dividido por el RTT, o con la estimación de tamaños enviados dividido por el tiempo de ejecución o una combinación entre los dos casos. Una vez realizadas las pruebas en la puesta en escena del proyecto se ha visto que el estimador reaccionaba de forma muy agresiva debido a la detección de pérdidas. Por esta razón se ha desarrollado una última versión en la que se puede elegir el peso de cada uno de los estimadores. El comando correspondiente es el siguiente: network_extractor in.264 @dst_IP dst_PORT TCP_est_height(%) En este caso se indica además el peso que tendrá el estimador de TCP en tanto por ciento. La otra utilidad necesaria para el funcionamiento del sistema es un receptor TCP estándar, que se encargue de almacenar el contenido recibido, o de enviarlo al reproductor. Es importante darse cuenta que el receptor se deberá ejecutar siempre antes que el transmisor ya que funcionara como servidor, y en caso de hacerlo en orden inverso, el transmisor no encontraría el socket escuchando en el puerto y dirección IP correspondientes. El comando correspondiente al receptor es el siguiente: tcp_server @src_IP src_PORT Se le indica la dirección IP y el puerto en la que realizar la escucha y se envía a la salida estándar el contenido de video recibido. Para terminar vamos a ver la utilización de estas comandas y otra adicional (bfr), para la realización de las pruebas que se han detallado en el capítulo 6. En primer lugar creamos un fichero FIFO, que utilizaremos como punto intermedio entre el receptor y el buffer que se encargara de cargar parte del fichero antes de empezar a reproducirse. mkfifo fifo_name En segundo lugar utilizamos el comando bfr para disponer del buffer, que nos va a permitir precargar parte de la secuencia antes de empezar a reproducir y redirigimos su salida estándar para ser reproducida con Mplayer. bfr fifo_name -v -pk1m -m 10% -i 99% --throttle 90% --speedcap 8000K 155 Sistema de video adaptativo H264/SVC sobre TCP --buffersize BUFFER_SIZE -o - | mplayer -nocache - 1>/dev/null En tercer lugar ponemos el receptor en escucha: tcp_server @src_IP src_PORT Para finalizar ejecutamos “network_extraction”: en el origen de la transmisión el comando network_extraction in.264 @dst_IP dst_PORT Lo que conseguimos con estas instrucciones es que empiece la transmisión y que se vaya cargando el video en el buffer intermedio. Entonces cuando ha terminado de cargar el buffer que le hemos indicado, empezara la reproducción de la secuencia de video en Mplayer. Sistema de video adaptativo H264/SVC sobre TCP 156 Bibliografía: [1] ITU-T, “H264, advanced video coding for generic audiovisual services”, 2012 [2+ Marc Torrent Vernetta, “Diseño de un sistema de transmisión de video escalable sobre un sistema de redes P2P”, 2010 [3] ITU-T, “JSVM software manual”, 2011 *4+ Médéric Blestel y Mickaël Raulet, “Open SVC Decoder: a flexible SVC library”, 2010 [5] Universidad Politécnica de Catalunya. Departamento de telemática. Jorge Mata *et al.+, “Multimedia communications. TCP Flows Practice”, 2014