From 51965549891d4f9d04477bfe8fac552acc03042e Mon Sep 17 00:00:00 2001 From: Mattias Wadman Date: Sat, 7 Oct 2023 11:01:44 +0200 Subject: [PATCH] avi: Add type, handler, format_tag and compreession per stream Also simplify stream tracking code a bit --- format/riff/avi.go | 81 +++++++++++++++------------- format/riff/testdata/avc.avi.fqtest | 7 ++- format/riff/testdata/flac.avi.fqtest | 7 ++- format/riff/testdata/mp3.avi.fqtest | 7 ++- format/riff/testdata/pcm.avi.fqtest | 7 ++- 5 files changed, 64 insertions(+), 45 deletions(-) diff --git a/format/riff/avi.go b/format/riff/avi.go index 0034ca923..78854eb31 100644 --- a/format/riff/avi.go +++ b/format/riff/avi.go @@ -105,12 +105,6 @@ var aviStreamChunkTypeDescriptions = scalar.StrMapDescription{ const aviRiffType = "AVI " -type aviStrl struct { - typ string - handler string - stream *aviStream -} - type idx1Sample struct { offset int64 size int64 @@ -119,6 +113,10 @@ type idx1Sample struct { } type aviStream struct { + typ string + handler string + formatTag uint64 + compression string hasFormat bool format *decode.Group formatInArg any @@ -244,7 +242,7 @@ func aviDecode(d *decode.D) any { typ := d.FieldUTF8("type", 4, aviListTypeDescriptions) switch typ { case "strl": - return true, &aviStrl{} + return true, &aviStream{} case "movi": moviListPos = d.Pos() } @@ -337,21 +335,19 @@ func aviDecode(d *decode.D) any { d.FieldU16("bottom") }) - if aviStrl, aviStrlOk := path.topData().(*aviStrl); aviStrlOk { - aviStrl.typ = typ - aviStrl.handler = handler + if stream, ok := path.topData().(*aviStream); ok { + stream.typ = typ + stream.handler = handler } return false, nil case "strf": - s := &aviStream{} - - typ := "" - if aviStrl, aviStrlOk := path.topData().(*aviStrl); aviStrlOk { - typ = aviStrl.typ - aviStrl.stream = s + stream, streamOk := path.topData().(*aviStream) + if !streamOk { + stream = &aviStream{} } + typ := stream.typ switch typ { case "vids": @@ -372,6 +368,8 @@ func aviDecode(d *decode.D) any { d.FieldRawLen("extra", d.BitsLeft()) } + stream.compression = compression + // TODO: if dvsd handler and extraSize >= 32 then DVINFO? switch compression { @@ -389,12 +387,12 @@ func aviDecode(d *decode.D) any { format.BMPTagH264_UMSV, format.BMPTagH264_tshd, format.BMPTagH264_INMC: - s.format = &aviMpegAVCAUGroup - s.hasFormat = true + stream.format = &aviMpegAVCAUGroup + stream.hasFormat = true case format.BMPTagHEVC, format.BMPTagHEVC_H265: - s.format = &aviMpegHEVCAUGroup - s.hasFormat = true + stream.format = &aviMpegHEVCAUGroup + stream.hasFormat = true } case "auds": @@ -411,14 +409,16 @@ func aviDecode(d *decode.D) any { d.FieldRawLen("extra", int64(cbSize)*8) } + stream.formatTag = formatTag + switch formatTag { case format.WAVTagMP3: - s.format = &aviMp3FrameGroup - s.hasFormat = true + stream.format = &aviMp3FrameGroup + stream.hasFormat = true case format.WAVTagFLAC: // TODO: can flac in avi have streaminfo somehow? - s.format = &aviFLACFrameGroup - s.hasFormat = true + stream.format = &aviFLACFrameGroup + stream.hasFormat = true } case "iavs": // DVINFO @@ -431,15 +431,12 @@ func aviDecode(d *decode.D) any { d.FieldRawLen("dvv_reserved", 32*2) } - streams = append(streams, s) + streams = append(streams, stream) return false, nil case "indx": - var stream *aviStream - if aviStrl, aviStrlOk := path.topData().(*aviStrl); aviStrlOk { - stream = aviStrl.stream - } + stream, _ := path.topData().(*aviStream) d.FieldU16("longs_per_entry") // TODO: use? d.FieldU8("index_subtype") @@ -532,12 +529,22 @@ func aviDecode(d *decode.D) any { } d.FieldArray("streams", func(d *decode.D) { - for si, s := range streams { + for streamIndex, stream := range streams { + d.FieldStruct("stream", func(d *decode.D) { + d.FieldValueStr("type", stream.typ) + d.FieldValueStr("handler", stream.handler) + switch stream.typ { + case "auds": + d.FieldValueUint("format_tag", stream.formatTag, format.WAVTagNames) + case "vids": + d.FieldValueStr("compression", stream.compression) + } + var streamIndexSampleRanges []ranges.Range - if len(s.indexes) > 0 { + if len(stream.indexes) > 0 { d.FieldArray("indexes", func(d *decode.D) { - for _, i := range s.indexes { + for _, i := range stream.indexes { d.FieldStruct("index", func(d *decode.D) { d.RangeFn(i.Start, i.Len, func(d *decode.D) { d.FieldUTF8("type", 4) @@ -554,8 +561,8 @@ func aviDecode(d *decode.D) any { // 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) + if sr.Len > 0 && ai.DecodeSamples && stream.hasFormat { + d.FieldFormat("sample", stream.format, stream.formatInArg) } else { d.FieldRawLen("sample", d.BitsLeft()) } @@ -572,16 +579,16 @@ func aviDecode(d *decode.D) any { decodeSample(d, sr) } }) - } else if len(s.ixSamples) > 0 { + } else if len(stream.ixSamples) > 0 { d.FieldArray("samples", func(d *decode.D) { - for _, sr := range s.ixSamples { + for _, sr := range stream.ixSamples { decodeSample(d, sr) } }) } else if len(idx1Samples) > 0 { d.FieldArray("samples", func(d *decode.D) { for _, is := range idx1Samples { - if is.streamNr != si { + if is.streamNr != streamIndex { continue } decodeSample(d, ranges.Range{ diff --git a/format/riff/testdata/avc.avi.fqtest b/format/riff/testdata/avc.avi.fqtest index 8b587b77c..7470893d8 100644 --- a/format/riff/testdata/avc.avi.fqtest +++ b/format/riff/testdata/avc.avi.fqtest @@ -343,8 +343,8 @@ $ fq dv avc.avi 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) + | | | streams[0:1]: 0x1682-0x2441.7 (3520) + | | | [0]{}: stream 0x1682-0x2441.7 (3520) | | | 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) @@ -487,3 +487,6 @@ $ fq dv avc.avi 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) | | + | | | type: "vids" 0x2442-NA (0) + | | | handler: "H264" 0x2442-NA (0) + | | | compression: "H264" 0x2442-NA (0) diff --git a/format/riff/testdata/flac.avi.fqtest b/format/riff/testdata/flac.avi.fqtest index 929ada89a..44afe54ea 100644 --- a/format/riff/testdata/flac.avi.fqtest +++ b/format/riff/testdata/flac.avi.fqtest @@ -205,8 +205,8 @@ $ fq dv flac.avi 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) - | | | streams[0:1]: 0x1642-0x18a3.7 (610) - | | | [0]{}: stream 0x1642-0x18a3.7 (610) + | | | streams[0:1]: 0x1642-0x18cb.7 (650) + | | | [0]{}: stream 0x1642-0x18cb.7 (650) | | | 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) @@ -260,3 +260,6 @@ $ fq dv flac.avi 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) + | | | type: "auds" 0x18cc-NA (0) + | | | handler: "\x01\x00\x00\x00" 0x18cc-NA (0) + | | | format_tag: "flac" (61868) 0x18cc-NA (0) diff --git a/format/riff/testdata/mp3.avi.fqtest b/format/riff/testdata/mp3.avi.fqtest index 54cf4ee5d..b3f2ccb74 100644 --- a/format/riff/testdata/mp3.avi.fqtest +++ b/format/riff/testdata/mp3.avi.fqtest @@ -351,8 +351,8 @@ $ fq dv mp3.avi 0x18d0| 00 00 00| ...| unused2: raw bits 0x18dd-0x18df.7 (3) 0x18e0|b6 01 00 00 |.... | offset: 438 0x18e0-0x18e3.7 (4) 0x18e0| d1 00 00 00| | ....| | length: 209 0x18e4-0x18e7.7 (4) - | | | streams[0:1]: 0x162c-0x18ae.7 (643) - | | | [0]{}: stream 0x162c-0x18ae.7 (643) + | | | streams[0:1]: 0x162c-0x18e7.7 (700) + | | | [0]{}: stream 0x162c-0x18e7.7 (700) | | | samples[0:3]: 0x162c-0x18ae.7 (643) |00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef| [0]{}: sample (mp3_frame) 0x162c-0x16fb.7 (208) | | | header{}: 0x162c-0x162f.7 (4) @@ -534,3 +534,6 @@ $ fq dv mp3.avi 0x1800|cb a0 77 10 07 47 8b 8c 7b 2e 82 33 01 c4 c0 04|..w..G..{..3....| * |until 0x18ae.7 (188) | | | | | crc_calculated: "c36b" (raw bits) 0x18af-NA (0) + | | | type: "auds" 0x18e8-NA (0) + | | | handler: "\x01\x00\x00\x00" 0x18e8-NA (0) + | | | format_tag: "mp3" (85) 0x18e8-NA (0) diff --git a/format/riff/testdata/pcm.avi.fqtest b/format/riff/testdata/pcm.avi.fqtest index de2f1127d..eadfa87bf 100644 --- a/format/riff/testdata/pcm.avi.fqtest +++ b/format/riff/testdata/pcm.avi.fqtest @@ -222,8 +222,8 @@ $ fq dv pcm.avi 0x3900|00 00 |.. | 0x3900| 24 20 00 00 | $ .. | offset: 8228 0x3902-0x3905.7 (4) 0x3900| 74 02 00 00| | t...| | length: 628 0x3906-0x3909.7 (4) - | | | streams[0:1]: 0x161e-0x38b1.7 (8852) - | | | [0]{}: stream 0x161e-0x38b1.7 (8852) + | | | streams[0:1]: 0x161e-0x3909.7 (8940) + | | | [0]{}: stream 0x161e-0x3909.7 (8940) | | | samples[0:5]: 0x161e-0x38b1.7 (8852) 0x1610| 00 00| ..| [0]: raw bits sample 0x161e-0x1e1d.7 (2048) 0x1620|00 01 ff 01 fd 02 f8 03 ee 04 e0 05 cc 06 b0 07|................| @@ -240,3 +240,6 @@ $ fq dv pcm.avi 0x3630| 24 f4| $.| [4]: raw bits sample 0x363e-0x38b1.7 (628) 0x3640|d6 f4 94 f5 5c f6 2d f7 08 f8 ea f8 d4 f9 c4 fa|....\.-.........| * |until 0x38b1.7 (628) | | + | | | type: "auds" 0x390a-NA (0) + | | | handler: "\x01\x00\x00\x00" 0x390a-NA (0) + | | | format_tag: "pcm_s16le" (1) 0x390a-NA (0)