Resource Interchange File Format

Resource Interchange File Format

El Resource Interchange File Format o RIFF es un formato contenedor genérico diseñado para almacenar datos en forma de fragmentos etiquetados o chunks. Siendo usado en la actualidad como formato contenedor de los conocidos formatos de archivo AVI, ANI y WAV de Microsoft, es indudable que resulta especialmente útil para almacenar contenidos multimedia, aunque realmente puede almacenar cualquier tipo de información.

Tipos de fragmentos

Hay dos tipos de fragmentos en un archivo RIFF. El más básico son los chunks o fragmentos de datos propiamente dichos:

struct Chunk
{
    uint32_t type;
    uint32_t size;
    uint8_t  data[size];        // contiene datos en general
};

donde type sirve para identificar el tipo y el formato de los datos que almacena el fragmento y size para especificar su tamaño —sin incluir ni el tamaño del campo type ni el de size—.

El otro tipo de fragmento son las listas:

struct List
{
    uint32_t type;
    uint32_t size;
    uint32_t listType;
    uint8_t  data[size-4];      // contiene otros Chunk o List
};

que son aquellos que contienen una colección de otros fragmentos o listas:

  • Las listas se identifican y distinguen de otros fragmentos porque su campo type contiene o los 4 caracteres de RIFF o los de LIST. Pero hay que tener en cuenta que si bien en el archivo se almacenan en type los caracteres 'R', 'R', 'I', 'F' en ese orden, hay que tener en cuenta que al interpretarlo como uint32_t en una máquina little-endian no veremos el número 0x52494646 sino 0x46464952.

  • Para este tipo de fragmentos, el tamaño en el campo size incluye tanto el de los datos almacenados dentro del fragmento como el del campo listType.

  • Dentro de la lista los fragmentos que contiene se disponen unos detrás de otros, pero siempre asegurando que cada fragmento comienza en una dirección par — es decir, que se alinean a 16 bits — .

El archivo contenedor en sí mismo es un gran fragmento de lista tipo RIFF que contiene otros fragmentos. Estos pueden ser chunks o listas de tipo LIST. Por lo tanto, en una archivo RIFF solo existe una lista de este tipo, que hace las veces de contenedor de todos los fragmentos del archivo. El valor del campo listType del fragmento RIFF es una secuencia de 4 bytes que identifica el formato del archivo y se lo conoce como el FourCC del mismo.

Estructura general

Para hacernos una idea del formato, este sería el esquema de un archivo AVI convencional:

RIFF ('AVI '
      LIST ('hdr1'
            AVIH (<cabecera principal del AVI>)
            LIST ('str1'
                  STRH (<cabecera del flujo>)
                  STRF (<formato del flujo>)
                  ...
            )
            ...
      )
      LIST ('movi'
            {Chunk | LIST ('rec '
                           Chunk1
                           Chunk2
                           ...
                     )
             ...
            }
            ...
      )
      [IDX1 (<índice AVI>)]
)

Donde los identificadores en mayúsculas denotan el valor del campo type al comienzo de un fragmento. Este siempre es seguido por el campo size, que no se muestra en el esquema anterior. Por otro lado, el valor de los campos listType de los fragmentos de tipo lista se indica entre comillas simples. Para observar una estructura real de archivo RIFF se puede utilizar el programa rifftree del paquete gigtools con cualquier archivo .avi o .wav que tengamos a mano.

Mi rifftree

Para ilustrar lo comentado sobre los archivos RIFF, he publicado en GitHub mi propia versión de rifftree. Está desarrollada con Qt y hace uso del mapeo de archivos en memoria para simplificar el acceso al archivo RIFF.

Referencias