protocolo - Detectar MPEG4/H264 I-Frame(IDR) en un flujo RTP
rtsp vs http (6)
Necesito detectar MPEG4 I-Frame en un paquete RTP. Sé cómo eliminar el encabezado RTP y obtener el marco MPEG4 en él, pero no puedo averiguar cómo identificar el I-Frame.
¿Tiene una firma / encabezado específico?
0x000001b6: vop_start_code (fotograma clave, si los dos bits siguientes son cero) esta es la forma correcta para MPEG-4
En realidad, era correcto para el flujo h264, si el valor NAL (primer byte) es 0x7C
significa que el I-Frame está fragmentado. No se pueden fragmentar otros marcos (P y B), por lo que si hay packetization-mode=1
en SDP
, significa que los marcos I están fragmentados y, por lo tanto, si lee 0x7C
como primer byte, entonces es I- Cuadro. Lea más aquí: here .
Esto funcionó para mí:
- Determine el "tipo de carga útil", por ejemplo: Tipo de carga útil: DynamicRTP-Type-96 (96)
- Indique a wireshark qué flujo es H264: Archivo-> preferencias-> protocolos-> H264. Introduzca 96 como tipo de carga útil.
- Filtro en slice_type: "h264.slice_type eq 7"
Ok, así que lo deduje a la corriente h264.
Cómo detectar I-Frame:
- eliminar el encabezado RTP
- verifique el valor del primer byte en la carga útil h264
- si el valor es 124 (0x7C) es un I-Frame
No puedo entenderlo para la transmisión de MPEG4-ES ... ¿alguna sugerencia?
EDITAR: IDR H264
Esto funciona para mi flujo h264 ( fmtp:96 packetization-mode=1; profile-level-id=420029;
). Simplemente pase la matriz de bytes que representa el fragmento h264 recibido a través de RTP. Si desea pasar todo el RTP, simplemente corrija el valor RTPHeaderBytes
para omitir el encabezado RTP. Siempre obtengo el I-Frame, porque es el único frame que se puede fragmentar, consulte here . ¡Utilizo este pedazo de código (simplificado) en mi servidor, y funciona como un encanto! Si el I-Frame (IDR) no está fragmentado, fragment_type
sería 5, por lo que este código devolvería true
para los IDR fragmentados y no fragmentados.
public static bool isH264iFrame(byte[] paket)
{
int RTPHeaderBytes = 0;
int fragment_type = paket[RTPHeaderBytes + 0] & 0x1F;
int nal_type = paket[RTPHeaderBytes + 1] & 0x1F;
int start_bit = paket[RTPHeaderBytes + 1] & 0x80;
if (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) || fragment_type == 5)
{
return true;
}
return false;
}
Aquí está la tabla de tipos de unidades NAL:
Type Name
0 [unspecified]
1 Coded slice
2 Data Partition A
3 Data Partition B
4 Data Partition C
5 IDR (Instantaneous Decoding Refresh) Picture
6 SEI (Supplemental Enhancement Information)
7 SPS (Sequence Parameter Set)
8 PPS (Picture Parameter Set)
9 Access Unit Delimiter
10 EoS (End of Sequence)
11 EoS (End of Stream)
12 Filter Data
13-23 [extended]
24-31 [unspecified]
EDIT 2: MPEG4 I-VOP
Olvidé actualizar este ... Gracias al documento de Che e ISO IEC 14496-2 , ¡logré resolver esto! Che fue un rito, pero no tan preciso en su respuesta ... así que aquí es cómo encontrar los cuadros I, P y B (I-VOP, P-VOP, B-VOP) en resumen:
- VOP (Video Object Plane - frame) comienza con un código
000001B6
(hex). Es igual para todos los cuadros MPEG4 (I, P, B) A continuación, se incluye mucha más información, que no voy a describir aquí (consulte el documento IEC), pero solo (como dice cheque) necesitamos los 2 bits más altos del siguiente byte (los siguientes dos bits después del byte con el valor
B6
) . Esos 2 bits le indican el VOP_CODING_TYPE, vea la tabla:VOP_CODING_TYPE (binary) Coding method 00 intra-coded (I) 01 predictive-coded (P) 10 bidirectionally-predictive-coded (B) 11 sprite (S)
Entonces, para encontrar I-Frame, encuentre el paquete que comienza con cuatro bytes 000001B6
y que tiene los dos bits más altos del siguiente byte 00
. Esto encontrará el marco I en la secuencia MPEG4 con un tipo de objeto de video simple (no estoy seguro de que sea simple avanzado).
Para cualquier otro problema, puede consultar el documento proporcionado ( ISO IEC 14496-2 ), hay todo lo que desea saber sobre MPEG4. :)
Para H264:
- Eliminar el encabezado RTP.
- Si el tipo de NAL del fragmento (en el primer byte) es SPS (7) o PPS (8), marque el marco como IFrame (muchas cámaras no usan SPS y PPS (eje incluido)).
- Si el tipo de NAL del fragmento es # 28 FU A (unidad de fragmentación A), verifique el encabezado de FU (el siguiente byte) si es de tipo NAL IDR (5) (Imagen de IDR (actualización de descodificación instantánea)) es un IFrame.
Ejemplos:
nal_ref_idc: 3, nal type: 7 (0x07) descripcion: 7 (SPS)<br>
00000000 24 00 00 2B 80 60 22 ED 96 57 3E 68 57 F3 22 B5 $..+.`"í.W>hWó"µ<br>
00000010 67 64 00 1E AD 84 01 0C 20 08 61 00 43 08 02 18 gd..... .a.C...
00000020 40 10 C2 00 84 2B 50 5A 09 34 DC 04 04 04 08 @.Â..+PZ.4Ü....<br>
nal_ref_idc: 3, nal type: 8 (0x08) descripcion: 8 (PPS)<br>
00000000 24 00 00 10 80 60 22 EE 96 57 3E 68 57 F3 22 B5 $....`"î.W>hWó"µ
00000010 68 EE 3C B0 hî<°
FU_A (fragmentation unit A)
nal_ref_idc: 3, nal type: 5 (0x05) descripcion: 5 (IDR (Instantaneous Decoding Refresh) Picture)
00000000 24 00 05 96 80 60 22 F1 96 57 3E 68 57 F3 22 B5 $....`"ñ.W>hWó"µ
00000010 7C 05 A0 AA 2F 81 92 AB CA FE 9E 34 D8 06 AD 74 |. ª/..«Êþ.4Ø.t
...
Por lo que sé, los fragmentos de flujo MPEG4-ES en la carga útil de RTP generalmente comienzan con el código de inicio MPEG4, que puede ser uno de los siguientes:
-
0x000001b0
: visual_object_sequence_start_code (probablemente fotograma clave) -
0x000001b6
: vop_start_code (fotograma clave, si los dos bits siguientes son cero) -
0x000001b3
: group_of_vop_start_code, que contiene tres bytes y luego, con suerte, un vop_start_code que puede o no pertenecer a un fotograma clave (ver arriba) -
0x00000120
: video_object_layer_start_code (probablemente fotograma clave) -
0x00000100
-0x0000011f
: video_object_start_code (también parecen fotogramas clave) - otra cosa (probablemente no sea un fotograma clave)
Me temo que tendrás que analizar el flujo para estar seguro: - /