Skip to content

Commit

Permalink
mpeg_annexb: Add format
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Sep 12, 2021
1 parent 69c6d15 commit f4b11b4
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 17 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ For more usage details see [usage.md](doc/usage.md).

[./formats_list.jq]: sh-start

aac_frame, adts, adts_frame, apev2, av1_ccr, av1_frame, av1_obu, avc_au, avc_dcr, avc_nalu, avc_pps, avc_sei, avc_sps, bzip2, dns, elf, exif, flac, flac_frame, flac_metadatablock, flac_picture, gif, gzip, hevc_au, hevc_dcr, hevc_nalu, icc_profile, id3v1, id3v11, id3v2, jpeg, json, matroska, mp3, mp3_frame, mp4, mpeg_asc, mpeg_es, mpeg_pes, mpeg_pes_packet, mpeg_spu, mpeg_ts, ogg, ogg_page, opus_packet, png, protobuf, protobuf_widevine, raw, tar, tiff, vorbis_comment, vorbis_packet, vp8_frame, vp9_cfm, vp9_frame, vpx_ccr, wav, webp, xing
aac_frame, adts, adts_frame, apev2, av1_ccr, av1_frame, av1_obu, avc_au, avc_dcr, avc_nalu, avc_pps, avc_sei, avc_sps, bzip2, dns, elf, exif, flac, flac_frame, flac_metadatablock, flac_picture, gif, gzip, hevc_au, hevc_dcr, hevc_nalu, icc_profile, id3v1, id3v11, id3v2, jpeg, json, matroska, mp3, mp3_frame, mp4, mpeg_annexb, mpeg_asc, mpeg_es, mpeg_pes, mpeg_pes_packet, mpeg_spu, mpeg_ts, ogg, ogg_page, opus_packet, png, protobuf, protobuf_widevine, raw, tar, tiff, vorbis_comment, vorbis_packet, vp8_frame, vp9_cfm, vp9_frame, vpx_ccr, wav, webp, xing

[#]: sh-end

Expand Down
3 changes: 2 additions & 1 deletion doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ To add own functions you can use `init.fq` that will be read from
|`mp3` |MP3&nbsp;file |<sub>`id3v2` `id3v1` `id3v11` `apev2` `mp3_frame`</sub>|
|`mp3_frame` |MPEG&nbsp;audio&nbsp;layer&nbsp;3&nbsp;frame |<sub>`xing`</sub>|
|`mp4` |MPEG-4&nbsp;file&nbsp;and&nbsp;similar |<sub>`aac_frame` `av1_ccr` `av1_frame` `flac_frame` `flac_metadatablock` `id3v2` `image` `jpeg` `mp3_frame` `avc_au` `avc_dcr` `mpeg_es` `hevc_au` `hevc_dcr` `mpeg_pes_packet` `opus_packet` `protobuf_widevine` `vorbis_packet` `vp9_frame` `vpx_ccr`</sub>|
|`mpeg_annexb` |H.264/AVC&nbsp;Annex&nbsp;B |<sub>`avc_nalu`</sub>|
|`mpeg_asc` |MPEG-4&nbsp;Audio&nbsp;Specific&nbsp;Config |<sub></sub>|
|`mpeg_es` |MPEG&nbsp;Elementary&nbsp;Stream |<sub>`mpeg_asc` `vorbis_packet`</sub>|
|`mpeg_pes` |MPEG&nbsp;Packetized&nbsp;elementary&nbsp;stream |<sub>`mpeg_pes_packet` `mpeg_spu`</sub>|
Expand All @@ -210,7 +211,7 @@ To add own functions you can use `init.fq` that will be read from
|`webp` |WebP&nbsp;image |<sub>`vp8_frame`</sub>|
|`xing` |Xing&nbsp;header |<sub></sub>|
|`image` |Group |<sub>`gif` `jpeg` `png` `tiff` `webp`</sub>|
|`probe` |Group |<sub>`adts` `bzip2` `elf` `flac` `gif` `gzip` `jpeg` `json` `matroska` `mp3` `mp4` `mpeg_ts` `ogg` `png` `tar` `tiff` `wav` `webp`</sub>|
|`probe` |Group |<sub>`adts` `bzip2` `elf` `flac` `gif` `gzip` `jpeg` `json` `matroska` `mp3` `mp4` `mpeg_annexb` `mpeg_ts` `ogg` `png` `tar` `tiff` `wav` `webp`</sub>|

[#]: sh-end

Expand Down
1 change: 1 addition & 0 deletions format/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const (
HEVC_AU = "hevc_au"
HEVC_NALU = "hevc_nalu"
HEVC_DCR = "hevc_dcr"
MPEG_ANNEXB = "mpeg_annexb"
MPEG_ES = "mpeg_es"
MPEG_PES = "mpeg_pes"
MPEG_PES_PACKET = "mpeg_pes_packet"
Expand Down
3 changes: 2 additions & 1 deletion format/id3/id3v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ func textNull(d *decode.D, encoding int) string {
nullLen = n
}

pos := d.PeekFind(nullLen*8, 8, func(v uint64) bool { return v == 0 }, -1) / 8
offset, _ := d.PeekFind(nullLen*8, 8, func(v uint64) bool { return v == 0 }, -1)
pos := offset / 8
textLen := int(pos + int64(nullLen))
text := text(d, encoding, textLen)

Expand Down
2 changes: 1 addition & 1 deletion format/mp3/mp3.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func mp3Decode(d *decode.D, in interface{}) interface{} {
d.FieldArrayFn("frames", func(d *decode.D) {
for d.NotEnd() {
startFindSync := d.Pos()
syncLen, err := d.TryPeekFind(16, 8, func(v uint64) bool { return v&0b1111_1111_1110_0000 == 0b1111_1111_1110_0000 }, d.BitsLeft())
syncLen, _, err := d.TryPeekFind(16, 8, func(v uint64) bool { return v&0b1111_1111_1110_0000 == 0b1111_1111_1110_0000 }, d.BitsLeft())
if err != nil {
break
}
Expand Down
66 changes: 66 additions & 0 deletions format/mpeg/mpeg_annexb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package mpeg

import (
"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/pkg/decode"
)

var annexBAVCNALUFormat []*decode.Format

func init() {
registry.MustRegister(&decode.Format{
Name: format.MPEG_ANNEXB,
Description: "H.264/AVC Annex B",
Groups: []string{format.PROBE},
DecodeFn: annexBDecode,
Dependencies: []decode.Dependency{
{Names: []string{format.AVC_NALU}, Formats: &annexBAVCNALUFormat},
},
})
}

func annexBFindStartCode(d *decode.D) (int64, int64, error) {
offset, v, err := d.TryPeekFind(32, 8, func(v uint64) bool {
return annexBDecodeStartCodeLen(v) > 0
}, d.BitsLeft())
return offset, annexBDecodeStartCodeLen(v), err
}

func annexBDecodeStartCodeLen(v uint64) int64 {
switch {
case v == 0x00_00_00_01:
return 4 * 8
case v&0xff_ff_ff_00 == 0x00_00_01_00:
return 3 * 8
default:
return 0
}
}

func annexBDecode(d *decode.D, in interface{}) interface{} {
currentOffset, currentPrefixLen, err := annexBFindStartCode(d)
// TODO: really restrict to 0?
if err != nil || currentOffset != 0 {
d.Invalid("could not find start code (first)")
}

// TODO: root array
d.FieldArrayFn("nalus", func(d *decode.D) {
for d.NotEnd() {
d.FieldBitBufLen("start_code", currentPrefixLen)

nextOffset, nextPrefixLen, err := annexBFindStartCode(d)
if err != nil {
nextOffset = d.Len() - d.Pos()
}

naluLen := nextOffset
d.FieldFormatLen("nalu", naluLen, avcNALUFormat)

currentPrefixLen = nextPrefixLen
}
})

return nil
}
119 changes: 119 additions & 0 deletions format/mpeg/testdata/mpeg_annexb.fqtest
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# ffmpeg -y -f lavfi -i testsrc -t 10ms -f h264 mpeg_annexb.h264
/mpeg_annexb.h264:
$ fq -d mpeg_annexb verbose /mpeg_annexb.h264
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f| |.: {} /mpeg_annexb.h264 (mpeg_annexb) 0x0-0xae4.7 (2789)
| | | nalus: [8] 0x0-0xae4.7 (2789)
0x0000|00 00 00 01 |.... | [0]: start_code 00000001 0x0-0x3.7 (4)
| | | [1]: nalu {} (avc_nalu) 0x4-0x1c.7 (25)
| | | sps: {} (avc_sps) 0x0-0x15.7 (22)
0x000|f4 |. | profile_idc: High 4:4:4 Predictive Profile (244) 0x0-0x0.7 (1)
0x000| 00 | . | constraint_set0_flag: false 0x1-0x1 (0.1)
0x000| 00 | . | constraint_set1_flag: false 0x1.1-0x1.1 (0.1)
0x000| 00 | . | constraint_set2_flag: false 0x1.2-0x1.2 (0.1)
0x000| 00 | . | constraint_set3_flag: false 0x1.3-0x1.3 (0.1)
0x000| 00 | . | constraint_set4_flag: false 0x1.4-0x1.4 (0.1)
0x000| 00 | . | constraint_set5_flag: false 0x1.5-0x1.5 (0.1)
0x000| 00 | . | reserved_zero_2bits: 0 0x1.6-0x1.7 (0.2)
0x000| 0d | . | level_idc: 1.3 (13) 0x2-0x2.7 (1)
0x000| 91 | . | seq_parameter_set_id: 0 0x3-0x3 (0.1)
0x000| 91 | . | chroma_format_idc: 3 0x3.1-0x3.5 (0.5)
0x000| 91 | . | separate_colour_plane_flag: false 0x3.6-0x3.6 (0.1)
0x000| 91 | . | bit_depth_luma_minus8: 0 0x3.7-0x3.7 (0.1)
0x000| 9b | . | bit_depth_chroma_minus8: 0 0x4-0x4 (0.1)
0x000| 9b | . | qpprime_y_zero_transform_bypass_flag: false 0x4.1-0x4.1 (0.1)
0x000| 9b | . | seq_scaling_matrix_present_flag: false 0x4.2-0x4.2 (0.1)
0x000| 9b | . | log2_max_frame_num_minus4: 0 0x4.3-0x4.3 (0.1)
0x000| 9b | . | pic_order_cnt_type: 0 0x4.4-0x4.4 (0.1)
0x000| 9b | . | log2_max_pic_order_cnt_lsb_minus4: 2 0x4.5-0x4.7 (0.3)
0x000| 28 | ( | max_num_ref_frames: 4 0x5-0x5.4 (0.5)
0x000| 28 | ( | gaps_in_frame_num_value_allowed_flag: false 0x5.5-0x5.5 (0.1)
0x000| 28 28 | (( | pic_width_in_mbs_minus1: 19 0x5.6-0x6.6 (1.1)
0x000| 28 3f | (? | pic_height_in_map_units_minus1: 14 0x6.7-0x7.5 (0.7)
0x000| 3f | ? | frame_mbs_only_flag: true 0x7.6-0x7.6 (0.1)
0x000| 3f | ? | direct_8x8_inference_flag: true 0x7.7-0x7.7 (0.1)
0x000| 60 | ` | frame_cropping_flag: false 0x8-0x8 (0.1)
0x000| 60 | ` | vui_parameters_present_flag: true 0x8.1-0x8.1 (0.1)
| | | vui_parameters: {} 0x8.2-0x15.4 (13.3)
0x000| 60 | ` | aspect_ratio_info_present_flag: true 0x8.2-0x8.2 (0.1)
0x000| 60 22 | `" | aspect_ratio_idc: 1 0x8.3-0x9.2 (1)
0x000| 22 | " | overscan_info_present_flag: false 0x9.3-0x9.3 (0.1)
0x000| 22 | " | video_signal_type_present_flag: false 0x9.4-0x9.4 (0.1)
0x000| 22 | " | chroma_loc_info_present_flag: false 0x9.5-0x9.5 (0.1)
0x000| 22 | " | timing_info_present_flag: true 0x9.6-0x9.6 (0.1)
0x000| 22 00 00 00 02 | ".... | num_units_in_tick: 1 0x9.7-0xd.6 (4)
0x000| 02 00 00| ...| time_scale: 50 0xd.7-0x11.6 (4)
0x010|00 64 |.d |
0x010| 64 | d | fixed_frame_rate_flag: false 0x11.7-0x11.7 (0.1)
0x010| 1e | . | nal_hrd_parameters_present_flag: false 0x12-0x12 (0.1)
0x010| 1e | . | vcl_hrd_parameters_present_flag: false 0x12.1-0x12.1 (0.1)
0x010| 1e | . | pic_struct_present_flag: false 0x12.2-0x12.2 (0.1)
0x010| 1e | . | bitstream_restriction_flag: true 0x12.3-0x12.3 (0.1)
0x010| 1e | . | motion_vectors_over_pic_boundaries_flag: true 0x12.4-0x12.4 (0.1)
0x010| 1e | . | max_bytes_per_pic_denom: 0 0x12.5-0x12.5 (0.1)
0x010| 1e | . | max_bits_per_mb_denom: 0 0x12.6-0x12.6 (0.1)
0x010| 1e 28 | .( | log2_max_mv_length_horizontal: 9 0x12.7-0x13.5 (0.7)
0x010| 28 53 | (S | log2_max_mv_length_vertical: 9 0x13.6-0x14.4 (0.7)
0x010| 53 | S | max_num_reorder_frames: 2 0x14.5-0x14.7 (0.3)
0x010| 2c| | ,| | max_dec_frame_buffering: 4 0x15-0x15.4 (0.5)
0x010| 2c| | ,| | rbsp_trailing_bits: 80 0x15.5-0x15.7 (0.3)
0x0000| 67 | g | forbidden_zero_bit: false 0x4-0x4 (0.1)
0x0000| 67 | g | nal_ref_idc: 3 0x4.1-0x4.2 (0.2)
0x0000| 67 | g | nal_unit_type: Sequence parameter set (7) 0x4.3-0x4.7 (0.5)
0x0000| f4 00 0d 91 9b 28 28 3f 60 22 00| .....((?`".| data: f4000d919b28283f6022000003000200... 0x5-0x1c.7 (24)
0x0010|00 03 00 02 00 00 03 00 64 1e 28 53 2c |........d.(S, |
0x0010| 00 00 00| ...| [2]: start_code 00000001 0x1d-0x20.7 (4)
0x0020|01 |. |
| | | [3]: nalu {} (avc_nalu) 0x21-0x26.7 (6)
| | | pps: {} (avc_pps) 0x0-0x4.7 (5)
0x000|eb |. | pic_parameter_set_id: 0 0x0-0x0 (0.1)
0x000|eb |. | seq_parameter_set_id: 0 0x0.1-0x0.1 (0.1)
0x000|eb |. | entropy_coding_mode_flag: true 0x0.2-0x0.2 (0.1)
0x000|eb |. | bottom_field_pic_order_in_frame_present_flag: false 0x0.3-0x0.3 (0.1)
0x000|eb |. | num_slice_groups_minus1: 0 0x0.4-0x0.4 (0.1)
0x000|eb |. | num_ref_idx_l0_default_active_minus1: 2 0x0.5-0x0.7 (0.3)
0x000| e3 | . | num_ref_idx_l1_default_active_minus1: 0 0x1-0x1 (0.1)
0x000| e3 | . | weighted_pred_flag: true 0x1.1-0x1.1 (0.1)
0x000| e3 | . | weighted_bipred_idc: 2 0x1.2-0x1.3 (0.2)
0x000| e3 c4 | .. | pic_init_qp_minus26: 3 0x1.4-0x2 (0.5)
0x000| c4 | . | pic_init_qs_minus26: 0 0x2.1-0x2.1 (0.1)
0x000| c4 48 | .H | chroma_qp_index_offset: -4 0x2.2-0x3 (0.7)
0x000| 48 | H | deblocking_filter_control_present_flag: true 0x3.1-0x3.1 (0.1)
0x000| 48 | H | constrained_intra_pred_flag: false 0x3.2-0x3.2 (0.1)
0x000| 48 | H | redundant_pic_cnt_present_flag: false 0x3.3-0x3.3 (0.1)
0x000| 48 | H | transform_8x8_mode_flag: true 0x3.4-0x3.4 (0.1)
0x000| 48 | H | pic_scaling_matrix_present_flag: false 0x3.5-0x3.5 (0.1)
0x000| 48 44| | HD| | second_chroma_qp_index_offset: -4 0x3.6-0x4.4 (0.7)
0x000| 44| | D| | rbsp_trailing_bits: 80 0x4.5-0x4.7 (0.3)
0x0020| 68 | h | forbidden_zero_bit: false 0x21-0x21 (0.1)
0x0020| 68 | h | nal_ref_idc: 3 0x21.1-0x21.2 (0.2)
0x0020| 68 | h | nal_unit_type: Picture parameter set (8) 0x21.3-0x21.7 (0.5)
0x0020| eb e3 c4 48 44 | ...HD | data: ebe3c44844 0x22-0x26.7 (5)
0x0020| 00 00 01 | ... | [4]: start_code 000001 0x27-0x29.7 (3)
| | | [5]: nalu {} (avc_nalu) 0x2a-0x2d6.7 (685)
| | | sei: {} (avc_sei) 0x0-0x2ab.7 (684)
0x000|05 |. | payload_type: user_data_unregistered (5) 0x0-0x0.7 (1)
0x000| ff ff a9 | ... | payload_size: 679 0x1-0x3.7 (3)
0x000| dc 45 e9 bd e6 d9 48 b7 96 2c d8 20| .E....H..,. | uuid: x264 (dc45e9bde6d948b7962cd820d923eeef) 0x4-0x13.7 (16)
0x010|d9 23 ee ef |.#.. |
0x010| 78 32 36 34 20 2d 20 63 6f 72 65 20| x264 - core | data: 78323634202d20636f72652031363120... 0x14-0x2aa.7 (663)
0x020|31 36 31 20 72 33 30 33 39 20 35 34 34 63 36 31|161 r3039 544c61|
* |until 0x2aa.7 (663) | |
0x2a0| 80| | .| | rbsp_trailing_bits: 80 0x2ab-0x2ab.7 (1)
0x0020| 06 | . | forbidden_zero_bit: false 0x2a-0x2a (0.1)
0x0020| 06 | . | nal_ref_idc: 0 0x2a.1-0x2a.2 (0.2)
0x0020| 06 | . | nal_unit_type: Supplemental enhancement information (SEI) (6) 0x2a.3-0x2a.7 (0.5)
0x0020| 05 ff ff a9 dc| .....| data: 05ffffa9dc45e9bde6d948b7962cd820... 0x2b-0x2d6.7 (684)
0x0030|45 e9 bd e6 d9 48 b7 96 2c d8 20 d9 23 ee ef 78|E....H..,. .#..x|
* |until 0x2d6.7 (684) | |
0x02d0| 00 00 01 | ... | [6]: start_code 000001 0x2d7-0x2d9.7 (3)
| | | [7]: nalu {} (avc_nalu) 0x2da-0xae4.7 (2059)
0x02d0| 65 | e | forbidden_zero_bit: false 0x2da-0x2da (0.1)
0x02d0| 65 | e | nal_ref_idc: 3 0x2da.1-0x2da.2 (0.2)
0x02d0| 65 | e | nal_unit_type: Coded slice of an IDR picture (5) 0x2da.3-0x2da.7 (0.5)
| | | slice_header: {} 0x2db-0x2dc (1.1)
0x02d0| 88 | . | first_mb_in_slice: 0 0x2db-0x2db (0.1)
0x02d0| 88 | . | slice_type: I (7) 0x2db.1-0x2db.7 (0.7)
0x02d0| 84 | . | pic_parameter_set_id: 0 0x2dc-0x2dc (0.1)
0x02d0| 84 00 2b ff| ..+.| data: 080057fffdebb7e65958ccce7bffda76... 0x2dc.1-0xae4.7 (2056.7)
0x02e0|fe f5 db f3 2c ac 66 67 3d ff ed 3b 60 00 21 74|....,.fg=..;`.!t|
* |until 0xae4.7 (end) (2057) | |
Binary file added format/mpeg/testdata/mpeg_annexb.h264
Binary file not shown.

0 comments on commit f4b11b4

Please sign in to comment.