Descarga la aplicación para disfrutar aún más
Esta es una vista previa del archivo. Inicie sesión para ver el archivo original
Parte1/.DS_Store __MACOSX/Parte1/._.DS_Store Parte1/01-comunicaciones_multimedia.pdf Transportando multimedia Comunicaciones multimedia Tipos de comunicación multimedia Según forma de distribución Broadcast Switched digital video ~ multicast On-demand ~ unicast Según forma de comunicación: Interactiva / no-interactiva No-interactivo: predomina one-way vídeo No interactiva, según quién provee IPTV: el proveedor que conecta ‘la última milla’ Ej: Movistar Plus (antes Movistar TV, antes Imagenio)… OTT (Over The Top): provee otro distinto del proveedor last-mile Ej: YouTube, RTVE, Netflix … Comunicaciones multimedia ¿Qué tecnología? Principalmente one- way vídeo, OTT Comunicaciones multimedia Tecnología para one-way video, versión #1 /* nos centramos en el transporte */ file = open (fileName , O_RDONLY); socketTCP = sock (…); /* establece sesion TCP */ while (datosEnviado < tamanoFich) { read (file, memor, TAM_BLOQ); write (socketTCP, memor, TAM_BLOQ); /* actualiza datosEnviados */ } /* nos centramos en el transporte */ socketTCP = sock (…); /* establece sesion TCP */ while (datosRecibidos< tamanoFich) { read (socketTCP, memor, TAM_BLOQ); /* actualiza datosRecibidos */ } /* configura dispositivo de video */ videoDevice = open (/dev/… ); while (datosReprod < tamanoFich) { write (videoDevice, memor, TAM_BLOQ); /* actualiza datosReprod */ } Servidor de video Cliente de video #1 = transferencia contenido completo, luego reproducción Comunicaciones multimedia Tecnología para one-way video, versión #1 Propiedades de TCP respecto a - Servicio de entrega de datos - Flujo - Congestión - Retardos /* nos centramos en el transporte */ file = open (fileName , O_RDONLY); socketTCP = sock (…); /* establece sesion TCP */ while (datosEnviado < tamanoFichero) { read (file, memor, TAM_BLOQ); write (socketTCP, memor, TAM_BLOQ); /* actualiza datos enviados */ } /* nos centramos en el transporte */ socketTCP = sock (…); /* establece sesion TCP */ while (datosRecibidos< tamanoFichero) { read (socketTCP, memor, TAM_BLOQ); /* actualiza datos recibidos */ } /* configura dispositivo de video */ videoDevice = open (/dev/… ); while (datosReproducidos < tamanoFichero) { write (videoDevice, memor, TAM_BLOQ); /* actualiza datosReproducidos */ } #1 = transferencia contenido completo, luego reproducción Comunicaciones multimedia #1: ¿cumple parámetros de calidad? ITU-T G.1010: ‘Categorías de calidad de servicio para los usuarios de extremo de servicios multimedios’, 2001 Medium Application Degree of symmetry Typical data rates Key performance parameters and target values One-way delay Delay variation Information loss (Note 2) Other Audio Conversational voice Two-way 4-64 kbit/s <150 ms preferred (Note 1) <400 ms limit (Note 1) < 1 ms < 3% packet loss ratio (PLR) Audio Voice messaging Primarily one-way 4-32 kbit/s < 1 s for playback < 2 s for record < 1 ms < 3% PLR Audio High quality streaming audio Primarily one-way 16-128 kbit/s (Note 3) < 10 s << 1 ms < 1% PLR Video Videophone Two-way 16-384 kbit/s < 150 ms preferred (Note 4) <400 ms limit BAJA (< 1ms) < 1% PLR Lip-synch: < 80 ms Video One-way One-way 16-384 kbit/s < 10 s BAJA (< 1ms) < 1% PLR NOTE 1 – Assumes adequate echo control. NOTE 2 – Exact values depend on specific codec, but assumes use of a packet loss concealment algorithm to minimise effect of packet loss. NOTE 3 – Quality is very dependent on codec type and bit-rate. NOTE 4 – These values are to be considered as long-term target values which may not be met by current technology. Jitter #1 = transferencia contenido completo, luego reproducción Comunicaciones multimedia #1: ¿cumple parámetros de calidad? ITU G.1010: ‘Categorías de calidad de servicio para los usuarios de extremo de servicios multimedios’, 2001 Medium Application Degree of symmetry Typical data rates Key performance parameters and target values One-way delay Delay variation Information loss (Note 2) Other Audio Conversational voice Two-way 4-64 kbit/s <150 ms preferred (Note 1) <400 ms limit (Note 1) < 1 ms < 3% packet loss ratio (PLR) Audio Voice messaging Primarily one-way 4-32 kbit/s < 1 s for playback < 2 s for record < 1 ms < 3% PLR Audio High quality streaming audio Primarily one-way 16-128 kbit/s (Note 3) < 10 s << 1 ms < 1% PLR Video Videophone Two-way 16-384 kbit/s < 150 ms preferred (Note 4) <400 ms limit BAJA (< 1ms) < 1% PLR Lip-synch: < 80 ms Video One-way One-way 16-384 kbit/s < 10 s BAJA (< 1ms) < 1% PLR NOTE 1 – Assumes adequate echo control. NOTE 2 – Exact values depend on specific codec, but assumes use of a packet loss concealment algorithm to minimise effect of packet loss. NOTE 3 – Quality is very dependent on codec type and bit-rate. NOTE 4 – These values are to be considered as long-term target values which may not be met by current technology. #1 = transferencia contenido completo, luego reproducción #1 = transferencia contenido completo, luego reproducción Comunicaciones multimedia #1: ¿cumple parámetros de calidad? ¿Retardos de reproducción aceptables? ¿Pérdida de paquetes en reproducción? Problema #1.1: retardo de inicio Intrínseco al diseño inicial: primero descarga el fichero entero, luego lo reproduce #1 = transferencia contenido completo, luego reproducción Comunicaciones multimedia Tecnología para one-way video, versión #2 /* nos centramos en el transporte */ file = open (fileName , O_RDONLY); socketTCP = sock (…); /* establece sesion TCP */ while (datosEnv < tamanoFich) { read (file, memor, TAM_BLOQ); write (socketTCP, memor, TAM_BLOQ); /* actualiza datosEnv */ } /* nos centramos en el transporte */ socketTCP = sock (…); /* establece sesion TCP */ /* configura dispositivo de video */ videoDisp = open (/dev/… ); while (datosRec< tamanoFich) { read (socketTCP, mem, TAM_BLOQ); /* actualiza datosRec */ write (videoDisp, mem, TAM_BLOQ); } Servidor de video Cliente de video #2 = reproduce bloque de datos nada más recibirlo Comunicaciones multimedia #2: ¿cumple parámetros de calidad? ¿Control de flujo? ¿Pérdida de paquetes en reproducción? ¿Retardos aceptables en reproducción? ¿Se puede mantener ‘delay variation’? La RED no es ideal, y afecta ¿Causas de pérdida de paquetes? ¿Causas de retardos de paquetes? ¿Puedo cuantificar el retardo máximo? #2 = reproduce bloque de datos nada más recibirlo Comunicaciones multimedia Pérdidas y retardos en la red ¿Causas de pérdida de paquetes? ¿Cómo son las pérdidas si utilizo TCP? ¿Causas de retardos de paquetes? ¿Puedo cuantificar el retardo máximo ‘one-way’? ¿Cómo es el retardo si utilizo TCP? ¿Cómo varía retardo / pérdida de paquetes con la distancia? Conmutador / Router Líneas de entrada Líneas de salida Comunicaciones multimedia #2: ¿cumple parámetros de calidad? Supongamos que de media, hay ancho de banda suficiente, pero puede haber variaciones en transitorio Si de media no hay ancho de banda suficiente, hay que REDUCIR la calidad del vídeo Problema #2.1: ¿cumple JITTER? ¿estoy seguro de que tendré datos suficientes para reproducir en cada momento? Solución #2.1: que la red tenga “mejor comportamiento” Soluciones de Calidad de Servicio Versión #3: acumular datos en el cliente antes de empezar la reproducción BUFFERING #2 = reproduce bloque de datos nada más recibirlo Comunicaciones multimedia Tecnología para one-way video, versión #3 (aka progressive download) /* nos centramos en el transporte */ file = open (fileName , O_RDONLY); socketTCP = sock (…); /* establece sesion TCP */ while (datosEnviado < tamanoFichero) { read (file, mem, TAM_BLOQ); write (socketTCP, mem, TAM_BLOQ); /* actualiza datosEnviado */ } /* nos centramos en el transporte */ socketTCP = sock (…); /* establece sesion TCP */ /* configura dispositivo de video */ videoDisp = open (/dev/… ); memIni = mem; while (datosRec < tamanoFichero) { read (socketTCP, mem, TAM_BLOQ); /* actualiza datos recibidos */ if (datosRec > BUFFER_INICIAL) { write (videoDisp, memIni, TAM_BLOQ); } } /* Cuando termina de recibir, quedan datos que hay que terminar de reproducir*/ Servidor de video Cliente de video #3 = buffering, acumula algunos datos antes de comenzar reproducción Comunicaciones multimedia Progressive download vs streaming Progressive download: Mandar todo el vídeo al destino Muy simple para el servidor que envía, muy fácil de implementar con TCP Forward sólo hasta parte de contenido recibida Streaming: El cliente pide explícitamente bloques para reproducir Facilita forward Comunicaciones multimedia Version #3 TCP no permite uso de multicast Comunicaciones multimedia Transporte de video one-way Transporte de comunicaciones interactivas Comunicaciones multimedia Comunicaciones Interactivas ¡El contenido se genera en tiempo real Cloud gaming requiere respuesta en <120 ms. Comunicaciones multimedia Comunicación interactiva, versión #1 Ejemplo típico: Audio generado a 8000 muestras por segundo, 1 byte por muestra T=20 ms (160 bytes) Retardo de codificación (codec delay): T Depende de tamaño de paquete Siempre presente (aunque lo obviamos en el resto de la discusión) Usuario 1 Usuario 2 tiempo T T Retardo de red Empieza a grabar Comunicaciones multimedia Comunicación interactiva, versión #1 Análisis de datos disponibles en la memoria del cliente Usuario 1 Usuario 2 tiempo datos disponibles en cliente (bytes) Cantidad de datos recibidos en un paquete Velocidad de reproducción #1 = reproduce bloque de datos nada más recibirlo Comunicaciones multimedia Comunicación interactiva, versión #1 Comunicación con retardos variables en la red tiempo datos disponibles en cliente Usuario 1 Usuario 2 #1 = reproduce bloque de datos nada más recibirlo Comunicaciones multimedia #1: ¿cumple parámetros de calidad? ITU G.1010: ‘Categorías de calidad de servicio para los usuarios de extremo de servicios multimedios’, 2001 Medium Application Degree of symmetry Typical data rates Key performance parameters and target values One-way delay Delay variation Information loss (Note 2) Other Audio Conversationa l voice Two-way 4-64 kbit/s <150 ms preferred (Note 1) <400 ms limit (Note 1) < 1 ms < 3% packet loss ratio (PLR) Audio Voice messaging Primarily one-way 4-32 kbit/s < 1 s for playback < 2 s for record < 1 ms < 3% PLR Audio High quality streaming audio Primarily one-way 16-128 kbit/s (Note 3) < 10 s << 1 ms < 1% PLR Video Videophone Two-way 16-384 kbit/s < 150 ms preferred (Note 4) <400 ms limit BAJA (< 1ms) < 1% PLR Lip-synch: < 80 ms Video One-way One-way 16-384 kbit/s < 10 s BAJA (< 1ms) < 1% PLR NOTE 1 – Assumes adequate echo control. NOTE 2 – Exact values depend on specific codec, but assumes use of a packet loss concealment algorithm to minimise effect of packet loss. NOTE 3 – Quality is very dependent on codec type and bit-rate. NOTE 4 – These values are to be considered as long-term target values which may not be met by current technology. #1 = reproduce bloque de datos nada más recibirlo Comunicaciones multimedia #1: ¿cumple parámetros de calidad? Delay variation <1 ms Necesitamos Versión #2: BUFFERING #1 = reproduce bloque de datos nada más recibirlo Comunicaciones multimedia Comunicación interactiva, versión #2 Usuario 1 Usuario 2 tiempo datos disponibles en cliente Comienza representación #2= buffering, acumula algunos datos antes de comenzar reproducción Comunicaciones multimedia #2: ¿cumple parámetros de calidad? One-way delay <150 ms preferred <400 ms limit #2= buffering, acumula algunos datos antes de comenzar reproducción Comunicaciones multimedia Versión #2: ¿cumple parámetros de calidad? Retardo medido en orden de magnitud del deseado ¡Cuidado con tamaño de buffering! RTT (=ida y vuelta) en función de distancia Medido para jugadores de Halo-3. En rojo, retardo de transmisión (RTT) mínimo Agarwal, Lorch [Sigcomm09] #2= buffering, acumula algunos datos antes de comenzar reproducción Comunicaciones multimedia #2: ¿cumple parámetros de calidad? Suponemos que utilizábamos TCP Problemas con one-way delay TCP puede empezar lento (control de congestión) TCP puede incorporar retardos si se pierden paquetes Retardo por pedir retransmisión Bajada de velocidad por mecanismo de control de congestión Toleramos ‘< 3% packet loss ratio’, pero no retardos grandes Recordar que los problemas de retardos se agravan con la distancia Solución #3: utilizar UDP Nota: TCP puede funcionar, hay quien lo utiliza para comunicaciones interactivas #2= buffering, acumula algunos datos antes de comenzar reproducción Comunicaciones multimedia #3: ¿cumple parámetros de calidad? One-way delay <150 ms preferred <400 ms limit Buffering incrementa one-way delay ¿Cuánto buffering? #3= UDP con buffering, Comunicaciones multimedia Comunicación interactiva, versión #3 Otra forma de verlo constant bit rate transmission time variable network delay client reception constant bit rate playout at client b u ff e re d v id e o Computer Networking: A Top Down Approach, 6th ed,, J. Kurose, K. Ross One-way delay buffer delay #3= UDP con buffering, Network delay Comunicaciones multimedia #3: ¿cumple parámetros de calidad? Solución #3.1: dimensionar correctamente buffering inicial #3= UDP con buffering, Comunicaciones multimedia Dimensionamiento del buffer Buffer delay: se establece para el primer paquete Idealmente, depende del Retardo máximo de la red Retardo del primer paquete constant bit rate transmission time MAXIMUM network delay constant bit rate playout at client 150 ms delay first packet buffering Comunicaciones multimedia Dimensionamiento del buffer ¿Puedo conocer retardo one-way máximo? ¿De qué depende? Pregunta previa: ¿puedo MEDIR el retardo one- way? Requiere relojes sincronizados en FRECUENCIA y OFFSET ¿Alguna estimación del retardo one-way? Comunicaciones multimedia #3 y pérdidas de paquetes En solución basada en TCP, no nos teníamos que preocupar de pérdidas de paquetes Pero UDP no gestiona esto TCP hacía control de flujo… ¿Puedo perder paquetes en #3 por ‘problemas de control de flujo’? #3= UDP con buffering, Comunicaciones multimedia #3 y pérdidas de paquetes Estrategia frente a pérdidas de paquetes en la red Pérdidas puntuales La aplicación pide retransmisión Si el retardo es muy bajo La fuente introduce redundancia Enviar más datos ‘Maquillar’ pérdidas puntuales Interpolación de paquetes adyacentes, ruido blanco… Pérdidas continuadas: Reducir calidad ante pérdidas continuadas (posible congestión) Receptor detecta pérdidas continuadas Receptor transmite evento a fuente Fuente cambia codec Necesitamos NUMERAR LOS PAQUETES para detectar pérdidas UDP no numera los paquetes #3= UDP con buffering, Comunicaciones multimedia #3 y medios ‘no continuos’ Medio es ‘continuo’: el tiempo de reproducción está implícito en los datos Ejemplo, al ‘echar datos seguidos’ a la tarjeta de sonido, la tarjeta de sonido sabe qué hacer con ellos Medio ‘no continuo’: el tiempo de reproducción no está implícito en el flujo de datos Audio con silencios: ¿cuándo termina el silencio? Sincronización de un flujo de video y de subtítulos Para medios no continuos, hacen falta MARCAS de TIEMPO Ni UDP ni TCP incluyen esta información #3= UDP con buffering, Comunicaciones multimedia Arquitectura de un sistema de VoIP Detector de silencios (VAD) Codificador audio Paquetiza ción Generador de redundancia Estimación retardo y jitter Buffer de reproducci ón Decodificador de audio Tratamiento de pérdidas Estimación de pérdidas y realimentación Entrada de audio Salida de audio Fuente Receptor Comunicaciones multimedia [NOTA al margen] También con one-way video puede tener sentido una estrategia de envío controlada Reduce memoria en cliente Muchos vídeos no se terminan, absurdo gastar servidor y ancho de banda en enviarlo Consumo de datos en reproducción Comunicaciones multimedia RTP Comunicaciones multimedia Introducción RTP La mayoría de las aplicaciones multimedia en red usan números de secuencia y marcas de tiempo RTP ofrece este servicio de forma estandarizada Diseñado para poder usarse en una grandísima variedad de escenarios Desde audioconferencias punto a punto a distribución de contenidos multimedia a miles de usuarios Permite transportar formatos comunes PCM, GSM, MP3, … para sonido y MPEG, H.263, H.264, etc., para video También transporta formatos propietarios Es el estándar utilizado para transporte de datos en muchas arquitecturas: SIP, H.323, RTSP… RTP No gestiona QoS (no tiene que ver con la infraestructura de red) No garantiza entrega fiable ni ordenada Va acompañado del intercambio de información de control: RTCP Comunicaciones multimedia Filosofía RTP Para datos multimedia, nadie mejor que la aplicación para saber qué hacer si se pierden paquetes o llegan tarde o cuáles son sus prioridades relativas No poner funciones a nivel de transporte que no sean universalmente necesarias El protocolo de transporte no debe implementar recuperación ante errores, control de flujo, ... Application level framing: La aplicación delimita en bloques la información que se envía (bloques que puedan procesarse de forma completa e independiente) Un mensaje (nivel de aplicación) debe empaquetarse en un paquete (nivel de red) Con application level framing Sin application level framing Comunicaciones multimedia Filosofía RTP RTP funciona extremo a extremo: los nodos intermedios no interpretan RTP Necesita de un protocolo de transporte por debajo para multiplexación RTP viaja preferentemente encima de UDP Conceptualmente, se puede entender como un servicio de transporte Aunque la frontera con aplicación no está clara Respecto a su implementación, se suele integrar como parte del procesamiento a nivel de la aplicación que lo usa, en espacio de usuario, por encima del interfaz de sockets Lo implementa el programador de la aplicación, o éste utiliza librerías que compila con su programa No es un servicio del sistema operativo Comunicaciones multimedia Repaso: multicast en IP Direcciones entre 224.0.0.0 y 239.255.255.255 Sólo se pueden utilizar como dirección destino ¿Qué tiene que hacer un nodo para enviar a un grupo multicast? ¿Qué tiene que hacer un nodo para recibir de un grupo multicast? 224.10.10.15 224.10.10.15 224.10.10.15 Comunicaciones multimedia Sesión RTP Sesiones “ligeras”: no hay control estricto ni centralizado sobre quién está en la sesión Se ajusta bien al modelo multicast de IP Sesión RTP es una asociación entre un conjunto de participantes que se comunican con RTP Indica los parámetros de destino de los paquetes, y está definida por Direcciones IP de los participantes IP multicast o lista de direcciones unicast Puerto RTP: Puerto destino (UDP), en general un número par, En general, lo utilizan TODOS los participantes (aunque podrían definirse puertos distintos para cada destino) Puerto por defecto: 5004 Puerto RTCP: Puerto destino (UDP) de los mensajes de control (RTCP), en general impar En general, lo utilizan TODOS los participantes (aunque podrían definirse puertos distintos para cada destino) En general, puerto RTCP = puerto RTP asociado + 1 RTP no dice cómo establecer las sesiones, determinar los parámetros que las definen Esto se hace a través de otros protocolos, ej. SIP Comunicaciones multimedia Sesión RTP Si un nodo participa en una sesión, es porque quiere recibir los datos (RTP) que se envían ahí Además, alguno de los que participa puede mandar datos (RTP) Roles posibles: ‘Receptor de datos’, ‘Emisor+Receptor de datos’ Los roles pueden cambiar dinámicamente (uno puede mandar un momento, y luego sólo recibir) Todos los nodos mandan y reciben información de control (RTCP) También los que no mandan datos Comunicaciones multimedia Ejemplos de uso de RTP Conferencia de audio multicast: 4 participantes 1 sesión RTP: dirección multicast 224.10.10.15, puerto RTP 5004, puerto RTCP 5005 El audio se muestrea en cada equipo de usuario y se envía en paquetes RTP Cada paquete RTP se envía en 1 paquete UDP, con dirección destino 224.10.10.15 y puerto destino 5004 224.10.10.15 224.10.10.15 224.10.10.15 Paquete RTP: -Tipo de codificación (e.g. PCM) -Marca de tiempo -Número de secuencia -Audio muestreado El usuario habla, y la voz se muestrea (e.g. con PCM, ADPCM o LPC) Comunicaciones multimedia Formato de Mensaje RTP Sequence Number Ve Timestamp Synchronization Source (SSRC) Identifier 0 4 16 31 P X CC 8 9 M Payload Type Contributing Source (CSRC) Identifier #1 . . . . Contributing Source (CSRC) Identifier #n Contenido Multimedia Comunicaciones multimedia Profiles y payload types Perfil (profiles): contextos en los que se define de forma más detallada cómo usar RTP Ejemplos: RTP/AVP (Audio Video Profile): Perfil genérico para conferencias de audio/vídeo con mínimo control (RFC3551: “RTP Profile for Audio and Video Conferences with Minimal Control”) RTP/I Para whiteboards, y medios interactivos Para transporte de audio y vídeo con retransmisión, … Todas las aplicaciones que pertenecen a una misma sesión RTP deben utilizar el mismo perfil Un perfil define Números de payload, que tienen significados distintos en cada perfil Se ‘reutiliza’ el mismo número en distintos perfiles, con significados diferentes Cómo se empaqueta la información multimedia para cada tipo de payload (cómo se calcula el Timestamp, cuántos datos meter por paquete…) También puede haber documentos específicos en los que se especifica el payload format Incluso refinar el comportamiento de RTP/RTCP en ese perfil Cambiar intervalo de generación de paquetes RTCP Añadir nuevos tipos de paquete RTCP Definir extensiones para RTP ... Nótese que NO hay un ‘identificador de perfil’ que viaje con los paquetes Comunicaciones multimedia Algunos documentos de “profiles” RTP Profile for Audio and Video Conferences with Minimal Control (RFC 3551) The Secure Real-time Transport Protocol (SRTP) (RFC 3711) Extended Secure RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/SAVPF) (RFC 5124) Extended RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/AVPF) (RFC4585) RTP Payload Format for JPEG-compressed Video (RFC 2035) obsoleted by RFC 2435 RTP Payload format for H.261 video streams (RFC 2032) RTP Payload Format for MPEG1/MPEG2 Video (RFC 2038) obsoleted by RFC 2250 RTP Payload Format of Sun's CellB Video Encoding (RFC 2029) RTP Payload Format for H.263 Video Streams (RFC 2190) RTP Payload for Redundant Audio Data (RFC 2198) RTP Payload Format for MPEG1/MPEG2 Video (RFC 2250) RTP Payload Format for Bundled MPEG (RFC 2343) RTP Payload Format for the 1998 Version of ITU-T Rec. H.263 Video (H.263+) (RFC 2429) RTP Payload Format for BT.656 Video Encoding (RFC 2431) RTP Payload Format for JPEG-compressed Video (RFC 2435) An RTP Payload Format for Generic Forward Error Correction (RFC 2733) RTP Payload for Text Conversation (RFC 2793) RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals (RFC 2833) RTP Payload Format for Real-Time Pointers (RFC 2862) RTP payload format for MPEG-4 Audio/Visual streams (RFC 3016) RTP Payload Format for ITU-T Recommendation G.722.1 (RFC 3047) A More Loss-Tolerant RTP Payload Format for MP3 Audio (RFC 3119) (37796 bytes) RTP Payload Format for DV Format Video (RFC 3189) (25991 bytes) RTP Payload Format for 12-bit DAT, 20- and 24-bit Linear Sampled Audio (RFC 3190) (34977 bytes) RTP payload format and file storage format for the Adoptive Multi-Rate (AMR) and Adaptive Multi-RTP Payload for Comfort Noise (RFC 3389) (17018 bytes) … Comunicaciones multimedia Negociación de perfiles y ‘payload types’ Se pueden utilizar distintos protocolos para negociar el perfil (nota: ‘fuera’ de RTP) SDP (Session Description Protocol, RFC 4556), define un formato en el que se especifican los parámetros de la sesión multimedia m=audio 49232 RTP/AVP 0 O también m=audio 49232 RTP/AVP 98 a=rtpmap:98 L16/16000/2 puerto UDP Usar RTP con ‘profile’ AVP (Audio- Vídeo Profile, es decir, RFC3551) Utilizar payload type 0 según AVP (u-law PCM…) Utilizar payload type 98 (según AVP, ‘dynamic’, es decir que puede tener distintos usos Defino lo que es ‘98’ para este uso L16 = codificación lineal de 16 bits (definido en RFC3551), 16000 es la frecuencia de muestreo, 2 es el número de canales Comunicaciones multimedia Formato de Mensaje RTP Marca de tiempo (timestamp): Permite sincronización y cálculo de jitter de paquete (útil para RTCP) … ¿con qué formato? (con qué precisión…) Ej: poner texto de subtítulos en instante 19.025 s, siguiente en 27.145 s Empezar a reproducir paquete de audio en 0 s, siguiente en 1/3 de segundo, luego 2/3 de segundo… 0.33333333333333 s ? Diferentes formatos de marca de tiempo en función de perfil y payload No debe requerir sincronización entre relojes: sólo indica valores de tiempo relativos entre paquetes Difícil requerir sincronización de offset entre relojes (razonable pedir una frecuencia similar) Comunicaciones multimedia Formato de Mensaje RTP Marca de tiempo (timestamp): 32 bits Como es dependiente del perfil, consideremos ejemplo de ‘audio’ en RFC3551 Timestamp indica el instante de reproducción del primer octeto de datos contenido en el paquete RTP Emplea el reloj (virtual) de muestreo del audio (NO reloj del sistema operativo, ni CPU) No tiene sentido pedir a la tarjeta de sonido un dato “en medio” de un periodo de muestreo. Tampoco iniciar una reproducción ahí (después de un silencio, por ejemplo) Ejemplo: en audio sin comprimir el tiempo pasa en 1 unidad en cada periodo de muestreo • Suponer paquete de 2048 bytes, 2 bytes por muestra (16 bits mono) ts=340 ts=1364 tiempo=2388 ts=2561 t Comunicaciones multimedia Formato de Mensaje RTP Marca de tiempo (timestamp): 32 bits Valor inicial es aleatorio (como el número de secuencia) Ejemplos de otros perfiles En video, paquetes del mismo frame (porque no quepan en un único paquete), llevan igual timestamp MPEG marca de forma no monótona creciente (interpolados se envían después) Comunicaciones multimedia Formato de Mensaje RTP SSRC (Synchronization Source Identifier): 32 bits Generado aleatoriamente por la fuente Identificador único a nivel RTP de una fuente para una sesión Permite mantener la temporización de la reproducción de cada fuente Los números de secuencia también tienen sólo sentido para una fuente dada SSRC=1 SSRC=2 TS: 100, SSRC=2 TS: 2200, SSRC=1 TS: 2190, SSRC=1 TS: 20, SSRC=2 Tiempo (proceso de reproducción) SSRC Ultimo seq Último ts 1 367 2190 2 1207 20 … … … Comunicaciones multimedia “Sesión ligera” en RTP Las sesiones RTP son “muy” ligeras, como es el control de IP multicast Cualquiera puede unirse sin que nos enteremos Si queremos restringir, puede hacerse cifrando y distribuyendo las claves con otros protocolos de nivel superior El emisor no sabe cuántos destinatarios hay ¡Puede ocurrir que no haya ninguno! Parece conveniente dar algún tipo de realimentación a los participantes – sobre todo a los emisores => RTCP 224.10.10.15 224.10.10.15 224.10.10.15 RTP Comunicaciones multimedia RTCP (Real Time Control Protocol) Funciones Monitorización de la congestión y del QoS Se envían informes sobre lo recibido de cada participante en una sesión Permite medir jitter, y RTT, y calcular tiempo de buffering Identificación Identificador de la fuente mediante una cadena de caracteres Puede utilizarse para asociar flujos de diferentes sesiones También permite enviar el nombre del usuario y otros parámetros textuales de tipo informativo Control de sesión mínimo Abandono de sesión Conocer el número de participantes Comunicaciones multimedia Paquetes RTCP Cinco tipos Sender Report (SR) Indica lo que ha enviado el nodo (y deberían haber recibido los demás) + lo que ha recibido el nodo Receiver Report (RR) Informa sobre lo que ha recibido el nodo Source Description (SDES) Descripción de la fuente: CNAME (canonical name), NAME, EMAIL, PHONE, LOC, TOOL, ... BYE Opcional, indica que un equipo abandona la sesión, y la razón por la que la abandona Específico de aplicación Opcional, permite añadir funcionalidades sin necesidad de definir nuevos paquetes en el protocolo Comunicaciones multimedia Cálculo del Round Trip Time ‘j’ es un ‘sender’, ‘k’ puede ser cualquier cosa ’k’ manda información relevante en Rec Report Block Cada emisor recibe estimación de RTT con cada uno de los miembros de la sesión j k Mide tiempo T0 Guarda T0 y lo asocia con fuente j Inicia temporizador DLSRj Al enviar paquete a j (cuando le toque!) detiene temporizador DLSRj y mete su valor en DLSR mete valor de T0 en campo LSR Mide tiempo T2. Resta T2-T0 – DLRSj Mide tiempo T1 Comunicaciones multimedia Cálculo del Round Trip Time ‘j’ no tiene que almacenar estado ‘k’ sólo guarda por emisor RTP: valor del campo NTP del último paquete recibido, tiempo en el que recibió el último paquete j k Mide tiempo T2. Resta T2-T0 – DLRSj DLRSj T2-T0 Comunicaciones multimedia RTCP y Round Trip Cálculo del Round Trip entre fuente j y k j envía mensaje RTCP SR a k instante T0 codificado en NTP (64 bits) k envía un tiempo después mensaje RTCP RR a j Delay since Last SR (DLSRj): tiempo desde que se recibió el mensaje de j hasta que k envía de vuelta a j Time of Last Sender Report (LSR): tiempo de generación del primer mensaje en j según j (ahora en otro formato: 32 bits centrales del NTP) Round trip: j recibe paquete de k en T Round trip = T-LSR - DLSR Comunicaciones multimedia Estado en los receptores Cada receptor debe mantener estado PARA CADA FUENTE de la que ha recibido ‘recientemente’ SSRC de la fuente, RTP timestamp del último paquete recibido, asociado a un tiempo ‘local’ en el que se debe haber reproducido Si no, no sabrá cuándo tiene que reproducir los contenidos de los paquetes de datos Número de secuencia del último paquete recibido y del último paquete enviado antes de enviar el último mensaje SR o RR Para poder calcular ‘fraction lost’, y saber si el siguiente paquete esperado se ha perdido o no… DLSR asociado al último mensaje RTCP recibido de la fuente Tiempo NTP recibido en el último mensaje RTCP recibido de la fuente … Comunicaciones multimedia Puertos en paquetes UDP RFC 3550 hace referencias sobre el puerto de destino de un paquete RTP o RTCP Ej: dice que por defecto para RTP sea 5004, En cualquier caso recomienda que el puerto para RTP sea par, y el de RTCP = RTP+1 El puerto origen podría ser cualquiera Sobre el puerto origen, RFC4961 sugiere que sea igual que el destino (tanto para RTP como para RTCP) Ej: si capturáramos un paquete “en tránsito”: Dir orig: 163.117.140.180, puerto orig: 5004, dir dest: 225.10.0.3, puerto dest: 5004 __MACOSX/Parte1/._01-comunicaciones_multimedia.pdf Parte1/01.5 - programación en C.pdf Repaso de programación en C Introducción a la programación en C 2 Programación en C C es un lenguaje imperativo (= le decimos paso a paso lo que tiene que hacer) Maneja Variables de distintos tipos En general C es MUY ESTRICTO con los tipos: no deja mezclar … salvo con punteros Constantes Funciones = bloque de código al que se le puede pasar varios parámetros y devuelve resultados Nos facilita reutilizar código: escribo algo que se comporta de forma levemente distinta según los argumentos de entrada Estructuras de control: if, bucles, … Escribimos uno o varios ficheros de texto, y con unas herramientas (compilador y enlazador) obtenemos UN fichero ejecutable Introducción a la programación en C 3 Ejemplo Fichero: holaMundo.c #include <stdio.h> #include <stdlib.h> int main (void) { printf(“Hello World\n”); exit(0); } (En Linux) se compila usando gcc gcc –o holaMundo holaMundo.c Se ejecuta con ./holaMundo Introducción a la programación en C 4 Entendiendo el ejemplo Todo programa en C tiene una función llamada main, que es donde comienza la ejecución Puede ser de la siguiente forma int main (void) { /* código */... }, Opcionalmente, el programa puede tener otras funciones que son llamadas desde el interior de main Si no son llamadas desde main, no se ejecutan Información recibida por la función Información que retornará la función Introducción a la programación en C 5 Entendiendo el ejemplo Hay cosas que C NO sabe hacer (ni nosotros tampoco): Acceder a ficheros, escribir cosas en la pantalla, leer del teclado… ¡C sólo sabe hacer operaciones matemáticas sencillas y mover/copiar datos de un lado a otro! Para solucionarlo utilizamos librerías del sistema: Funciones que han escrito otros (ej., los que han hecho el Sistema Operativo, los que han hecho el compilador…) Las funciones están declaradas en ficheros *.h (ficheros de cabeceras) Hay que incorporar las declaraciones de las funciones en nuestro fichero #include <stdio.h> #include <stdlib.h> #include sustituye la línea en la que está por el fichero completo Gracias a stdio.h, el compilador sabe que hay una función llamada printf(), que sirve para escribir cosas por la pantalla stdlib.h, conoce la función exit() que sirve para terminar y devolver un valor a la línea de comando (típicamente -1 si ha habido un error, 0 en caso contrario) El #include sólo indica la declaración de la función (= el nombre, el valor que devuelve, y los argumentos que toma) Más ficheros que declaran funciones en /usr/include El compilador sabe encontrar el código que *realmente* hace el trabajo de printf y exit Está en una librería llamada glibc, que el compilador conoce sin necesidad de que le tengamos que decir nada Introducción a la programación en C 6 Tipos de datos y operadores Tipos de datos básicos Tipos: char, int, float, double char es un byte. Recordar que los números representan caracteres (según ASCII) Calificadores: short (16 bit), long (64 bit), unsigned, signed, const Ejemplo de declaración de variables unsigned int variable1, variable2; Declaro y asigno valor inicial int indice = 0; Asignación variable1 = 2; variable2 = variable1 + 9; Aritmética: +, -, *, /, % Sólo con números, y sólo entre números del mismo tipo Otro tipo de aritmética con funciones; ejemplo log (3.4556) /*logaritmo decimal, utilizando función definida en #include math */ variable1++ ; /* es igual que variable1 = variable1 + 1 */ Introducción a la programación en C 7 Tipos de datos y operadores Constantes #define constante1 0x1234 #define texto “Cadena de caracteres” Relaciones y lógica: <, >, <=, >=, ==, !=, &&, || (1 && 0) es igual a 0 Ojo: ASIGNACIÓN es =, COMPARACION es == Cuidado con asignar cuando se quiere comparar! if ( a = 3 ) … ¡Siempre verdadero! Introducción a la programación en C 8 Aritmética entera ¡Cuidado con orden de las operaciones! int resultado; resultado = 30*400/1000; /*resultado es 12, lo que queríamos*/ resultado = 30/1000*400 /* resultado es 0, no deseado */ Dividir siempre al final Con aritmética flotante, el orden de las operaciones es menos relevante, pero en aritmética entera sí lo es Introducción a la programación en C 9 Arrays Un array es una serie de N elementos del mismo tipo int x[4]; /* existen cuatro variables de tipo entero, referibles como x[0], x[1], x[2] y x[3] */ ¡NO existe x[4]! char texto[10]; Los arrays son muy útiles para utilizar con estructuras de control ‘repetitivas’ (bucles…) sobre datos del mismo tipo Strings son cadenas de caracteres (arrays de char) especiales: siempre terminadas en un 0 (byte con valor 0 en uno de los char) El valor (numérico) 0 se escribe en una variable de tipo ‘carácter’ como ‘\0’ texto[0]=‘h’; texto[1]=‘o’, texto[2]=‘l’, texto[3]=‘a’; texto[4]=‘\0’; /* ‘backslash’ cero */ ¡El espacio necesario para almacenar una palabra de 4 caracteres (‘hola’) son CINCO chars! printf trabaja con strings printf ("%s", texto); /* imprime ‘hola’ */ Introducción a la programación en C 10 Condiciones /* defino una función que compara un número con 10. La función indica si es mayor/menor/igual devolviendo ‘1’ si es igual, ‘0’ en caso contrario */ int comparaCon10 (int a) { if (a < 10) { printf(“a es menor que 10\n”); return 0; /* no es igual que 10 */ } else if (a == 10) { printf(“a es igual a 10\n”); return 1; else { printf(“a es mayor que 10\n”); return 0; } } == Introducción a la programación en C 11 Bucles while (n != 10) { … /* haz cosas */ } do { … /* haz cosas */ } while (m < 20); Introducción a la programación en C 12 Bucles for (i = 0; i < MAXVAL; i++) { … /* haz cosas */ } Es una abreviatura para i = 0; while (i < MAXVAL) { … /* haz cosas */ i++;} Introducción a la programación en C 13 Funciones Los argumentos de las funciones SIEMPRE se pasan en C por valor = al entrar en la función se copia el valor, la función NO modifica la variable original int i=10; int resultado; main () {… resultado = elevaASiMismo(i); printf ("%d elevado a si mismo es %d", i, resultado); /* i sigue valiendo 10? O vale 100? */ } int elevaASiMismo (int n) { int i, resultado=1; for (i = 0; i < n; i++) { resultado = resultado * n;} n = resultado; return n; } Introducción a la programación en C 14 Funciones int i=10; int resultado; main () {… resultado = elevaASiMismo(i); printf ("%d elevado a si mismo es %d", i, resultado); } int elevaASiMismo (int n) { int i, resultado = 1; for (i = 0; i < n; i++) { resultado = resultado * n;} n = resultado; return n; } Contenido 10 ????? global_i global_resultado Nombre variable Introducción a la programación en C 15 Funciones Contenido 10 ????? global_i global_resultado elevaASiMismo_n 10 Nombre variable elevaASiMismo_i 0, 1, … 1, 10, … elevaASiMismo_ resultado int i=10; int resultado; main () {… resultado = elevaASiMismo(i); printf ("%d elevado a si mismo es %d", i, resultado); } int elevaASiMismo (int n) { int i, resultado = 1; for (i = 0; i < n; i++) { resultado = resultado * n;} n = resultado; return n; } Copia al entrar en la función Introducción a la programación en C 16 Funciones Contenido 10 ????? 10000000000 Nombre variable 9 10000000000 int i=10; int resultado; main () {… resultado = elevaASiMismo(i); printf ("%d elevado a si mismo es %d", i, resultado); } int elevaASiMismo (int n) { int i, resultado = 1; for (i = 0; i < n; i++) { resultado = resultado * n;} n = resultado; return n; } global_i global_resultado elevaASiMismo_n elevaASiMismo_i elevaASiMismo_ resultado Introducción a la programación en C 17 Funciones Contenido 10 10000000000 elevaASiMismo_n Nombre variable elevaASiMismo_i 10000000000 9 100 elevaASiMismo_ resultado return copia valor int i=10; int resultado; main () {… resultado = elevaASiMismo(i); printf ("%d elevado a si mismo es %d", i, resultado); } int elevaASiMismo (int n) { int i, resultado = 1; for (i = 0; i < n; i++) { resultado = resultado * n;} n = resultado; return n; } global_i global_resultado Introducción a la programación en C 18 Funciones A veces quiero que la función PUEDA CAMBIAR el valor de la variable que utilizo al llamarla Porque quiero que la función devuelva varios resultados (y no sólo uno, como permiten las funciones de C en general) Porque quiero que devuelva algún resultado complejo, y las funciones sólo pueden retornar tipos sencillos (int, float…) Para esto utilizo PUNTEROS Los punteros también se utilizan para más cosas (estructuras de datos complejas como listas enlazadas, etc.), … En nuestro proyecto sólo los utilizaremos para pasar/retornar valores al llamar a funciones Introducción a la programación en C 19 Punteros Para cualquier tipo T, podemos formar un ‘puntero a (tipo T)’ El valor del puntero es la primera dirección de la zona de memoria que ocupa la variable de tipo T Ejemplos de declaraciones de punteros: int *i; char *x; Operadores de punteros: * puntero obtiene el valor de un puntero (retorna el valor al que apunta el puntero) & variable obtiene la dirección de una variable (retorna la primera dirección de memoria de la posición en la que está almacenada una variable – la variable no tiene por qué ser un puntero, y en general no lo es) Introducción a la programación en C 21 Punteros int res; int *y; int x; x = 4; y = &x; res = *y+1; /* da 5*/ x++; res = *y+1 /* da 6 */ Dirección 0x300 0x304 Contenido 0x308 4 0x300 No usado x y res 5 Estado en este punto Nombre variable Para los ejemplos, supongo que valores int y punteros ocupan todos 4 bytes. Esto no tiene por qué ser así. Introducción a la programación en C 22 Punteros y Arrays Un identificador de un array es equivalente a un puntero que apunta al primer elemento del array int array[5]; int *ptr; ptr = &array[0] es equivalente a ptr = array; Si una función se define como int func (int *ptr_dato); Entonces también vale llamarla con func(array); Aritmética de punteros y arrays array[2] es igual que *(ptr + 2), El compilador asume que (ptr+2) significa apuntar a 2 objetos del tipo de lo apuntado (int) más allá de ptr Introducción a la programación en C 23 void * void * es un tipo de datos especial que no admite el operador * ni la aritmética de punteros Símplemente, apunta a un sitio Puedo aplicar aritmética de punteros si ‘fuerzo’ un tipo al puntero A esto se le llama hacer un cast void * punt_void; int * numero; punt_void = 0x…; /* apunto a una dirección */ numero = (int *) punt_void + 2; /* apunta a un espacio ‘dos enteros después’ del espacio inicial punt_void */ Introducción a la programación en C 24 ¡Cuidado con los punteros! Valores apuntados inesperados En C, al definir una variables lo que se hace es reservar una zona de memoria para la variable Pero NO se borra el contenido de la variable Puede haber valores previos (distintos de 0) Punteros a zonas erráticas Cuando definimos un puntero, el puntero puede tener un valor Puede apuntar a una zona de memoria reservada para otra cosa, o A una zona de memoria que está prohibida para la aplicación Si accedemos en Linux, vemos error ‘Segmentation fault’ (o ‘Violación de segmento’) Entonces, es mala práctica hacer int *puntero; *puntero = 3; /* escribo un 3… ¡no sé en dónde! */ Precaución: Valor especial de un puntero: NULL (ó 0 ) Indica que el puntero todavía no está apuntado a nada Útil porque… Puedo preguntar al puntero si está apuntando válidamente a algún sitio o no if (puntero == NULL) … Si se referencia (*), da error ‘Segmentation fault’ Al menos, está claro cuál es el problema (pero cuando declaras un puntero… NO se inicializa como NULL – hay que hacerlo explícitamente, si se desea) Introducción a la programación en C 25 Punteros Hay que apuntar el puntero a una zona de memoria que esté asociada de forma única con el uso que queremos dar al puntero Dos formas Declaro variable (creo el espacio) y apunto puntero a variable int a; int *ptrInt; ptrInt = &a; *ptrInt = 7; /* lo escribe en el espacio de la variable ‘a’ */ Crear espacio de memoria dinámica, utilizando llamada al SO: malloc (void *malloc(size_t size) ); Ejemplo char *ptrChar; ptrChar = (char *) malloc (10); /* crea espacio para guardar 10 caracteres */ La memoria dinámica hay que eliminarla antes de terminar el programa (no se elimina automáticamente) free (ptrChar); La memoria dinámica permite definir en tiempo de ejecución espacio de memoria (~ variables) para ser usado por el programa (char *) es un cast – una conversión de tipos explicitada por el programador “compilador, hazme caso porque sé lo que estoy haciendo, supón que el void * que devuelve malloc en realidad es un char *” • Si no hago el cast, el compilador genera un warning • NO queremos warnings Introducción a la programación en C 26 Tamaños de variables A veces necesitamos conocer el tamaño de un tipo o una variable: operador sizeof() tamano = sizeof(int); ¡Puede variar según el equipo! (4, 8…) tamano = sizeof (struct xxx); Devuelve el tamaño ocupado por una estructura struct xxx que habremos definido antes char buffer_1[100]; tamano = sizeof(buffer_1); Devuelve 100 char * buffer_2; buffer_2 = malloc(100); tamano = sizeof (buffer_2); Devuelve…4 bytes, ¡el tamaño del puntero! sizeof no funciona aquí como esperábamos, porque es un operador que se aplica en tiempo de compilación (y el tamaño de buffer_2 se define en tiempo de ejecución) ¡Cuidado en su código con esto! Introducción a la programación en C 27 Copiando memoria #include <string.h> void *memcpy(void *dest, const void *orig, size_t n); Copia n bytes contando a partir de posición de memoria apuntada por orig a posición de memoria apuntada por dest Devuelve un puntero a dest El modificador const de const void * orig indica que la función NO cambia nada en las posiciones de memoria apuntadas por orig (el compilador asegura esto) char *strcpy(char *dest, const char *orig); Espera un string: copia hasta que encuentra un ‘\0’ ¡Bastante distinto a memcpy! Introducción a la programación en C 28 Estructuras Forma de definir variables que tienen diferentes partes (diferentes componentes) struct servicio {int direccion, short int puerto}; struct servicio web; /* variable de tipo struct servicio */ web.direccion = 0xA3758B80; /* 163.177.139.128 en un entero de 32 bits, en formato hexadecimal */ web.puerto = 80; Y con punteros struct servicio *ptrServicio; ptrServicio = &web; if ( (ptrServicio ->puerto) == 80) {ptrServicio->puerto = 8080;} /*cambia a https */ Nota (prtServicio -> puerto) es una abreviatura C de ((*ptrServicio).puerto) Las funciones que manipulan estructuras declaran como parámetros punteros a la estructura Introducción a la programación en C 29 Estructuras C permite ‘tocar’ los bits typedef struct { unsigned int version:2; /* protocol version */ unsigned int p:1; /* padding flag */ unsigned int x:1; /* header extension flag */ unsigned int cc:4; /* CSRC count */ unsigned int m:1; /* marker bit */ unsigned int pt:7; /* payload type */ unsigned int seq:16; /* sequence number */ u_int32 ts; /* timestamp */ u_int32 ssrc; /* synchronization source */ } rtp_hdr_t; rtp_hdr_t miCabecera; /* si no hubiera utilizado typedef, tendria que haber declarado esta variable como struct rtp_hdr_t miCabecera; */ miCabecera.version = 2; miCabecera.pt = 8; /* payload type 8 */ … Introducción a la programación en C 30 Pasando parámetros por referencia struct tiempo { int segundos, int miliseg }; main () { … struct tiempo tiempoAhora; tomaTiempo (&tiempoAhora); } void tomaTiempo (struct tiempo *ptrTiempo) { (*ptrTiempo).segundos = /* accedo a hw…*/; (*ptrTiempo).miliseg = /*…*/ } Direc 0x300 0x304 Contenido 0x308 ??? ??? main_tiempoAhora Nombre variable Introducción a la programación en C 31 Pasando parámetros por referencia struct tiempo { int segundos, int miliseg }; main () { … struct tiempo tiempoAhora; tomaTiempo (&tiempoAhora); } void tomaTiempo (struct tiempo *ptrTiempo) { (*ptrTiempo).segundos = /* accedo a hw…*/; (*ptrTiempo).miliseg = /*…*/ } Direc 0x300 0x304 Contenido 0x308 ??? ??? main_tiempoAhora Nombre variable 0x300 tomaTiempo_ ptrTiempo Introducción a la programación en C 32 Pasando parámetros por referencia struct tiempo { int segundos, int miliseg }; main () { … struct tiempo tiempoAhora; tomaTiempo (&tiempoAhora); } void tomaTiempo (struct tiempo *ptrTiempo) { (*ptrTiempo).segundos = /* accedo a hw…*/; (*ptrTiempo).miliseg = /*…*/ } Direc Contenido 2078 ??? main_tiempoAhora Nombre variable 0x300 tomaTiempo_ ptrTiempo (*ptrTiempo).segundos (*ptrTiempo).miliseg Introducción a la programación en C 33 Pasando parámetros por referencia struct tiempo { int segundos, int miliseg }; main () { … struct tiempo tiempoAhora; tomaTiempo (&tiempoAhora); } void tomaTiempo (struct tiempo *ptrTiempo) { (*ptrTiempo).segundos = /* accedo a hw…*/; (*ptrTiempo).miliseg = /*…*/ } Direc Contenido 2078 389 main_tiempoAhora Nombre variable 0x300 tomaTiempo_ ptrTiempo Introducción a la programación en C 34 Ejemplo de aritmética de punteros Supongamos que queremos construir un paquete RTP para ser enviado: necesito una zona de memoria consecutiva en la que Los 12 primeros bytes sean la cabecera RTP Los 128 (por ejemplo) siguientes bytes sean datos de audio void * paquete; rtp_hdr_t *cabeceraRTP; char * datosAudio; paquete = malloc (140); cabeceraRTP = (rtp_hdr_t *) paquete; (*cabeceraRTP).version = 2; /* relleno cabecera… */ datosAudio = ((char *) paquete) + sizeof (rtp_hdr_t); /* copio datos o llamo a read(…, datosAudio,…) NO sizeof(cabeceraRTP) Introducción a la programación en C 35 Ejemplo de aritmética de punteros void * paquete; rtp_hdr_t *cabeceraRTP; char * datosAudio; paquete = malloc (140); cabeceraRTP = (rtp_hdr_t *) paquete; (*cabeceraRTP).version = 2; /* relleno cabecera… */ datosAudio = ((char *) paquete) + sizeof (rtp_hdr_t); /* copio datos o llamo a read(…, datosAudio,…) Direc Contenido main_cabeceraRTP Nombre variable ??? ??? main_paquete main_datosAudio 0x100 0x100 Introducción a la programación en C 36 Ejemplo de aritmética de punteros void * paquete; rtp_hdr_t *cabeceraRTP; char * datosAudio; paquete = malloc (140); cabeceraRTP = (rtp_hdr_t *) paquete; (*cabeceraRTP).version = 2; /* relleno cabecera… */ datosAudio = ((char *) paquete) + sizeof (rtp_hdr_t); /* copio datos o llamo a read(…, datosAudio,…) Direc Contenido main_cabeceraRTP Nombre variable 0x100 ??? main_paquete main_datosAudio 0x100 0x100 2 *cabeceraRTP Introducción a la programación en C 37 Ejemplo de aritmética de punteros void * paquete; rtp_hdr_t *cabeceraRTP; char * datosAudio; paquete = malloc (140); cabeceraRTP = (rtp_hdr_t *) paquete; (*cabeceraRTP).version = 2; /* relleno cabecera… */ datosAudio = ((char *) paquete) + sizeof (rtp_hdr_t); /* copio datos o llamo a read(…, datosAudio,…) Direc Contenido main_cabeceraRTP Nombre variable 0x100 0x10B main_paquete main_datosAudio 0x100 0x100 2 0x10B char * es como decir ‘puntero a byte’ Introducción a la programación en C 38 printf Permite combinar ‘texto fijo’ con variables Indicación de sustituir por una variable %d - variable de tipo entero, imprimir en formato decimal %s - variable de tipo string (char *, terminado por un caracter ‘\0’) Más formatos disponibles (ver man 3 printf) printf ("Volumen de reproducción: %d. Numero de bits por muestra: %d", vol, bits); Numero variable de argumentos, pero Tiene que haber tantas %_ como variables El tipo indicado en %_ tiene que corresponderse con el de la variable ‘que le toca’ Si hay variables ‘char *’, tienen que ser cadenas de caracteres, es decir, terminar en ‘\0’ Introducción a la programación en C 39 Generando un ejecutable Utilizaremos la herramienta gcc (GNU C Compiler) En realidad, son varias herramientas: Compilador: coge 1 fichero .c y lo convierte en 1 fichero .o que está en formato ‘código objeto’ También ejecuta un preprocesador: sustituye #include… Enlazador: coge uno o varios ficheros .o y los junta en 1 ejecutable (posiblemente, juntando código de otras funciones del sistema – printf, exit, open…) El ejecutable no suele llevar extensión Por motivos de seguridad, el ejecutable lo deberá invocar como ./nombreEjecutable Al compilar, gcc tiene que entender todos los términos que aparezcan en el programa O son variables definidas, o funciones definidas dentro o en un #include… Al enlazar, gcc tiene que encontrar el código (.o o .so) de todas las funciones utilizadas Parte de este código (el de printf, exit, open…) está en ‘librerías’ P.ej, printf está en glibc (/usr/lib…/libc-2.13.so) Si está en glibc, no tengo que decir nada al compilador Si está en otra librería, tengo que decirle el nombre de la librería Ejemplo: log está en libm. Al compilador hay que decirle –lm (= "enlaza con libm") Introducción a la programación en C 40 Escribiendo código Puede escribir su código en varios ficheros Facilita que varias personas trabajen en el mismo programa En su caso, yo doy varios ficheros hechos! Facilita reutilizar código Se puede utilizar fácilmente algunas funciones en otros programas Permite estructurar mejor el código Cuando se utilizan varios ficheros En *.h se ponen la declaración de las funciones Se pueden definir tipos, constantes… siempre que sean importantes para otros ficheros que vayan a utilizar estas funciones En *.c se pone la cabecera de la función (otra vez)… y el código que lo hace (de verdad) Si un fichero uno.c utiliza funciones de otro dos.c, uno.c tiene que tener un #include dos.h Puede compilar cada .c por separado gcc –c fichero.c -- genera un fichero.o Sólo puede haber 1 main entre todos los ficheros Cuando están todos los .o disponibles, se pueden enlazar en un ejecutable gcc –o ejecutable fich1.o fich2.o fich3.o … Introducción a la programación en C 41 Compilando Usuarios avanzados utilizan make Pero NO merece la pena ‘pegarse’ con él Alternativa Cree un fichero compila que contiene una línea gcc –o audioSimple audioSimple.c audioSimpleArgs.c configureSndcard.c … -Wall -lm Todos los .c que necesita -Wall: chequeo más estricto -lm: enlazar con librería matemática En audioSimple no hace falta, pero puede hacerle falta; no hace daño Ejecute # chmod 755 compila Cada vez que quiera compilar, # ./compila Introducción a la programación en C 44 Si quiero utilizar una función ‘estándar’… ¿cómo sé qué argumentos toma y que valores devuelve? ¿cómo sé qué fichero tengo que incluir? Ejecutar ‘man funcion’ man exp También se detalla cómo se usa la función Introducción a la programación en C 45 Sobre #include Si se quiere incluir una cabecera estándar, utilizar #include <cabecera.h> El compilador sabe en qué directorios buscar estas cabeceras Si se quiere incluir una cabecera desarrollada por nosotros #include "cabecera.h" Si está en el mismo directorio que el fichero que lo incluye #include "/home/…/cabecera.h" Si está en otro directorio que el fichero que lo incluye Introducción a la programación en C 46 Capturando argumentos de la línea de comandos ¿Cómo sabe el programa que al llamar a conf utilicé los argumentos second –y11 163.117.144.10? C dice que en la función main se define como int main (int argc, char *argv[]) ‘mágicamente’, cuando el código se ejecute, en la variable argc y argv está la información para recuperar los argumentos No damos valor a estas variables, sino que el valor sale de ‘la ejecución’ Introducción a la programación en C 47 Capturando argumentos de la línea de comandos ESTO NO LO TENEIS QUE HACER VOSOTROS Ya lo damos hecho (pero…) La función main está declarada como int main (int argc, char *argv[]) { ... } Tipo de argv se ‘lee’ aplicando la regla de ‘apretar el tornillo’ Declaraciones complejas se pueden analizar con herramienta cdecl (o en web http://www.lemoda.net/c/cdecl/ $ cdecl explain char *argv[] declare argv as array of pointer to char aunque main también se puede utilizar como int main (void) C es muy estricto con las declaraciones… ¡salvo con las de main! El intérprete de la línea de comandos deja en argc el número de argumentos del comando argv un puntero a un array de punteros a strings argv[0] es el nombre de programa, con que argc es siempre al menos 1. http://www.lemoda.net/c/cdecl/ Introducción a la programación en C 48 Capturando argumentos de la línea de comandos ./audiosimple play –v100 music argc = 4, argv = <direcc 0> ‘a’‘u’‘d’‘i’‘o’‘S’‘i’‘m’‘p’‘l’‘e’‘\0’ argv: [0] <dir 1> [1] <dir 2> [2] <dir 3> [3] <dir 4> [4] NULL ‘-’‘v’‘1’‘0’‘0’‘\0’ ‘p’‘l’‘a’‘y’‘\0’ ‘m’‘u’‘s’‘i’‘c’‘\0’ Introducción a la programación en C 49 Ejercicio: compilar práctica 0 Analizar el código de los ficheros audioSimpleArgs.h y audioSimpleArgs.c __MACOSX/Parte1/._01.5 - programación en C.pdf Parte1/02-programacion - parte 1.pdf Técnicas de programación de software multimedia (parte 1) Técnicas de programación de sw multimedia 2 Acceso a los dispositivos en Linux Abstracción común para los dispositivos en Linux (Unix): los dispositivos aparecen como ficheros En /dev/… Nota: algunos dispositivos también pueden ser accesibles a través de APIs (posiblemente con “más capacidades” o “más fácilmente” que con el interfaz de ficheros) Los ficheros tienen unas operaciones comunes: open, close read, write ioctl La semántica de las operaciones se adapta a cada dispositivo Pensar en disco duro, línea serie, control de un LED, … tarjeta de sonido Técnicas de programación de sw multimedia 3 Tarjeta de sonido Output Mixer Input Mixer Conversor D/A Conversor A/D Sintetizador FM CD-ROM Bus /dev/dsp /dev/sequencer /dev/cdrom /dev/dsp /dev/dsp (o /dev/mixer) /dev/dsp (o /dev/mixer) analógico analógico analógico digital Técnicas de programación de sw multimedia 4 Tarjeta de sonido (para nosotros) Output Mixer Input Mixer Conversor D/A Conversor A/D /dev/dsp /dev/dsp /dev/dsp (o /dev/mixer) /dev/dsp (o /dev/mixer) Técnicas de programación de sw multimedia 5 Referencias para programación de tarjeta de sonido Referencia para programar tarjeta de sonido según API de OSS (Open Sound System): http://www.4front-tech.com/pguide/index.html Definiciones en fichero soundcard.h Ejecuta locate soundcard.h para saber dónde está Técnicas de programación de sw multimedia 7 Dispositivo /dev/dsp /dev/dsp: conversión analógica/digital (muestreo y cuantificación) y digital/analógica Generalmente hay UN dispositivo en un equipo Sólo puede tenerlo abierto UN programa a la vez Programas que lo necesitan esporádicamente lo abren, lo usan, y lo cierran inmediatamente read obtiene datos del conversor analógico/digital (= graba datos) write vuelca datos en el conversor digital/analógico ( = reproduce datos) Técnicas de programación de sw multimedia 8 Dispositivo /dev/dsp ioctl a /dev/dsp permite configurar los parámetros básicos de funcionamiento de la tarjeta Frecuencia de muestreo (8000 Hz, 44100 Hz) Número de canales (1, 2, 5.1) Formato de la muestra para cada canal Número de bits por muestra (8 o 16 bits) Tipo de codificación (uniforme o con algún tipo compresión) Puede hacerse por software o por hardware Los parámetros usados al ejecutar read o write son los últimos configurados en el dispositivo /dev/dsp = la tarjeta de sonido mantiene estado Lógica hardware de 32 bits 16 bits 16 bits Ejemplo de grabación de dos canales de 16 bits cada uno 0111000011011011 0001110000101011 Técnicas de programación de sw multimedia 9 Fragmentos La tarjeta dispone de una zona de memoria interna Esta memoria está gestionada en bloques de igual tamaño llamados “fragmentos” El tamaño del fragmento es configurable, aunque debe ser potencia de 2 128, 256, 512 … bytes Interesante configurar explícitamente el tamaño de los fragmentos si trabajamos con select y la aplicación es sensible a los bloqueos Técnicas de programación de sw multimedia 10 Bloqueos en la tarjeta de sonido Lectura (read) esporádica: el proceso solicitante se bloquea hasta obtener la cantidad de datos correspondiente al un número de fragmentos necesarios para obtener esa cantidad de datos No hasta obtener los datos, sino más (si el fragmento > datos solicitados)! Mínimo tiempo de bloqueo si el número de datos que se solicita en el read es igual que el tamaño del fragmento read(256) fragmento 256 bytes proceso bloqueado read(256) fragmento 256 bytes programa Kernel (driver tarjeta…), otras tareas… tarjeta de sonido Interrupción (hw) Interrupción (hw) Retorna read(256) Retorna read(256) Técnicas de programación de sw multimedia 11 Bloqueos en la tarjeta de sonido Lectura si el tamaño solicitado es distinto del tamaño del fragmento Ej: tamaño de fragmento = 128 bytes. Se solicita lectura de 230 bytes Tarjeta bloquea durante el tiempo necesario para leer 2 fragmentos de 128 bytes (=256 bytes, potencia de 2 inmediatamente superior a 230 bytes) La operación de lectura devuelve 230 bytes read(230) fragmento 128 bytes proceso bloqueado programa Kernel (driver tarjeta…), otras tareas… Interrupción (hw) Tiempo requerido para 230 bytes Retorna read(230) tarjeta de sonido Técnicas de programación de sw multimedia 12 Bloqueos en la tarjeta de sonido No obstante, si la lectura es frecuente, y la cantidad de datos solicitados es menor que un fragmento, la tarjeta devuelve datos que habían sido leídos con anterioridad Ej: fragmento 256 bytes, lecturas (read) que solicitan 128 bytes En este caso, algunas lecturas no son bloqueantes No obstante, conviene evitar este funcionamiento: para el tipo de aplicaciones que queremos, introduce un retardo indeseado (algunas lecturas de 128 bytes tardan como leer 256) read(128) fragmento 256 bytes proceso bloqueado read(128) fragmento 256 bytes programa Kernel (driver tarjeta…), otras tareas… Interrupción (hw) Interrupción (hw) read(128) – no bloquea y recibe datos leídos justo antes Retorna read(128) tarjeta de sonido Lectura frecuente Técnicas de programación de sw multimedia 13 Bloqueos en la tarjeta de sonido La escritura es no bloqueante: mientras haya memoria suficiente en la tarjeta de sonido La escritura es bloqueante si la memoria de la tarjeta de sonido asociada a escritura está llena, en cuyo caso bloquea El proceso se desbloquea cuando hay memoria suficiente para almacenar los datos de la solicitud de escritura Técnicas de programación de sw multimedia 14 Modo dúplex Modo Dúplex: La tarjeta puede grabar y reproducir A LA VEZ Ej: el código puede hacer un read e inmediatamente después un write… y la tarjeta graba y reproduce simultaneamente Nota: si el ‘ancho’ del conversor A/D, D/A es de 32 bits, cada sentido sólo puede disponer de 16 bits, limitando las opciones a 1 canal de 16 bits 2 canales de 8 bits Lógica de 32 bits 16 bits 16 bits 0111000011011011 0001110000101011 Técnicas de programación de sw multimedia 20 /* Truco de programación */ Comprobar siempre resultados de llamadas al Sistema Operativo ¡pueden haber salido mal! Habitualmente, las llamadas que salen mal devuelven -1 Leer siempre la página de manual de la llamada, para ver cómo se codifica el éxito o fallo en la llamada al SO (si devuelven un puntero, el error se notifica devolviendo NULL) Automatizando el chequeo del éxito en llamadas al SO Macro C que comprueba si una llamada al SO devuelve -1 => mensaje de error y detiene la ejecución de la función #define CALL(v,m) {if ( (v)==-1) {perror (m); printf (“Error number: %d, %s\n", errno, strerror (errno)); exit (1); }}; Ejemplo de uso CALL (callX (argumento1, argumento2..), “La llamada a callX fracasó después de haberse ejecutado…”); Técnicas de programación de sw multimedia 21 Configurando parámetros int ioctl_arg; /* argumentos para ioctl */ /* abrimos dispositivo de audio */ CALL ( (descSnd = open("/dev/dsp", O_RDWR), "Fallo en apertura de /dev/dsp“ ); /* fijar parametros de muestreo */ ioctl_arg = formato; /* Ej: 8 es PCM (con cuantificación lineal de 8 bits); 16 es PCM con 16 bits little endian con signo; ver /usr/include/linux/soundcard.h para más posibilidades */ CALL( ioctl(descSnd, SNDCTL_DSP_SETFMT, &ioctl_arg), “Fallo en establecimiento del formato de grabac/reproduc” ); if (ioctl_arg != formato) perror("Imposible seleccionar codificación pedida"); ¡Comprobar si la tarjeta hizo lo que se le pedía! Técnicas de programación de sw multimedia 22 Configurar parámetros conversión A/D y D/A: ioctl… SNDCTL_DSP_SETFMT – número de bits por muestra y codificación (ver soundcard.h para qué codificaciones) SNDCTL_DSP_CHANNELS – número de canales SNDCTL_DSP_SPEED – frecuencia de muestreo Duplex: CALL (ioctl (descSnd, SNDCTL_DSP_SETDUPLEX, 0), "Fallo al poner la tarjeta de sonido en modo DUPLEX"); Configurando el volumen CALL (ioctl (descSnd, MIXER_WRITE (SOUND_MIXER_MIC), &volFinal), "Fallo en onfiguración volumen del microfono"); volFinal: 8 bits más signif= canal derecho / 8 menos significativos canal izquierdo CALL (ioctl (descSnd, MIXER_WRITE (SOUND_MIXER_PCM), &volFinal), "Fallo en configuración volumen de la salida"); Programando la tarjeta de sonido Técnicas de programación de sw multimedia 23 Programando la tarjeta de sonido: tamaño de fragmento Ajustar el tamaño del fragmento al tiempo de respuesta requerido por la aplicación La llamada al ioctl que ajusta el tamaño de los fragmentos tiene que hacerse ANTES de otros ioctls, read, write… Si se quiere cambiar el tamaño del fragmento, hay que cerrar y abrir otra vez el dispositivo Datos: requestedFragmentSize es el número de bytes que se quieren manejar en la tarjeta. Código obtiene tamaño en bytes que es potencia de 2 inmediatamente inferior al solicitado (función logaritmo). Configura tarjeta para que el fragmento sea de ese tamaño Es decir, Si queremos tamaño de fragmento 32, hay que utilizar 5 como argumento Tamaño de fragmento 64, hay que utilizar 6 como argumento Tamaño de fragmento 43… tendremos que poner 5, y el tamaño de fragmento real será 32 (argumento=5) Referencia: http://www.4front-tech.com/pguide/audio2.html Técnicas de programación de sw multimedia 24 Programando la tarjeta de sonido void configSndcard (int *descSnd, struct structSndQuality *datosQosSnd, int *requestedFragmentSize) { unsigned int frgmArg, requestedFrgmArg; /* local variables for fragment conf */ /* Argument to construct: 0xMMMMSSSS , being MMMM fragments (MMMM=number of fragments) of size 2^SSSS (SSSS= log2 of the size of the fragments. We set the size of the fragments, and we do not request anything about the number of fragments */ requestedFrgmArg = floor_log2 (*requestedFragmentSize); /* floor_log2 is defined at the end of this file. Sets ‘SSSS’ part of fragment argument */ requestedFrgmArg = requestedFrgmArg | 0x7FFF0000 ; /* this value is used to request the soundcard not to limit the number of fragments available. Sets ‘MMMM’ part of fragment argument */ frgmArg = requestedFrgmArg ; CALL (ioctl ( (*descSnd), SNDCTL_DSP_SETFRAGMENT, & frgmArg ), "Failure when setting the fragment size\n"); if (frgmArg != requestedFrgmArg ) { printf ("Fragment size could not be set to the requested value: requested argument was %d, resulting argument is %d\n", requestedFrgmArg, frgmArg); exit (-1);} /* returns configured fragment value, in bytes, so it performs 2^frgmArg by shifting one bit the appropriate number of times */ * requestedFragmentSize = 1 << frgmArg; /* returns actual configured value of the fragment size, in bytes*/ } Referencia: http://www.4front-tech.com/pguide/audio2.html Técnicas de programación de sw multimedia 25 Programando la tarjeta de sonido: datos en el buffer de escritura int bytes; ioctl(soundcard, SNDCTL_DSP_GETODELAY, &bytes); Indica el número de bytes que quedan por reproducir en la tarjeta de sonido en el momento en el que se hace la llamada Convertir en segundos= bytes / (sample_rate * num_of_channels * sample_size_in_bytes) Técnicas de programación de sw multimedia 27 Reproductor/Grabador de Audio fich = open (“FicheroAudio”,... tarjeta = open (“/dev/dsp”, ... while ( ) { numLecturas = read (fich, datos, 4096); numEscrituras= write (tarjeta, datos, 4096); } audioSimple play / record ... (bits, estereo, duración, frecuencia ...) Buffer En la página de web hay un programa sencillo para grabar y reproducir audio (ver Práctica 0) __MACOSX/Parte1/._02-programacion - parte 1.pdf Parte1/03-practica_conf.pdf Introducción a la práctica: conf Introducción a las prácticas de SMA 2 Prácticas introductorias Práctica 0: probar herramientas básicas para el desarrollo de las siguientes prácticas Sobre todo, LEER transparencias de programación, y código Familiarizarse con el funcionamiento y programación de la tarjeta de sonido Práctica 1: pruebas más exhaustivas de funcionamiento de la tarjeta de sonido Ejemplo de cómo analizar el comportamiento de un dispositivo o herramienta de programación Ni Práctica 0 ni Práctica 1 generan ningún resultado evaluable Introducción a las prácticas de SMA 3 Aplicación conf Aplicación de audioconferencia Tarjeta de sonido en modo duplex Dos modos en la aplicación para permitir el inicio de comunicación Modo first (primero – en ser arrancado desde la línea de comandos), espera a recibir datos de algún nodo (no tiene por qué conocer su dirección). Cuando recibe el primer dato, “aprende” qué dirección IP tiene su interlocutor, y le empieza a enviar a datos Modo second (segundo), directamente datos a una dirección especificada en la línea de comandos Podría ser utilizada en entorno multicast Aunque cada aplicación está preparada para tener sólo un vecino ¡No se puede utilizar TCP! Introducción a las prácticas de SMA 4 Aplicación conf Dos formas de arrancar first y second Comunicación unicast equipo1> ./conf first equipo2> ./conf second 163.117... First escucha en multicast equipo1> ./conf first –m227.1… equipo2> ./conf second 227.1… conf, escucha en dir unicast conf, escucha en dir multicast rtpdump, escucha en dir multicast Introducción a las prácticas de SMA 5 Aplicación conf T viene determinado por el formato y el tamaño del paquete first second T T T T T T T T Espera x paquetes (buffer) y comienza reproducción ./conf primero … ./conf segundo formato tamanho paquete… Introducción a las prácticas de SMA 6 Aplicación conf Es necesario desacoplar 1. Recepción de paquetes de audio 2. Reproducción de los paquetes de audio recibidos 3. Grabación y envío de audio local 4. Generación y envío de mensajes RTCP 5. Recepción y tratamiento de mensajes RTCP Cualquier retardo en los 3 primeros procesos resulta en un retardo que puede hacer que un contenido no se pueda reproducir en su momento Para desacoplar recepción de paquetes y reproducción (1 y 2) se utiliza select + buffer circular Lee paquetes de la red y los deja en el buffer circular Lee paquetes del buffer circular y los deja en la tarjeta de sonido Introducción a las prácticas de SMA 7 Aplicación conf Su aplicación se debe encargar de construir la cabecera RTP en el envío de paquetes Rellena estructura en C Lee los datos de la tarjeta de sonido, y los deja a continuación El mensaje resultante es empaquetado con UDP y IP Esta tarea la realiza el SO, a través de la interfaz de sockets (haciendo sendto) Puerto estándar para RTP=5004; puerto estándar para RTCP=5005 La tarjeta de red añade por hardware la cabecera y la cola para Ethernet RTP Datos (audio) UDP IP Eth. Eth. Generado por su código Introducción a las prácticas de SMA 8 Aplicación conf Optimice la reproducción configurando los fragmentos de la tarjeta de sonido De esta forma se evitan añadir retardos innecesarios Implemente
Compartir