17 April, 11:08pm

El uso de los buffers en la especificación del OMX

Un componente, de manera simplificada, tiene dos puertos: uno de entrada y otro de salida. El puerto de entrada recibe datos a procesar y el de salida entrega datos procesados. Cuando estamos en el estado de Executing los buffers son intercambiados de la siguiente manera:

En el buffer de entrada:

  1. OMX_EmptyThisBuffer le dice al puerto que el buffer especificado tiene información a procesar.
  2. El buffer es procesado por el componente y se entrega su información al buffer del puerto de salida.
  3. El OMX avisa al programa cliente, a través de la retrollamada EmptyBufferDone, que el buffer ya fue procesado y lo puede volver a utilizar.

En el buffer de salida:

  1. La retrollamada de OMX FillBufferDone avisa al programa cliente que el buffer ya fue procesado por el componente y que tiene información nueva.
  2. La información del buffer es extraída.
  3. OMX_FillThisBuffer le dice al puerto que ya se le extrajo la información al buffer y lo puede volver a utilizar.

Esto es básicamente, en ambos casos, un buffer circular, o, desde otra perspectiva, una cola de buffers asíncrona.

image0

image1

Ahora, esto sólo ocurre en los puertos que son proveedores de buffers (alojan de manera explícita cada uno de ellos). Cuando son puertos dentro de un túnel, el comportamiento es distinto, ya las llamadas OMX_FillThisBuffer y OMX_EmptyThisBuffer no deben ser llamadas dado que son movidas internamente en el túnel.

GOmx empuja los buffers hacia afuera directamente en la retrollamada FillBufferDone, lo cual va contra la especificación, pero mejora en mucho el desempeño del componente, sobre todo en los decoders, donde los datos expulsados son mayores que los de entrada, ya que estos últimos están comprimidos y los primeros no.

Preguntas abiertas:

¿En los puertos de salida, la retrollamada FillBufferDone es siempre ejecutada por el hilo de OMX aún en puertos tuneleados? Si esto es así, podremos mover buffers en GStreamer.