2012-03-08 14 views
10

Tengo una transmisión H.264 sin procesar desde una cámara IP empaquetada en tramas RTP. Quiero obtener datos H.264 sin formato en un archivo para poder convertirlo con ffmpeg.H.264 sobre RTP - Identificar tramas SPS y PPS

Así que cuando quiero escribir los datos en mi archivo H.264 prima descubrí que tiene que tener este aspecto:

00 00 01 [SPS] 
00 00 01 [PPS] 
00 00 01 [NALByte] 
[PAYLOAD RTP Frame 1]  // Payload always without the first 2 Bytes -> NAL 
[PAYLOAD RTP Frame 2] 
[... until PAYLOAD Frame with Mark Bit received] // From here its a new Video Frame 
00 00 01 [NAL BYTE] 
[PAYLOAD RTP Frame 1] 
.... 

por lo que obtener la SPS y la PPS del Session Description Protocol de mi precedente a la comunicación RTSP. Además, la cámara envía SPS y PPS en dos mensajes individuales antes de comenzar con la transmisión de video.

Así que capturan los mensajes en este orden:

1. Preceding RTSP Communication here (including SDP with SPS and PPS) 
2. RTP Frame with Payload: 67 42 80 28 DA 01 40 16 C4 // This is the SPS 
3. RTP Frame with Payload: 68 CE 3C 80     // This is the PPS 
4. RTP Frame with Payload: ... // Video Data 

Luego vienen algunos marcos con carga útil y en algún momento un marco de RTP con el Marker Bit = 1. Esto significa (si lo hice bien) que tengo un marco de video completo. Después de esto, escribo la Secuencia de Prefijo (00 00 01) y el NAL de la carga útil nuevamente y continúo con el mismo procedimiento.

Ahora mi cámara me envía después de cada 8 marcos de video completos al SPS y al PPS nuevamente. (De nuevo en dos marcos RTP, como se ve en el ejemplo anterior). Sé que especialmente el PPS puede cambiar entre transmisiones, pero ese no es el problema.

Mis preguntas son ahora:

1. ¿Es necesario escribir el SPS/PPS cada fotograma de vídeo octava?

Si mi SPS y mi PPS no cambian, debería ser suficiente para tenerlos escritos al comienzo de mi archivo y nada más?

2. ¿Cómo distinguir entre SPS/PPS y marcos RTP normales?

En mi código C++ que analiza los datos transmitidos, necesito hacer una diferencia entre las tramas RTP con carga normal y las que llevan el SPS/PPS. ¿Cómo puedo distinguirlos? De acuerdo, los marcos SPS/PPS son generalmente mucho más pequeños, pero eso no es una llamada a guardar en la que confiar. Porque si los ignoro necesito saber qué datos puedo descartar, o si necesito escribirlos tengo que poner el Prefijo 00 00 01 delante de ellos. ? ¿O es una regla fija que ocurren cada 8vo Video Frame?

+0

Gracias por esta pregunta. Tengo la misma pregunta que tú. Leí el código fuente de live555 y no sé por qué guardan cada paquete/foto de esa manera. Después de leer este hilo, las cosas se vuelven claras para mí. Como una sugerencia basada en la implementación de live555, el bit marcador solo se usa en otro códec, H264 tiene su propio bit de inicio y final para representar para el inicio/fin del cuadro, el bit marcador no se usa para H264. – user534498

Respuesta

10
  1. Si el SPS y el PPS no cambian, puede omitirlos excepto los primeros.
  2. Necesita analizar el campo tipo_unidad_nal de cada NAL, para SPS, tipo_unidad_nal == 7; para PPS, nal_unit_type == 8.

Como recuerdo, nal_unit_type es los 5 bits inferiores del 1er byte de un fotograma.

nal_unit_type = frame[0] & 0x1f; 
+0

Esto significaría que los primeros 2 Bytes del marco 'SPS' y' PPS' también son algún tipo de "Estado NAL" al igual que los primeros dos bytes de cada otro Marco RTP. O en otras palabras, el campo tipo_unidad_nal, donde espero que 7 u 8 para el SPS y el PPS, sea el mismo campo donde espero 28, lo que significa que son datos de video. – Toby

+2

Para una definición detallada de nal_unit_type, puede hacer referencia al documento H.264. btw, (payload [0] & 0x1f) == 28 significa que se trata de un cuadro de video fragmentado, en esta situación, el tipo nal_unit_real debe ser (carga útil [1] y 0x1f). Esto se define en RFC3984. – ciphor

+0

Sí, acabo de leerlo y lo tengo ... pero ¿cómo sabes que el nal_unit_type = 28 es un fotograma de video fragmentado? El RFC 3984 se refiere a http://www-ee.uta.edu/dip/courses/ee5356/H264systems.pdf Tabla 7.1 (Página 63) - allí el código 28 caería bajo "Unspecified" ..? – Toby

10
  1. Usted debe escribir SPS y PPS en el inicio de la corriente, y sólo cuando se cambie en medio de la corriente.

  2. marcos de SPS y PPS son envasados ​​en una unidad de STAP NAL (generalmente STAP-A) con NAL tipo 24 (STAP-A) o 25 (STAP-B) formato STAP se describe en RFC-3984 section 5.7.1

  3. Don No confíe en el bit de marcador, utilice el bit de inicio y el bit de finalización en el encabezado NAL.

  4. Para los cuadros de video fragmentados debe regenerar la unidad NAL utilizando 3 unidades NAL del primer fragmento (F, NRI) combinadas con 5 bits NAL de primer byte en carga útil (solo para paquetes con bit de inicio establecido en 1) RFC-3984 section 5.8:

    el NAL tipo de unidad de octeto de la unidad de NAL fragmentado no está incluido como tal en la unidad de fragmentación de carga útil, sino la información del octeto NAL tipo de unidad de la unidad NAL fragmentada se transmite en Campos F y NRI del FU octeto indicador de la unidad de fragmentación y en el campo tipo de el encabezado FU.

EDIT: explicación más acerca de construcción de la unidad NAL para las unidades de fragmentación:

esto es los dos primeros bytes de un FU-A de carga útil (justo después de cabecera RTP):

| FU indicator | FU header | 
+---------------+---------------+ 
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|F|NRI| Type |S|E|R| Type | 
+---------------+---------------+ 

para construir la unidad NAL debe tomar "Tipo" de "Cabecera FU" y "F" y "NRI" del "indicador FU"

here es una implementación simple

+0

¿Puedes explicar el ítem 4? He leído esa sección de la especificación y la propaganda que citó varias veces y no entiendo lo que está describiendo. ¿Significa que el indicador FU debe reconstruirse según estas reglas, y el encabezado FU descartado, y los primeros 5 bits de la carga útil descartados, y el indicador FU ahora reconstruido debe concatenarse con la carga útil (menos los primeros 5 bits)?Gracias – Joshua

+1

@Joshua: He añadido algunas explicaciones más –

+0

Gracias, el ejemplo del código es muy elegante, y agradezco su explicación simplificada. En retrospectiva, la propaganda que citó es directa, pero su explicación en el ítem 4 sugiere usar bits de la carga útil, de ahí mi confusión. Ahora entiendo lo que quieres decir. – Joshua

Cuestiones relacionadas