Análisis del protocolo RTMP de audio y video

Entender la endianidad

Modo
endian apreciado endian

Little-Endian significa que el byte de orden inferior está dispuesto en el extremo de la dirección inferior de la memoria, y el byte de orden superior está dispuesto en el extremo de la dirección superior de la memoria; Big-Endian significa que el byte de orden superior está organizado en el extremo de la dirección inferior de la memoria, y el byte de orden inferior se dispone en el extremo de la dirección superior de la memoria.

  • Por ejemplo, la representación del número 0x12 34 56 78 en la memoria es:

    • Modo big-endian:
      dirección baja -----------------> dirección alta
      0x12 | 0x34 | 0x56 | 0x78
    • Modo little endian:
      dirección baja ------------------> dirección alta
      0x78 | 0x56 | 0x34 | 0x12
      se puede ver, el modo big endian y el modo de almacenamiento de cadenas son similares.
  • RTMP está en modo big-endian, por lo que el modo big-endian debe completarse al enviar datos, encabezados y mensajes interactivos, pero solo streamID está en modo little-endian.

Que es RMTP

El protocolo RTMP, Real Time Messaging Protocol (Real Time Messaging Protocol), es un protocolo de capa de aplicación que depende del protocolo de capa de transporte confiable subyacente (TCP, UDP) para garantizar la confiabilidad de la transmisión de información.

Una vez que RTMP se ha establecido correctamente en la capa de transporte, hay cuatro pasos: reconocimiento, establecimiento de la conexión RTMP, establecimiento de la secuencia CreateStream y reproducción / envío.

La fase de establecimiento del enlace establece un "enlace de red" entre el cliente y el servidor.
La fase de establecimiento de flujo se utiliza para establecer un "flujo de red" entre el cliente y el servidor.
La etapa de reproducción / envío se utiliza para transmitir datos de audio y video.

Documento oficial

leyenda

Apretón de manos

El cliente necesita enviar tres fragmentos C0, C1, C2 (en orden) al servidor, y el servidor envía tres fragmentos S0, S1, S2 (en orden) al cliente, y luego se puede llevar a cabo una transmisión de información efectiva. El protocolo RTMP en sí no especifica la secuencia de transmisión específica de estos 6
mensajes , pero el implementador del protocolo RTMP necesita asegurar estos puntos: el cliente debe esperar a que se envíe S1 antes de que el
cliente C2 pueda enviar otros mensajes después de recibir S2 ( Datos como información de control y audio y video real) El
servidor debe esperar hasta que se reciba C0 para enviar S1
. El servidor debe esperar hasta que se reciba C1 antes de enviar S2
. El servidor debe esperar hasta que se reciba C2 antes de enviar otra información (información de control y audio y video reales) Espere datos)
Si se envía un fragmento de protocolo de enlace cada vez, la secuencia de protocolo de enlace será la siguiente:
Representación pictórica del apretón de manos

En la implementación real, con el fin de reducir el número de comunicaciones tanto como sea posible sobre la base de garantizar la función de autenticación del protocolo de enlace, la secuencia de envío general es así, que se puede verificar capturando paquetes push de ffmpeg por wirehark:
| cliente | Servidor |
| --- C0 + C1 ----> |
| <-- S0 + S1 + S2-- |
| --- C2 ----> |

Tirar corriente

Flujo de mensajes en el comando de reproducción

Empuje el extremo

Flujo de mensajes al publicar una transmisión de video

Definición del término RTMP

  • Carga útil:
    los datos contenidos en un paquete, por ejemplo, muestras de audio o datos de video comprimidos. El formato de carga útil y la interpretación están más allá del alcance de este documento.

  • Paquete:
    un paquete de datos consta de un encabezado fijo y datos de carga útil. Algunos protocolos subyacentes pueden requerir que se defina una encapsulación del paquete.


  • Flujo de mensajes : canal lógico de comunicación por el que fluyen los mensajes.

  • Chunk:
    fragmento de un mensaje. Los mensajes se dividen en partes más pequeñas y se intercalan antes de enviarse a través de la red. Los fragmentos garantizan la entrega de todos los mensajes de un extremo a otro con un orden de marca de tiempo, a través de múltiples flujos.

  • Chunk stream:
    un canal lógico de comunicación que permite el flujo de fragmentos en una dirección particular. El chunk stream puede viajar desde el cliente al servidor y viceversa.

  • Multiplexación:
    Proceso de convertir datos de audio / video separados en un flujo de audio / video coherente, lo que hace posible transmitir varios videos y audio simultáneamente.

  • Action Message Format (AMF):
    formato binario compacto que se utiliza para serializar gráficos de objetos ActionScript. AMF tiene dos versiones: AMF 0 [AMF0] y AMF 3 [AMF3].

Acuerdo de apretón de manos detallado

Formato C0, S0

En C0, este campo identifica la versión de RTMP solicitada por el cliente. En S0, este campo identifica la versión de RTMP seleccionada por el servidor. La versión definida por esta especificación es 3.
占 一个 字节 , 表达 versión , 一般 是 3。
Bits C0 y S0

Formato C1, S1

C1 y S1 tienen 1536 bytes de longitud, 4 bytes de tiempo, 4 bytes de 0, 1528 bytes de datos aleatorios.
Bits C1 y S1

Formato C2, S2

La longitud de C2 y S2 es 1536 bytes, el tiempo de 4 bytes es Time, el tiempo de 4 bytes es Time2 (el tiempo leído por S1, C1) y el eco aleatorio de 1528 bytes contiene los datos aleatorios anteriores.

Bits C2 y S2

Secuencia de fragmentos de RTMP

  • El protocolo RTMP formateará los datos en sí cuando se transmitan. El mensaje en este formato se llama Mensaje RTMP

  • En la transmisión real, para lograr una mejor multiplexación, subenvasado y equidad de la información, el remitente dividirá el mensaje en fragmentos con ID de mensaje. Cada fragmento puede ser un mensaje o un mensaje separado. Como parte del extremo receptor restaurará el fragmento a un mensaje completo de acuerdo con la longitud de los datos contenidos en el fragmento, el ID del mensaje y la longitud del mensaje, para realizar el envío y la recepción de información.

  • Mediante la división, los mensajes con una mayor cantidad de datos se pueden dividir en "Mensajes" más pequeños, lo que puede evitar que los mensajes con baja prioridad envíen y bloqueen continuamente datos de alta prioridad. Por ejemplo, durante la transmisión de video, incluirá cuadros de video, audio fotogramas y la información de control de RTMP, si continúa enviando datos de audio o datos de control, es posible que se bloquee el fotograma de video y, a continuación, se producirá el retraso más molesto al ver el video. Al mismo tiempo, para mensajes con una pequeña cantidad de datos, la información se puede comprimir a través del campo del encabezado de fragmento, reduciendo así la cantidad de transmisión de información.

  • El tamaño predeterminado de Chunk es 128 bytes.
    Durante el proceso de transmisión, la cantidad máxima de datos de fragmentos se puede configurar a través de una información de control llamada Establecer tamaño de fragmento. El remitente y el receptor mantendrán un tamaño de fragmento respectivamente. Puede configurar este valor para cambiar el fragmento enviado por usted mismo. Tamaño máximo.
    Un fragmento más grande reduce el tiempo para calcular cada fragmento y, por lo tanto, reduce el uso de la CPU, pero llevará más tiempo enviar, especialmente en el caso de una red de ancho de banda bajo, es probable que bloquee información más importante más adelante en la transmisión.
    Un fragmento más pequeño puede reducir este problema de congestión, pero un fragmento pequeño introducirá demasiada información adicional (encabezado en fragmento), y una pequeña cantidad de transmisiones múltiples también puede causar discontinuidades en el envío y hacer imposible aprovechar al máximo el ancho de banda alto. Por lo tanto, no es adecuado para la transmisión en flujos de alta velocidad de bits.
    En la transmisión real, debe intentar utilizar diferentes tamaños de fragmentos para los datos que se enviarán y obtener el tamaño de fragmentos adecuado mediante el análisis de captura de paquetes y otros medios, y ajustar dinámicamente el tamaño de fragmentos de acuerdo con la información de ancho de banda actual y el tamaño de la información real durante la transmisión Tamaño, para maximizar la utilización de la CPU y reducir la probabilidad de bloqueo de información.

1. Bloque de mensajes RTMP

Cada fragmento se compone de encabezado de fragmento + datos de fragmento y el encabezado de fragmento
se compone de encabezado básico + encabezado de mensaje + marca de tiempo extendida;
como se muestra en la siguiente figura:
Formato de fragmentos

Encabezado básico de fragmentos, 1 ~ 3 bytes

  • Este campo codifica el ID de flujo de fragmentos y el tipo de fragmentos.
    El tipo de fragmento determina el formato del encabezado del mensaje codificado.
    La longitud depende completamente del ID de flujo de fragmentos, que es un campo de longitud variable.
    根据 ID de flujo de fragmentos 来 决定 Encabezado básico de fragmentos 长度 , 1 字节 长 到 3 字节 长

  • El protocolo admite hasta 65597 flujos con ID 3-65599. Los ID 0, 1 y 2 están reservados. Chunk Stream ID con valor 2 está reservado para mensajes y comandos de control de protocolo de bajo nivel. El
    protocolo RTMP solo admite 3-65599 .Múltiples ID de chunk, un total de 65597 flujos. 0, 1, 2 están reservados y son comandos de control para otros protocolos.

  • El valor 0 indica la forma de 2 bytes y un ID en el rango de 64-319 (el segundo byte + 64).
    El valor 1 indica la forma de 3 bytes y un ID en el rango de 64-65599 ((el tercer byte) * 256 + el segundo byte + 64).
    Los valores en el rango de 3 a 63 representan el ID de flujo completo.
    0 表示 2 字节 、 1 表示 3 字节 、 其它 表示 1 字节。

  • Los ID de flujo de fragmentos 2-63 se pueden codificar en la versión de 1 byte de este campo.
    1 byte

  • Los ID de flujo de fragmentos 64-319 se pueden codificar en el formato de 2 bytes del encabezado. El ID se calcula como (el segundo byte + 64 , 即 2 ^ 8 + 64)
    2 bytes

  • Los ID de flujo de fragmentos 64-65599 se pueden codificar en la versión de 3 bytes de este campo. El ID se calcula como ((el tercer byte) * 256 + (el segundo byte) + 64 , 即 2 ^ 16 +64).
    3 bytes

Encabezado de mensaje fragmentado, 0, 3, 7, 11 bytes

  • Este campo codifica información sobre el mensaje que se envía (ya sea en su totalidad o en parte).
    La longitud se puede determinar mediante el campo "fmt" en el encabezado básico del fragmento.

  • fmt = 0, 11 bytes
    Este tipo DEBE usarse al comienzo de una secuencia de fragmentos,
    el punto de partida de la secuencia de fragmentos.
    tipo 0

  • fmt = 1, 7 bytes
    El ID del flujo de mensajes no está incluido; este fragmento toma el mismo ID del flujo que el fragmento anterior.
    El fragmento de datos sin streamID es el mismo que el streamID del fragmento anterior.
    tipo 1

  • fmt = 2, 3 bytes
    No se incluyen ni el ID de flujo ni la longitud del mensaje; este fragmento tiene el mismo ID de flujo y la misma longitud del mensaje que el fragmento anterior.
    El streamID y la longitud del fragmento anterior son los mismos.
    type3

  • fmt = 3, 0 bytes
    Cuando un solo mensaje se divide en fragmentos, todos los fragmentos de un mensaje excepto el primero DEBEN usar este tipo.
    Cuando un mensaje se divide en varios fragmentos, excepto el primero, utilice este tipo.

  • Nota: identificación del tipo de mensaje al enviar datos de audio y video

    • Si el encabezado MessageTypeID es 0x8 o 0x9, los datos (fragmentos de datos) son datos de etiqueta flv (sin encabezado de etiqueta), consulte el análisis de formato FLV para la encapsulación del formato flv
    • También puede usar el nuevo tipo MessageTypeID como 0x16, y los datos (fragmentos de datos) son una etiqueta flv completa (encabezado de etiqueta + datos de etiqueta)
    • La identificación del flujo de mensajes usa almacenamiento Little Endian
    • RTMP está en modo big-endian, por lo que el modo big-endian debe completarse al enviar datos, encabezados y mensajes interactivos, pero solo streamID está en modo little-endian.

Marca de tiempo extendida, 0 o 4 bytes

El campo de marca de tiempo extendida se utiliza para codificar marcas de tiempo o deltas de marcas de tiempo superiores a 16777215 (0xFFFFFF);
si la longitud supera los tres bytes, utilice este encabezado.

Si el delta es mayor o igual a 16777215 (hexadecimal 0xFFFFFF), este campo DEBE ser 16777215, lo que indica la presencia del campo de marca de tiempo extendido para codificar el delta completo de 32 bits. De lo contrario, este campo DEBE ser el delta real.
Si se lee El La marca de tiempo de 3 bytes es mayor o igual que 0xFFFFFF, y la marca de tiempo de 4 bytes debe leerse de nuevo, porque se agrega la marca de tiempo extendida.

Chunk Data

La carga útil de este fragmento, hasta el tamaño máximo configurado del fragmento.
Los datos reales de este fragmento son el valor acordado en el acuerdo.
Es el valor establecido por el mensaje de control del protocolo Establecer tamaño de fragmento y el valor predeterminado es 128 bytes.

2. Clasificación de mensajes RTMP Mensajes de comando RTMP

Todas las referencias: comprensión profunda del análisis de implementación del protocolo rtmp (cuatro)

1. Mensaje de control de protocolo

  • El rango de MessageType es 1 ~ 7:
    1 ~ 2 para el protocolo de fragmentos
    3 ~ 6 para el protocolo rtmp en sí, se debe requerir un mensaje de control de protocolo

  • ID de secuencia de mensajes = 0 和 ID de secuencia de fragmentos = 2

    • MessageType = 1, Set Chunk Size Establece el tamaño del bloque y notifica al par para usar el nuevo tamaño de bloque, un total de 4 bytes. El tamaño predeterminado es 128 bytes.
    • MessageType = 2, mensaje de cancelación El mensaje de cancelación se utiliza para notificar al par que está esperando recibir el bloque para completar el mensaje, descartar la parte recibida de un flujo de bloque y cancelar el procesamiento del mensaje, un total de 4 bytes.
    • MessageType = 3, Acuse de recibo Mensaje de acuse de recibo, el cliente o servidor envía un mensaje de acuse de recibo a la otra parte después de recibir el número de bytes igual al tamaño de la ventana. El tamaño de la ventana es el número máximo de bytes enviados antes de que no se reciba el mensaje de confirmación enviado por el receptor. El servidor envía el tamaño de la ventana después de establecer la conexión. Este mensaje especifica el número de serie. El número de serie es el número de bytes que se han recibido hasta el momento actual. Un total de 4 bytes.
    • MessageType = 4, User Control Message Mensaje de control de usuario, el cliente o servidor envía este mensaje para notificar al otro usuario del evento de control. Este mensaje incluye el tipo de evento y los datos del evento. Los primeros dos bytes de los datos del mensaje se utilizan para identificar el tipo de evento. Después del tipo de evento están los datos del evento. El campo de datos del evento es de longitud variable.
    • MessageType = 5, Tamaño de la ventana de confirmación Tamaño de la ventana de confirmación, el cliente o servidor envía este mensaje para notificar a la otra parte que envíe el tamaño de la ventana del mensaje de confirmación, un total de 4 bytes.
    • MessageType = 6, Set Peer Bandwidth Establece el ancho de banda del peer, el cliente o servidor envía este mensaje para actualizar el ancho de banda de salida del peer. El remitente puede marcar el mensaje como duro (0), blando (1) o dinámico (2) en el campo de tipo de restricción (1 bytes). Si es un límite estricto, el par debe enviar datos de acuerdo con el ancho de banda proporcionado. Si es un límite flexible, el par puede determinar de manera flexible el ancho de banda y el remitente puede limitar el ancho de banda. Si es un límite dinámico, el ancho de banda puede ser un límite rígido o un límite flexible.

2. Mensaje de audio

MessageType = 8, mensaje de audio: el
cliente o servidor envía este mensaje para enviar datos de audio. Tipo de mensaje 8, reservado como mensaje de audio

3. Mensaje de video

MessageType = 9, mensaje de video: el
cliente o servidor utiliza este mensaje para enviar datos de video a la otra parte. El valor del tipo de mensaje es 9 y está reservado como mensaje de video.

4. Mensaje de datos

MessageType = 15 o 18, mensaje de datos: el
cliente o servidor envía metadatos y datos del usuario a la otra parte a través de este mensaje.
Los metadatos incluyen detalles como la hora de creación, la duración y el tema de los datos.
El tipo de mensaje 18 se codifica con AMF0; el tipo de mensaje 15 se codifica con AMF3.

5. Mensaje de objeto compartido

MessageType = 16 o 19, mensaje de objeto compartido: el
objeto compartido es un objeto FLASH (una colección de pares nombre-valor) que se sincroniza entre varios clientes e instancias.

6. Mensaje de comando

MessageType = 17 o 20, Mensaje de comando: Los
mensajes de comando están todos codificados con AMF. Hay dos tipos de AMF, AMF0 y AMF3.
El mensaje de comando consta del nombre del comando, el ID de transmisión y el objeto nombrado. El objeto nombrado está compuesto por una serie de parámetros.

Los tipos de mensajes de comando son:

1. Comandos de NetConnection (comandos de la capa de conexión)

Objeto de nivel superior que representa la conexión entre el servidor y el cliente. Contiene 4 tipos de comando:

  • El
    comando de conexión se envía primero desde el cliente al servidor, lo que significa que quiero conectarme, ¿puedo establecer una conexión? El servidor devuelve el nombre del comando con "_result" o "_error" y devuelve "_result", lo que indica que el servidor puede proporcionar servicios y el cliente puede continuar con el siguiente paso. "_Error", es obvio que el servidor no puede proporcionar servicios.

  • El método de llamada del objeto de llamada NetConnection ejecuta una llamada a procedimiento remoto en el extremo receptor. El nombre del método remoto se utiliza como parámetro del comando de llamada.
  • cerca
  • El
    cliente createStream envía este comando al servidor para crear un canal lógico para la comunicación de mensajes. La distribución de audio, video y metadatos se realiza mediante el canal de transmisión establecido por el comando create stream.

Después del protocolo de enlace RTMP, envíe primero un mensaje de comando de conexión. Lo que contiene el comando no se especifica en el protocolo. En la comunicación real, parte de la información del códec debe especificarse y enviarse en formato AMF.
El servidor devuelve un mensaje de tipo de comando _result. La longitud de carga útil de este mensaje generalmente no es mayor de 128 bytes, pero la longitud del mensaje devuelto en el último nginx-rtmp será mayor de 128 bytes.
El transactionID del mensaje se utiliza para identificar el tipo de mensaje de comando. El mensaje _result devuelto por el servidor se puede utilizar para distinguir la respuesta al comando por el transactionID. Después de enviar el comando de conexión, se deben enviar otros mensajes de comando. Asegúrese de que sus ID de transacción no son los mismos.

2. Comandos de NetStream (comandos en la conexión de transmisión)

Netstream se basa en NetConnection, creado por el comando createStream de NetConnection y se utiliza para transmitir audio, video y otra información específica.
Solo se puede conectar una NetConnection al protocolo de la capa de transporte, pero una NetConnection puede establecer múltiples NetStreams para establecer diferentes canales de transmisión para transmitir datos.
A continuación, se enumeran algunos de los comandos de NetStream que se utilizan con más frecuencia. Después de recibir el comando, el servidor responderá al cliente con el comando onStatus para indicar el estado actual de NetStream.
La estructura del mensaje del comando onStatus es la siguiente:

  • jugar
    jugar
  • play2 El
    comando play2 puede cambiar a una velocidad de bits diferente sin cambiar la línea de tiempo del contenido que se ha reproducido. El servidor mantiene múltiples archivos para múltiples tasas de código que pueden ser solicitadas por el comando play 2.
  • deleteStream
    envía un comando delete stream cuando se destruye el objeto NetStream.
  • closeStream
  • El
    objeto ReceiveAudio NetStream envía y recibe mensajes de audio para notificar al servidor que envíe o no el audio al cliente.
  • El
    objeto ReceiveVideo NetStream envía un mensaje ReceiveVideo para notificar al servidor si debe enviar video al cliente.

  • El paso final de la publicación de flujo de empuje trabajo de preparación está Publicar Stream, que es para enviar un mensaje de comando publicar en el servidor. El ID de flujo de mensajes de este comando es el ID de flujo devuelto por el servidor después de que el flujo por encima de crear. Después de enviar este , generalmente no necesita esperar la respuesta del servidor, simplemente envíe paquetes RTMP de tipos de audio y video directamente.
    Algunas bibliotecas rtmp también envían un mensaje setMetaData. Este mensaje se puede enviar o no. Contiene información de metadatos de audio y video, como la resolución del video.
  • buscar una
    posición en el video o audio, en milisegundos. El cliente envía un comando de búsqueda para buscar compensaciones en un archivo multimedia o una lista de reproducción.
  • El
    cliente de pausa le dice al servidor que detenga o reanude la reproducción, y el cliente envía un comando de pausa para indicarle al servidor que pause o inicie un comando.

El cliente envía el comando releaseStream en el mensaje de comando al servidor. El
cliente envía el comando FCPublish en el mensaje de comando al servidor. El
cliente envía el comando "createStream" en el mensaje de comando al servidor.
Una vez que el servidor recibe el comando "crear flujo", envía el "resultado" (_result) en el mensaje de comando para notificar al cliente sobre el estado del flujo.
Al analizar el mensaje devuelto por el servidor, se obtendrá un ID de flujo, que es el ID de flujo de mensajes que se comunicará con el servidor en el futuro. Generalmente, devuelve 1 y no es fijo.

7. Mensaje agregado

MessageType = 22, Mensaje agregado:
El mensaje agregado es un tipo de mensaje que contiene una lista de mensajes. El valor del tipo de mensaje es 22, reservado para mensajes de agregación.

3. Recibir el resultado de la retroalimentación del mensaje de comando ResponseCommand

Los datos transportados por el mensaje de bloqueo se empalman en el contenido del mensaje y el contenido del mensaje se interpreta a través de AMF
RTMPResponseCommandType

Capturar

Al capturar paquetes y comparar el protocolo y el código fuente, puede ver más claramente y comprender mejor el protocolo;
Capturar
image.png

para resumir

Este artículo clasifica los formatos relacionados con el protocolo RTMP para facilitar la comprensión del código.

Referencia: Comprensión completa de
RTMP Transmisión de
RTMP y aprendizaje de protocolos
Comprensión en profundidad del análisis de implementación del protocolo rtmp (4)
Especificación de RTMP Análisis simple
documento oficial
srs-librtmp

Supongo que te gusta

Origin blog.csdn.net/u014099894/article/details/107976783
Recomendado
Clasificación