NALU Explorer - Herramienta de visualización de NAL Units de flujos de video H.264
(nalu.funnify.org)Antecedentes de desarrollo e idea de implementación
- Al desarrollar o depurar el códec de video H.264, quería poder verificar visualmente la estructura de las NAL Units
- Era posible analizarlas con la línea de comandos de FFmpeg, pero quería ver cada NAL Unit haciendo clic en ella y junto con la imagen real del frame
- Se necesitaba un parser de Annex B que funcionara directamente en el navegador, y usando FFmpeg basado en WebAssembly también era posible decodificar frames
- Se desarrolló la biblioteca propia
h264-parserpara parsear hasta SPS/PPS/Slice Header (publicada como paquete de NPM) - Salida basada en la estructura sintáctica estándar de H.264: los campos se muestran con estructura jerárquica (indentación) siguiendo exactamente el árbol sintáctico de parsing de la especificación ITU-T H.264
Cómo funciona
- Parsing de Annex B: detección de start codes
00 00 00 01o00 00 01 - Parsing de parámetros:
- SPS/PPS: extracción de parámetros con el parser
- Slice Header:
first_mb_in_slice,slice_type,pic_parameter_set_id, etc. - Cumplimiento de la sintaxis estándar: muestra la estructura de la especificación H.264 tal cual, como
nal_unit()→seq_parameter_set_rbsp()→vui_parameters()
- Decodificación de frames:
- Cálculo del rango GOP al que pertenece la NAL Unit seleccionada (buscando el IDR anterior/siguiente)
- Reconstrucción de Annex B junto con las cabeceras SPS/PPS
Funciones principales
Parsing
- Separación de NAL Units basada en Annex B Start Code
- Parsing según el tipo de NAL Unit:
- Type 7 (SPS): profile, level, resolution, frame rate, etc.
- Type 8 (PPS): entropy coding mode, slice groups, etc.
- Type 1/5 (Slice):
slice_type,first_mb_in_slice,frame_num, etc. - Type 6 (SEI): metadatos (parsing limitado)
- Salida en árbol de sintaxis estándar H.264: muestra el parsing condicional (bloques
if), la estructura jerárquica y el orden de lectura del bitstream tal cual - Volcado hex de RBSP: permite revisar datos raw en formato offset, hex bytes y ASCII
Ejemplo de salida real de parsing SPS:
nal_unit()
forbidden_zero_bit: 0
nal_ref_idc: 3
nal_unit_type: 7
seq_parameter_set_rbsp()
profile_idc: 100
constraint_set0_flag: 0
constraint_set1_flag: 0
constraint_set2_flag: 0
constraint_set3_flag: 0
constraint_set4_flag: 0
constraint_set5_flag: 0
reserved_zero_2bits: 0
...
Decodificación de frames
- Cálculo automático del rango por GOP (buscando el IDR anterior/siguiente)
- Búsqueda automática e inserción previa de cabeceras SPS/PPS
- Extracción de BMP con FFmpeg.wasm y renderizado en Canvas
Extracción de datos
- Descarga de NAL Units individuales (Annex B Start Code + rawData)
- Descarga por GOP (SPS/PPS + NAL Units del rango GOP)
- Visualización de NAL Units en forma de línea de tiempo (color por tipo, tamaño proporcional)
Limitaciones
- Sin soporte para Slice Data: solo se parsea hasta Slice Header. No se analiza el área
slice_data, como datos de macrobloques, MVD o coeficientes residuales - Formato AVC sin validar: el código de parsing basado en longitud está implementado, pero no ha sido probado
- Carga inicial de FFmpeg.wasm: en la primera ejecución se descargan bibliotecas de ~10-20MB
Enlaces
- Demo en vivo: https://nalu.funnify.org
- Biblioteca de NPM: https://www.npmjs.com/package/h264-parser
Aún no hay comentarios.