Introducción

Un descodificador compatible con DVBIPTV para recibir información básica necesaria para su funcionamiento, tal y como la lista de proveedores de servicio (SP Discovery Information), o la información de un SP concreto (Service Discovery Information), lo que incluye, por ejemplo, la lista de canales o la lista de paquetes.

La recepción de la información se puede hacer mediante un modelo pull (petición bajo demanda) o push. Un decodificador debe admitir ambas formas de recibir la información.

Para implementar el modelo push bajo IP DVB define un protocolo para la recepción de archivos XML utilizando multicast. El protocolo se llama DVB SD&S Transport Protocol, o DVBSTP. Aunque diseñado para recibir XML, el protocolo admite perfectamente otros formatos, incluso puros datos binarios.

Funcionamiento

La terminología que se utiliza en los estándares suele ser un poco «confusa», así que en este documento utilizaremos nombres «normales», fáciles de entender, junto con sus correspondientes nombres «técnicos».

A diferencia de una conexión TCP/IP (recepción de datos en modo pull), en multicast (UDP) existe un límite en la cantidad de información que se puede recibir de una sola vez (determinada normalmente por la MTU de la conexión). Por tanto, y dado que la información que hay que recibir es un flujo de datos de longitud variable, y que no disponemos de un protocolo orientado a conexión (como es TCP), es necesario crear un mecanismo que nos permita enviar archivos (registros o records) de diferente tamaño mediante su envío en fragmentos (datagramas UDP).

El escenario

El decodificador necesita recibir tanto diferentes categorías de archivo, como, dentro de cada categoría, diferentes archivos con contenidos diferentes. Además, necesita saber si alguno de los archivos ha cambiado para poder actuar en consecuencia.

DVBSTP define, precisamente, como realizar el envío y recepción de datos de longitud variable (normalmente archivos XML) de forma sencilla. A diferencia de TCP, corresponde al programa realizar la ordenación de los fragmentos recibidos. De igual modo, DVBSTP permite recibir en un único datastream multicast diferentes tipos de archivos, de diferentes longitudes cada uno, sin «mezclarse» mediante multiplexación.

La terminología

En terminología DVB, un archivo de datos se denomina registro (record).

Cada categoría de archivo viene identificado por un Payload ID. La tabla 2 especifica las diferentes categorías de archivos.

Los archivos pueden tener un «nombre», que se especifica mediante un identificador de segmento (Segment ID), que es un número de 16 bits (2 bytes). Así, dos archivos con el mismo Segment ID y diferente Payload ID son archivos diferentes.

El «nombre» (identificador de segmento) y lo que ello significa depende de cada categoría de archivo.

Al ser limitada la cantidad de información que puede llevar un datagrama UDP, resulta necesario «trocear» o dividir el archivo en diferentes fragmentos. A cada «fragmento» se le denomina sección (section) y cada una tiene su propio Section Number. Los números de sección siempre comienzan en 0 y son correlativos.

Por último, y dado que la información contenida en los archivos XML (registros) puede variar a lo largo del tiempo, DVBSTP añade un mecanismo de versionado. Cada versión concreta de un registro (record) determinado se especifica en el Segment Version.

La versión es un número de 0 a 255. Cada vez que cambia el contenido del archivo, el número de versión se incrementa. Si el número de versión supera 255 se comienza de nuevo en 0.

El flujo de datos multicast

En un flujo de datos DVBSTP nos podemos encontrar con fragmentos (section) que corresponden a diferentes categorías de archivo (Payload ID), diferente «nombre» (Segment ID) y diferente versión.

Cada servidor tiene su propio ritmo de envío de datagramas. Algunos flujos son muy lentos (menos de un datagrama por segundo) o muy rápidos. A la hora de enviar los fragmentos, la especificación no explicita que deben mandarse seguidos todos los fragmentos de un determinado registro. Pueden enviarse «salteados», repetirse con más o menos frecuencia, etc.

Por tanto: no debe asumirse que los paquetes de datos llegan con ningún orden concreto.

Incluso es posible encontrar que se están publicando (push) archivos de varios proveedores de servicio (SP, Service Provider) de forma «simultánea».

Ejemplo de flujo

Para simplificar, especificaremos de cada datagrama los campos más importantes (Payload ID, Segment ID, version, section y último número de sección) mediante la nomenclatura P00 S0000 V00: n/nn. Los números se especifican en hexadecimal.

#1: P01 S0000 VF0: 1/2
#2: P01 S0000 VF0: 2/3
#3: P02 S0000 V80: 2/4
#4: P02 S0000 V80: 3/4
#5: P01 S0000 VF0: 0/2
#6: P05 S30C0 V05: 2/4
#7: P05 S30D0 V05: 1/6

Así, vemos que se envían archivos de 3 categorías diferentes (0x01, 0x02 y 0x05) y con las siguientes características:

Categoría
Payload ID
«Nombre»
Segment ID
Total de
fragmentos
Fragmentos
recibidos
0x010x000040, 1 y 2
0x020x000052 y 3
0x050x30C052
0x30D071

Implementación abstracta de un receptor de datos DVBSTP

Pseudocódigo básico

Socket.Open socket
Socket.Join socket, multicast_address
WHILE TRUE
    LET datagram = Socket.Receive socket
    LET header = ParseHeader datagram
    IF AcceptSection header THEN
        SaveSection datagram, header
    END IF
    IF ExitLoop THEN
        BREAK WHILE
    END IF
END WHILE
Socket.Close socket

La función ParseHeader extrae todos los valores de la cabecera y el CRC y los devuelve en una estructura de datos.

La función AcceptSection permite realizar un «filtrado» según la información de la cabecera, para descartar, por ejemplo, payloads determinados o provenientes de un determinado SP.

La función ExitLoop determina si se dan las condiciones necesarias para dejar de recibir información del datastream multicast. Por ejemplo, si se quiere «descargar» un determinado Payload ID con un Segment ID concreto, una vez recibidas todos los fragmentos (sections) correspondientes, devolvería TRUE para finalizar el bucle de recepción.

Implementación recomendada de SaveSection

Vamos a asumir el caso generalizado, en el que se quieren «descargar» todos los registros que se envían en un determinado flujo.

El elemento básico es el «ensamblador» de secciones, una estructura de datos que almacenará cada una de las secciones que se reciban de un determinado Payload/SegmentID y que, una vez recibidos todas las secciones (fragmentos), las une de forma ordenada para obtener el registro.

Otro elemento es el «contenedor» de ensambladores, una estructura de datos que almacenará «ensambladores» de secciones correspondientes a un determinado SegmentID.

Por último, tenemos el «contenedor» de registros, una estructura de datos que almacenará contenedores de ensambladores correspondientes a un determinado PayloadID.

Cada vez que se recibe un datagrama:

  • Se busca en el contenedor de registros el contenedor de ensambladores para el Payload ID recibido, creando uno si es necesario.
  • Se busca en el contenedor el ensamblador para el Segment ID recibido, creando uno si es necesario. Como se sabe de antemano el número de secciones de que constará el par Payload/SegmentID, puede reservarse memoria al crear un ensamblador nuevo.
  • Si el número de versión del ensamblador es diferente, se descartan todos los fragmentos recibidos (section).
  • Se guarda la información contenida en el datagrama en el ensamblador en el hueco correspondiente al número de sección, reescribiendo en caso de ser necesario.

Estructura del datagrama UDP

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver|Resrv|Enc|C| Total Segment Size                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload ID    | Segment ID                    |Segment Version|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Section_Number        | Last Section Number   |Compr|P|HDR_LEN|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (Conditional) IPv4 ServiceProviderID                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: (Optional) Private Header Data                                :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| : payload :                                                   |
|                                                               |
|                                               +-+-+-+-+-+-+-+-+
|                                               |(Optional) CRC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (Optional) CRC (Cont)                         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Descripción de los campos

CampoOffsetLongitudDescripción
Version02 bitsLa versión del protocolo.
Ver tabla 1 para valores válidos.
Reserved23 bitsReservado. Debe ser «000».
Encryption52 bitSe utiliza para señalar la presencia de cifrado. El valor «00» indica que los datos (payload) no está encriptada.
La sintaxis, la semántica, el comportamiento y el significado de otros valores no están definidos.
CRC flag71 bitSi el valor es «1», esto indica la presencia de un CRC de 32 bits al final del paquete.
Este flag (bandera) solo se establecerá en el paquete final de un segmento, es decir, cuando Section number es igual a Last section number.
Total segment size824 bitsCuando no hay compresión (el campo Compression es «000»), especifica el tamaño total del segmento.
O lo que es lo mismo, el tamaño acumulado de todas los datos útiles de todas las secciones que comprenden el segmento.
Payload ID328 bitsIdentifica el tipo de datos que se transportan dentro del payload.
Ver tabla 2 para valores posibles.
Segment ID4016 bitsIdentificador del segmento de datos para ID de datos declarado.
Por ejemplo, pueden existir varios registros de Broadcast Discovery Information, y cada uno será asignado un ID único.
Segment version568 bitsDefine la versión actual del segmento que se transporta.
Cuando los datos de un segmento cambian, se mantienen los identificadores de segmento (segment ID) y de datos (payload ID) y se aumenta el campo de versión.
La versión del segmento es módulo 256.
Section number6412 bitsIdentifica el número de sección (o fragmento).
La primera sección siempre empieza en 0.
Last section number7612 bitsEspecifica el último número de sección del segmento.
O lo que es lo mismo, el número de secciones menos 1.
Compression883 bitsIndica si los datos (payload) están comprimidos o no y el tipo de compresión.
Ver tabla 3 para valores posibles.
Todos los segmentos de un determinado tipo de datos (payload ID) deben usar el mismo tipo de compresión.
P flag911 bitIndica si el campo Service Provider ID está presente o no.
Private header
length
924 bitsIndica si existen datos de cabecera privado, y su longitud en el número de palabras de 32 bits (ejemplo 96 bits se indica con «0011» (3).
Si no se envían datos de encabezado adicionales, este tendrá el valor «0000».
Service Provider ID96???La dirección IP que identifica al proveedor de servicios al que pertenecen los datos.
Permite filtrar los paquetes recibidos sin tener que decodificar los datos.
Para IPv4 son 32 bits y 128 bits para IPv6.
Private header
data
96 + ????Datos de cabecera privados. Este campo será un múltiplo de 4 bytes.
El significado, la sintaxis, la semántica y el uso de estos datos están fuera del alcance del estándar.
Payload96 + ????La carga útil del paquete (datagrama).
Siempre es un número entero de bytes (8, 16, 32, … bits) y la longitud puede ser cero.
CRC32 bitsUn valor CRC de 32 bits. El CRC se calcula utilizando el algoritmo estándar de CRC especificado en ISO/IEC 13818-1, annex A, sobre el total de los datos útiles (payload) recibidos.

Tabla 1: Versión del protocolo

ValorSignificado
00El identificador del SP es una dirección IPv4
01El identificador del SP es una dirección IPv6
10 a 11Reservado

Tabla 2: Payload ID

ValorSignificado
0x00Reservado
0x01SD&S Service Provider Discovery Information
0x02SD&S Broadcast Discovery Information
0x03SD&S COD Discovery Information
0x04SD&S Services from other SPs
0x05SD&S Package Discovery Information
0x06SD&S BCG Discovery Information
0x07SD&S Regionalization Discovery Information
0x08FUS Stub file and SD&S RMS-FUS record
0x09SRM announcement Information
0x0A a 0x0FReservado
0xA1 a 0xAFBCG Payload ID. Referir a ETSI TS 102 539.
0xB0Reservado
0xB1CDS XML download session description
0xB2RMS-FUS Firmware Update Announcements. Referir a ETSI TS 102 824.
0xB3 a 0xBFReservado
0xC0Reservado
0xC1Application Discovery Information
0xC2 a 0xCFReservado
0xD0 a 0xDFReservado
0xE0 a 0xEFReservado
0xF0 a 0xFFUser private
El significado, la sintaxis, la semántica y el uso de estos datos están fuera del alcance del estándar.

Tabla 3: Compresión

ValorSignificado
000Sin compresión
001BiM (Binary MPEG format for XML)
010GZIP
011 a 101Reservado
110Reservado para uso de ITU-T
111Uso privado

p

La presente información está extraída y redactada del documento de especificación técnica (TS) de la ETSI (European Telecommunications Standards Institute) número 102 034 («Transport of MPEG-2 TS Based DVB Services over IP Based Networks»), capítulo 5 (Service discovery), sección 5.4 (Transport mechanisms), apartado 5.4.1 (Protocol for multicast delivery of SD&S information).

Se puede consultar este documento (versión 2.1.1, de fecha 2016-04-07). en www.etsi.org.