From 0cf46e119601e5c562e0bee377d1984015064819 Mon Sep 17 00:00:00 2001 From: Mattias Wadman Date: Sat, 29 Oct 2022 19:23:50 +0200 Subject: [PATCH] wav,avi,avc_au: Add avi decoder and refactor wav decoder avi and wav now share common riff decode code avc_au decoder can now handle annexb format --- README.md | 1 + doc/formats.md | 49 +- doc/formats.svg | 2738 +++++++++-------- format/all/all.fqtest | 2 + format/all/all.go | 2 +- format/format.go | 5 + format/media.go | 604 ++++ format/mpeg/avc_au.go | 15 +- format/mpeg/hevc_au.go | 14 +- format/mpeg/testdata/help_avc_au.fqtest | 6 +- format/riff/avi.go | 601 ++++ format/riff/avi.md | 19 + format/riff/common.go | 120 + format/riff/testdata/avc.avi | Bin 0 -> 9282 bytes format/riff/testdata/avc.avi.fqtest | 489 +++ .../{wav => riff}/testdata/end-of-file.fqtest | 14 +- format/{wav => riff}/testdata/end-of-file.wav | Bin format/riff/testdata/flac.avi | Bin 0 -> 6348 bytes format/riff/testdata/flac.avi.fqtest | 263 ++ format/riff/testdata/help_avi.fqtest | 40 + format/riff/testdata/mp3.avi | Bin 0 -> 6376 bytes format/riff/testdata/mp3.avi.fqtest | 536 ++++ format/riff/testdata/pcm.avi | Bin 0 -> 14602 bytes format/riff/testdata/pcm.avi.fqtest | 242 ++ format/{wav => riff}/testdata/rf64.fqtest | 0 format/{wav => riff}/testdata/rf64.wav | Bin format/{wav => riff}/testdata/stereo.fqtest | 14 +- format/{wav => riff}/testdata/stereo.wav | Bin format/riff/wav.go | 164 + format/wav/wav.go | 239 -- 30 files changed, 4558 insertions(+), 1619 deletions(-) create mode 100644 format/riff/avi.go create mode 100644 format/riff/avi.md create mode 100644 format/riff/common.go create mode 100644 format/riff/testdata/avc.avi create mode 100644 format/riff/testdata/avc.avi.fqtest rename format/{wav => riff}/testdata/end-of-file.fqtest (87%) rename format/{wav => riff}/testdata/end-of-file.wav (100%) create mode 100644 format/riff/testdata/flac.avi create mode 100644 format/riff/testdata/flac.avi.fqtest create mode 100644 format/riff/testdata/help_avi.fqtest create mode 100644 format/riff/testdata/mp3.avi create mode 100644 format/riff/testdata/mp3.avi.fqtest create mode 100644 format/riff/testdata/pcm.avi create mode 100644 format/riff/testdata/pcm.avi.fqtest rename format/{wav => riff}/testdata/rf64.fqtest (100%) rename format/{wav => riff}/testdata/rf64.wav (100%) rename format/{wav => riff}/testdata/stereo.fqtest (87%) rename format/{wav => riff}/testdata/stereo.wav (100%) create mode 100644 format/riff/wav.go delete mode 100644 format/wav/wav.go diff --git a/README.md b/README.md index 7bb654aa..b8ec0b57 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ avc_nalu, avc_pps, avc_sei, avc_sps, +[avi](doc/formats.md#avi), [avro_ocf](doc/formats.md#avro_ocf), [bencode](doc/formats.md#bencode), bitcoin_blkdat, diff --git a/doc/formats.md b/doc/formats.md index 8ceb4c2b..84913241 100644 --- a/doc/formats.md +++ b/doc/formats.md @@ -21,6 +21,7 @@ |`avc_pps` |H.264/AVC Picture Parameter Set || |`avc_sei` |H.264/AVC Supplemental Enhancement Information || |`avc_sps` |H.264/AVC Sequence Parameter Set || +|[`avi`](#avi) |Audio Video Interleaved |`avc_au` `hevc_au` `mp3_frame` `flac_frame`| |[`avro_ocf`](#avro_ocf) |Avro object container file || |[`bencode`](#bencode) |BitTorrent bencoding || |`bitcoin_blkdat` |Bitcoin blk.dat |`bitcoin_block`| @@ -116,7 +117,7 @@ |`inet_packet` |Group |`ipv4_packet` `ipv6_packet`| |`ip_packet` |Group |`icmp` `icmpv6` `tcp_segment` `udp_datagram`| |`link_frame` |Group |`bsd_loopback_frame` `ether8023_frame` `sll2_packet` `sll_packet`| -|`probe` |Group |`adts` `ar` `avro_ocf` `bitcoin_blkdat` `bplist` `bzip2` `elf` `flac` `gif` `gzip` `jpeg` `json` `jsonl` `macho` `macho_fat` `matroska` `mp3` `mp4` `mpeg_ts` `ogg` `pcap` `pcapng` `png` `tar` `tiff` `toml` `wasm` `wav` `webp` `xml` `yaml` `zip`| +|`probe` |Group |`adts` `ar` `avi` `avro_ocf` `bitcoin_blkdat` `bplist` `bzip2` `elf` `flac` `gif` `gzip` `jpeg` `json` `jsonl` `macho` `macho_fat` `matroska` `mp3` `mp4` `mpeg_ts` `ogg` `pcap` `pcapng` `png` `tar` `tiff` `toml` `wasm` `wav` `webp` `xml` `yaml` `zip`| |`tcp_stream` |Group |`dns_tcp` `rtmp`| |`udp_payload` |Group |`dns`| @@ -193,20 +194,60 @@ $ fq -d asn1_ber 'torepr as $r | ["version", "modulus", "private_exponent", "pri |Name |Default|Description| |- |- |-| -|`length_size`|4 |Length value size| +|`length_size`|0 |Length value size| ### Examples Decode file using avc_au options ``` -$ fq -d avc_au -o length_size=4 . file +$ fq -d avc_au -o length_size=0 . file ``` Decode value as avc_au ``` -... | avc_au({length_size:4}) +... | avc_au({length_size:0}) ``` +## avi + +### Options + +|Name |Default|Description| +|- |- |-| +|`decode_samples`|true |Decode supported media samples| + +### Examples + +Decode file using avi options +``` +$ fq -d avi -o decode_samples=true . file +``` + +Decode value as avi +``` +... | avi({decode_samples:true}) +``` + +### Samples + +AVI has many redundant ways to index samples so currently `.streams[].samples` will only include samples the most "modern" way used in the file. That is in order of stream super index, movi ix index then idx1 index. + +### Extract samples for stream 1 + +```sh +$ fq '.streams[1].samples[] | tobytes' file.avi > stream01.mp3 +``` + +### Show stream summary +```sh +$ fq -o decode_samples=false '[.chunks[0] | grep_by(.id=="LIST" and .type=="strl") | grep_by(.id=="strh") as {$type} | grep_by(.id=="strf") as {$format_tag, $compression} | {$type,$format_tag,$compression}]' *.avi +``` + +### References + +- [AVI RIFF File Reference](https://learn.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference) +- [OpenDML AVI File Format Extensions](http://www.jmcgowan.com/odmlff2.pdf) + ## avro_ocf Supports reading Avro Object Container Format (OCF) files based on the 1.11.0 specification. diff --git a/doc/formats.svg b/doc/formats.svg index 7d9529cf..c3c2ade2 100644 --- a/doc/formats.svg +++ b/doc/formats.svg @@ -4,1950 +4,1994 @@ - + formats - + adts - -adts - -adts_frame + +adts + +adts_frame adts_frame - -adts_frame - -aac_frame + +adts_frame + +aac_frame adts:e->adts_frame:n - - + + aac_frame - -aac_frame + +aac_frame adts_frame:e->aac_frame:n - - + + apev2 - -apev2 - -image + +apev2 + +image image - -image + +image apev2:e->image:n - - + + - + jpeg - -jpeg - -exif - -icc_profile + +jpeg + +exif + +icc_profile - + image->jpeg:n - - + + - + mp4 - -mp4 - -aac_frame - -av1_ccr - -av1_frame - -avc_au - -avc_dcr - -flac_frame - -flac_metadatablocks - -hevc_au - -hevc_dcr - -icc_profile - -id3v2 - -image - -jpeg - -mp3_frame - -mpeg_es - -mpeg_pes_packet - -opus_packet - -prores_frame - -protobuf_widevine - -pssh_playready - -vorbis_packet - -vp9_frame - -vpx_ccr + +mp4 + +aac_frame + +av1_ccr + +av1_frame + +avc_au + +avc_dcr + +flac_frame + +flac_metadatablocks + +hevc_au + +hevc_dcr + +icc_profile + +id3v2 + +image + +jpeg + +mp3_frame + +mpeg_es + +mpeg_pes_packet + +opus_packet + +prores_frame + +protobuf_widevine + +pssh_playready + +vorbis_packet + +vp9_frame + +vpx_ccr - + image->mp4:n - - + + - + png - -png - -icc_profile - -exif + +png + +icc_profile + +exif - + image->png:n - - + + - + tiff - -tiff - -icc_profile + +tiff + +icc_profile - + image->tiff:n - - + + - + webp - -webp - -vp8_frame + +webp + +vp8_frame - + image->webp:n - - + + - + gif - -gif + +gif - + image->gif:n - - + + ar - -ar - -probe + +ar + +probe probe - -probe + +probe ar:e->probe:n - - + + - + probe->adts:n - - + + - + probe->ar:n - - + + + + + +avi + +avi + +avc_au + +hevc_au + +mp3_frame + +flac_frame + + + +probe->avi:n + + - + bitcoin_blkdat - -bitcoin_blkdat - -bitcoin_block + +bitcoin_blkdat + +bitcoin_block - + probe->bitcoin_blkdat:n - - + + - + bzip2 - -bzip2 - -probe + +bzip2 + +probe - + probe->bzip2:n - - + + - + flac - -flac - -flac_metadatablocks - -flac_frame + +flac + +flac_metadatablocks + +flac_frame - + probe->flac:n - - + + - + gzip - -gzip - -probe + +gzip + +probe - + probe->gzip:n - - + + - + probe->jpeg:n - - + + - + macho_fat - -macho_fat - -macho + +macho_fat + +macho - + probe->macho_fat:n - - + + - + macho - -macho + +macho - + probe->macho:n - - + + - + matroska - -matroska - -aac_frame - -av1_ccr - -av1_frame - -avc_au - -avc_dcr - -flac_frame - -flac_metadatablocks - -hevc_au - -hevc_dcr - -image - -mp3_frame - -mpeg_asc - -mpeg_pes_packet - -mpeg_spu - -opus_packet - -vorbis_packet - -vp8_frame - -vp9_cfm - -vp9_frame + +matroska + +aac_frame + +av1_ccr + +av1_frame + +avc_au + +avc_dcr + +flac_frame + +flac_metadatablocks + +hevc_au + +hevc_dcr + +image + +mp3_frame + +mpeg_asc + +mpeg_pes_packet + +mpeg_spu + +opus_packet + +vorbis_packet + +vp8_frame + +vp9_cfm + +vp9_frame - + probe->matroska:n - - + + - + mp3 - -mp3 - -id3v2 - -id3v1 - -id3v11 - -apev2 - -mp3_frame + +mp3 + +id3v2 + +id3v1 + +id3v11 + +apev2 + +mp3_frame - + probe->mp3:n - - + + - + probe->mp4:n - - + + - + ogg - -ogg - -ogg_page - -vorbis_packet - -opus_packet - -flac_metadatablock - -flac_frame + +ogg + +ogg_page + +vorbis_packet + +opus_packet + +flac_metadatablock + +flac_frame - + probe->ogg:n - - + + - + pcap - -pcap - -link_frame - -tcp_stream - -ipv4_packet + +pcap + +link_frame + +tcp_stream + +ipv4_packet - + probe->pcap:n - - + + - + pcapng - -pcapng - -link_frame - -tcp_stream - -ipv4_packet + +pcapng + +link_frame + +tcp_stream + +ipv4_packet - + probe->pcapng:n - - + + - + probe->png:n - - + + - + tar - -tar - -probe + +tar + +probe - + probe->tar:n - - + + - + probe->tiff:n - - + + - + wav - -wav - -id3v2 - -id3v1 - -id3v11 + +wav + +id3v2 + +id3v1 + +id3v11 - + probe->wav:n - - + + - + probe->webp:n - - + + - + zip - -zip - -probe + +zip + +probe - + probe->zip:n - - + + - + avro_ocf - -avro_ocf + +avro_ocf - + probe->avro_ocf:n - - + + - + bplist - -bplist + +bplist - + probe->bplist:n - - + + - + elf - -elf + +elf - + probe->elf:n - - + + - + probe->gif:n - - + + - + json - -json + +json - + probe->json:n - - + + - + jsonl - -jsonl + +jsonl - + probe->jsonl:n - - + + - + mpeg_ts - -mpeg_ts + +mpeg_ts - + probe->mpeg_ts:n - - + + - + toml - -toml + +toml - + probe->toml:n - - + + - + wasm - -wasm + +wasm - + probe->wasm:n - - + + - + xml - -xml + +xml - + probe->xml:n - - + + - + yaml - -yaml + +yaml - + probe->yaml:n - - + + av1_frame - -av1_frame - -av1_obu + +av1_frame + +av1_obu av1_obu - -av1_obu + +av1_obu av1_frame:e->av1_obu:n - - + + avc_annexb - -avc_annexb - -avc_nalu + +avc_annexb + +avc_nalu avc_nalu - -avc_nalu - -avc_sps - -avc_pps - -avc_sei + +avc_nalu + +avc_sps + +avc_pps + +avc_sei avc_annexb:e->avc_nalu:n - - + + avc_sps - -avc_sps + +avc_sps avc_nalu:e->avc_sps:n - - + + avc_pps - -avc_pps + +avc_pps avc_nalu:e->avc_pps:n - - + + avc_sei - -avc_sei + +avc_sei avc_nalu:e->avc_sei:n - - + + avc_au - -avc_au - -avc_nalu + +avc_au + +avc_nalu avc_au:e->avc_nalu:n - - + + avc_dcr - -avc_dcr - -avc_nalu + +avc_dcr + +avc_nalu avc_dcr:e->avc_nalu:n - - + + - - -bitcoin_block - -bitcoin_block - -bitcoin_transaction - - + -bitcoin_blkdat:e->bitcoin_block:n - - - - - -bitcoin_transaction - -bitcoin_transaction - -bitcoin_script - - - -bitcoin_block:e->bitcoin_transaction:n - - - - - -bitcoin_script - -bitcoin_script - - - -bitcoin_transaction:e->bitcoin_script:n - - - - - -bsd_loopback_frame - -bsd_loopback_frame - -inet_packet - - - -inet_packet - -inet_packet - - - -bsd_loopback_frame:e->inet_packet:n - - - - - -ipv4_packet - -ipv4_packet - -ip_packet - - - -inet_packet->ipv4_packet:n - - - - - -ipv6_packet - -ipv6_packet - -ip_packet - - - -inet_packet->ipv6_packet:n - - - - - -bzip2:e->probe:n - - - - - -ether8023_frame - -ether8023_frame - -inet_packet - - - -ether8023_frame:e->inet_packet:n - - - - - -flac_metadatablocks - -flac_metadatablocks - -flac_metadatablock - - - -flac:e->flac_metadatablocks:n - - - - - -flac_frame - -flac_frame - - - -flac:e->flac_frame:n - - - - - -flac_metadatablock - -flac_metadatablock - -flac_streaminfo - -flac_picture - -vorbis_comment - - - -flac_metadatablocks:e->flac_metadatablock:n - - - - - -flac_streaminfo - -flac_streaminfo - - - -flac_metadatablock:e->flac_streaminfo:n - - - - - -flac_picture - -flac_picture - -image - - - -flac_metadatablock:e->flac_picture:n - - - - - -vorbis_comment - -vorbis_comment - -flac_picture - - - -flac_metadatablock:e->vorbis_comment:n - - - - - -flac_picture:e->image:n - - - - - -vorbis_comment:e->flac_picture:n - - - - - -gzip:e->probe:n - - - - - -hevc_annexb - -hevc_annexb - -hevc_nalu - - - -hevc_nalu - -hevc_nalu - -hevc_vps - -hevc_pps - -hevc_sps - - - -hevc_annexb:e->hevc_nalu:n - - - - - -hevc_vps - -hevc_vps - - - -hevc_nalu:e->hevc_vps:n - - - - - -hevc_pps - -hevc_pps - - - -hevc_nalu:e->hevc_pps:n - - - - - -hevc_sps - -hevc_sps - - - -hevc_nalu:e->hevc_sps:n - - +avi:e->avc_au:n + + - + hevc_au - -hevc_au - -hevc_nalu + +hevc_au + +hevc_nalu - - -hevc_au:e->hevc_nalu:n - - - - - -hevc_dcr - -hevc_dcr - -hevc_nalu - - - -hevc_dcr:e->hevc_nalu:n - - - - - -id3v2 - -id3v2 - -image - - - -id3v2:e->image:n - - - - - -ip_packet - -ip_packet - - - -ipv4_packet:e->ip_packet:n - - - - - -udp_datagram - -udp_datagram - -udp_payload - - - -ip_packet->udp_datagram:n - - - - - -icmp - -icmp - - - -ip_packet->icmp:n - - - - - -icmpv6 - -icmpv6 - - - -ip_packet->icmpv6:n - - - - - -tcp_segment - -tcp_segment - - - -ip_packet->tcp_segment:n - - - - - -ipv6_packet:e->ip_packet:n - - - - - -exif - -exif - - - -jpeg:e->exif:n - - - - - -icc_profile - -icc_profile - - - -jpeg:e->icc_profile:n - - - - - -macho_fat:e->macho:n - - - - - -matroska:e->aac_frame:n - - - - - -matroska:e->image:n - - - - - -matroska:e->av1_frame:n - - - - - -matroska:e->avc_au:n - - - - - -matroska:e->avc_dcr:n - - - - - -matroska:e->flac_metadatablocks:n - - - - - -matroska:e->flac_frame:n - - - - - -matroska:e->hevc_au:n - - - - - -matroska:e->hevc_dcr:n - - - - - -av1_ccr - -av1_ccr - - - -matroska:e->av1_ccr:n - - + + +avi:e->hevc_au:n + + - + mp3_frame - -mp3_frame - -mp3_frame_tags + +mp3_frame + +mp3_frame_tags - - -matroska:e->mp3_frame:n - - + + +avi:e->mp3_frame:n + + - - -mpeg_asc - -mpeg_asc + + +flac_frame + +flac_frame - - -matroska:e->mpeg_asc:n - - + + +avi:e->flac_frame:n + + - - -mpeg_pes_packet - -mpeg_pes_packet + + +hevc_nalu + +hevc_nalu + +hevc_vps + +hevc_pps + +hevc_sps - - -matroska:e->mpeg_pes_packet:n - - - - - -mpeg_spu - -mpeg_spu - - - -matroska:e->mpeg_spu:n - - - - - -opus_packet - -opus_packet - -vorbis_comment - - - -matroska:e->opus_packet:n - - - - - -vorbis_packet - -vorbis_packet - -vorbis_comment - - - -matroska:e->vorbis_packet:n - - - - - -vp8_frame - -vp8_frame - - - -matroska:e->vp8_frame:n - - - - - -vp9_cfm - -vp9_cfm - - - -matroska:e->vp9_cfm:n - - - - - -vp9_frame - -vp9_frame - - - -matroska:e->vp9_frame:n - - + + +hevc_au:e->hevc_nalu:n + + - + mp3_frame_tags - -mp3_frame_tags + +mp3_frame_tags - + mp3_frame:e->mp3_frame_tags:n - - + + + + + +bitcoin_block + +bitcoin_block + +bitcoin_transaction + + + +bitcoin_blkdat:e->bitcoin_block:n + + + + + +bitcoin_transaction + +bitcoin_transaction + +bitcoin_script + + + +bitcoin_block:e->bitcoin_transaction:n + + + + + +bitcoin_script + +bitcoin_script + + + +bitcoin_transaction:e->bitcoin_script:n + + + + + +bsd_loopback_frame + +bsd_loopback_frame + +inet_packet + + + +inet_packet + +inet_packet + + + +bsd_loopback_frame:e->inet_packet:n + + + + + +ipv4_packet + +ipv4_packet + +ip_packet + + + +inet_packet->ipv4_packet:n + + + + + +ipv6_packet + +ipv6_packet + +ip_packet + + + +inet_packet->ipv6_packet:n + + + + + +bzip2:e->probe:n + + + + + +ether8023_frame + +ether8023_frame + +inet_packet + + + +ether8023_frame:e->inet_packet:n + + + + + +flac:e->flac_frame:n + + + + + +flac_metadatablocks + +flac_metadatablocks + +flac_metadatablock + + + +flac:e->flac_metadatablocks:n + + + + + +flac_metadatablock + +flac_metadatablock + +flac_streaminfo + +flac_picture + +vorbis_comment + + + +flac_metadatablocks:e->flac_metadatablock:n + + + + + +flac_streaminfo + +flac_streaminfo + + + +flac_metadatablock:e->flac_streaminfo:n + + + + + +flac_picture + +flac_picture + +image + + + +flac_metadatablock:e->flac_picture:n + + + + + +vorbis_comment + +vorbis_comment + +flac_picture + + + +flac_metadatablock:e->vorbis_comment:n + + + + + +flac_picture:e->image:n + + + + + +vorbis_comment:e->flac_picture:n + + + + + +gzip:e->probe:n + + + + + +hevc_annexb + +hevc_annexb + +hevc_nalu + + + +hevc_annexb:e->hevc_nalu:n + + + + + +hevc_vps + +hevc_vps + + + +hevc_nalu:e->hevc_vps:n + + + + + +hevc_pps + +hevc_pps + + + +hevc_nalu:e->hevc_pps:n + + + + + +hevc_sps + +hevc_sps + + + +hevc_nalu:e->hevc_sps:n + + + + + +hevc_dcr + +hevc_dcr + +hevc_nalu + + + +hevc_dcr:e->hevc_nalu:n + + + + + +id3v2 + +id3v2 + +image + + + +id3v2:e->image:n + + + + + +ip_packet + +ip_packet + + + +ipv4_packet:e->ip_packet:n + + + + + +udp_datagram + +udp_datagram + +udp_payload + + + +ip_packet->udp_datagram:n + + + + + +icmp + +icmp + + + +ip_packet->icmp:n + + + + + +icmpv6 + +icmpv6 + + + +ip_packet->icmpv6:n + + + + + +tcp_segment + +tcp_segment + + + +ip_packet->tcp_segment:n + + + + + +ipv6_packet:e->ip_packet:n + + + + + +exif + +exif + + + +jpeg:e->exif:n + + + + + +icc_profile + +icc_profile + + + +jpeg:e->icc_profile:n + + + + + +macho_fat:e->macho:n + + + + + +matroska:e->aac_frame:n + + + + + +matroska:e->image:n + + + + + +matroska:e->av1_frame:n + + + + + +matroska:e->avc_au:n + + + + + +matroska:e->avc_dcr:n + + + + + +matroska:e->hevc_au:n + + + + + +matroska:e->mp3_frame:n + + + + + +matroska:e->flac_frame:n + + + + + +matroska:e->flac_metadatablocks:n + + + + + +matroska:e->hevc_dcr:n + + + + + +av1_ccr + +av1_ccr + + + +matroska:e->av1_ccr:n + + + + + +mpeg_asc + +mpeg_asc + + + +matroska:e->mpeg_asc:n + + + + + +mpeg_pes_packet + +mpeg_pes_packet + + + +matroska:e->mpeg_pes_packet:n + + + + + +mpeg_spu + +mpeg_spu + + + +matroska:e->mpeg_spu:n + + + + + +opus_packet + +opus_packet + +vorbis_comment + + + +matroska:e->opus_packet:n + + + + + +vorbis_packet + +vorbis_packet + +vorbis_comment + + + +matroska:e->vorbis_packet:n + + + + + +vp8_frame + +vp8_frame + + + +matroska:e->vp8_frame:n + + + + + +vp9_cfm + +vp9_cfm + + + +matroska:e->vp9_cfm:n + + + + + +vp9_frame + +vp9_frame + + + +matroska:e->vp9_frame:n + + - + opus_packet:e->vorbis_comment:n - - + + - + vorbis_packet:e->vorbis_comment:n - - + + - + mp3:e->apev2:n - - - - - -mp3:e->id3v2:n - - + + - + mp3:e->mp3_frame:n - - + + + + + +mp3:e->id3v2:n + + - + id3v1 - -id3v1 + +id3v1 - + mp3:e->id3v1:n - - + + - + id3v11 - -id3v11 + +id3v11 - + mp3:e->id3v11:n - - + + - + mp4:e->aac_frame:n - - + + - + mp4:e->image:n - - + + - + mp4:e->av1_frame:n - - + + - + mp4:e->avc_au:n - - + + - + mp4:e->avc_dcr:n - - - - - -mp4:e->flac_metadatablocks:n - - - - - -mp4:e->flac_frame:n - - + + - + mp4:e->hevc_au:n - - - - - -mp4:e->hevc_dcr:n - - - - - -mp4:e->id3v2:n - - - - - -mp4:e->jpeg:n - - - - - -mp4:e->icc_profile:n - - - - - -mp4:e->av1_ccr:n - - + + - + mp4:e->mp3_frame:n - - + + + + + +mp4:e->flac_frame:n + + + + + +mp4:e->flac_metadatablocks:n + + + + + +mp4:e->hevc_dcr:n + + + + + +mp4:e->id3v2:n + + + + + +mp4:e->jpeg:n + + + + + +mp4:e->icc_profile:n + + + + + +mp4:e->av1_ccr:n + + - + mp4:e->mpeg_pes_packet:n - - + + - + mp4:e->opus_packet:n - - + + - + mp4:e->vorbis_packet:n - - + + - + mp4:e->vp9_frame:n - - + + - + mpeg_es - -mpeg_es - -mpeg_asc - -vorbis_packet + +mpeg_es + +mpeg_asc + +vorbis_packet - + mp4:e->mpeg_es:n - - + + - + prores_frame - -prores_frame + +prores_frame - + mp4:e->prores_frame:n - - + + - + protobuf_widevine - -protobuf_widevine - -protobuf + +protobuf_widevine + +protobuf - + mp4:e->protobuf_widevine:n - - + + - + pssh_playready - -pssh_playready + +pssh_playready - + mp4:e->pssh_playready:n - - + + - + vpx_ccr - -vpx_ccr + +vpx_ccr - + mp4:e->vpx_ccr:n - - + + - + mpeg_es:e->mpeg_asc:n - - + + - + mpeg_es:e->vorbis_packet:n - - + + - + protobuf - -protobuf + +protobuf - + protobuf_widevine:e->protobuf:n - - + + - + mpeg_pes - -mpeg_pes - -mpeg_pes_packet - -mpeg_spu + +mpeg_pes + +mpeg_pes_packet + +mpeg_spu - + mpeg_pes:e->mpeg_pes_packet:n - - + + - + mpeg_pes:e->mpeg_spu:n - - + + - + ogg:e->flac_frame:n - - + + - + ogg:e->flac_metadatablock:n - - + + - + ogg:e->opus_packet:n - - + + - + ogg:e->vorbis_packet:n - - + + - + ogg_page - -ogg_page + +ogg_page - + ogg:e->ogg_page:n - - + + - + pcap:e->ipv4_packet:n - - + + - + link_frame - -link_frame + +link_frame - + pcap:e->link_frame:n - - + + - + tcp_stream - -tcp_stream + +tcp_stream - + pcap:e->tcp_stream:n - - + + - + link_frame->bsd_loopback_frame:n - - + + - + link_frame->ether8023_frame:n - - + + - + sll2_packet - -sll2_packet - -inet_packet + +sll2_packet + +inet_packet - + link_frame->sll2_packet:n - - + + - + sll_packet - -sll_packet - -inet_packet + +sll_packet + +inet_packet - + link_frame->sll_packet:n - - + + - + rtmp - -rtmp - -amf0 - -mpeg_asc + +rtmp + +amf0 + +mpeg_asc - + tcp_stream->rtmp:n - - + + - + dns_tcp - -dns_tcp + +dns_tcp - + tcp_stream->dns_tcp:n - - + + - + pcapng:e->ipv4_packet:n - - + + - + pcapng:e->link_frame:n - - + + - + pcapng:e->tcp_stream:n - - + + - + png:e->exif:n - - + + - + png:e->icc_profile:n - - + + - + rtmp:e->mpeg_asc:n - - + + - + amf0 - -amf0 + +amf0 - + rtmp:e->amf0:n - - + + - + sll2_packet:e->inet_packet:n - - + + - + sll_packet:e->inet_packet:n - - + + - + tar:e->probe:n - - + + - + tiff:e->icc_profile:n - - + + - + udp_payload - -udp_payload + +udp_payload - + udp_datagram:e->udp_payload:n - - + + - + dns - -dns + +dns - + udp_payload->dns:n - - + + - + wav:e->id3v2:n - - + + - + wav:e->id3v1:n - - + + - + wav:e->id3v11:n - - + + - + webp:e->vp8_frame:n - - + + - + zip:e->probe:n - - + + - + asn1_ber - -asn1_ber + +asn1_ber - + bencode - -bencode + +bencode - + bson - -bson + +bson - + cbor - -cbor + +cbor - + csv - -csv + +csv - + fairplay_spc - -fairplay_spc + +fairplay_spc - + html - -html + +html - + markdown - -markdown + +markdown - + msgpack - -msgpack + +msgpack - + raw - -raw + +raw diff --git a/format/all/all.fqtest b/format/all/all.fqtest index c77eb789..bfe69a73 100644 --- a/format/all/all.fqtest +++ b/format/all/all.fqtest @@ -2,6 +2,7 @@ $ fq -n _registry.groups.probe [ "adts", "ar", + "avi", "avro_ocf", "bitcoin_blkdat", "bplist", @@ -51,6 +52,7 @@ avc_nalu H.264/AVC Network Access Layer Unit avc_pps H.264/AVC Picture Parameter Set avc_sei H.264/AVC Supplemental Enhancement Information avc_sps H.264/AVC Sequence Parameter Set +avi Audio Video Interleaved avro_ocf Avro object container file bencode BitTorrent bencoding bitcoin_blkdat Bitcoin blk.dat diff --git a/format/all/all.go b/format/all/all.go index 7a7b1ba0..52cda06c 100644 --- a/format/all/all.go +++ b/format/all/all.go @@ -43,6 +43,7 @@ import ( _ "github.com/wader/fq/format/prores" _ "github.com/wader/fq/format/protobuf" _ "github.com/wader/fq/format/raw" + _ "github.com/wader/fq/format/riff" _ "github.com/wader/fq/format/rtmp" _ "github.com/wader/fq/format/tar" _ "github.com/wader/fq/format/text" @@ -51,7 +52,6 @@ import ( _ "github.com/wader/fq/format/vorbis" _ "github.com/wader/fq/format/vpx" _ "github.com/wader/fq/format/wasm" - _ "github.com/wader/fq/format/wav" _ "github.com/wader/fq/format/webp" _ "github.com/wader/fq/format/xml" _ "github.com/wader/fq/format/yaml" diff --git a/format/format.go b/format/format.go index f69fb200..ba65475d 100644 --- a/format/format.go +++ b/format/format.go @@ -39,6 +39,7 @@ const ( AVC_PPS = "avc_pps" AVC_SEI = "avc_sei" AVC_SPS = "avc_sps" + AVI = "avi" AVRO_OCF = "avro_ocf" BENCODE = "bencode" BITCOIN_BLKDAT = "bitcoin_blkdat" @@ -292,6 +293,10 @@ type Mp4In struct { AllowTruncated bool `doc:"Allow box to be truncated"` } +type AviIn struct { + DecodeSamples bool `doc:"Decode supported media samples"` +} + type ZipIn struct { Uncompress bool `doc:"Uncompress and probe files"` } diff --git a/format/media.go b/format/media.go index 5228a905..fdd81381 100644 --- a/format/media.go +++ b/format/media.go @@ -250,3 +250,607 @@ var ISO_23091_2_MatrixCoefficients = scalar.UToScalar{ 13: {Sym: "chroma_derived_cl", Description: "Chromaticity-derived constant luminance system"}, 14: {Sym: "ictcp", Description: "ITU-R BT.2100-0, ICtCp"}, } + +// based on ffmpeg libavformat/riff.c +// +//nolint:revive +const ( + WAVTagPCM_S16LE = 0x0001 + WAVTagADPCM_MS = 0x0002 + WAVTagPCM_F32LE = 0x0003 + WAVTagPCM_ALAW = 0x0006 + WAVTagPCM_MULAW = 0x0007 + WAVTagWMAVOICE = 0x000a + WAVTagADPCM_IMA_OKI = 0x0010 + WAVTagADPCM_IMA_WAV = 0x0011 + WAVTagADPCM_IMA_OKI_2 = 0x0017 + WAVTagADPCM_YAMAHA = 0x0020 + WAVTagTRUESPEECH = 0x0022 + WAVTagGSM_MS = 0x0031 + WAVTagGSM_MS_2 = 0x0032 + WAVTagAMR_NB = 0x0038 + WAVTagG723_1 = 0x0042 + WAVTagADPCM_G726 = 0x0045 + WAVTagADPCM_G726_2 = 0x0014 + WAVTagADPCM_G726_3 = 0x0040 + WAVTagMP2 = 0x0050 + WAVTagMP3 = 0x0055 + WAVTagAMR_NB_2 = 0x0057 + WAVTagAMR_WB = 0x0058 + WAVTagADPCM_IMA_DK4 = 0x0061 + WAVTagADPCM_IMA_DK3 = 0x0062 + WAVTagADPCM_G726_4 = 0x0064 + WAVTagADPCM_IMA_WAV_2 = 0x0069 + WAVTagMETASOUND = 0x0075 + WAVTagG729 = 0x0083 + WAVTagAAC = 0x00ff + WAVTagG723_1_2 = 0x0111 + WAVTagSIPR = 0x0130 + WAVTagACELP_KELVIN = 0x0135 + WAVTagWMAV1 = 0x0160 + WAVTagWMAV2 = 0x0161 + WAVTagWMAPRO = 0x0162 + WAVTagWMALOSSLESS = 0x0163 + WAVTagXMA1 = 0x0165 + WAVTagXMA2 = 0x0166 + WAVTagFTR = 0x0180 + WAVTagADPCM_CT = 0x0200 + WAVTagDVAUDIO = 0x0215 + WAVTagDVAUDIO_2 = 0x0216 + WAVTagATRAC3 = 0x0270 + WAVTagMSNSIREN = 0x028e + WAVTagADPCM_G722 = 0x028f + WAVTagMISC4 = 0x0350 + WAVTagIMC = 0x0401 + WAVTagIAC = 0x0402 + WAVTagON2AVC = 0x0500 + WAVTagON2AVC_2 = 0x0501 + WAVTagGSM_MS_3 = 0x1500 + WAVTagTRUESPEECH_2 = 0x1501 + WAVTagAAC_2 = 0x1600 + WAVTagAAC_LATM = 0x1602 + WAVTagAC3 = 0x2000 + WAVTagDTS = 0x2001 + WAVTagSONIC = 0x2048 + WAVTagG729_2 = 0x2222 + WAVTagPCM_MULAW_2 = 0x6c75 + WAVTagAAC_3 = 0x706d + WAVTagAAC_4 = 0x4143 + WAVTagFTR_2 = 0x4180 + WAVTagXAN_DPCM = 0x594a + WAVTagG729_3 = 0x729a + WAVTagFTR_3 = 0x8180 + WAVTagG723_1_3 = 0xa100 + WAVTagAAC_5 = 0xa106 + WAVTagSPEEX = 0xa109 + WAVTagFLAC = 0xf1ac + WAVTagFORMATEX = 0xfffe + WAVTagADPCM_SWF = 0x5356 + WAVTagVORBIS = 0x566f +) + +var WAVTagNames = scalar.UToSymStr{ + WAVTagPCM_S16LE: "pcm_s16le", + WAVTagADPCM_MS: "adpcm_ms", + WAVTagPCM_F32LE: "pcm_f32le", + WAVTagPCM_ALAW: "pcm_alaw", + WAVTagPCM_MULAW: "pcm_mulaw", + WAVTagWMAVOICE: "wmavoice", + WAVTagADPCM_IMA_OKI: "adpcm_ima_oki", + WAVTagADPCM_IMA_WAV: "adpcm_ima_wav", + WAVTagADPCM_IMA_OKI_2: "adpcm_ima_oki_2", + WAVTagADPCM_YAMAHA: "adpcm_yamaha", + WAVTagTRUESPEECH: "truespeech", + WAVTagGSM_MS: "gsm_ms", + WAVTagGSM_MS_2: "gsm_ms_2", + WAVTagAMR_NB: "amr_nb", + WAVTagG723_1: "g723_1", + WAVTagADPCM_G726: "adpcm_g726", + WAVTagADPCM_G726_2: "adpcm_g726_2", + WAVTagADPCM_G726_3: "adpcm_g726_3", + WAVTagMP2: "mp2", + WAVTagMP3: "mp3", + WAVTagAMR_NB_2: "amr_nb_2", + WAVTagAMR_WB: "amr_wb", + WAVTagADPCM_IMA_DK4: "adpcm_ima_dk4", + WAVTagADPCM_IMA_DK3: "adpcm_ima_dk3", + WAVTagADPCM_G726_4: "adpcm_g726_4", + WAVTagADPCM_IMA_WAV_2: "adpcm_ima_wav_2", + WAVTagMETASOUND: "metasound", + WAVTagG729: "g729", + WAVTagAAC: "aac", + WAVTagG723_1_2: "g723_1_2", + WAVTagSIPR: "sipr", + WAVTagACELP_KELVIN: "acelp_kelvin", + WAVTagWMAV1: "wmav1", + WAVTagWMAV2: "wmav2", + WAVTagWMAPRO: "wmapro", + WAVTagWMALOSSLESS: "wmalossless", + WAVTagXMA1: "xma1", + WAVTagXMA2: "xma2", + WAVTagFTR: "ftr", + WAVTagADPCM_CT: "adpcm_ct", + WAVTagDVAUDIO: "dvaudio", + WAVTagDVAUDIO_2: "dvaudio_2", + WAVTagATRAC3: "atrac3", + WAVTagMSNSIREN: "msnsiren", + WAVTagADPCM_G722: "adpcm_g722", + WAVTagMISC4: "misc4", + WAVTagIMC: "imc", + WAVTagIAC: "iac", + WAVTagON2AVC: "on2avc", + WAVTagON2AVC_2: "on2avc_2", + WAVTagGSM_MS_3: "gsm_ms_3", + WAVTagTRUESPEECH_2: "truespeech_2", + WAVTagAAC_2: "aac_2", + WAVTagAAC_LATM: "aac_latm", + WAVTagAC3: "ac3", + WAVTagDTS: "dts", + WAVTagSONIC: "sonic", + WAVTagG729_2: "g729_2", + WAVTagPCM_MULAW_2: "pcm_mulaw_2", + WAVTagAAC_3: "aac_3", + WAVTagAAC_4: "aac_4", + WAVTagFTR_2: "ftr_2", + WAVTagXAN_DPCM: "xan_dpcm", + WAVTagG729_3: "g729_3", + WAVTagFTR_3: "ftr_3", + WAVTagG723_1_3: "g723_1_3", + WAVTagAAC_5: "aac_5", + WAVTagSPEEX: "speex", + WAVTagFLAC: "flac", + WAVTagFORMATEX: "formatex", + WAVTagADPCM_SWF: "adpcm_swf", + WAVTagVORBIS: "vorbis", +} + +// based on ffmpeg libavformat/riff.c +// +//nolint:revive +const ( + BMPTagH264 = "H264" + BMPTagH264_h264 = "h264" + BMPTagH264_X264 = "X264" + BMPTagH264_x264 = "x264" + BMPTagH264_avc1 = "avc1" + BMPTagH264_DAVC = "DAVC" + BMPTagH264_SMV2 = "SMV2" + BMPTagH264_VSSH = "VSSH" + BMPTagH264_Q264 = "Q264" // QNAP surveillance system + BMPTagH264_V264 = "V264" // CCTV recordings + BMPTagH264_GAVC = "GAVC" // GeoVision camera + BMPTagH264_UMSV = "UMSV" + BMPTagH264_tshd = "tshd" + BMPTagH264_INMC = "INMC" + BMPTagH263 = "H263" + BMPTagH263_X263 = "X263" + BMPTagH263_T263 = "T263" + BMPTagH263_L263 = "L263" + BMPTagH263_VX1K = "VX1K" + BMPTagH263_ZyGo = "ZyGo" + BMPTagH263_M263 = "M263" + BMPTagH263_lsvm = "lsvm" + BMPTagH263P = "H263" + BMPTagH263I = "I263" // Intel H.263 + BMPTagH261 = "H261" + BMPTagH263_U263 = "U263" + BMPTagH263_VSM4 = "VSM4" // needs -vf il=l=i:c=i + BMPTagMPEG4 = "FMP4" + BMPTagMPEG4_DIVX = "DIVX" + BMPTagMPEG4_DX50 = "DX50" + BMPTagMPEG4_XVID = "XVID" + BMPTagMPEG4_MP4S = "MP4S" + BMPTagMPEG4_M4S2 = "M4S2" // some broken AVIs use this + BMPTagMPEG4_04000000 = "\x04\x00\x00\x00" // some broken AVIs use this + BMPTagMPEG4_ZMP4 = "ZMP4" + BMPTagMPEG4_DIV1 = "DIV1" + BMPTagMPEG4_BLZ0 = "BLZ0" + BMPTagMPEG4_mp4v = "mp4v" + BMPTagMPEG4_UMP4 = "UMP4" + BMPTagMPEG4_WV1F = "WV1F" + BMPTagMPEG4_SEDG = "SEDG" + BMPTagMPEG4_RMP4 = "RMP4" + BMPTagMPEG4_3IV2 = "3IV2" // WaWv MPEG-4 Video Codec + BMPTagMPEG4_WAWV = "WAWV" + BMPTagMPEG4_FFDS = "FFDS" + BMPTagMPEG4_FVFW = "FVFW" + BMPTagMPEG4_DCOD = "DCOD" + BMPTagMPEG4_MVXM = "MVXM" + BMPTagMPEG4_PM4V = "PM4V" + BMPTagMPEG4_SMP4 = "SMP4" + BMPTagMPEG4_DXGM = "DXGM" + BMPTagMPEG4_VIDM = "VIDM" + BMPTagMPEG4_M4T3 = "M4T3" + BMPTagMPEG4_GEOX = "GEOX" // flipped video + BMPTagMPEG4_G264 = "G264" // flipped video + BMPTagMPEG4_HDX4 = "HDX4" + BMPTagMPEG4_DM4V = "DM4V" + BMPTagMPEG4_DMK2 = "DMK2" + BMPTagMPEG4_DYM4 = "DYM4" + BMPTagMPEG4_DIGI = "DIGI" // Ephv MPEG-4 + BMPTagMPEG4_EPHV = "EPHV" + BMPTagMPEG4_EM4A = "EM4A" // Divio MPEG-4 + BMPTagMPEG4_M4CC = "M4CC" + BMPTagMPEG4_SN40 = "SN40" + BMPTagMPEG4_VSPX = "VSPX" + BMPTagMPEG4_ULDX = "ULDX" + BMPTagMPEG4_GEOV = "GEOV" // Samsung SHR-6040 + BMPTagMPEG4_SIPP = "SIPP" + BMPTagMPEG4_SM4V = "SM4V" + BMPTagMPEG4_XVIX = "XVIX" + BMPTagMPEG4_DreX = "DreX" + BMPTagMPEG4_QMP4 = "QMP4" // QNAP Systems + BMPTagMPEG4_PLV1 = "PLV1" // Pelco DVR MPEG-4 + BMPTagMPEG4_GLV4 = "GLV4" + BMPTagMPEG4_GMP4 = "GMP4" // GeoVision camera + BMPTagMPEG4_MNM4 = "MNM4" // March Networks DVR + BMPTagMPEG4_GTM4 = "GTM4" // Telefactor + BMPTagMSMPEG4V3 = "MP43" + BMPTagMSMPEG4V3_DIV3 = "DIV3" + BMPTagMSMPEG4V3_MPG3 = "MPG3" + BMPTagMSMPEG4V3_DIV5 = "DIV5" + BMPTagMSMPEG4V3_DIV6 = "DIV6" + BMPTagMSMPEG4V3_DIV4 = "DIV4" + BMPTagMSMPEG4V3_DVX3 = "DVX3" + BMPTagMSMPEG4V3_AP41 = "AP41" + BMPTagMSMPEG4V3_COL1 = "COL1" + BMPTagMSMPEG4V3_COL0 = "COL0" + BMPTagMSMPEG4V2 = "MP42" + BMPTagMSMPEG4V2_DIV2 = "DIV2" + BMPTagMSMPEG4V1 = "MPG4" + BMPTagMSMPEG4V1_MP41 = "MP41" + BMPTagWMV1 = "WMV1" + BMPTagWMV2 = "WMV2" + BMPTagWMV2_GXVE = "GXVE" + BMPTagDVVIDEO = "dvsd" + BMPTagDVVIDEO_dvhd = "dvhd" + BMPTagDVVIDEO_dvh1 = "dvh1" + BMPTagDVVIDEO_dvsl = "dvsl" + BMPTagDVVIDEO_dv25 = "dv25" + BMPTagDVVIDEO_dv50 = "dv50" // Canopus DV + BMPTagDVVIDEO_cdvc = "cdvc" // Canopus DV + BMPTagDVVIDEO_CDVH = "CDVH" // Canopus DV + BMPTagDVVIDEO_CDV5 = "CDV5" + BMPTagDVVIDEO_dvc = "dvc " + BMPTagDVVIDEO_dvcs = "dvcs" + BMPTagDVVIDEO_dvis = "dvis" + BMPTagDVVIDEO_pdvc = "pdvc" + BMPTagDVVIDEO_SL25 = "SL25" + BMPTagDVVIDEO_SLDV = "SLDV" + BMPTagDVVIDEO_AVd1 = "AVd1" + BMPTagMPEG1VIDEO = "mpg1" + BMPTagMPEG2VIDEO_mpg2 = "mpg2" + BMPTagMPEG2VIDEO_MPEG = "MPEG" + BMPTagMPEG1VIDEO_PIM1 = "PIM1" + BMPTagMPEG2VIDEO_PIM2 = "PIM2" + BMPTagMPEG1VIDEO_VCR2 = "VCR2" + BMPTagMPEG1VIDEO_01000016 = "\x01\x00\x00\x16" + BMPTagMPEG2VIDEO_02000016 = "\x02\x00\x00\x16" + BMPTagMPEG4_04000016 = "\x04\x00\x00\x16" + BMPTagMPEG2VIDEO = "DVR " + BMPTagMPEG2VIDEOMMES = "MMES" // Lead MPEG-2 in AVI + BMPTagMPEG2VIDEOLMP2 = "LMP2" + BMPTagMPEG2VIDEOslif = "slif" + BMPTagMPEG2VIDEOEM2V = "EM2V" // Matrox MPEG-2 intra-only + BMPTagMPEG2VIDEOM701 = "M701" + BMPTagMPEG2VIDEOM702 = "M702" + BMPTagMPEG2VIDEOM703 = "M703" + BMPTagMPEG2VIDEOM704 = "M704" + BMPTagMPEG2VIDEOM705 = "M705" + BMPTagMPEG2VIDEOmpgv = "mpgv" + BMPTagMPEG1VIDEO_BW10 = "BW10" + BMPTagMPEG1VIDEO_XMPG = "XMPG" // Xing MPEG intra only + BMPTagMJPEG = "MJPG" + BMPTagMJPEG_MSC2 = "MSC2" // Multiscope II + BMPTagMJPEG_LJPG = "LJPG" + BMPTagMJPEG_dmb1 = "dmb1" + BMPTagMJPEG_mjpa = "mjpa" + BMPTagMJPEG_JR24 = "JR24" // Quadrox Mjpeg + BMPTagLJPEG = "LJPG" // Pegasus lossless JPEG + BMPTagMJPEG_JPGL = "JPGL" // JPEG-LS custom FOURCC for AVI - encoder + BMPTagJPEGLS = "MJLS" + BMPTagJPEGLS_MJPG = "MJPG" // JPEG-LS custom FOURCC for AVI - decoder + BMPTagMJPEG_MJLS = "MJLS" + BMPTagMJPEG_jpeg = "jpeg" + BMPTagMJPEG_IJPG = "IJPG" + BMPTagAVRN = "AVRn" + BMPTagMJPEG_ACDV = "ACDV" + BMPTagMJPEG_QIVG = "QIVG" // SL M-JPEG + BMPTagMJPEG_SLMJ = "SLMJ" // Creative Webcam JPEG + BMPTagMJPEG_CJPG = "CJPG" // Intel JPEG Library Video Codec + BMPTagMJPEG_IJLV = "IJLV" // Midvid JPEG Video Codec + BMPTagMJPEG_MVJP = "MVJP" + BMPTagMJPEG_AVI1 = "AVI1" + BMPTagMJPEG_AVI2 = "AVI2" + BMPTagMJPEG_MTSJ = "MTSJ" // Paradigm Matrix M-JPEG Codec + BMPTagMJPEG_ZJPG = "ZJPG" + BMPTagMJPEG_MMJP = "MMJP" + BMPTagHUFFYUV = "HFYU" + BMPTagFFVHUFF = "FFVH" + BMPTagCYUV = "CYUV" + BMPTagRAWVIDEO_00000000 = "\x00\x00\x00\x00" + BMPTagRAWVIDEO_03000000 = "\x03\x00\x00\x00" + BMPTagRAWVIDEO_I420 = "I420" + BMPTagRAWVIDEO_YUY2 = "YUY2" + BMPTagRAWVIDEO_Y422 = "Y422" + BMPTagRAWVIDEO_V422 = "V422" + BMPTagRAWVIDEO_YUNV = "YUNV" + BMPTagRAWVIDEO_UYNV = "UYNV" + BMPTagRAWVIDEO_UYNY = "UYNY" + BMPTagRAWVIDEO_uyv1 = "uyv1" + BMPTagRAWVIDEO_2Vu1 = "2Vu1" + BMPTagRAWVIDEO_2vuy = "2vuy" + BMPTagRAWVIDEO_yuvs = "yuvs" + BMPTagRAWVIDEO_yuv2 = "yuv2" + BMPTagRAWVIDEO_P422 = "P422" + BMPTagRAWVIDEO_YV12 = "YV12" + BMPTagRAWVIDEO_YV16 = "YV16" + BMPTagRAWVIDEO_YV24 = "YV24" + BMPTagRAWVIDEO_UYVY = "UYVY" + BMPTagRAWVIDEO_VYUY = "VYUY" + BMPTagRAWVIDEO_IYUV = "IYUV" + BMPTagRAWVIDEO_AYUV = "AYUV" + BMPTagRAWVIDEO_Y800 = "Y800" + BMPTagRAWVIDEO_Y8 = "Y8 " + BMPTagRAWVIDEO_HDYC = "HDYC" + BMPTagRAWVIDEO_VDTZ = "VDTZ" + BMPTagRAWVIDEO_Y411 = "Y411" + BMPTagRAWVIDEO_NV12 = "NV12" + BMPTagRAWVIDEO_NV21 = "NV21" + BMPTagRAWVIDEO_Y41B = "Y41B" + BMPTagRAWVIDEO_Y42B = "Y42B" + BMPTagRAWVIDEO_YUV9 = "YUV9" + BMPTagRAWVIDEO_YVU9 = "YVU9" + BMPTagRAWVIDEO_auv2 = "auv2" + BMPTagRAWVIDEO_YVYU = "YVYU" + BMPTagRAWVIDEO_YUYV = "YUYV" + BMPTagRAWVIDEO_I410 = "I410" + BMPTagRAWVIDEO_I411 = "I411" + BMPTagRAWVIDEO_I422 = "I422" + BMPTagRAWVIDEO_I440 = "I440" + BMPTagRAWVIDEO_I444 = "I444" + BMPTagRAWVIDEO_J420 = "J420" + BMPTagRAWVIDEO_J422 = "J422" + BMPTagRAWVIDEO_J440 = "J440" + BMPTagRAWVIDEO_J444 = "J444" + BMPTagRAWVIDEO_YUVA = "YUVA" + BMPTagRAWVIDEO_I40A = "I40A" + BMPTagRAWVIDEO_I42A = "I42A" + BMPTagRAWVIDEO_RGB2 = "RGB2" + BMPTagRAWVIDEO_RV15 = "RV15" + BMPTagRAWVIDEO_RV16 = "RV16" + BMPTagRAWVIDEO_RV24 = "RV24" + BMPTagRAWVIDEO_RV32 = "RV32" + BMPTagRAWVIDEO_RGBA = "RGBA" + BMPTagRAWVIDEO_AV32 = "AV32" + BMPTagRAWVIDEO_GREY = "GREY" + BMPTagRAWVIDEO_I09L = "I09L" + BMPTagRAWVIDEO_I09B = "I09B" + BMPTagRAWVIDEO_I29L = "I29L" + BMPTagRAWVIDEO_I29B = "I29B" + BMPTagRAWVIDEO_I49L = "I49L" + BMPTagRAWVIDEO_I49B = "I49B" + BMPTagRAWVIDEO_I0AL = "I0AL" + BMPTagRAWVIDEO_I0AB = "I0AB" + BMPTagRAWVIDEO_I2AL = "I2AL" + BMPTagRAWVIDEO_I2AB = "I2AB" + BMPTagRAWVIDEO_I4AL = "I4AL" + BMPTagRAWVIDEO_I4AB = "I4AB" + BMPTagRAWVIDEO_I4FL = "I4FL" + BMPTagRAWVIDEO_I4FB = "I4FB" + BMPTagRAWVIDEO_I0CL = "I0CL" + BMPTagRAWVIDEO_I0CB = "I0CB" + BMPTagRAWVIDEO_I2CL = "I2CL" + BMPTagRAWVIDEO_I2CB = "I2CB" + BMPTagRAWVIDEO_I4CL = "I4CL" + BMPTagRAWVIDEO_I4CB = "I4CB" + BMPTagRAWVIDEO_I0FL = "I0FL" + BMPTagRAWVIDEO_I0FB = "I0FB" + BMPTagFRWU = "FRWU" + BMPTagR10K = "R10k" + BMPTagR210 = "r210" + BMPTagV210_v210 = "v210" + BMPTagV210_C210 = "C210" + BMPTagV308 = "v308" + BMPTagV408 = "v408" + BMPTagV410 = "v410" + BMPTagYUV4 = "yuv4" + BMPTagINDEO3_IV31 = "IV31" + BMPTagINDEO3_IV32 = "IV32" + BMPTagINDEO4 = "IV41" + BMPTagINDEO5 = "IV50" + BMPTagVP3_VP31 = "VP31" + BMPTagVP3_VP30 = "VP30" + BMPTagVP4 = "VP40" + BMPTagVP5 = "VP50" + BMPTagVP6_VP60 = "VP60" + BMPTagVP6_VP61 = "VP61" + BMPTagVP6_VP62 = "VP62" + BMPTagVP6A = "VP6A" + BMPTagVP6F_VP6F = "VP6F" + BMPTagVP6F_FLV4 = "FLV4" + BMPTagVP7_VP70 = "VP70" + BMPTagVP7_VP71 = "VP71" + BMPTagVP8 = "VP80" + BMPTagVP9 = "VP90" + BMPTagASV1 = "ASV1" + BMPTagASV2 = "ASV2" + BMPTagVCR1 = "VCR1" + BMPTagFFV1 = "FFV1" + BMPTagXAN_WC4 = "Xxan" + BMPTagMIMIC = "LM20" + BMPTagMSRLE_mrle = "mrle" + BMPTagMSRLE_01000000 = "\x01\x00\x00\x00" + BMPTagMSRLE_02000000 = "\x02\x00\x00\x00" + BMPTagMSVIDEO1_MSVC = "MSVC" + BMPTagMSVIDEO1_msvc = "msvc" + BMPTagMSVIDEO1_CRAM = "CRAM" + BMPTagMSVIDEO1_cram = "cram" + BMPTagMSVIDEO1_WHAM = "WHAM" + BMPTagMSVIDEO1_wham = "wham" + BMPTagCINEPAK = "cvid" + BMPTagTRUEMOTION1_DUCK = "DUCK" + BMPTagTRUEMOTION1_PVEZ = "PVEZ" + BMPTagMSZH = "MSZH" + BMPTagZLIB = "ZLIB" + BMPTagSNOW = "SNOW" + BMPTag4XM = "4XMV" + BMPTagFLV1 = "FLV1" + BMPTagFLV1_S263 = "S263" + BMPTagFLASHSV = "FSV1" + BMPTagSVQ1 = "svq1" + BMPTagTSCC = "tscc" + BMPTagULTI = "ULTI" + BMPTagVIXL = "VIXL" + BMPTagQPEG = "QPEG" + BMPTagQPEG_Q1_0 = "Q1.0" + BMPTagQPEG_Q1_1 = "Q1.1" + BMPTagWMV3 = "WMV3" + BMPTagWMV3IMAGE = "WMVP" + BMPTagVC1_WVC1 = "WVC1" + BMPTagVC1_WMVA = "WMVA" + BMPTagVC1IMAGE = "WVP2" + BMPTagLOCO = "LOCO" + BMPTagWNV1_WNV1 = "WNV1" + BMPTagWNV1_YUV8 = "YUV8" + BMPTagAASC_AAS4 = "AAS4" // Autodesk 24 bit RLE compressor + BMPTagAASC = "AASC" + BMPTagINDEO2 = "RT21" + BMPTagFRAPS = "FPS1" + BMPTagTHEORA = "theo" + BMPTagTRUEMOTION2 = "TM20" + BMPTagTRUEMOTION2RT = "TR20" + BMPTagCSCD = "CSCD" + BMPTagZMBV = "ZMBV" + BMPTagKMVC = "KMVC" + BMPTagCAVS = "CAVS" + BMPTagAVS2 = "AVS2" + BMPTagJPEG2000_mjp2 = "mjp2" + BMPTagJPEG2000_MJ2C = "MJ2C" + BMPTagJPEG2000_LJ2C = "LJ2C" + BMPTagJPEG2000_LJ2K = "LJ2K" + BMPTagJPEG2000_IPJ2 = "IPJ2" + BMPTagJPEG2000_AVj2 = "AVj2" // Avid jpeg2000 + BMPTagVMNC = "VMnc" + BMPTagTARGA = "tga " + BMPTagPNG_MPNG = "MPNG" + BMPTagPNG_PNG1 = "PNG1" + BMPTagPNG = "png " // ImageJ + BMPTagCLJR = "CLJR" + BMPTagDIRAC = "drac" + BMPTagRPZA_azpr = "azpr" + BMPTagRPZA = "RPZA" + BMPTagRPZA_rpza = "rpza" + BMPTagSP5X = "SP54" + BMPTagAURA = "AURA" + BMPTagAURA2 = "AUR2" + BMPTagDPX = "dpx " + BMPTagKGV1 = "KGV1" + BMPTagLAGARITH = "LAGS" + BMPTagAMV = "AMVF" + BMPTagUTVIDEO_ULRA = "ULRA" + BMPTagUTVIDEO_ULRG = "ULRG" + BMPTagUTVIDEO_ULY0 = "ULY0" + BMPTagUTVIDEO_ULY2 = "ULY2" + BMPTagUTVIDEO_ULY4 = "ULY4" // Ut Video version 13.0.1 BT.709 codecs + BMPTagUTVIDEO_ULH0 = "ULH0" + BMPTagUTVIDEO_ULH2 = "ULH2" + BMPTagUTVIDEO_ULH4 = "ULH4" + BMPTagUTVIDEO_UQY0 = "UQY0" + BMPTagUTVIDEO_UQY2 = "UQY2" + BMPTagUTVIDEO_UQRA = "UQRA" + BMPTagUTVIDEO_UQRG = "UQRG" + BMPTagUTVIDEO_UMY2 = "UMY2" + BMPTagUTVIDEO_UMH2 = "UMH2" + BMPTagUTVIDEO_UMY4 = "UMY4" + BMPTagUTVIDEO_UMH4 = "UMH4" + BMPTagUTVIDEO_UMRA = "UMRA" + BMPTagUTVIDEO_UMRG = "UMRG" + BMPTagVBLE = "VBLE" + BMPTagESCAPE130 = "E130" + BMPTagDXTORY = "xtor" + BMPTagZEROCODEC = "ZECO" + BMPTagY41P = "Y41P" + BMPTagFLIC = "AFLC" + BMPTagMSS1 = "MSS1" + BMPTagMSA1 = "MSA1" + BMPTagTSCC2 = "TSC2" + BMPTagMTS2 = "MTS2" + BMPTagCLLC = "CLLC" + BMPTagMSS2 = "MSS2" + BMPTagSVQ3 = "SVQ3" + BMPTag012V = "012v" + BMPTag012V_a12v = "a12v" + BMPTagG2M_G2M2 = "G2M2" + BMPTagG2M_G2M3 = "G2M3" + BMPTagG2M_G2M4 = "G2M4" + BMPTagG2M_G2M5 = "G2M5" + BMPTagFIC = "FICV" + BMPTagHQX = "CHQX" + BMPTagTDSC = "TDSC" + BMPTagHQ_HQA = "CUVC" + BMPTagRV40 = "RV40" + BMPTagSCREENPRESSO = "SPV1" + BMPTagRSCC = "RSCC" + BMPTagRSCC_ISCC = "ISCC" + BMPTagCFHD = "CFHD" + BMPTagM101 = "M101" + BMPTagM101_M102 = "M102" + BMPTagMAGICYUV_MAGY = "MAGY" + BMPTagMAGICYUV_M8RG = "M8RG" + BMPTagMAGICYUV_M8RA = "M8RA" + BMPTagMAGICYUV_M8G0 = "M8G0" + BMPTagMAGICYUV_M8Y0 = "M8Y0" + BMPTagMAGICYUV_M8Y2 = "M8Y2" + BMPTagMAGICYUV_M8Y4 = "M8Y4" + BMPTagMAGICYUV_M8YA = "M8YA" + BMPTagMAGICYUV_M0RA = "M0RA" + BMPTagMAGICYUV_M0RG = "M0RG" + BMPTagMAGICYUV_M0G0 = "M0G0" + BMPTagMAGICYUV_M0Y0 = "M0Y0" + BMPTagMAGICYUV_M0Y2 = "M0Y2" + BMPTagMAGICYUV_M0Y4 = "M0Y4" + BMPTagMAGICYUV_M2RA = "M2RA" + BMPTagMAGICYUV_M2RG = "M2RG" + BMPTagYLC = "YLC0" + BMPTagSPEEDHQ_SHQ0 = "SHQ0" + BMPTagSPEEDHQ_SHQ1 = "SHQ1" + BMPTagSPEEDHQ_SHQ2 = "SHQ2" + BMPTagSPEEDHQ_SHQ3 = "SHQ3" + BMPTagSPEEDHQ_SHQ4 = "SHQ4" + BMPTagSPEEDHQ_SHQ5 = "SHQ5" + BMPTagSPEEDHQ_SHQ7 = "SHQ7" + BMPTagSPEEDHQ_SHQ9 = "SHQ9" + BMPTagFMVC = "FMVC" + BMPTagSCPR = "SCPR" + BMPTagCLEARVIDEO = "UCOD" + BMPTagAV1 = "AV01" + BMPTagMSCC = "MSCC" + BMPTagSRGC = "SRGC" + BMPTagIMM4 = "IMM4" + BMPTagPROSUMER = "BT20" + BMPTagMWSC = "MWSC" + BMPTagWCMV = "WCMV" + BMPTagRASC = "RASC" + BMPTagHYMT = "HYMT" + BMPTagARBC = "ARBC" + BMPTagAGM_AGM0 = "AGM0" + BMPTagAGM_AGM1 = "AGM1" + BMPTagAGM_AGM2 = "AGM2" + BMPTagAGM_AGM3 = "AGM3" + BMPTagAGM_AGM4 = "AGM4" + BMPTagAGM_AGM5 = "AGM5" + BMPTagAGM_AGM6 = "AGM6" + BMPTagAGM_AGM7 = "AGM7" + BMPTagLSCR = "LSCR" + BMPTagIMM5 = "IMM5" + BMPTagMVDV = "MVDV" + BMPTagMVHA = "MVHA" + BMPTagMV30 = "MV30" + BMPTagNOTCHLC = "nlc1" + BMPTagVQC_VQC1 = "VQC1" + BMPTagVQC_VQC2 = "VQC2" + // unofficial + BMPTagHEVC = "HEVC" + BMPTagHEVC_H265 = "H265" +) diff --git a/format/mpeg/avc_au.go b/format/mpeg/avc_au.go index 38edfb51..c687a06a 100644 --- a/format/mpeg/avc_au.go +++ b/format/mpeg/avc_au.go @@ -16,7 +16,7 @@ func init() { Description: "H.264/AVC Access Unit", DecodeFn: avcAUDecode, DecodeInArg: format.AvcAuIn{ - LengthSize: 4, + LengthSize: 0, }, RootArray: true, RootName: "access_unit", @@ -27,15 +27,18 @@ func init() { } func avcAUDecode(d *decode.D, in any) any { - avcIn, ok := in.(format.AvcAuIn) - if !ok { - d.Fatalf("avcIn required") + avcIn, _ := in.(format.AvcAuIn) + + if avcIn.LengthSize == 0 { + // TODO: is annexb the correct name? + annexBDecode(d, nil, avcNALUFormat) + return nil } for d.NotEnd() { d.FieldStruct("nalu", func(d *decode.D) { - l := d.FieldU("length", int(avcIn.LengthSize)*8) - d.FieldFormatLen("nalu", int64(l)*8, avcNALUFormat, nil) + l := int64(d.FieldU("length", int(avcIn.LengthSize)*8)) * 8 + d.FieldFormatLen("nalu", l, avcNALUFormat, nil) }) } diff --git a/format/mpeg/hevc_au.go b/format/mpeg/hevc_au.go index 4eb39783..e59a92a9 100644 --- a/format/mpeg/hevc_au.go +++ b/format/mpeg/hevc_au.go @@ -24,16 +24,20 @@ func init() { }) } +// TODO: share/refactor with avcAUDecode? func hevcAUDecode(d *decode.D, in any) any { - hevcIn, ok := in.(format.HevcAuIn) - if !ok { - d.Errorf("HevcAuIn required") + hevcIn, _ := in.(format.HevcAuIn) + + if hevcIn.LengthSize == 0 { + // TODO: is annexb the correct name? + annexBDecode(d, nil, hevcAUNALFormat) + return nil } for d.NotEnd() { d.FieldStruct("nalu", func(d *decode.D) { - l := d.FieldU("length", int(hevcIn.LengthSize)*8) - d.FieldFormatLen("nalu", int64(l)*8, hevcAUNALFormat, nil) + l := int64(d.FieldU("length", int(hevcIn.LengthSize)*8)) * 8 + d.FieldFormatLen("nalu", l, hevcAUNALFormat, nil) }) } diff --git a/format/mpeg/testdata/help_avc_au.fqtest b/format/mpeg/testdata/help_avc_au.fqtest index 3e986e05..c6a63cc2 100644 --- a/format/mpeg/testdata/help_avc_au.fqtest +++ b/format/mpeg/testdata/help_avc_au.fqtest @@ -4,7 +4,7 @@ avc_au: H.264/AVC Access Unit decoder Options ======= - length_size=4 Length value size + length_size=0 Length value size Decode examples =============== @@ -14,7 +14,7 @@ Decode examples # Decode value as avc_au ... | avc_au # Decode file using avc_au options - $ fq -d avc_au -o length_size=4 . file + $ fq -d avc_au -o length_size=0 . file # Decode value as avc_au - ... | avc_au({length_size:4}) + ... | avc_au({length_size:0}) diff --git a/format/riff/avi.go b/format/riff/avi.go new file mode 100644 index 00000000..a6a26ce4 --- /dev/null +++ b/format/riff/avi.go @@ -0,0 +1,601 @@ +package riff + +// TODO: +// mp3 mappig, seem there can be many frames in one sample and they span samples? +// hevc mapping? +// DV handler https://learn.microsoft.com/en-us/windows/win32/directshow/dv-data-in-the-avi-file-format +// palette change +// rec groups +// AVIX, multiple RIFF headers? +// nested indexes +// unknown fields for unreachable chunk header for > 1gb samples +// 2fields, field index? + +// https://learn.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference +// http://www.jmcgowan.com/odmlff2.pdf +// https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/avidec.c +// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/um/aviriff.h + +import ( + "embed" + "strconv" + + "github.com/wader/fq/format" + "github.com/wader/fq/pkg/decode" + "github.com/wader/fq/pkg/interp" + "github.com/wader/fq/pkg/ranges" + "github.com/wader/fq/pkg/scalar" +) + +//go:embed avi.md +var aviFS embed.FS + +var aviMp3FrameFormat decode.Group +var aviMpegAVCAUFormat decode.Group +var aviMpegHEVCAUFormat decode.Group +var aviFLACFrameFormat decode.Group + +func init() { + interp.RegisterFormat(decode.Format{ + Name: format.AVI, + Description: "Audio Video Interleaved", + DecodeFn: aviDecode, + DecodeInArg: format.AviIn{ + DecodeSamples: true, + }, + Dependencies: []decode.Dependency{ + {Names: []string{format.AVC_AU}, Group: &aviMpegAVCAUFormat}, + {Names: []string{format.HEVC_AU}, Group: &aviMpegHEVCAUFormat}, + {Names: []string{format.MP3_FRAME}, Group: &aviMp3FrameFormat}, + {Names: []string{format.FLAC_FRAME}, Group: &aviFLACFrameFormat}, + }, + Groups: []string{format.PROBE}, + }) + interp.RegisterFS(aviFS) +} + +var aviListTypeDescriptions = scalar.StrToDescription{ + "hdrl": "AVI main list", + "strl": "Stream list", + "movi": "Stream Data", + "rec ": "Chunk group", +} + +var aviStrhTypeDescriptions = scalar.StrToDescription{ + "auds": "Audio stream", + "mids": "MIDI stream", + "txts": "Text stream", + "vids": "Video stream", +} + +const ( + aviIndexTypeIndexes = 0 + aviIndexTypeChunks = 1 +) + +var aviIndexTypeNames = scalar.UToSymStr{ + aviIndexTypeIndexes: "indexes", + aviIndexTypeChunks: "chunks", +} + +const ( + aviIndexSubType2Fields = 1 +) + +var aviIndexSubTypeNames = scalar.UToSymStr{ + aviIndexSubType2Fields: "2fields", +} + +const ( + aviStreamChunkTypeUncompressedVideo = "db" + aviStreamChunkTypeCompressedVideo = "dc" + aviStreamChunkTypePaletteChange = "pc" + aviStreamChunkTypeAudio = "wb" + aviStreamChunkTypeIndex = "ix" +) + +var aviStreamChunkTypeDescriptions = scalar.StrToDescription{ + aviStreamChunkTypeUncompressedVideo: "Uncompressed video frame", + aviStreamChunkTypeCompressedVideo: "Compressed video frame", + aviStreamChunkTypePaletteChange: "Palette change", + aviStreamChunkTypeAudio: "Audio data", + aviStreamChunkTypeIndex: "Index", +} + +const aviRiffType = "AVI " + +type aviStrl struct { + typ string + handler string + stream *aviStream +} + +type idx1Sample struct { + offset int64 + size int64 + streamNr int + streamType string +} + +type aviStream struct { + hasFormat bool + format decode.Group + formatInArg any + indexes []ranges.Range + ixSamples []ranges.Range +} + +func aviParseChunkID(id string) (string, int, bool) { + if len(id) != 4 { + return "", 0, false + } + + isDigits := func(s string) bool { + for _, c := range s { + if !(c >= '0' && c <= '9') { + return false + } + } + return true + } + + var typ string + var indexStr string + switch { + case isDigits(id[0:2]): + // ##dc media etc + indexStr, typ = id[0:2], id[2:4] + case isDigits(id[2:4]): + // ix## index etc + typ, indexStr = id[0:2], id[2:4] + default: + return "", 0, false + } + + index, err := strconv.Atoi(indexStr) + if err != nil { + panic("unreachable") + } + + return typ, index, true + +} + +func aviIsStreamType(typ string) bool { + switch typ { + case aviStreamChunkTypeUncompressedVideo, + aviStreamChunkTypeCompressedVideo, + aviStreamChunkTypeAudio: + return true + default: + return false + } +} + +func aviDecorateStreamID(d *decode.D, id string) (string, int) { + typ, index, ok := aviParseChunkID(id) + if ok && aviIsStreamType(typ) { + d.FieldValueStr("stream_type", typ, aviStreamChunkTypeDescriptions) + d.FieldValueU("stream_nr", uint64(index)) + return typ, index + } + return "", 0 +} + +// ix frame index and indx frame index +func aviDecodeChunkIndex(d *decode.D) []ranges.Range { + var rs []ranges.Range + + d.FieldU16("longs_per_entry") // TODO: use? + d.FieldU8("index_subtype", aviIndexSubTypeNames) + d.FieldU8("index_type", aviIndexTypeNames) + nEntriesInUse := d.FieldU32("entries_in_use") + chunkID := d.FieldUTF8("chunk_id", 4) + aviDecorateStreamID(d, chunkID) + baseOffset := int64(d.FieldU64("base_offset")) + d.FieldU32("unused") + d.FieldArray("index", func(d *decode.D) { + for i := 0; i < int(nEntriesInUse); i++ { + d.FieldStruct("index", func(d *decode.D) { + offset := int64(d.FieldU32("offset")) + sizeKeyFrame := d.FieldU32("size_keyframe") + size := sizeKeyFrame & 0x7f_ff_ff_ff + d.FieldValueU("size", size) + d.FieldValueBool("key_frame", sizeKeyFrame&0x80_00_00_00 == 0) + rs = append(rs, ranges.Range{ + Start: baseOffset*8 + offset*8, + Len: int64(size) * 8, + }) + }) + } + }) + + return rs +} + +func aviDecode(d *decode.D, in any) any { + ai, _ := in.(format.AviIn) + + d.Endian = decode.LittleEndian + + var streams []*aviStream + var idx1Samples []idx1Sample + var moviListPos int64 // point to first bit after type + + var riffType string + riffDecode( + d, + nil, + func(d *decode.D, path path) (string, int64) { + id := d.FieldUTF8("id", 4, chunkIDDescriptions) + aviDecorateStreamID(d, id) + size := d.FieldU32("size") + return id, int64(size) + }, + func(d *decode.D, id string, path path) (bool, any) { + switch id { + case "RIFF": + riffType = d.FieldUTF8("type", 4, d.AssertStr(aviRiffType)) + return true, nil + + case "LIST": + typ := d.FieldUTF8("type", 4, aviListTypeDescriptions) + switch typ { + case "strl": + return true, &aviStrl{} + case "movi": + moviListPos = d.Pos() + } + return true, nil + + case "idx1": + d.FieldArray("indexes", func(d *decode.D) { + // TODO: seems there are files with weird tailing extra index entries + // TODO: limit using total_frame somehow instead? + for d.BitsLeft() >= 4*32 { + d.FieldStruct("index", func(d *decode.D) { + id := d.FieldUTF8("id", 4) + typ, index := aviDecorateStreamID(d, id) + d.FieldStruct("flags", func(d *decode.D) { + d.FieldRawLen("unused0", 3) + d.FieldBool("key_frame") + d.FieldRawLen("unused1", 3) + d.FieldBool("list") + d.FieldRawLen("unused2", 24) + }) + offset := int64(d.FieldU32("offset")) + length := int64(d.FieldU32("length")) + + idx1Samples = append(idx1Samples, idx1Sample{ + offset: offset * 8, + size: length * 8, + streamNr: index, + streamType: typ, + }) + }) + } + }) + return false, nil + + case "avih": + d.FieldU32("micro_sec_per_frame") + d.FieldU32("max_bytes_per_sec") + d.FieldU32("padding_granularity") + d.FieldStruct("flags", func(d *decode.D) { + d.FieldRawLen("unused0", 2) + d.FieldBool("must_use_index") + d.FieldBool("has_index") // Index at end of file? + d.FieldRawLen("unused1", 8) + d.FieldBool("trust_ck_type") // Use CKType to find key frames + d.FieldRawLen("unused2", 2) + d.FieldBool("is_interleaved") + d.FieldRawLen("unused3", 6) + d.FieldBool("copyrighted") + d.FieldBool("was_capture_file") + d.FieldRawLen("unused4", 8) + }) + d.FieldU32("total_frames") + d.FieldU32("initial_frames") + d.FieldU32("streams") + d.FieldU32("suggested_buffer_size") + d.FieldU32("width") + d.FieldU32("height") + d.FieldRawLen("reserved", 32*4) + return false, nil + + case "dmlh": + d.FieldU32("total_frames") + d.FieldRawLen("future", 32*61) + return false, nil + + case "strh": + typ := d.FieldUTF8("type", 4, aviStrhTypeDescriptions) + handler := d.FieldUTF8("handler", 4) + d.FieldStruct("flags", func(d *decode.D) { + d.FieldRawLen("unused0", 7) + d.FieldBool("disabled") + d.FieldRawLen("unused1", 15) + d.FieldBool("pal_changes") + d.FieldRawLen("unused2", 8) + }) + d.FieldU16("priority") + d.FieldU16("language") + d.FieldU32("initial_frames") + d.FieldU32("scale") + d.FieldU32("rate") + d.FieldU32("start") + d.FieldU32("length") + d.FieldU32("suggested_buffer_size") + d.FieldU32("quality") + d.FieldU32("sample_size") + d.FieldStruct("frame", func(d *decode.D) { + d.FieldU16("left") + d.FieldU16("top") + d.FieldU16("right") + d.FieldU16("bottom") + }) + + if aviStrl, aviStrlOk := path.topData().(*aviStrl); aviStrlOk { + aviStrl.typ = typ + aviStrl.handler = handler + } + + return false, nil + + case "strf": + s := &aviStream{} + + typ := "" + if aviStrl, aviStrlOk := path.topData().(*aviStrl); aviStrlOk { + typ = aviStrl.typ + aviStrl.stream = s + } + + switch typ { + case "vids": + // BITMAPINFOHEADER + size := d.BitsLeft() + biSize := d.FieldU32("bi_size") + d.FieldU32("width") + d.FieldU32("height") + d.FieldU16("planes") + d.FieldU16("bit_count") + compression := d.FieldUTF8("compression", 4) + d.FieldU32("size_image") + d.FieldU32("x_pels_per_meter") + d.FieldU32("y_pels_per_meter") + d.FieldU32("clr_used") + d.FieldU32("clr_important") + extraSize := size - int64(biSize)*8 - 2*32 + if extraSize > 0 { + d.FieldRawLen("extra", extraSize) + } + + // TODO: if dvsd handler and extraSize >= 32 then DVINFO? + + switch compression { + case format.BMPTagH264, + format.BMPTagH264_h264, + format.BMPTagH264_X264, + format.BMPTagH264_x264, + format.BMPTagH264_avc1, + format.BMPTagH264_DAVC, + format.BMPTagH264_SMV2, + format.BMPTagH264_VSSH, + format.BMPTagH264_Q264, + format.BMPTagH264_V264, + format.BMPTagH264_GAVC, + format.BMPTagH264_UMSV, + format.BMPTagH264_tshd, + format.BMPTagH264_INMC: + s.format = aviMpegAVCAUFormat + s.hasFormat = true + case format.BMPTagHEVC, + format.BMPTagHEVC_H265: + s.format = aviMpegHEVCAUFormat + s.hasFormat = true + } + + case "auds": + // WAVEFORMATEX + formatTag := d.FieldU16("format_tag", format.WAVTagNames) + d.FieldU16("channels") + d.FieldU32("samples_per_sec") + d.FieldU32("avg_bytes_per_sec") + d.FieldU16("block_align") + d.FieldU16("bits_per_sample") + // TODO: seems to be optional + if d.BitsLeft() >= 16 { + cbSize := d.FieldU16("cb_size") + // TODO: correct? seems to be what is seen in the wild + if cbSize > 18 { + d.FieldRawLen("extra", int64(cbSize-18)*8) + } + } + + switch formatTag { + case format.WAVTagMP3: + s.format = aviMp3FrameFormat + s.hasFormat = true + case format.WAVTagFLAC: + // TODO: can flac in avi have streaminfo somehow? + s.format = aviFLACFrameFormat + s.hasFormat = true + } + case "iavs": + // DVINFO + d.FieldU32("dva_aux_src") + d.FieldU32("dva_aux_ctl") + d.FieldU32("dva_aux_src1") + d.FieldU32("dva_aux_ctl1") + d.FieldU32("dvv_aux_src") + d.FieldU32("dvv_aux_ctl") + d.FieldRawLen("dvv_reserved", 32*2) + } + + streams = append(streams, s) + + return false, nil + + case "indx": + var stream *aviStream + if aviStrl, aviStrlOk := path.topData().(*aviStrl); aviStrlOk { + stream = aviStrl.stream + } + + d.FieldU16("longs_per_entry") // TODO: use? + d.FieldU8("index_subtype") + d.FieldU8("index_type") + nEntriesInUse := d.FieldU32("entries_in_use") + chunkID := d.FieldUTF8("chunk_id", 4) + aviDecorateStreamID(d, chunkID) + d.FieldU64("base") + d.FieldU32("unused") + d.FieldArray("index", func(d *decode.D) { + for i := 0; i < int(nEntriesInUse); i++ { + d.FieldStruct("index", func(d *decode.D) { + offset := int64(d.FieldU64("offset")) + size := int64(d.FieldU32("size")) + d.FieldU32("duration") + + if stream != nil { + stream.indexes = append(stream.indexes, ranges.Range{ + Start: offset * 8, + Len: size * 8, + }) + } + }) + } + }) + + return false, nil + + case "vprp": + d.FieldU32("video_format_token") + d.FieldU32("video_standard") + d.FieldU32("vertical_refresh_rate") + d.FieldU32("h_total_in_t") + d.FieldU32("v_total_in_lines") + d.FieldStruct("frame_aspect_ratio", func(d *decode.D) { + d.FieldU16("x") + d.FieldU16("y") + }) + d.FieldU32("frame_width_in_pixels") + d.FieldU32("frame_height_in_lines") + nbFieldPerFrame := d.FieldU32("nb_field_per_frame") + d.FieldArray("field_info", func(d *decode.D) { + for i := 0; i < int(nbFieldPerFrame); i++ { + d.FieldStruct("field_info", func(d *decode.D) { + d.FieldU32("compressed_bm_height") + d.FieldU32("compressed_bm_width") + d.FieldU32("valid_bm_height") + d.FieldU32("valid_bm_width") + d.FieldU32("valid_bmx_offset") + d.FieldU32("valid_bmy_offset") + d.FieldU32("video_x_offset_in_t") + d.FieldU32("video_y_valid_start_line") + }) + } + }) + return false, nil + + default: + if riffIsStringChunkID(id) { + d.FieldUTF8NullFixedLen("value", int(d.BitsLeft())/8) + return false, nil + } + + typ, index, _ := aviParseChunkID(id) + switch { + case typ == "ix": + sampleRanges := aviDecodeChunkIndex(d) + if index < len(streams) { + s := streams[index] + s.ixSamples = append(s.ixSamples, sampleRanges...) + } + case d.BitsLeft() > 0 && + ai.DecodeSamples && + aviIsStreamType(typ) && + index < len(streams) && + streams[index].hasFormat: + s := streams[index] + d.FieldFormatLen("data", d.BitsLeft(), s.format, s.formatInArg) + default: + d.FieldRawLen("data", d.BitsLeft()) + } + + return false, nil + } + }, + ) + + if riffType != aviRiffType { + d.Errorf("wrong or no AVI riff type found (%s)", riffType) + } + + d.FieldArray("streams", func(d *decode.D) { + for si, s := range streams { + d.FieldStruct("stream", func(d *decode.D) { + var streamIndexSampleRanges []ranges.Range + if len(s.indexes) > 0 { + d.FieldArray("indexes", func(d *decode.D) { + for _, i := range s.indexes { + d.FieldStruct("index", func(d *decode.D) { + d.RangeFn(i.Start, i.Len, func(d *decode.D) { + d.FieldUTF8("type", 4) + d.FieldU32("cb") + sampleRanges := aviDecodeChunkIndex(d) + streamIndexSampleRanges = append(streamIndexSampleRanges, sampleRanges...) + }) + }) + } + }) + } + + // TODO: handle zero length samples differently? + // TODO: palette change + decodeSample := func(d *decode.D, sr ranges.Range) { + d.RangeFn(sr.Start, sr.Len, func(d *decode.D) { + if sr.Len > 0 && ai.DecodeSamples && s.hasFormat { + d.FieldFormat("sample", s.format, s.formatInArg) + } else { + d.FieldRawLen("sample", d.BitsLeft()) + } + }) + } + + // try only add indexed samples once with priority: + // stream index + // ix chunks (might be same as stream index) + // idx chunks + if len(streamIndexSampleRanges) > 0 { + d.FieldArray("samples", func(d *decode.D) { + for _, sr := range streamIndexSampleRanges { + decodeSample(d, sr) + } + }) + } else if len(s.ixSamples) > 0 { + d.FieldArray("samples", func(d *decode.D) { + for _, sr := range s.ixSamples { + decodeSample(d, sr) + } + }) + } else if len(idx1Samples) > 0 { + d.FieldArray("samples", func(d *decode.D) { + for _, is := range idx1Samples { + if is.streamNr != si { + continue + } + decodeSample(d, ranges.Range{ + Start: moviListPos + is.offset + 32, // +32 skip size field + Len: is.size, + }) + } + }) + } + }) + } + }) + + return nil +} diff --git a/format/riff/avi.md b/format/riff/avi.md new file mode 100644 index 00000000..b0bffc3c --- /dev/null +++ b/format/riff/avi.md @@ -0,0 +1,19 @@ +### Samples + +AVI has many redundant ways to index samples so currently `.streams[].samples` will only include samples the most "modern" way used in the file. That is in order of stream super index, movi ix index then idx1 index. + +### Extract samples for stream 1 + +```sh +$ fq '.streams[1].samples[] | tobytes' file.avi > stream01.mp3 +``` + +### Show stream summary +```sh +$ fq -o decode_samples=false '[.chunks[0] | grep_by(.id=="LIST" and .type=="strl") | grep_by(.id=="strh") as {$type} | grep_by(.id=="strf") as {$format_tag, $compression} | {$type,$format_tag,$compression}]' *.avi +``` + +### References + +- [AVI RIFF File Reference](https://learn.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference) +- [OpenDML AVI File Format Extensions](http://www.jmcgowan.com/odmlff2.pdf) diff --git a/format/riff/common.go b/format/riff/common.go new file mode 100644 index 00000000..d7933985 --- /dev/null +++ b/format/riff/common.go @@ -0,0 +1,120 @@ +package riff + +import ( + "github.com/wader/fq/pkg/decode" + "github.com/wader/fq/pkg/scalar" +) + +type pathEntry struct { + id string + data any +} + +type path []pathEntry + +func (p path) topData() any { + if len(p) < 1 { + return nil + } + return p[len(p)-1].data +} + +func riffDecode(d *decode.D, path path, headFn func(d *decode.D, path path) (string, int64), chunkFn func(d *decode.D, id string, path path) (bool, any)) { + id, size := headFn(d, path) + + d.FramedFn(size*8, func(d *decode.D) { + hasChildren, data := chunkFn(d, id, path) + if hasChildren { + np := append(path, pathEntry{id: id, data: data}) + d.FieldArray("chunks", func(d *decode.D) { + for !d.End() { + d.FieldStruct("chunk", func(d *decode.D) { + riffDecode(d, np, headFn, chunkFn) + }) + } + }) + } + }) + + wordAlgin := d.AlignBits(16) + if wordAlgin != 0 { + d.FieldRawLen("align", int64(wordAlgin)) + } +} + +// TODO: sym name? +var chunkIDDescriptions = scalar.StrToDescription{ + "LIST": "Chunk list", + "JUNK": "Alignment", + + "idx1": "Index", + "indx": "Base index", + + "avih": "AVI main header", + "strh": "Stream header", + "strf": "Stream format", + "strn": "Stream name", + "vprp": "Video properties", + + "dmlh": "Extended AVI header", + + "ISMP": "SMPTE timecode", + "IDIT": "Time and date digitizing commenced", + "IARL": "Archival Location. Indicates where the subject of the file is archived.", + "IART": "Artist. Lists the artist of the original subject of the file", + "ICMS": "Commissioned. Lists the name of the person or organization that commissioned the subject of the file", + "ICMT": "Comments. Provides general comments about the file or the subject of the file", + "ICOP": "Copyright. Records the copyright information for the file", + "ICRD": "Creation date. Specifies the date the subject of the file was created.", + "ICRP": "Cropped. Describes whether an image has been cropped and, if so, how it was cropped", + "IDIM": "Dimensions. Specifies the size of the original subject of the file", + "IDPI": "Dots Per Inch. Stores dots per inch setting of the digitizer used to produce the file", + "IENG": "Engineer. Stores the name of the engineer who worked on the file. If there are multiple engineers, separate the names by a semicolon and a blank", + "IGNR": "Genre. Describes the original work", + "IKEY": "Keywords. Provides a list of keywords that refer to the file or subject of the file", + "ILGT": "Lightness. Describes the changes in lightness settings on the digitizer required to produce the file.", + "IMED": "Medium. Describes the original subject of the file", + "INAM": "Name. Stores the title of the subject of the file", + "IPLT": "Palette Setting. Specifies the number of colors requested when digitizing an image", + "IPRD": "Product. Specifies the name of the title the file was originally intended for", + "ISBJ": "Subject. Describes the contents of the file", + "ISFT": "Software. Identifies the name of the software package used to create the file", + "ISHP": "Sharpness. Identifies the changes in sharpness for the digitizer required to produce the file", + "ISRC": "Source. Identifies the name of the person or organization who supplied the original subject of the file", + "ISRF": "Source Form. Identifies the original form of the material that was digitized", + "ITCH": "Technician. Identifies the technician who digitized the subject file", +} + +func riffIsStringChunkID(id string) bool { + switch id { + case "strn", + "ISMP", + "IDIT", + "IARL", + "IART", + "ICMS", + "ICMT", + "ICOP", + "ICRD", + "ICRP", + "IDIM", + "IDPI", + "IENG", + "IGNR", + "IKEY", + "ILGT", + "IMED", + "INAM", + "IPLT", + "IPRD", + "ISBJ", + "ISFT", + "ISHP", + "ISRC", + "ISRF", + "ITCH": + return true + default: + return false + } +} diff --git a/format/riff/testdata/avc.avi b/format/riff/testdata/avc.avi new file mode 100644 index 0000000000000000000000000000000000000000..a01f41dad115fbdde235bf18d50875ba02539061 GIT binary patch literal 9282 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 literal 0 HcmV?d00001 diff --git a/format/riff/testdata/avc.avi.fqtest b/format/riff/testdata/avc.avi.fqtest new file mode 100644 index 00000000..8b587b77 --- /dev/null +++ b/format/riff/testdata/avc.avi.fqtest @@ -0,0 +1,489 @@ +# ffmpeg -f lavfi -i testsrc -t 50ms -c:v h264 -f avi avc.avi +$ fq dv avc.avi + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: avc.avi (avi) 0x0-0x2441.7 (9282) +0x00000|52 49 46 46 |RIFF | id: "RIFF" 0x0-0x3.7 (4) +0x00000| 3a 24 00 00 | :$.. | size: 9274 0x4-0x7.7 (4) +0x00000| 41 56 49 20 | AVI | type: "AVI " (valid) 0x8-0xb.7 (4) + | | | chunks[0:5]: 0xc-0x2441.7 (9270) + | | | [0]{}: chunk 0xc-0x124b.7 (4672) +0x00000| 4c 49 53 54| LIST| id: "LIST" (Chunk list) 0xc-0xf.7 (4) +0x00010|38 12 00 00 |8... | size: 4664 0x10-0x13.7 (4) +0x00010| 68 64 72 6c | hdrl | type: "hdrl" (AVI main list) 0x14-0x17.7 (4) + | | | chunks[0:3]: 0x18-0x124b.7 (4660) + | | | [0]{}: chunk 0x18-0x57.7 (64) +0x00010| 61 76 69 68 | avih | id: "avih" (AVI main header) 0x18-0x1b.7 (4) +0x00010| 38 00 00 00| 8...| size: 56 0x1c-0x1f.7 (4) +0x00020|40 9c 00 00 |@... | micro_sec_per_frame: 40000 0x20-0x23.7 (4) +0x00020| 00 00 00 00 | .... | max_bytes_per_sec: 0 0x24-0x27.7 (4) +0x00020| 00 00 00 00 | .... | padding_granularity: 0 0x28-0x2b.7 (4) + | | | flags{}: 0x2c-0x2f.7 (4) +0x00020| 10 | . | unused0: raw bits 0x2c-0x2c.1 (0.2) +0x00020| 10 | . | must_use_index: false 0x2c.2-0x2c.2 (0.1) +0x00020| 10 | . | has_index: true 0x2c.3-0x2c.3 (0.1) +0x00020| 10 09 | .. | unused1: raw bits 0x2c.4-0x2d.3 (1) +0x00020| 09 | . | trust_ck_type: true 0x2d.4-0x2d.4 (0.1) +0x00020| 09 | . | unused2: raw bits 0x2d.5-0x2d.6 (0.2) +0x00020| 09 | . | is_interleaved: true 0x2d.7-0x2d.7 (0.1) +0x00020| 00 | . | unused3: raw bits 0x2e-0x2e.5 (0.6) +0x00020| 00 | . | copyrighted: false 0x2e.6-0x2e.6 (0.1) +0x00020| 00 | . | was_capture_file: false 0x2e.7-0x2e.7 (0.1) +0x00020| 00| .| unused4: raw bits 0x2f-0x2f.7 (1) +0x00030|03 00 00 00 |.... | total_frames: 3 0x30-0x33.7 (4) +0x00030| 00 00 00 00 | .... | initial_frames: 0 0x34-0x37.7 (4) +0x00030| 01 00 00 00 | .... | streams: 1 0x38-0x3b.7 (4) +0x00030| 00 00 10 00| ....| suggested_buffer_size: 1048576 0x3c-0x3f.7 (4) +0x00040|40 01 00 00 |@... | width: 320 0x40-0x43.7 (4) +0x00040| f0 00 00 00 | .... | height: 240 0x44-0x47.7 (4) +0x00040| 00 00 00 00 00 00 00 00| ........| reserved: raw bits 0x48-0x57.7 (16) +0x00050|00 00 00 00 00 00 00 00 |........ | + | | | [1]{}: chunk 0x58-0x113f.7 (4328) +0x00050| 4c 49 53 54 | LIST | id: "LIST" (Chunk list) 0x58-0x5b.7 (4) +0x00050| e0 10 00 00| ....| size: 4320 0x5c-0x5f.7 (4) +0x00060|73 74 72 6c |strl | type: "strl" (Stream list) 0x60-0x63.7 (4) + | | | chunks[0:4]: 0x64-0x113f.7 (4316) + | | | [0]{}: chunk 0x64-0xa3.7 (64) +0x00060| 73 74 72 68 | strh | id: "strh" (Stream header) 0x64-0x67.7 (4) +0x00060| 38 00 00 00 | 8... | size: 56 0x68-0x6b.7 (4) +0x00060| 76 69 64 73| vids| type: "vids" (Video stream) 0x6c-0x6f.7 (4) +0x00070|48 32 36 34 |H264 | handler: "H264" 0x70-0x73.7 (4) + | | | flags{}: 0x74-0x77.7 (4) +0x00070| 00 | . | unused0: raw bits 0x74-0x74.6 (0.7) +0x00070| 00 | . | disabled: false 0x74.7-0x74.7 (0.1) +0x00070| 00 00 | .. | unused1: raw bits 0x75-0x76.6 (1.7) +0x00070| 00 | . | pal_changes: false 0x76.7-0x76.7 (0.1) +0x00070| 00 | . | unused2: raw bits 0x77-0x77.7 (1) +0x00070| 00 00 | .. | priority: 0 0x78-0x79.7 (2) +0x00070| 00 00 | .. | language: 0 0x7a-0x7b.7 (2) +0x00070| 00 00 00 00| ....| initial_frames: 0 0x7c-0x7f.7 (4) +0x00080|01 00 00 00 |.... | scale: 1 0x80-0x83.7 (4) +0x00080| 19 00 00 00 | .... | rate: 25 0x84-0x87.7 (4) +0x00080| 00 00 00 00 | .... | start: 0 0x88-0x8b.7 (4) +0x00080| 03 00 00 00| ....| length: 3 0x8c-0x8f.7 (4) +0x00090|f1 0b 00 00 |.... | suggested_buffer_size: 3057 0x90-0x93.7 (4) +0x00090| ff ff ff ff | .... | quality: 4294967295 0x94-0x97.7 (4) +0x00090| 00 00 00 00 | .... | sample_size: 0 0x98-0x9b.7 (4) + | | | frame{}: 0x9c-0xa3.7 (8) +0x00090| 00 00 | .. | left: 0 0x9c-0x9d.7 (2) +0x00090| 00 00| ..| top: 0 0x9e-0x9f.7 (2) +0x000a0|40 01 |@. | right: 320 0xa0-0xa1.7 (2) +0x000a0| f0 00 | .. | bottom: 240 0xa2-0xa3.7 (2) + | | | [1]{}: chunk 0xa4-0xd3.7 (48) +0x000a0| 73 74 72 66 | strf | id: "strf" (Stream format) 0xa4-0xa7.7 (4) +0x000a0| 28 00 00 00 | (... | size: 40 0xa8-0xab.7 (4) +0x000a0| 28 00 00 00| (...| bi_size: 40 0xac-0xaf.7 (4) +0x000b0|40 01 00 00 |@... | width: 320 0xb0-0xb3.7 (4) +0x000b0| f0 00 00 00 | .... | height: 240 0xb4-0xb7.7 (4) +0x000b0| 01 00 | .. | planes: 1 0xb8-0xb9.7 (2) +0x000b0| 18 00 | .. | bit_count: 24 0xba-0xbb.7 (2) +0x000b0| 48 32 36 34| H264| compression: "H264" 0xbc-0xbf.7 (4) +0x000c0|00 84 03 00 |.... | size_image: 230400 0xc0-0xc3.7 (4) +0x000c0| 00 00 00 00 | .... | x_pels_per_meter: 0 0xc4-0xc7.7 (4) +0x000c0| 00 00 00 00 | .... | y_pels_per_meter: 0 0xc8-0xcb.7 (4) +0x000c0| 00 00 00 00| ....| clr_used: 0 0xcc-0xcf.7 (4) +0x000d0|00 00 00 00 |.... | clr_important: 0 0xd0-0xd3.7 (4) + | | | [2]{}: chunk 0xd4-0x10f3.7 (4128) +0x000d0| 4a 55 4e 4b | JUNK | id: "JUNK" (Alignment) 0xd4-0xd7.7 (4) +0x000d0| 18 10 00 00 | .... | size: 4120 0xd8-0xdb.7 (4) +0x000d0| 04 00 00 00| ....| data: raw bits 0xdc-0x10f3.7 (4120) +0x000e0|00 00 00 00 30 30 64 63 00 00 00 00 00 00 00 00|....00dc........| +* |until 0x10f3.7 (4120) | | + | | | [3]{}: chunk 0x10f4-0x113f.7 (76) +0x010f0| 76 70 72 70 | vprp | id: "vprp" (Video properties) 0x10f4-0x10f7.7 (4) +0x010f0| 44 00 00 00 | D... | size: 68 0x10f8-0x10fb.7 (4) +0x010f0| 00 00 00 00| ....| video_format_token: 0 0x10fc-0x10ff.7 (4) +0x01100|00 00 00 00 |.... | video_standard: 0 0x1100-0x1103.7 (4) +0x01100| 19 00 00 00 | .... | vertical_refresh_rate: 25 0x1104-0x1107.7 (4) +0x01100| 40 01 00 00 | @... | h_total_in_t: 320 0x1108-0x110b.7 (4) +0x01100| f0 00 00 00| ....| v_total_in_lines: 240 0x110c-0x110f.7 (4) + | | | frame_aspect_ratio{}: 0x1110-0x1113.7 (4) +0x01110|03 00 |.. | x: 3 0x1110-0x1111.7 (2) +0x01110| 04 00 | .. | y: 4 0x1112-0x1113.7 (2) +0x01110| 40 01 00 00 | @... | frame_width_in_pixels: 320 0x1114-0x1117.7 (4) +0x01110| f0 00 00 00 | .... | frame_height_in_lines: 240 0x1118-0x111b.7 (4) +0x01110| 01 00 00 00| ....| nb_field_per_frame: 1 0x111c-0x111f.7 (4) + | | | field_info[0:1]: 0x1120-0x113f.7 (32) + | | | [0]{}: field_info 0x1120-0x113f.7 (32) +0x01120|f0 00 00 00 |.... | compressed_bm_height: 240 0x1120-0x1123.7 (4) +0x01120| 40 01 00 00 | @... | compressed_bm_width: 320 0x1124-0x1127.7 (4) +0x01120| f0 00 00 00 | .... | valid_bm_height: 240 0x1128-0x112b.7 (4) +0x01120| 40 01 00 00| @...| valid_bm_width: 320 0x112c-0x112f.7 (4) +0x01130|00 00 00 00 |.... | valid_bmx_offset: 0 0x1130-0x1133.7 (4) +0x01130| 00 00 00 00 | .... | valid_bmy_offset: 0 0x1134-0x1137.7 (4) +0x01130| 00 00 00 00 | .... | video_x_offset_in_t: 0 0x1138-0x113b.7 (4) +0x01130| 00 00 00 00| ....| video_y_valid_start_line: 0 0x113c-0x113f.7 (4) + | | | [2]{}: chunk 0x1140-0x124b.7 (268) +0x01140|4a 55 4e 4b |JUNK | id: "JUNK" (Alignment) 0x1140-0x1143.7 (4) +0x01140| 04 01 00 00 | .... | size: 260 0x1144-0x1147.7 (4) +0x01140| 6f 64 6d 6c 64 6d 6c 68| odmldmlh| data: raw bits 0x1148-0x124b.7 (260) +0x01150|f8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................| +* |until 0x124b.7 (260) | | + | | | [1]{}: chunk 0x124c-0x126d.7 (34) +0x01240| 4c 49 53 54| LIST| id: "LIST" (Chunk list) 0x124c-0x124f.7 (4) +0x01250|1a 00 00 00 |.... | size: 26 0x1250-0x1253.7 (4) +0x01250| 49 4e 46 4f | INFO | type: "INFO" 0x1254-0x1257.7 (4) + | | | chunks[0:1]: 0x1258-0x126d.7 (22) + | | | [0]{}: chunk 0x1258-0x126d.7 (22) +0x01250| 49 53 46 54 | ISFT | id: "ISFT" (Software. Identifies the name of the software package used to create the file) 0x1258-0x125b.7 (4) +0x01250| 0e 00 00 00| ....| size: 14 0x125c-0x125f.7 (4) +0x01260|4c 61 76 66 35 38 2e 37 36 2e 31 30 30 00 |Lavf58.76.100. | value: "Lavf58.76.100" 0x1260-0x126d.7 (14) + | | | [2]{}: chunk 0x126e-0x166d.7 (1024) +0x01260| 4a 55| JU| id: "JUNK" (Alignment) 0x126e-0x1271.7 (4) +0x01270|4e 4b |NK | +0x01270| f8 03 00 00 | .... | size: 1016 0x1272-0x1275.7 (4) +0x01270| 00 00 00 00 00 00 00 00 00 00| ..........| data: raw bits 0x1276-0x166d.7 (1016) +0x01280|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................| +* |until 0x166d.7 (1016) | | + | | | [3]{}: chunk 0x166e-0x2409.7 (3484) +0x01660| 4c 49| LI| id: "LIST" (Chunk list) 0x166e-0x1671.7 (4) +0x01670|53 54 |ST | +0x01670| 94 0d 00 00 | .... | size: 3476 0x1672-0x1675.7 (4) +0x01670| 6d 6f 76 69 | movi | type: "movi" (Stream Data) 0x1676-0x1679.7 (4) + | | | chunks[0:3]: 0x167a-0x2409.7 (3472) + | | | [0]{}: chunk 0x167a-0x2273.7 (3066) +0x01670| 30 30 64 63 | 00dc | id: "00dc" 0x167a-0x167d.7 (4) + | | | stream_type: "dc" (Compressed video frame) 0x167e-NA (0) + | | | stream_nr: 0 0x167e-NA (0) +0x01670| f1 0b| ..| size: 3057 0x167e-0x1681.7 (4) +0x01680|00 00 |.. | + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| data[0:8]: (avc_au) 0x1682-0x2272.7 (3057) +0x01680| 00 00 00 01 | .... | [0]: raw bits start_code 0x1682-0x1685.7 (4) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [1]{}: nalu (avc_nalu) 0x1686-0x169e.7 (25) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| sps{}: (avc_sps) 0x0-0x15.7 (22) + 0x000|f4 |. | profile_idc: "high_444_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: "4:4:4" (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: 8 0x3.7-0x3.7 (0.1) + 0x000| 9b | . | bit_depth_chroma: 8 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: 4 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: 6 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: 20 0x5.6-0x6.6 (1.1) + 0x000| 28 3f | (? | pic_height_in_map_units: 15 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:1" (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) + 0x001|00 64 |.d | + 0x001| 64 | d | fixed_frame_rate_flag: false 0x11.7-0x11.7 (0.1) + 0x001| 1e | . | nal_hrd_parameters_present_flag: false 0x12-0x12 (0.1) + 0x001| 1e | . | vcl_hrd_parameters_present_flag: false 0x12.1-0x12.1 (0.1) + 0x001| 1e | . | pic_struct_present_flag: false 0x12.2-0x12.2 (0.1) + 0x001| 1e | . | bitstream_restriction_flag: true 0x12.3-0x12.3 (0.1) + 0x001| 1e | . | motion_vectors_over_pic_boundaries_flag: true 0x12.4-0x12.4 (0.1) + 0x001| 1e | . | max_bytes_per_pic_denom: 0 0x12.5-0x12.5 (0.1) + 0x001| 1e | . | max_bits_per_mb_denom: 0 0x12.6-0x12.6 (0.1) + 0x001| 1e 28 | .( | log2_max_mv_length_horizontal: 9 0x12.7-0x13.5 (0.7) + 0x001| 28 53 | (S | log2_max_mv_length_vertical: 9 0x13.6-0x14.4 (0.7) + 0x001| 53 | S | max_num_reorder_frames: 2 0x14.5-0x14.7 (0.3) + 0x001| 2c| | ,| | max_dec_frame_buffering: 4 0x15-0x15.4 (0.5) + 0x001| 2c| | ,| | rbsp_trailing_bits: raw bits 0x15.5-0x15.7 (0.3) +0x01680| 67 | g | forbidden_zero_bit: false 0x1686-0x1686 (0.1) +0x01680| 67 | g | nal_ref_idc: 3 0x1686.1-0x1686.2 (0.2) +0x01680| 67 | g | nal_unit_type: "sps" (7) (Sequence parameter set) 0x1686.3-0x1686.7 (0.5) +0x01680| f4 00 0d 91 9b 28 28 3f 60| .....((?`| data: raw bits 0x1687-0x169e.7 (24) +0x01690|22 00 00 03 00 02 00 00 03 00 64 1e 28 53 2c |".........d.(S, | +0x01690| 00| .| [2]: raw bits start_code 0x169f-0x16a2.7 (4) +0x016a0|00 00 01 |... | + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [3]{}: nalu (avc_nalu) 0x16a3-0x16a8.7 (6) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| 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: 1 0x0.4-0x0.4 (0.1) + 0x000|eb |. | num_ref_idx_l0_default_active: 3 0x0.5-0x0.7 (0.3) + 0x000| e3 | . | num_ref_idx_l1_default_active: 1 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: 23 0x1.4-0x2 (0.5) + 0x000| c4 | . | pic_init_qs: 26 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: raw bits 0x4.5-0x4.7 (0.3) +0x016a0| 68 | h | forbidden_zero_bit: false 0x16a3-0x16a3 (0.1) +0x016a0| 68 | h | nal_ref_idc: 3 0x16a3.1-0x16a3.2 (0.2) +0x016a0| 68 | h | nal_unit_type: "pps" (8) (Picture parameter set) 0x16a3.3-0x16a3.7 (0.5) +0x016a0| eb e3 c4 48 44 | ...HD | data: raw bits 0x16a4-0x16a8.7 (5) +0x016a0| 00 00 01 | ... | [4]: raw bits start_code 0x16a9-0x16ab.7 (3) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [5]{}: nalu (avc_nalu) 0x16ac-0x1958.7 (685) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| 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" (raw bits) 0x4-0x13.7 (16) + 0x001|d9 23 ee ef |.#.. | + 0x001| 78 32 36 34 20 2d 20 63 6f 72 65 20| x264 - core | data: raw bits 0x14-0x2aa.7 (663) + 0x002|31 36 33 20 72 33 30 36 30 20 35 64 62 36 61 61|163 r3060 5db6aa| + * |until 0x2aa.7 (663) | | + 0x02a| 80| | .| | rbsp_trailing_bits: raw bits 0x2ab-0x2ab.7 (1) +0x016a0| 06 | . | forbidden_zero_bit: false 0x16ac-0x16ac (0.1) +0x016a0| 06 | . | nal_ref_idc: 0 0x16ac.1-0x16ac.2 (0.2) +0x016a0| 06 | . | nal_unit_type: "sei" (6) (Supplemental enhancement information) 0x16ac.3-0x16ac.7 (0.5) +0x016a0| 05 ff ff| ...| data: raw bits 0x16ad-0x1958.7 (684) +0x016b0|a9 dc 45 e9 bd e6 d9 48 b7 96 2c d8 20 d9 23 ee|..E....H..,. .#.| +* |until 0x1958.7 (684) | | +0x01950| 00 00 01 | ... | [6]: raw bits start_code 0x1959-0x195b.7 (3) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [7]{}: nalu (avc_nalu) 0x195c-0x2272.7 (2327) +0x01950| 65 | e | forbidden_zero_bit: false 0x195c-0x195c (0.1) +0x01950| 65 | e | nal_ref_idc: 3 0x195c.1-0x195c.2 (0.2) +0x01950| 65 | e | nal_unit_type: "idr_slice" (5) (Coded slice of an IDR picture) 0x195c.3-0x195c.7 (0.5) + | | | slice_header{}: 0x195d-0x195e (1.1) +0x01950| 88 | . | first_mb_in_slice: 0 0x195d-0x195d (0.1) +0x01950| 88 | . | slice_type: "i" (7) 0x195d.1-0x195d.7 (0.7) +0x01950| 84 | . | pic_parameter_set_id: 0 0x195e-0x195e (0.1) +0x01950| 84 00| ..| data: raw bits 0x195e.1-0x2272.7 (2324.7) +0x01960|33 ff fe f6 86 f8 14 d8 53 23 af ff f2 50 06 7f|3.......S#...P..| +* |until 0x2272.7 (2325) | | +0x02270| 00 | . | align: raw bits 0x2273-0x2273.7 (1) + | | | [1]{}: chunk 0x2274-0x23c9.7 (342) +0x02270| 30 30 64 63 | 00dc | id: "00dc" 0x2274-0x2277.7 (4) + | | | stream_type: "dc" (Compressed video frame) 0x2278-NA (0) + | | | stream_nr: 0 0x2278-NA (0) +0x02270| 4d 01 00 00 | M... | size: 333 0x2278-0x227b.7 (4) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| data[0:2]: (avc_au) 0x227c-0x23c8.7 (333) +0x02270| 00 00 00 01| ....| [0]: raw bits start_code 0x227c-0x227f.7 (4) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [1]{}: nalu (avc_nalu) 0x2280-0x23c8.7 (329) +0x02280|41 |A | forbidden_zero_bit: false 0x2280-0x2280 (0.1) +0x02280|41 |A | nal_ref_idc: 2 0x2280.1-0x2280.2 (0.2) +0x02280|41 |A | nal_unit_type: "slice" (1) (Coded slice of a non-IDR picture) 0x2280.3-0x2280.7 (0.5) + | | | slice_header{}: 0x2281-0x2281.6 (0.7) +0x02280| 9a | . | first_mb_in_slice: 0 0x2281-0x2281 (0.1) +0x02280| 9a | . | slice_type: "p" (5) 0x2281.1-0x2281.5 (0.5) +0x02280| 9a | . | pic_parameter_set_id: 0 0x2281.6-0x2281.6 (0.1) +0x02280| 9a 22 6c 42 bf fe 38 85 de c2 03 1a de 79 0a| ."lB..8......y.| data: raw bits 0x2281.7-0x23c8.7 (327.1) +0x02290|56 fd b3 4b b4 0f 24 7f e9 d3 b6 f2 5e 6f dd b7|V..K..$.....^o..| +* |until 0x23c8.7 (328) | | +0x023c0| 00 | . | align: raw bits 0x23c9-0x23c9.7 (1) + | | | [2]{}: chunk 0x23ca-0x2409.7 (64) +0x023c0| 30 30 64 63 | 00dc | id: "00dc" 0x23ca-0x23cd.7 (4) + | | | stream_type: "dc" (Compressed video frame) 0x23ce-NA (0) + | | | stream_nr: 0 0x23ce-NA (0) +0x023c0| 38 00| 8.| size: 56 0x23ce-0x23d1.7 (4) +0x023d0|00 00 |.. | + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| data[0:2]: (avc_au) 0x23d2-0x2409.7 (56) +0x023d0| 00 00 00 01 | .... | [0]: raw bits start_code 0x23d2-0x23d5.7 (4) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [1]{}: nalu (avc_nalu) 0x23d6-0x2409.7 (52) +0x023d0| 01 | . | forbidden_zero_bit: false 0x23d6-0x23d6 (0.1) +0x023d0| 01 | . | nal_ref_idc: 0 0x23d6.1-0x23d6.2 (0.2) +0x023d0| 01 | . | nal_unit_type: "slice" (1) (Coded slice of a non-IDR picture) 0x23d6.3-0x23d6.7 (0.5) + | | | slice_header{}: 0x23d7-0x23d7.6 (0.7) +0x023d0| 9e | . | first_mb_in_slice: 0 0x23d7-0x23d7 (0.1) +0x023d0| 9e | . | slice_type: "b" (6) 0x23d7.1-0x23d7.5 (0.5) +0x023d0| 9e | . | pic_parameter_set_id: 0 0x23d7.6-0x23d7.6 (0.1) +0x023d0| 9e 41 79 0a ff 01 f9 2d 04| .Ay....-.| data: raw bits 0x23d7.7-0x2409.7 (50.1) +0x023e0|d3 29 fe 4d 76 42 26 f6 cd 13 9c 32 05 69 f5 56|.).MvB&....2.i.V| +* |until 0x2409.7 (51) | | + | | | [4]{}: chunk 0x240a-0x2441.7 (56) +0x02400| 69 64 78 31 | idx1 | id: "idx1" (Index) 0x240a-0x240d.7 (4) +0x02400| 30 00| 0.| size: 48 0x240e-0x2411.7 (4) +0x02410|00 00 |.. | + | | | indexes[0:3]: 0x2412-0x2441.7 (48) + | | | [0]{}: index 0x2412-0x2421.7 (16) +0x02410| 30 30 64 63 | 00dc | id: "00dc" 0x2412-0x2415.7 (4) + | | | stream_type: "dc" (Compressed video frame) 0x2416-NA (0) + | | | stream_nr: 0 0x2416-NA (0) + | | | flags{}: 0x2416-0x2419.7 (4) +0x02410| 10 | . | unused0: raw bits 0x2416-0x2416.2 (0.3) +0x02410| 10 | . | key_frame: true 0x2416.3-0x2416.3 (0.1) +0x02410| 10 | . | unused1: raw bits 0x2416.4-0x2416.6 (0.3) +0x02410| 10 | . | list: false 0x2416.7-0x2416.7 (0.1) +0x02410| 00 00 00 | ... | unused2: raw bits 0x2417-0x2419.7 (3) +0x02410| 04 00 00 00 | .... | offset: 4 0x241a-0x241d.7 (4) +0x02410| f1 0b| ..| length: 3057 0x241e-0x2421.7 (4) +0x02420|00 00 |.. | + | | | [1]{}: index 0x2422-0x2431.7 (16) +0x02420| 30 30 64 63 | 00dc | id: "00dc" 0x2422-0x2425.7 (4) + | | | stream_type: "dc" (Compressed video frame) 0x2426-NA (0) + | | | stream_nr: 0 0x2426-NA (0) + | | | flags{}: 0x2426-0x2429.7 (4) +0x02420| 00 | . | unused0: raw bits 0x2426-0x2426.2 (0.3) +0x02420| 00 | . | key_frame: false 0x2426.3-0x2426.3 (0.1) +0x02420| 00 | . | unused1: raw bits 0x2426.4-0x2426.6 (0.3) +0x02420| 00 | . | list: false 0x2426.7-0x2426.7 (0.1) +0x02420| 00 00 00 | ... | unused2: raw bits 0x2427-0x2429.7 (3) +0x02420| fe 0b 00 00 | .... | offset: 3070 0x242a-0x242d.7 (4) +0x02420| 4d 01| M.| length: 333 0x242e-0x2431.7 (4) +0x02430|00 00 |.. | + | | | [2]{}: index 0x2432-0x2441.7 (16) +0x02430| 30 30 64 63 | 00dc | id: "00dc" 0x2432-0x2435.7 (4) + | | | stream_type: "dc" (Compressed video frame) 0x2436-NA (0) + | | | stream_nr: 0 0x2436-NA (0) + | | | flags{}: 0x2436-0x2439.7 (4) +0x02430| 00 | . | unused0: raw bits 0x2436-0x2436.2 (0.3) +0x02430| 00 | . | key_frame: false 0x2436.3-0x2436.3 (0.1) +0x02430| 00 | . | unused1: raw bits 0x2436.4-0x2436.6 (0.3) +0x02430| 00 | . | list: false 0x2436.7-0x2436.7 (0.1) +0x02430| 00 00 00 | ... | unused2: raw bits 0x2437-0x2439.7 (3) +0x02430| 54 0d 00 00 | T... | offset: 3412 0x243a-0x243d.7 (4) +0x02430| 38 00| 8.| length: 56 0x243e-0x2441.7 (4) +0x02440|00 00| |..| | + | | | streams[0:1]: 0x1682-0x2409.7 (3464) + | | | [0]{}: stream 0x1682-0x2409.7 (3464) + | | | samples[0:3]: 0x1682-0x2409.7 (3464) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [0][0:8]: sample (avc_au) 0x1682-0x2272.7 (3057) +0x01680| 00 00 00 01 | .... | [0]: raw bits start_code 0x1682-0x1685.7 (4) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [1]{}: nalu (avc_nalu) 0x1686-0x169e.7 (25) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| sps{}: (avc_sps) 0x0-0x15.7 (22) + 0x000|f4 |. | profile_idc: "high_444_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: "4:4:4" (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: 8 0x3.7-0x3.7 (0.1) + 0x000| 9b | . | bit_depth_chroma: 8 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: 4 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: 6 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: 20 0x5.6-0x6.6 (1.1) + 0x000| 28 3f | (? | pic_height_in_map_units: 15 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:1" (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) + 0x001|00 64 |.d | + 0x001| 64 | d | fixed_frame_rate_flag: false 0x11.7-0x11.7 (0.1) + 0x001| 1e | . | nal_hrd_parameters_present_flag: false 0x12-0x12 (0.1) + 0x001| 1e | . | vcl_hrd_parameters_present_flag: false 0x12.1-0x12.1 (0.1) + 0x001| 1e | . | pic_struct_present_flag: false 0x12.2-0x12.2 (0.1) + 0x001| 1e | . | bitstream_restriction_flag: true 0x12.3-0x12.3 (0.1) + 0x001| 1e | . | motion_vectors_over_pic_boundaries_flag: true 0x12.4-0x12.4 (0.1) + 0x001| 1e | . | max_bytes_per_pic_denom: 0 0x12.5-0x12.5 (0.1) + 0x001| 1e | . | max_bits_per_mb_denom: 0 0x12.6-0x12.6 (0.1) + 0x001| 1e 28 | .( | log2_max_mv_length_horizontal: 9 0x12.7-0x13.5 (0.7) + 0x001| 28 53 | (S | log2_max_mv_length_vertical: 9 0x13.6-0x14.4 (0.7) + 0x001| 53 | S | max_num_reorder_frames: 2 0x14.5-0x14.7 (0.3) + 0x001| 2c| | ,| | max_dec_frame_buffering: 4 0x15-0x15.4 (0.5) + 0x001| 2c| | ,| | rbsp_trailing_bits: raw bits 0x15.5-0x15.7 (0.3) +0x01680| 67 | g | forbidden_zero_bit: false 0x1686-0x1686 (0.1) +0x01680| 67 | g | nal_ref_idc: 3 0x1686.1-0x1686.2 (0.2) +0x01680| 67 | g | nal_unit_type: "sps" (7) (Sequence parameter set) 0x1686.3-0x1686.7 (0.5) +0x01680| f4 00 0d 91 9b 28 28 3f 60| .....((?`| data: raw bits 0x1687-0x169e.7 (24) +0x01690|22 00 00 03 00 02 00 00 03 00 64 1e 28 53 2c |".........d.(S, | +0x01690| 00| .| [2]: raw bits start_code 0x169f-0x16a2.7 (4) +0x016a0|00 00 01 |... | + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [3]{}: nalu (avc_nalu) 0x16a3-0x16a8.7 (6) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| 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: 1 0x0.4-0x0.4 (0.1) + 0x000|eb |. | num_ref_idx_l0_default_active: 3 0x0.5-0x0.7 (0.3) + 0x000| e3 | . | num_ref_idx_l1_default_active: 1 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: 23 0x1.4-0x2 (0.5) + 0x000| c4 | . | pic_init_qs: 26 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: raw bits 0x4.5-0x4.7 (0.3) +0x016a0| 68 | h | forbidden_zero_bit: false 0x16a3-0x16a3 (0.1) +0x016a0| 68 | h | nal_ref_idc: 3 0x16a3.1-0x16a3.2 (0.2) +0x016a0| 68 | h | nal_unit_type: "pps" (8) (Picture parameter set) 0x16a3.3-0x16a3.7 (0.5) +0x016a0| eb e3 c4 48 44 | ...HD | data: raw bits 0x16a4-0x16a8.7 (5) +0x016a0| 00 00 01 | ... | [4]: raw bits start_code 0x16a9-0x16ab.7 (3) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [5]{}: nalu (avc_nalu) 0x16ac-0x1958.7 (685) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| 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" (raw bits) 0x4-0x13.7 (16) + 0x001|d9 23 ee ef |.#.. | + 0x001| 78 32 36 34 20 2d 20 63 6f 72 65 20| x264 - core | data: raw bits 0x14-0x2aa.7 (663) + 0x002|31 36 33 20 72 33 30 36 30 20 35 64 62 36 61 61|163 r3060 5db6aa| + * |until 0x2aa.7 (663) | | + 0x02a| 80| | .| | rbsp_trailing_bits: raw bits 0x2ab-0x2ab.7 (1) +0x016a0| 06 | . | forbidden_zero_bit: false 0x16ac-0x16ac (0.1) +0x016a0| 06 | . | nal_ref_idc: 0 0x16ac.1-0x16ac.2 (0.2) +0x016a0| 06 | . | nal_unit_type: "sei" (6) (Supplemental enhancement information) 0x16ac.3-0x16ac.7 (0.5) +0x016a0| 05 ff ff| ...| data: raw bits 0x16ad-0x1958.7 (684) +0x016b0|a9 dc 45 e9 bd e6 d9 48 b7 96 2c d8 20 d9 23 ee|..E....H..,. .#.| +* |until 0x1958.7 (684) | | +0x01950| 00 00 01 | ... | [6]: raw bits start_code 0x1959-0x195b.7 (3) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [7]{}: nalu (avc_nalu) 0x195c-0x2272.7 (2327) +0x01950| 65 | e | forbidden_zero_bit: false 0x195c-0x195c (0.1) +0x01950| 65 | e | nal_ref_idc: 3 0x195c.1-0x195c.2 (0.2) +0x01950| 65 | e | nal_unit_type: "idr_slice" (5) (Coded slice of an IDR picture) 0x195c.3-0x195c.7 (0.5) + | | | slice_header{}: 0x195d-0x195e (1.1) +0x01950| 88 | . | first_mb_in_slice: 0 0x195d-0x195d (0.1) +0x01950| 88 | . | slice_type: "i" (7) 0x195d.1-0x195d.7 (0.7) +0x01950| 84 | . | pic_parameter_set_id: 0 0x195e-0x195e (0.1) +0x01950| 84 00| ..| data: raw bits 0x195e.1-0x2272.7 (2324.7) +0x01960|33 ff fe f6 86 f8 14 d8 53 23 af ff f2 50 06 7f|3.......S#...P..| +* |until 0x2272.7 (2325) | | + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [1][0:2]: sample (avc_au) 0x227c-0x23c8.7 (333) +0x02270| 00 00 00 01| ....| [0]: raw bits start_code 0x227c-0x227f.7 (4) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [1]{}: nalu (avc_nalu) 0x2280-0x23c8.7 (329) +0x02280|41 |A | forbidden_zero_bit: false 0x2280-0x2280 (0.1) +0x02280|41 |A | nal_ref_idc: 2 0x2280.1-0x2280.2 (0.2) +0x02280|41 |A | nal_unit_type: "slice" (1) (Coded slice of a non-IDR picture) 0x2280.3-0x2280.7 (0.5) + | | | slice_header{}: 0x2281-0x2281.6 (0.7) +0x02280| 9a | . | first_mb_in_slice: 0 0x2281-0x2281 (0.1) +0x02280| 9a | . | slice_type: "p" (5) 0x2281.1-0x2281.5 (0.5) +0x02280| 9a | . | pic_parameter_set_id: 0 0x2281.6-0x2281.6 (0.1) +0x02280| 9a 22 6c 42 bf fe 38 85 de c2 03 1a de 79 0a| ."lB..8......y.| data: raw bits 0x2281.7-0x23c8.7 (327.1) +0x02290|56 fd b3 4b b4 0f 24 7f e9 d3 b6 f2 5e 6f dd b7|V..K..$.....^o..| +* |until 0x23c8.7 (328) | | + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [2][0:2]: sample (avc_au) 0x23d2-0x2409.7 (56) +0x023d0| 00 00 00 01 | .... | [0]: raw bits start_code 0x23d2-0x23d5.7 (4) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [1]{}: nalu (avc_nalu) 0x23d6-0x2409.7 (52) +0x023d0| 01 | . | forbidden_zero_bit: false 0x23d6-0x23d6 (0.1) +0x023d0| 01 | . | nal_ref_idc: 0 0x23d6.1-0x23d6.2 (0.2) +0x023d0| 01 | . | nal_unit_type: "slice" (1) (Coded slice of a non-IDR picture) 0x23d6.3-0x23d6.7 (0.5) + | | | slice_header{}: 0x23d7-0x23d7.6 (0.7) +0x023d0| 9e | . | first_mb_in_slice: 0 0x23d7-0x23d7 (0.1) +0x023d0| 9e | . | slice_type: "b" (6) 0x23d7.1-0x23d7.5 (0.5) +0x023d0| 9e | . | pic_parameter_set_id: 0 0x23d7.6-0x23d7.6 (0.1) +0x023d0| 9e 41 79 0a ff 01 f9 2d 04| .Ay....-.| data: raw bits 0x23d7.7-0x2409.7 (50.1) +0x023e0|d3 29 fe 4d 76 42 26 f6 cd 13 9c 32 05 69 f5 56|.).MvB&....2.i.V| +* |until 0x2409.7 (51) | | diff --git a/format/wav/testdata/end-of-file.fqtest b/format/riff/testdata/end-of-file.fqtest similarity index 87% rename from format/wav/testdata/end-of-file.fqtest rename to format/riff/testdata/end-of-file.fqtest index ab0337a5..9fcd7a23 100644 --- a/format/wav/testdata/end-of-file.fqtest +++ b/format/riff/testdata/end-of-file.fqtest @@ -3,26 +3,26 @@ $ fq -d wav dv end-of-file.wav |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: end-of-file.wav (wav) 0x0-0x731.7 (1842) 0x000|52 49 46 46 |RIFF | id: "RIFF" 0x0-0x3.7 (4) 0x000| ff ff ff ff | .... | size: 0xffffffff (Rest of file) 0x4-0x7.7 (4) -0x000| 57 41 56 45 | WAVE | format: "WAVE" 0x8-0xb.7 (4) +0x000| 57 41 56 45 | WAVE | format: "WAVE" (valid) 0x8-0xb.7 (4) | | | chunks[0:3]: 0xc-0x731.7 (1830) | | | [0]{}: chunk 0xc-0x23.7 (24) -0x000| 66 6d 74 20| fmt | id: "fmt" 0xc-0xf.7 (4) +0x000| 66 6d 74 20| fmt | id: "fmt " 0xc-0xf.7 (4) 0x010|10 00 00 00 |.... | size: 16 0x10-0x13.7 (4) -0x010| 01 00 | .. | audio_format: "pcm" (1) 0x14-0x15.7 (2) +0x010| 01 00 | .. | audio_format: "pcm_s16le" (1) 0x14-0x15.7 (2) 0x010| 02 00 | .. | num_channels: 2 0x16-0x17.7 (2) 0x010| 44 ac 00 00 | D... | sample_rate: 44100 0x18-0x1b.7 (4) 0x010| 10 b1 02 00| ....| byte_rate: 176400 0x1c-0x1f.7 (4) 0x020|04 00 |.. | block_align: 4 0x20-0x21.7 (2) 0x020| 10 00 | .. | bits_per_sample: 16 0x22-0x23.7 (2) | | | [1]{}: chunk 0x24-0x45.7 (34) -0x020| 4c 49 53 54 | LIST | id: "LIST" 0x24-0x27.7 (4) +0x020| 4c 49 53 54 | LIST | id: "LIST" (Chunk list) 0x24-0x27.7 (4) 0x020| 1a 00 00 00 | .... | size: 26 0x28-0x2b.7 (4) -0x020| 49 4e 46 4f| INFO| list_type: "INFO" 0x2c-0x2f.7 (4) +0x020| 49 4e 46 4f| INFO| type: "INFO" 0x2c-0x2f.7 (4) | | | chunks[0:1]: 0x30-0x45.7 (22) | | | [0]{}: chunk 0x30-0x45.7 (22) -0x030|49 53 46 54 |ISFT | id: "ISFT" 0x30-0x33.7 (4) +0x030|49 53 46 54 |ISFT | id: "ISFT" (Software. Identifies the name of the software package used to create the file) 0x30-0x33.7 (4) 0x030| 0e 00 00 00 | .... | size: 14 0x34-0x37.7 (4) -0x030| 4c 61 76 66 35 38 2e 34| Lavf58.4| data: "Lavf58.45.100" 0x38-0x45.7 (14) +0x030| 4c 61 76 66 35 38 2e 34| Lavf58.4| value: "Lavf58.45.100" 0x38-0x45.7 (14) 0x040|35 2e 31 30 30 00 |5.100. | | | | [2]{}: chunk 0x46-0x731.7 (1772) 0x040| 64 61 74 61 | data | id: "data" 0x46-0x49.7 (4) diff --git a/format/wav/testdata/end-of-file.wav b/format/riff/testdata/end-of-file.wav similarity index 100% rename from format/wav/testdata/end-of-file.wav rename to format/riff/testdata/end-of-file.wav diff --git a/format/riff/testdata/flac.avi b/format/riff/testdata/flac.avi new file mode 100644 index 0000000000000000000000000000000000000000..6c2f5f706fcab14cad356ea35197f9b50ea7454f GIT binary patch literal 6348 zcmeI0!HeBQ9LKZUJ@kplx>aaBtuoG_NO{e)-429RK^A^BBw%X~qQaJt?84TCq^^Cf zhaMKa&v+Re-t!$1i){Mv`x>?`&>d@Mh)q>a1PtJn68_+|*or)^W&c zbNyg%7uWMGdrfn#f0-1sanFKpTT?I0{CV4aVynlt%z9?E9iN`H=H0*NybtbrUOS(8 zZ_#_hTe3%6(5o-pfA7)MJXBr$IQsCUoyU_$c-`(-R}Y0a*AZ|8905nb5pVqO(eg`GrS(?Qr2l42wrG3K|k^s zwW&A|qic1*tAWOfho)YFfTw^OKgu(HGgFOFst$RtqdVG2>I18EAWA(j{T}d{-yZ&N=G&U^LHxbfvC~|H3-WGitZ_0ia4C$pre.. | max_bytes_per_sec: 16000 0x24-0x27.7 (4) +0x0020| 00 00 00 00 | .... | padding_granularity: 0 0x28-0x2b.7 (4) + | | | flags{}: 0x2c-0x2f.7 (4) +0x0020| 10 | . | unused0: raw bits 0x2c-0x2c.1 (0.2) +0x0020| 10 | . | must_use_index: false 0x2c.2-0x2c.2 (0.1) +0x0020| 10 | . | has_index: true 0x2c.3-0x2c.3 (0.1) +0x0020| 10 09 | .. | unused1: raw bits 0x2c.4-0x2d.3 (1) +0x0020| 09 | . | trust_ck_type: true 0x2d.4-0x2d.4 (0.1) +0x0020| 09 | . | unused2: raw bits 0x2d.5-0x2d.6 (0.2) +0x0020| 09 | . | is_interleaved: true 0x2d.7-0x2d.7 (0.1) +0x0020| 00 | . | unused3: raw bits 0x2e-0x2e.5 (0.6) +0x0020| 00 | . | copyrighted: false 0x2e.6-0x2e.6 (0.1) +0x0020| 00 | . | was_capture_file: false 0x2e.7-0x2e.7 (0.1) +0x0020| 00| .| unused4: raw bits 0x2f-0x2f.7 (1) +0x0030|00 00 00 00 |.... | total_frames: 0 0x30-0x33.7 (4) +0x0030| 00 00 00 00 | .... | initial_frames: 0 0x34-0x37.7 (4) +0x0030| 01 00 00 00 | .... | streams: 1 0x38-0x3b.7 (4) +0x0030| 00 00 10 00| ....| suggested_buffer_size: 1048576 0x3c-0x3f.7 (4) +0x0040|00 00 00 00 |.... | width: 0 0x40-0x43.7 (4) +0x0040| 00 00 00 00 | .... | height: 0 0x44-0x47.7 (4) +0x0040| 00 00 00 00 00 00 00 00| ........| reserved: raw bits 0x48-0x57.7 (16) +0x0050|00 00 00 00 00 00 00 00 |........ | + | | | [1]{}: chunk 0x58-0x10ff.7 (4264) +0x0050| 4c 49 53 54 | LIST | id: "LIST" (Chunk list) 0x58-0x5b.7 (4) +0x0050| a0 10 00 00| ....| size: 4256 0x5c-0x5f.7 (4) +0x0060|73 74 72 6c |strl | type: "strl" (Stream list) 0x60-0x63.7 (4) + | | | chunks[0:3]: 0x64-0x10ff.7 (4252) + | | | [0]{}: chunk 0x64-0xa3.7 (64) +0x0060| 73 74 72 68 | strh | id: "strh" (Stream header) 0x64-0x67.7 (4) +0x0060| 38 00 00 00 | 8... | size: 56 0x68-0x6b.7 (4) +0x0060| 61 75 64 73| auds| type: "auds" (Audio stream) 0x6c-0x6f.7 (4) +0x0070|01 00 00 00 |.... | handler: "\x01\x00\x00\x00" 0x70-0x73.7 (4) + | | | flags{}: 0x74-0x77.7 (4) +0x0070| 00 | . | unused0: raw bits 0x74-0x74.6 (0.7) +0x0070| 00 | . | disabled: false 0x74.7-0x74.7 (0.1) +0x0070| 00 00 | .. | unused1: raw bits 0x75-0x76.6 (1.7) +0x0070| 00 | . | pal_changes: false 0x76.7-0x76.7 (0.1) +0x0070| 00 | . | unused2: raw bits 0x77-0x77.7 (1) +0x0070| 00 00 | .. | priority: 0 0x78-0x79.7 (2) +0x0070| 00 00 | .. | language: 0 0x7a-0x7b.7 (2) +0x0070| 00 00 00 00| ....| initial_frames: 0 0x7c-0x7f.7 (4) +0x0080|80 00 00 00 |.... | scale: 128 0x80-0x83.7 (4) +0x0080| c9 04 00 00 | .... | rate: 1225 0x84-0x87.7 (4) +0x0080| 00 00 00 00 | .... | start: 0 0x88-0x8b.7 (4) +0x0080| 02 00 00 00| ....| length: 2 0x8c-0x8f.7 (4) +0x0090|5a 02 00 00 |Z... | suggested_buffer_size: 602 0x90-0x93.7 (4) +0x0090| ff ff ff ff | .... | quality: 4294967295 0x94-0x97.7 (4) +0x0090| 00 00 00 00 | .... | sample_size: 0 0x98-0x9b.7 (4) + | | | frame{}: 0x9c-0xa3.7 (8) +0x0090| 00 00 | .. | left: 0 0x9c-0x9d.7 (2) +0x0090| 00 00| ..| top: 0 0x9e-0x9f.7 (2) +0x00a0|00 00 |.. | right: 0 0xa0-0xa1.7 (2) +0x00a0| 00 00 | .. | bottom: 0 0xa2-0xa3.7 (2) + | | | [1]{}: chunk 0xa4-0xcd.7 (42) +0x00a0| 73 74 72 66 | strf | id: "strf" (Stream format) 0xa4-0xa7.7 (4) +0x00a0| 34 00 00 00 | 4... | size: 52 0xa8-0xab.7 (4) +0x00a0| ac f1 | .. | format_tag: "flac" (61868) 0xac-0xad.7 (2) +0x00a0| 01 00| ..| channels: 1 0xae-0xaf.7 (2) +0x00b0|44 ac 00 00 |D... | samples_per_sec: 44100 0xb0-0xb3.7 (4) +0x00b0| 80 3e 00 00 | .>.. | avg_bytes_per_sec: 16000 0xb4-0xb7.7 (4) +0x00b0| 02 00 | .. | block_align: 2 0xb8-0xb9.7 (2) +0x00b0| 10 00 | .. | bits_per_sample: 16 0xba-0xbb.7 (2) +0x00b0| 22 00 | ". | cb_size: 34 0xbc-0xbd.7 (2) +0x00b0| 12 00| ..| extra: raw bits 0xbe-0xcd.7 (16) +0x00c0|12 00 00 00 00 00 24 15 0a c4 40 f0 00 00 |......$...@... | + | | | [2]{}: chunk 0xe0-0x10ff.7 (4128) +0x00e0|4a 55 4e 4b |JUNK | id: "JUNK" (Alignment) 0xe0-0xe3.7 (4) +0x00e0| 18 10 00 00 | .... | size: 4120 0xe4-0xe7.7 (4) +0x00e0| 04 00 00 00 00 00 00 00| ........| data: raw bits 0xe8-0x10ff.7 (4120) +0x00f0|30 30 77 62 00 00 00 00 00 00 00 00 00 00 00 00|00wb............| +* |until 0x10ff.7 (4120) | | + | | | [2]{}: chunk 0x1100-0x120b.7 (268) +0x1100|4a 55 4e 4b |JUNK | id: "JUNK" (Alignment) 0x1100-0x1103.7 (4) +0x1100| 04 01 00 00 | .... | size: 260 0x1104-0x1107.7 (4) +0x1100| 6f 64 6d 6c 64 6d 6c 68| odmldmlh| data: raw bits 0x1108-0x120b.7 (260) +0x1110|f8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................| +* |until 0x120b.7 (260) | | + | | | [1]{}: chunk 0x120c-0x122d.7 (34) +0x1200| 4c 49 53 54| LIST| id: "LIST" (Chunk list) 0x120c-0x120f.7 (4) +0x1210|1a 00 00 00 |.... | size: 26 0x1210-0x1213.7 (4) +0x1210| 49 4e 46 4f | INFO | type: "INFO" 0x1214-0x1217.7 (4) + | | | chunks[0:1]: 0x1218-0x122d.7 (22) + | | | [0]{}: chunk 0x1218-0x122d.7 (22) +0x1210| 49 53 46 54 | ISFT | id: "ISFT" (Software. Identifies the name of the software package used to create the file) 0x1218-0x121b.7 (4) +0x1210| 0e 00 00 00| ....| size: 14 0x121c-0x121f.7 (4) +0x1220|4c 61 76 66 35 38 2e 37 36 2e 31 30 30 00 |Lavf58.76.100. | value: "Lavf58.76.100" 0x1220-0x122d.7 (14) + | | | [2]{}: chunk 0x122e-0x162d.7 (1024) +0x1220| 4a 55| JU| id: "JUNK" (Alignment) 0x122e-0x1231.7 (4) +0x1230|4e 4b |NK | +0x1230| f8 03 00 00 | .... | size: 1016 0x1232-0x1235.7 (4) +0x1230| 00 00 00 00 00 00 00 00 00 00| ..........| data: raw bits 0x1236-0x162d.7 (1016) +0x1240|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................| +* |until 0x162d.7 (1016) | | + | | | [3]{}: chunk 0x162e-0x18a3.7 (630) +0x1620| 4c 49| LI| id: "LIST" (Chunk list) 0x162e-0x1631.7 (4) +0x1630|53 54 |ST | +0x1630| 6e 02 00 00 | n... | size: 622 0x1632-0x1635.7 (4) +0x1630| 6d 6f 76 69 | movi | type: "movi" (Stream Data) 0x1636-0x1639.7 (4) + | | | chunks[0:2]: 0x163a-0x18a3.7 (618) + | | | [0]{}: chunk 0x163a-0x189b.7 (610) +0x1630| 30 30 77 62 | 00wb | id: "00wb" 0x163a-0x163d.7 (4) + | | | stream_type: "wb" (Audio data) 0x163e-NA (0) + | | | stream_nr: 0 0x163e-NA (0) +0x1630| 5a 02| Z.| size: 602 0x163e-0x1641.7 (4) +0x1640|00 00 |.. | + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| data{}: (flac_frame) 0x1642-0x189b.7 (602) + | | | header{}: 0x1642-0x1649.7 (8) +0x1640| ff f8 | .. | sync: 0b11111111111110 (valid) 0x1642-0x1643.5 (1.6) +0x1640| f8 | . | reserved0: 0 (valid) 0x1643.6-0x1643.6 (0.1) +0x1640| f8 | . | blocking_strategy: "fixed" (0) 0x1643.7-0x1643.7 (0.1) +0x1640| 79 | y | block_size: 0b111 (end of header (16 bit)) 0x1644-0x1644.3 (0.4) +0x1640| 79 | y | sample_rate: 44100 (0b1001) 0x1644.4-0x1644.7 (0.4) +0x1640| 08 | . | channel_assignment: 1 (0) (mono) 0x1645-0x1645.3 (0.4) +0x1640| 08 | . | sample_size: 16 (0b100) 0x1645.4-0x1645.6 (0.3) +0x1640| 08 | . | reserved1: 0 (valid) 0x1645.7-0x1645.7 (0.1) + | | | end_of_header{}: 0x1646-0x1648.7 (3) +0x1640| 00 | . | frame_number: 0 0x1646-0x1646.7 (1) +0x1640| 08 9c | .. | block_size: 2205 0x1647-0x1648.7 (2) +0x1640| 14 | . | crc: 0x14 (valid) 0x1649-0x1649.7 (1) + | | | subframes[0:1]: 0x164a-0x1899.1 (591.2) + | | | [0]{}: subframe 0x164a-0x1899.1 (591.2) +0x1640| 4a | J | zero_bit: 0 (valid) 0x164a-0x164a (0.1) +0x1640| 4a | J | subframe_type: "lpc" (0b100101) 0x164a.1-0x164a.6 (0.6) + | | | lpc_order: 6 0x164a.7-NA (0) +0x1640| 4a | J | wasted_bits_flag: 0 0x164a.7-0x164a.7 (0.1) + | | | subframe_sample_size: 16 0x164b-NA (0) + | | | warmup_samples[0:6]: 0x164b-0x1656.7 (12) +0x1640| 00 00 | .. | [0]: 0 value 0x164b-0x164c.7 (2) +0x1640| 01 00 | .. | [1]: 256 value 0x164d-0x164e.7 (2) +0x1640| 01| .| [2]: 511 value 0x164f-0x1650.7 (2) +0x1650|ff |. | +0x1650| 02 fd | .. | [3]: 765 value 0x1651-0x1652.7 (2) +0x1650| 03 f8 | .. | [4]: 1016 value 0x1653-0x1654.7 (2) +0x1650| 04 ee | .. | [5]: 1262 value 0x1655-0x1656.7 (2) +0x1650| e7 | . | precision: 15 0x1657-0x1657.3 (0.4) +0x1650| e7 32 | .2 | shift: 14 0x1657.4-0x1658 (0.5) + | | | coefficients[0:6]: 0x1658.1-0x1663.2 (11.2) +0x1650| 32 5e | 2^ | [0]: 12894 value 0x1658.1-0x1659.7 (1.7) +0x1650| 37 ca | 7. | [1]: 7141 value 0x165a-0x165b.6 (1.7) +0x1650| ca 2a f7 | .*. | [2]: 2749 value 0x165b.7-0x165d.5 (1.7) +0x1650| f7 eb e7| ...| [3]: -644 value 0x165d.6-0x165f.4 (1.7) +0x1650| e7| .| [4]: -2605 value 0x165f.5-0x1661.3 (1.7) +0x1660|5d 3e |]> | +0x1660| 3e 56 20 | >V | [5]: -3407 value 0x1661.4-0x1663.2 (1.7) +0x1660| 20 | | residual_coding_method: 4 (0) (rice) 0x1663.3-0x1663.4 (0.2) +0x1660| 20 01 | . | partition_order: 0 0x1663.5-0x1664 (0.4) + | | | rice_partitions: 1 0x1664.1-NA (0) + | | | partitions[0:1]: 0x1664.1-0x1899.1 (565.1) + | | | [0]{}: partition 0x1664.1-0x1899.1 (565.1) + | | | count: 2199 0x1664.1-NA (0) +0x1660| 01 | . | rice_parameter: 0 0x1664.1-0x1664.4 (0.4) +0x1660| 01 39 24 ce 12 64 92 49 39 9e 73 84| .9$..d.I9.s.| samples: raw bits 0x1664.5-0x1899.1 (564.5) +0x1670|d3 39 2c ce 49 29 f3 e7 e6 4e 4f 27 84 93 92 72|.9,.I)...NO'...r| +* |until 0x1899.1 (565) | | +0x1890| c0 | . | byte_align: 0 (valid) 0x1899.2-0x1899.7 (0.6) +0x1890| 7b 66 | {f | footer_crc: "7b66" (raw bits) (valid) 0x189a-0x189b.7 (2) + | | | [1]{}: chunk 0x189c-0x18a3.7 (8) +0x1890| 30 30 77 62| 00wb| id: "00wb" 0x189c-0x189f.7 (4) + | | | stream_type: "wb" (Audio data) 0x18a0-NA (0) + | | | stream_nr: 0 0x18a0-NA (0) +0x18a0|00 00 00 00 |.... | size: 0 0x18a0-0x18a3.7 (4) + | | | data: raw bits 0x18a4-NA (0) + | | | [4]{}: chunk 0x18a4-0x18cb.7 (40) +0x18a0| 69 64 78 31 | idx1 | id: "idx1" (Index) 0x18a4-0x18a7.7 (4) +0x18a0| 20 00 00 00 | ... | size: 32 0x18a8-0x18ab.7 (4) + | | | indexes[0:2]: 0x18ac-0x18cb.7 (32) + | | | [0]{}: index 0x18ac-0x18bb.7 (16) +0x18a0| 30 30 77 62| 00wb| id: "00wb" 0x18ac-0x18af.7 (4) + | | | stream_type: "wb" (Audio data) 0x18b0-NA (0) + | | | stream_nr: 0 0x18b0-NA (0) + | | | flags{}: 0x18b0-0x18b3.7 (4) +0x18b0|10 |. | unused0: raw bits 0x18b0-0x18b0.2 (0.3) +0x18b0|10 |. | key_frame: true 0x18b0.3-0x18b0.3 (0.1) +0x18b0|10 |. | unused1: raw bits 0x18b0.4-0x18b0.6 (0.3) +0x18b0|10 |. | list: false 0x18b0.7-0x18b0.7 (0.1) +0x18b0| 00 00 00 | ... | unused2: raw bits 0x18b1-0x18b3.7 (3) +0x18b0| 04 00 00 00 | .... | offset: 4 0x18b4-0x18b7.7 (4) +0x18b0| 5a 02 00 00 | Z... | length: 602 0x18b8-0x18bb.7 (4) + | | | [1]{}: index 0x18bc-0x18cb.7 (16) +0x18b0| 30 30 77 62| 00wb| id: "00wb" 0x18bc-0x18bf.7 (4) + | | | stream_type: "wb" (Audio data) 0x18c0-NA (0) + | | | stream_nr: 0 0x18c0-NA (0) + | | | flags{}: 0x18c0-0x18c3.7 (4) +0x18c0|10 |. | unused0: raw bits 0x18c0-0x18c0.2 (0.3) +0x18c0|10 |. | key_frame: true 0x18c0.3-0x18c0.3 (0.1) +0x18c0|10 |. | unused1: raw bits 0x18c0.4-0x18c0.6 (0.3) +0x18c0|10 |. | list: false 0x18c0.7-0x18c0.7 (0.1) +0x18c0| 00 00 00 | ... | unused2: raw bits 0x18c1-0x18c3.7 (3) +0x18c0| 66 02 00 00 | f... | offset: 614 0x18c4-0x18c7.7 (4) +0x18c0| 00 00 00 00| | ....| | length: 0 0x18c8-0x18cb.7 (4) +0x00c0| 00 00| ..| unknown0: raw bits 0xce-0xdf.7 (18) +0x00d0|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................| + | | | streams[0:1]: 0x1642-0x18a3.7 (610) + | | | [0]{}: stream 0x1642-0x18a3.7 (610) + | | | samples[0:2]: 0x1642-0x18a3.7 (610) + |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [0]{}: sample (flac_frame) 0x1642-0x189b.7 (602) + | | | header{}: 0x1642-0x1649.7 (8) +0x1640| ff f8 | .. | sync: 0b11111111111110 (valid) 0x1642-0x1643.5 (1.6) +0x1640| f8 | . | reserved0: 0 (valid) 0x1643.6-0x1643.6 (0.1) +0x1640| f8 | . | blocking_strategy: "fixed" (0) 0x1643.7-0x1643.7 (0.1) +0x1640| 79 | y | block_size: 0b111 (end of header (16 bit)) 0x1644-0x1644.3 (0.4) +0x1640| 79 | y | sample_rate: 44100 (0b1001) 0x1644.4-0x1644.7 (0.4) +0x1640| 08 | . | channel_assignment: 1 (0) (mono) 0x1645-0x1645.3 (0.4) +0x1640| 08 | . | sample_size: 16 (0b100) 0x1645.4-0x1645.6 (0.3) +0x1640| 08 | . | reserved1: 0 (valid) 0x1645.7-0x1645.7 (0.1) + | | | end_of_header{}: 0x1646-0x1648.7 (3) +0x1640| 00 | . | frame_number: 0 0x1646-0x1646.7 (1) +0x1640| 08 9c | .. | block_size: 2205 0x1647-0x1648.7 (2) +0x1640| 14 | . | crc: 0x14 (valid) 0x1649-0x1649.7 (1) + | | | subframes[0:1]: 0x164a-0x1899.1 (591.2) + | | | [0]{}: subframe 0x164a-0x1899.1 (591.2) +0x1640| 4a | J | zero_bit: 0 (valid) 0x164a-0x164a (0.1) +0x1640| 4a | J | subframe_type: "lpc" (0b100101) 0x164a.1-0x164a.6 (0.6) + | | | lpc_order: 6 0x164a.7-NA (0) +0x1640| 4a | J | wasted_bits_flag: 0 0x164a.7-0x164a.7 (0.1) + | | | subframe_sample_size: 16 0x164b-NA (0) + | | | warmup_samples[0:6]: 0x164b-0x1656.7 (12) +0x1640| 00 00 | .. | [0]: 0 value 0x164b-0x164c.7 (2) +0x1640| 01 00 | .. | [1]: 256 value 0x164d-0x164e.7 (2) +0x1640| 01| .| [2]: 511 value 0x164f-0x1650.7 (2) +0x1650|ff |. | +0x1650| 02 fd | .. | [3]: 765 value 0x1651-0x1652.7 (2) +0x1650| 03 f8 | .. | [4]: 1016 value 0x1653-0x1654.7 (2) +0x1650| 04 ee | .. | [5]: 1262 value 0x1655-0x1656.7 (2) +0x1650| e7 | . | precision: 15 0x1657-0x1657.3 (0.4) +0x1650| e7 32 | .2 | shift: 14 0x1657.4-0x1658 (0.5) + | | | coefficients[0:6]: 0x1658.1-0x1663.2 (11.2) +0x1650| 32 5e | 2^ | [0]: 12894 value 0x1658.1-0x1659.7 (1.7) +0x1650| 37 ca | 7. | [1]: 7141 value 0x165a-0x165b.6 (1.7) +0x1650| ca 2a f7 | .*. | [2]: 2749 value 0x165b.7-0x165d.5 (1.7) +0x1650| f7 eb e7| ...| [3]: -644 value 0x165d.6-0x165f.4 (1.7) +0x1650| e7| .| [4]: -2605 value 0x165f.5-0x1661.3 (1.7) +0x1660|5d 3e |]> | +0x1660| 3e 56 20 | >V | [5]: -3407 value 0x1661.4-0x1663.2 (1.7) +0x1660| 20 | | residual_coding_method: 4 (0) (rice) 0x1663.3-0x1663.4 (0.2) +0x1660| 20 01 | . | partition_order: 0 0x1663.5-0x1664 (0.4) + | | | rice_partitions: 1 0x1664.1-NA (0) + | | | partitions[0:1]: 0x1664.1-0x1899.1 (565.1) + | | | [0]{}: partition 0x1664.1-0x1899.1 (565.1) + | | | count: 2199 0x1664.1-NA (0) +0x1660| 01 | . | rice_parameter: 0 0x1664.1-0x1664.4 (0.4) +0x1660| 01 39 24 ce 12 64 92 49 39 9e 73 84| .9$..d.I9.s.| samples: raw bits 0x1664.5-0x1899.1 (564.5) +0x1670|d3 39 2c ce 49 29 f3 e7 e6 4e 4f 27 84 93 92 72|.9,.I)...NO'...r| +* |until 0x1899.1 (565) | | +0x1890| c0 | . | byte_align: 0 (valid) 0x1899.2-0x1899.7 (0.6) +0x1890| 7b 66 | {f | footer_crc: "7b66" (raw bits) (valid) 0x189a-0x189b.7 (2) + | | | [1]: raw bits sample 0x18a4-NA (0) diff --git a/format/riff/testdata/help_avi.fqtest b/format/riff/testdata/help_avi.fqtest new file mode 100644 index 00000000..48d2d00a --- /dev/null +++ b/format/riff/testdata/help_avi.fqtest @@ -0,0 +1,40 @@ +$ fq -h avi +avi: Audio Video Interleaved decoder + +Options +======= + + decode_samples=true Decode supported media samples + +Decode examples +=============== + + # Decode file as avi + $ fq -d avi . file + # Decode value as avi + ... | avi + # Decode file using avi options + $ fq -d avi -o decode_samples=true . file + # Decode value as avi + ... | avi({decode_samples:true}) + +Samples +======= +AVI has many redundant ways to index samples so currently .streams[].samples will only include samples the most "modern" way used in the file. That is in order +of stream super index, movi ix index then idx1 index. + +Extract samples for stream 1 +============================ + + $ fq '.streams[1].samples[] | tobytes' file.avi > stream01.mp3 + +Show stream summary +=================== + + $ fq -o decode_samples=false '[.chunks[0] | grep_by(.id=="LIST" and .type=="strl") | grep_by(.id=="strh") as {$type} | grep_by(.id=="strf") as {$format_tag, $compression} | {$type,$format_tag,$compression}]' *.avi + +References +========== +- AVI RIFF File Reference (https://learn.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference) +- OpenDML AVI File Format Extensions (http://www.jmcgowan.com/odmlff2.pdf) + diff --git a/format/riff/testdata/mp3.avi b/format/riff/testdata/mp3.avi new file mode 100644 index 0000000000000000000000000000000000000000..e8dacf9bf3c166476182d850b4a38216c8c5cfd5 GIT binary patch literal 6376 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 0 { + d.FieldU16("extension_size") + d.FieldU16("valid_bits_per_sample") + d.FieldU32("channel_mask") + d.FieldRawLen("sub_format", 16*8, subFormatNames) + } + return false, nil + + case "data": + d.FieldRawLen("samples", d.BitsLeft()) + return false, nil + + case "fact": + d.FieldU32("sample_length") + return false, nil + + case "smpl": + d.FieldU32("manufacturer") + d.FieldU32("product") + d.FieldU32("sample_period") + d.FieldU32("midi_unity_note") + d.FieldU32("midi_pitch_fraction") + d.FieldU32("smpte_format") + d.FieldU32("smpte_offset") + numSampleLoops := int(d.FieldU32("number_of_sample_loops")) + samplerDataBytes := int(d.FieldU32("sampler_data_bytes")) + d.FieldArray("samples_loops", func(d *decode.D) { + for i := 0; i < numSampleLoops; i++ { + d.FieldStruct("sample_loop", func(d *decode.D) { + d.FieldUTF8("id", 4) + d.FieldU32("type", scalar.UToSymStr{ + 0: "forward", + 1: "forward_backward", + 2: "backward", + }) + d.FieldU32("start") + d.FieldU32("end") + d.FieldU32("fraction") + d.FieldU32("number_of_times") + }) + } + }) + d.FieldRawLen("sampler_data", int64(samplerDataBytes)*8) + return false, nil + + default: + if riffIsStringChunkID(id) { + d.FieldUTF8NullFixedLen("value", int(d.BitsLeft())/8) + return false, nil + } + + d.FieldRawLen("data", d.BitsLeft()) + return false, nil + } + }, + ) + + if riffType != wavRiffType { + d.Errorf("wrong or no AVI riff type found (%s)", riffType) + } + _, _, _ = d.TryFieldFormat("footer", wavFooterFormat, nil) + + return nil +} diff --git a/format/wav/wav.go b/format/wav/wav.go deleted file mode 100644 index e3f13b8c..00000000 --- a/format/wav/wav.go +++ /dev/null @@ -1,239 +0,0 @@ -package wav - -// http://soundfile.sapp.org/doc/WaveFormat/ -// https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/wavdec.c -// https://tech.ebu.ch/docs/tech/tech3285.pdf -// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html -// TODO: audio/wav -// TODO: default little endian - -import ( - "fmt" - "strings" - - "github.com/wader/fq/format" - "github.com/wader/fq/pkg/decode" - "github.com/wader/fq/pkg/interp" - "github.com/wader/fq/pkg/scalar" -) - -var headerFormat decode.Group -var footerFormat decode.Group - -func init() { - interp.RegisterFormat(decode.Format{ - Name: format.WAV, - ProbeOrder: format.ProbeOrderBinFuzzy, // after most others (overlap some with webp) - Description: "WAV file", - Groups: []string{format.PROBE}, - DecodeFn: wavDecode, - Dependencies: []decode.Dependency{ - {Names: []string{format.ID3V2}, Group: &headerFormat}, - {Names: []string{format.ID3V1, format.ID3V11}, Group: &footerFormat}, - }, - }) -} - -const ( - formatExtensible = 0xfffe -) - -// transformed from ffmpeg libavformat/riff.c -var audioFormatName = scalar.UToSymStr{ - 0x0001: "pcm", - 0x0002: "adpcm_ms", - 0x0003: "pcm_float", - /* must come after f32le in this list */ - 0x0006: "pcm_alaw", - 0x0007: "pcm_mulaw", - 0x000a: "wmavoice", - 0x0010: "adpcm_ima_oki", - 0x0011: "adpcm_ima_wav", - /* must come after adpcm_ima_wav in this list */ - 0x0017: "adpcm_ima_oki", - 0x0020: "adpcm_yamaha", - 0x0022: "truespeech", - 0x0031: "gsm_ms", - 0x0032: "gsm_ms", /* msn audio */ - 0x0038: "amr_nb", /* rogue format number */ - 0x0042: "g723_1", - 0x0045: "adpcm_g726", - 0x0014: "adpcm_g726", /* g723 Antex */ - 0x0040: "adpcm_g726", /* g721 Antex */ - 0x0050: "mp2", - 0x0055: "mp3", - 0x0057: "amr_nb", - 0x0058: "amr_wb", - /* rogue format number */ - 0x0061: "adpcm_ima_dk4", - /* rogue format number */ - 0x0062: "adpcm_ima_dk3", - 0x0064: "adpcm_g726", - 0x0069: "adpcm_ima_wav", - 0x0075: "metasound", - 0x0083: "g729", - 0x00ff: "aac", - 0x0111: "g723_1", - 0x0130: "sipr", - 0x0135: "acelp_kelvin", - 0x0160: "wmav1", - 0x0161: "wmav2", - 0x0162: "wmapro", - 0x0163: "wmalossless", - 0x0165: "xma1", - 0x0166: "xma2", - 0x0200: "adpcm_ct", - 0x0215: "dvaudio", - 0x0216: "dvaudio", - 0x0270: "atrac3", - 0x028f: "adpcm_g722", - 0x0401: "imc", - 0x0402: "iac", - 0x0500: "on2avc", - 0x0501: "on2avc", - 0x1500: "gsm_ms", - 0x1501: "truespeech", - 0x1600: "aac", - 0x1602: "aac_latm", - 0x2000: "ac3", - 0x2001: "dts", - 0x2048: "sonic", - 0x6c75: "pcm_mulaw", - 0x706d: "aac", - 0x4143: "aac", - 0x594a: "xan_dpcm", - 0x729a: "g729", - 0xa100: "g723_1", /* Comverse Infosys Ltd. G723 1 */ - 0xa106: "aac", - 0xa109: "speex", - 0xf1ac: "flac", - ('S' << 8) + 'F': "adpcm_swf", - /* HACK/FIXME: Does Vorbis in WAV/AVI have an (in)official ID? */ - ('V' << 8) + 'o': "vorbis", - - formatExtensible: "extensible", -} - -var ( - subFormatPCMBytes = [16]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} - subFormatIEEEFloat = [16]byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -) - -var subFormatNames = scalar.BytesToScalar{ - {Bytes: subFormatPCMBytes[:], Scalar: scalar.S{Sym: "pcm"}}, - {Bytes: subFormatIEEEFloat[:], Scalar: scalar.S{Sym: "ieee_float"}}, -} - -func decodeChunk(d *decode.D, expectedChunkID string, stringData bool) { - d.Endian = decode.LittleEndian - - chunks := map[string]func(d *decode.D){ - "RIFF": func(d *decode.D) { - d.FieldUTF8("format", 4) - decodeChunks(d, false) - }, - "fmt": func(d *decode.D) { - audioFormat := d.FieldU16("audio_format", audioFormatName) - d.FieldU16("num_channels") - d.FieldU32("sample_rate") - d.FieldU32("byte_rate") - d.FieldU16("block_align") - d.FieldU16("bits_per_sample") - - if audioFormat == formatExtensible && d.BitsLeft() > 0 { - d.FieldU16("extension_size") - d.FieldU16("valid_bits_per_sample") - d.FieldU32("channel_mask") - d.FieldRawLen("sub_format", 16*8, subFormatNames) - } - }, - "data": func(d *decode.D) { - d.FieldRawLen("samples", d.BitsLeft()) - }, - "LIST": func(d *decode.D) { - d.FieldUTF8("list_type", 4) - decodeChunks(d, true) - }, - "fact": func(d *decode.D) { - d.FieldU32("sample_length") - }, - "smpl": func(d *decode.D) { - d.FieldU32("manufacturer") - d.FieldU32("product") - d.FieldU32("sample_period") - d.FieldU32("midi_unity_note") - d.FieldU32("midi_pitch_fraction") - d.FieldU32("smpte_format") - d.FieldU32("smpte_offset") - numSampleLoops := int(d.FieldU32("number_of_sample_loops")) - samplerDataBytes := int(d.FieldU32("sampler_data_bytes")) - d.FieldArray("samples_loops", func(d *decode.D) { - for i := 0; i < numSampleLoops; i++ { - d.FieldStruct("sample_loop", func(d *decode.D) { - d.FieldUTF8("id", 4) - d.FieldU32("type", scalar.UToSymStr{ - 0: "forward", - 1: "forward_backward", - 2: "backward", - }) - d.FieldU32("start") - d.FieldU32("end") - d.FieldU32("fraction") - d.FieldU32("number_of_times") - }) - } - }) - d.FieldRawLen("sampler_data", int64(samplerDataBytes)*8) - }, - } - - trimChunkID := d.FieldStrFn("id", func(d *decode.D) string { - return strings.TrimSpace(d.UTF8(4)) - }) - if expectedChunkID != "" && trimChunkID != expectedChunkID { - d.Errorf(fmt.Sprintf("expected chunk id %q found %q", expectedChunkID, trimChunkID)) - } - const restOfFileLen = 0xffffffff - chunkLen := int64(d.FieldUScalarFn("size", func(d *decode.D) scalar.S { - l := d.U32() - if l == restOfFileLen { - return scalar.S{Actual: l, ActualDisplay: scalar.NumberHex, Description: "Rest of file"} - } - return scalar.S{Actual: l, ActualDisplay: scalar.NumberDecimal} - })) - - if chunkLen == restOfFileLen { - chunkLen = d.BitsLeft() / 8 - } - - if fn, ok := chunks[trimChunkID]; ok { - d.FramedFn(chunkLen*8, fn) - } else { - if stringData { - d.FieldUTF8("data", int(chunkLen), scalar.ActualTrim(" \x00")) - } else { - d.FieldRawLen("data", chunkLen*8) - } - } - - if chunkLen%2 != 0 { - d.FieldRawLen("align", 8) - } -} - -func decodeChunks(d *decode.D, stringData bool) { - d.FieldStructArrayLoop("chunks", "chunk", d.NotEnd, func(d *decode.D) { - decodeChunk(d, "", stringData) - }) -} - -func wavDecode(d *decode.D, _ any) any { - // there are wav files in the wild with id3v2 header id3v1 footer - _, _, _ = d.TryFieldFormat("header", headerFormat, nil) - - decodeChunk(d, "RIFF", false) - - _, _, _ = d.TryFieldFormat("footer", footerFormat, nil) - - return nil -}