1
1
mirror of https://github.com/wader/fq.git synced 2024-09-11 12:05:39 +03:00

webp: Refactor to use riff code and decode VP8X, EXIF, ICCP and XMP chunks

This commit is contained in:
Mattias Wadman 2023-11-01 17:31:32 +01:00
parent 7c8fa05e30
commit 9e58067f4b
10 changed files with 1389 additions and 1183 deletions

View File

@ -122,7 +122,7 @@
|`vpx_ccr` |VPX&nbsp;Codec&nbsp;Configuration&nbsp;Record |<sub></sub>|
|[`wasm`](#wasm) |WebAssembly&nbsp;Binary&nbsp;Format |<sub></sub>|
|`wav` |WAV&nbsp;file |<sub>`id3v2` `id3v1` `id3v11`</sub>|
|`webp` |WebP&nbsp;image |<sub>`vp8_frame`</sub>|
|`webp` |WebP&nbsp;image |<sub>`exif` `vp8_frame` `icc_profile` `xml`</sub>|
|[`xml`](#xml) |Extensible&nbsp;Markup&nbsp;Language |<sub></sub>|
|`yaml` |YAML&nbsp;Ain't&nbsp;Markup&nbsp;Language |<sub></sub>|
|[`zip`](#zip) |ZIP&nbsp;archive |<sub>`probe`</sub>|

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 153 KiB

View File

@ -58,7 +58,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/webp"
_ "github.com/wader/fq/format/xml"
_ "github.com/wader/fq/format/yaml"
_ "github.com/wader/fq/format/zip"

View File

@ -1,29 +1,30 @@
# convert -size 4x4 "xc:#000" 4x4.webp
$ fq -d webp dv 4x4.webp
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: 4x4.webp (webp) 0x0-0x2c (44)
0x00|52 49 46 46 |RIFF | riff_id: "RIFF" (valid) 0x0-0x4 (4)
0x00| 24 00 00 00 | $... | riff_length: 36 0x4-0x8 (4)
0x00| 57 45 42 50 | WEBP | webp_id: "WEBP" (valid) 0x8-0xc (4)
| | | image{}: 0xc-0x2c (32)
0x00| 56 50 38 20| VP8 | id: "VP8" 0xc-0x10 (4)
0x10|18 00 00 00 |.... | size: 24 0x10-0x14 (4)
| | | tag{}: 0x14-0x17 (3)
0x10| 30 | 0 | first_part_size0: 1 0x14-0x14.3 (0.3)
0x10| 30 | 0 | show_frame: 1 0x14.3-0x14.4 (0.1)
0x10| 30 | 0 | version: 0 0x14.4-0x14.7 (0.3)
0x10| 30 | 0 | frame_type: "key_frame" (false) 0x14.7-0x15 (0.1)
0x10| 01 00 | .. | first_part_size1: 1 0x15-0x17 (2)
| | | first_part_size: 9
| | | reconstruction: "Bicubic"
| | | loop: "Normal"
0x10| 9d 01 2a | ..* | start_code: 0x9d012a (valid) 0x17-0x1a (3)
0x10| 04 | . | width0: 4 0x1a-0x1b (1)
0x10| 00 | . | horizontal_scale: 0 0x1b-0x1b.2 (0.2)
0x10| 00 | . | width1: 0 0x1b.2-0x1c (0.6)
| | | width: 4
0x10| 04 | . | height0: 4 0x1c-0x1d (1)
0x10| 00 | . | vertical_scale: 0 0x1d-0x1d.2 (0.2)
0x10| 00 | . | height1: 0 0x1d.2-0x1e (0.6)
| | | height: 4
0x10| 02 00| ..| data: raw bits 0x1e-0x2c (14)
0x00|52 49 46 46 |RIFF | id: "RIFF" 0x0-0x4 (4)
0x00| 24 00 00 00 | $... | size: 36 0x4-0x8 (4)
0x00| 57 45 42 50 | WEBP | format: "WEBP" (valid) 0x8-0xc (4)
| | | chunks[0:1]: 0xc-0x2c (32)
| | | [0]{}: chunk 0xc-0x2c (32)
0x00| 56 50 38 20| VP8 | id: "VP8 " 0xc-0x10 (4)
0x10|18 00 00 00 |.... | size: 24 0x10-0x14 (4)
| | | tag{}: 0x14-0x17 (3)
0x10| 30 | 0 | first_part_size0: 1 0x14-0x14.3 (0.3)
0x10| 30 | 0 | show_frame: 1 0x14.3-0x14.4 (0.1)
0x10| 30 | 0 | version: 0 0x14.4-0x14.7 (0.3)
0x10| 30 | 0 | frame_type: "key_frame" (false) 0x14.7-0x15 (0.1)
0x10| 01 00 | .. | first_part_size1: 1 0x15-0x17 (2)
| | | first_part_size: 9
| | | reconstruction: "Bicubic"
| | | loop: "Normal"
0x10| 9d 01 2a | ..* | start_code: 0x9d012a (valid) 0x17-0x1a (3)
0x10| 04 | . | width0: 4 0x1a-0x1b (1)
0x10| 00 | . | horizontal_scale: 0 0x1b-0x1b.2 (0.2)
0x10| 00 | . | width1: 0 0x1b.2-0x1c (0.6)
| | | width: 4
0x10| 04 | . | height0: 4 0x1c-0x1d (1)
0x10| 00 | . | vertical_scale: 0 0x1d-0x1d.2 (0.2)
0x10| 00 | . | height1: 0 0x1d.2-0x1e (0.6)
| | | height: 4
0x10| 02 00| ..| data: raw bits 0x1e-0x2c (14)
0x20|34 25 a4 00 03 70 00 fe fb fd 50 00| |4%...p....P.| |

View File

Before

Width:  |  Height:  |  Size: 44 B

After

Width:  |  Height:  |  Size: 44 B

163
format/riff/testdata/xmp_exif.fqtest vendored Normal file
View File

@ -0,0 +1,163 @@
# exiftool -tagsFromFile file.jpeg xmp_exif.webp
$ fq -d webp dv xmp_exif.webp
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: xmp_exif.webp (webp) 0x0-0xd02 (3330)
0x000|52 49 46 46 |RIFF | id: "RIFF" 0x0-0x4 (4)
0x000| fa 0c 00 00 | .... | size: 3322 0x4-0x8 (4)
0x000| 57 45 42 50 | WEBP | format: "WEBP" (valid) 0x8-0xc (4)
| | | chunks[0:4]: 0xc-0xd02 (3318)
| | | [0]{}: chunk 0xc-0x1e (18)
0x000| 56 50 38 58| VP8X| id: "VP8X" 0xc-0x10 (4)
0x010|0a 00 00 00 |.... | size: 10 0x10-0x14 (4)
0x010| 0c | . | reserved0: 0 0x14-0x14.2 (0.2)
0x010| 0c | . | icc_profile: false 0x14.2-0x14.3 (0.1)
0x010| 0c | . | alpha: false 0x14.3-0x14.4 (0.1)
0x010| 0c | . | exif_metadata: true 0x14.4-0x14.5 (0.1)
0x010| 0c | . | xml_metadata: true 0x14.5-0x14.6 (0.1)
0x010| 0c | . | animation: false 0x14.6-0x14.7 (0.1)
0x010| 0c | . | reserved1: false 0x14.7-0x15 (0.1)
0x010| 00 00 00 | ... | reserved2: 0 0x15-0x18 (3)
0x010| 03 00 00 | ... | width: 4 0x18-0x1b (3)
0x010| 03 00 00 | ... | height: 4 0x1b-0x1e (3)
| | | [1]{}: chunk 0x1e-0x3e (32)
0x010| 56 50| VP| id: "VP8 " 0x1e-0x22 (4)
0x020|38 20 |8 |
0x020| 18 00 00 00 | .... | size: 24 0x22-0x26 (4)
| | | tag{}: 0x26-0x29 (3)
0x020| 30 | 0 | first_part_size0: 1 0x26-0x26.3 (0.3)
0x020| 30 | 0 | show_frame: 1 0x26.3-0x26.4 (0.1)
0x020| 30 | 0 | version: 0 0x26.4-0x26.7 (0.3)
0x020| 30 | 0 | frame_type: "key_frame" (false) 0x26.7-0x27 (0.1)
0x020| 01 00 | .. | first_part_size1: 1 0x27-0x29 (2)
| | | first_part_size: 9
| | | reconstruction: "Bicubic"
| | | loop: "Normal"
0x020| 9d 01 2a | ..* | start_code: 0x9d012a (valid) 0x29-0x2c (3)
0x020| 04 | . | width0: 4 0x2c-0x2d (1)
0x020| 00 | . | horizontal_scale: 0 0x2d-0x2d.2 (0.2)
0x020| 00 | . | width1: 0 0x2d.2-0x2e (0.6)
| | | width: 4
0x020| 04 | . | height0: 4 0x2e-0x2f (1)
0x020| 00| .| vertical_scale: 0 0x2f-0x2f.2 (0.2)
0x020| 00| .| height1: 0 0x2f.2-0x30 (0.6)
| | | height: 4
0x030|02 00 34 25 a4 00 03 70 00 fe fb fd 50 00 |..4%...p....P. | data: raw bits 0x30-0x3e (14)
| | | [2]{}: chunk 0x3e-0x102 (196)
0x030| 45 58| EX| id: "EXIF" 0x3e-0x42 (4)
0x040|49 46 |IF |
0x040| bc 00 00 00 | .... | size: 188 0x42-0x46 (4)
0x040| 4d 4d 00 2a | MM.* | endian: "big-endian" (0x4d4d002a) 0x46-0x4a (4)
0x040| 4d 4d | MM | order: "MM" (valid) 0x46-0x48 (2)
0x040| 00 2a | .* | integer_42: 42 (valid) 0x48-0x4a (2)
0x040| 00 00 00 10 | .... | first_ifd: 16 0x4a-0x4e (4)
| | | ifds[0:1]: 0x56-0x102 (172)
| | | [0]{}: ifd 0x56-0x102 (172)
0x050| 00 06 | .. | number_of_field: 6 0x56-0x58 (2)
| | | entries[0:6]: 0x58-0x102 (170)
| | | [0]{}: entry 0x58-0x64 (12)
0x050| 01 12 | .. | tag: "Orientation" (0x112) 0x58-0x5a (2)
0x050| 00 03 | .. | type: "SHORT" (3) 0x5a-0x5c (2)
0x050| 00 00 00 01| ....| count: 1 0x5c-0x60 (4)
0x060|00 01 00 00 |.... | value_offset: 65536 0x60-0x64 (4)
| | | values[0:1]: 0x60-0x62 (2)
0x060|00 01 |.. | [0]: 1 value 0x60-0x62 (2)
| | | [1]{}: entry 0x64-0xac (72)
0x060| 01 1a | .. | tag: "XResolution" (0x11a) 0x64-0x66 (2)
0x060| 00 05 | .. | type: "RATIONAL" (5) 0x66-0x68 (2)
0x060| 00 00 00 01 | .... | count: 1 0x68-0x6c (4)
0x060| 00 00 00 5e| ...^| value_offset: 94 0x6c-0x70 (4)
| | | values[0:1]: 0xa4-0xac (8)
| | | [0]{}: value 0xa4-0xac (8)
0x0a0| 00 00 00 48 | ...H | numerator: 72 0xa4-0xa8 (4)
0x0a0| 00 00 00 01 | .... | denominator: 1 0xa8-0xac (4)
| | | float: 72
| | | [2]{}: entry 0x70-0xb4 (68)
0x070|01 1b |.. | tag: "YResolution" (0x11b) 0x70-0x72 (2)
0x070| 00 05 | .. | type: "RATIONAL" (5) 0x72-0x74 (2)
0x070| 00 00 00 01 | .... | count: 1 0x74-0x78 (4)
0x070| 00 00 00 66 | ...f | value_offset: 102 0x78-0x7c (4)
| | | values[0:1]: 0xac-0xb4 (8)
| | | [0]{}: value 0xac-0xb4 (8)
0x0a0| 00 00 00 48| ...H| numerator: 72 0xac-0xb0 (4)
0x0b0|00 00 00 01 |.... | denominator: 1 0xb0-0xb4 (4)
| | | float: 72
| | | [3]{}: entry 0x7c-0x88 (12)
0x070| 01 28 | .( | tag: "ResolutionUnit" (0x128) 0x7c-0x7e (2)
0x070| 00 03| ..| type: "SHORT" (3) 0x7e-0x80 (2)
0x080|00 00 00 01 |.... | count: 1 0x80-0x84 (4)
0x080| 00 01 00 00 | .... | value_offset: 65536 0x84-0x88 (4)
| | | values[0:1]: 0x84-0x86 (2)
0x080| 00 01 | .. | [0]: 1 value 0x84-0x86 (2)
| | | [4]{}: entry 0x88-0x94 (12)
0x080| 02 13 | .. | tag: "YCbCrPositioning" (0x213) 0x88-0x8a (2)
0x080| 00 03 | .. | type: "SHORT" (3) 0x8a-0x8c (2)
0x080| 00 00 00 01| ....| count: 1 0x8c-0x90 (4)
0x090|00 01 00 00 |.... | value_offset: 65536 0x90-0x94 (4)
| | | values[0:1]: 0x90-0x92 (2)
0x090|00 01 |.. | [0]: 1 value 0x90-0x92 (2)
| | | [5]{}: entry 0x94-0x102 (110)
0x090| 87 69 | .i | tag: "ExifIFD" (0x8769) 0x94-0x96 (2)
0x090| 00 04 | .. | type: "LONG" (4) 0x96-0x98 (2)
0x090| 00 00 00 01 | .... | count: 1 0x98-0x9c (4)
0x090| 00 00 00 6e| ...n| value_offset: 110 0x9c-0xa0 (4)
| | | ifd{}: 0xb4-0x102 (78)
0x0b0| 00 06 | .. | number_of_field: 6 0xb4-0xb6 (2)
| | | entries[0:6]: 0xb6-0xfe (72)
| | | [0]{}: entry 0xb6-0xc2 (12)
0x0b0| 90 00 | .. | tag: "ExifVersion" (0x9000) 0xb6-0xb8 (2)
0x0b0| 00 07 | .. | type: "UNDEFINED" (7) 0xb8-0xba (2)
0x0b0| 00 00 00 04 | .... | count: 4 0xba-0xbe (4)
0x0b0| 30 32| 02| value_offset: 808596274 0xbe-0xc2 (4)
0x0c0|33 32 |32 |
| | | values[0:1]: 0xbe-0xc2 (4)
0x0b0| 30 32| 02| [0]: raw bits value 0xbe-0xc2 (4)
0x0c0|33 32 |32 |
| | | [1]{}: entry 0xc2-0xce (12)
0x0c0| 91 01 | .. | tag: "ComponentsConfiguration" (0x9101) 0xc2-0xc4 (2)
0x0c0| 00 07 | .. | type: "UNDEFINED" (7) 0xc4-0xc6 (2)
0x0c0| 00 00 00 04 | .... | count: 4 0xc6-0xca (4)
0x0c0| 01 02 03 00 | .... | value_offset: 16909056 0xca-0xce (4)
| | | values[0:1]: 0xca-0xce (4)
0x0c0| 01 02 03 00 | .... | [0]: raw bits value 0xca-0xce (4)
| | | [2]{}: entry 0xce-0xda (12)
0x0c0| a0 00| ..| tag: "FlashpixVersion" (0xa000) 0xce-0xd0 (2)
0x0d0|00 07 |.. | type: "UNDEFINED" (7) 0xd0-0xd2 (2)
0x0d0| 00 00 00 04 | .... | count: 4 0xd2-0xd6 (4)
0x0d0| 30 31 30 30 | 0100 | value_offset: 808529968 0xd6-0xda (4)
| | | values[0:1]: 0xd6-0xda (4)
0x0d0| 30 31 30 30 | 0100 | [0]: raw bits value 0xd6-0xda (4)
| | | [3]{}: entry 0xda-0xe6 (12)
0x0d0| a0 01 | .. | tag: "ColorSpace" (0xa001) 0xda-0xdc (2)
0x0d0| 00 03 | .. | type: "SHORT" (3) 0xdc-0xde (2)
0x0d0| 00 00| ..| count: 1 0xde-0xe2 (4)
0x0e0|00 01 |.. |
0x0e0| 00 01 00 00 | .... | value_offset: 65536 0xe2-0xe6 (4)
| | | values[0:1]: 0xe2-0xe4 (2)
0x0e0| 00 01 | .. | [0]: 1 value 0xe2-0xe4 (2)
| | | [4]{}: entry 0xe6-0xf2 (12)
0x0e0| a0 02 | .. | tag: "PixelXDimension" (0xa002) 0xe6-0xe8 (2)
0x0e0| 00 03 | .. | type: "SHORT" (3) 0xe8-0xea (2)
0x0e0| 00 00 00 01 | .... | count: 1 0xea-0xee (4)
0x0e0| 04 d8| ..| value_offset: 81264640 0xee-0xf2 (4)
0x0f0|00 00 |.. |
| | | values[0:1]: 0xee-0xf0 (2)
0x0e0| 04 d8| ..| [0]: 1240 value 0xee-0xf0 (2)
| | | [5]{}: entry 0xf2-0xfe (12)
0x0f0| a0 03 | .. | tag: "PixelYDimension" (0xa003) 0xf2-0xf4 (2)
0x0f0| 00 03 | .. | type: "SHORT" (3) 0xf4-0xf6 (2)
0x0f0| 00 00 00 01 | .... | count: 1 0xf6-0xfa (4)
0x0f0| 05 00 00 00 | .... | value_offset: 83886080 0xfa-0xfe (4)
| | | values[0:1]: 0xfa-0xfc (2)
0x0f0| 05 00 | .. | [0]: 1280 value 0xfa-0xfc (2)
0x0f0| 00 00| ..| next_ifd: 0 0xfe-0x102 (4)
0x100|00 00 |.. |
0x0a0|00 00 00 00 |.... | next_ifd: 0 0xa0-0xa4 (4)
| | | [3]{}: chunk 0x102-0xd02 (3072)
0x100| 58 4d 50 20 | XMP | id: "XMP " 0x102-0x106 (4)
0x100| f7 0b 00 00 | .... | size: 3063 0x106-0x10a (4)
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
0x100| 3c 3f 78 70 61 63| <?xpac| data: {} (xml) 0x10a-0xd01 (3063)
0x110|6b 65 74 20 62 65 67 69 6e 3d 27 ef bb bf 27 20|ket begin='...' |
* |until 0xd00.7 (3063) | |
0xd00| 00| | .| | align: raw bits 0xd01-0xd02 (1)
0x040| 45 78| Ex| gap0: raw bits 0x4e-0x56 (8)
0x050|69 66 4d 65 74 61 |ifMeta |

BIN
format/riff/testdata/xmp_exif.webp vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

93
format/riff/webp.go Normal file
View File

@ -0,0 +1,93 @@
package riff
// https://developers.google.com/speed/webp/docs/riff_container
import (
"github.com/wader/fq/format"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar"
)
var exifGroup decode.Group
var iccpGroup decode.Group
var vp8FrameGroup decode.Group
var xmlGroup decode.Group
func init() {
interp.RegisterFormat(
format.WebP,
&decode.Format{
Description: "WebP image",
Groups: []*decode.Group{format.Probe, format.Image},
DecodeFn: webpDecode,
Dependencies: []decode.Dependency{
{Groups: []*decode.Group{format.Exif}, Out: &exifGroup},
{Groups: []*decode.Group{format.VP8_Frame}, Out: &vp8FrameGroup},
{Groups: []*decode.Group{format.ICC_Profile}, Out: &iccpGroup},
{Groups: []*decode.Group{format.XML}, Out: &xmlGroup},
},
})
}
const webpRiffType = "WEBP"
func webpDecode(d *decode.D) any {
d.Endian = decode.LittleEndian
var riffType string
riffDecode(
d,
nil,
func(d *decode.D, path path) (string, int64) {
id := d.FieldUTF8("id", 4, chunkIDDescriptions)
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("format", 4, d.StrAssert(webpRiffType))
return true, nil
case "VP8 ":
d.Format(&vp8FrameGroup, nil)
return false, nil
case "VP8X":
d.FieldU2("reserved0")
d.FieldBool("icc_profile")
d.FieldBool("alpha")
d.FieldBool("exif_metadata")
d.FieldBool("xml_metadata")
d.FieldBool("animation")
d.FieldBool("reserved1")
d.FieldU24("reserved2")
d.FieldU24("width", scalar.UintActualAdd(1))
d.FieldU24("height", scalar.UintActualAdd(1))
return false, nil
case "EXIF":
// TODO: where is this documented? both exif in jpeg and webp has this prefix sometimes
var exifPrefix = []byte("Exif\x00\x00")
hasExifPrefix := d.TryHasBytes(exifPrefix)
if hasExifPrefix {
d.FieldUTF8("exif_prefix", len(exifPrefix))
}
d.Format(&exifGroup, nil)
return false, nil
case "ICCP":
d.Format(&iccpGroup, nil)
return false, nil
case "XMP ":
d.FieldFormatOrRawLen("data", d.BitsLeft(), &xmlGroup, nil)
return false, nil
default:
d.FieldRawLen("data", d.BitsLeft())
return false, nil
}
})
if riffType != webpRiffType {
d.Errorf("wrong or no WEBP riff type found (%s)", riffType)
}
return nil
}

View File

@ -237,8 +237,8 @@ func tiffDecode(d *decode.D) any {
})
if len(s.offsets) != len(s.byteCounts) {
// TODO: warning
} else {
d.Errorf("unmatched strips offset (%d) and byte counts (%d)", len(s.offsets), len(s.byteCounts))
} else if len(s.offsets) > 0 {
d.FieldArray("strips", func(d *decode.D) {
for i := 0; i < len(s.offsets); i++ {
d.RangeFn(s.offsets[i], s.byteCounts[i], func(d *decode.D) {

View File

@ -1,74 +0,0 @@
package webp
// https://developers.google.com/speed/webp/docs/riff_container
import (
"bytes"
"github.com/wader/fq/format"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar"
)
var vp8FrameGroup decode.Group
func init() {
interp.RegisterFormat(
format.WebP,
&decode.Format{
Description: "WebP image",
Groups: []*decode.Group{format.Probe, format.Image},
DecodeFn: webpDecode,
Dependencies: []decode.Dependency{
{Groups: []*decode.Group{format.VP8_Frame}, Out: &vp8FrameGroup},
},
})
}
func decodeChunk(d *decode.D, expectedChunkID string, fn func(d *decode.D)) {
trimChunkID := d.FieldUTF8("id", 4, scalar.ActualTrimSpace)
if expectedChunkID != "" && trimChunkID != expectedChunkID {
return
}
chunkLen := int64(d.FieldU32("size"))
if fn != nil {
d.FramedFn(chunkLen*8, fn)
} else {
d.FieldRawLen("data", chunkLen*8)
}
}
func webpDecode(d *decode.D) any {
d.Endian = decode.LittleEndian
d.FieldUTF8("riff_id", 4, d.StrAssert("RIFF"))
riffLength := d.FieldU32("riff_length")
d.FieldUTF8("webp_id", 4, d.StrAssert("WEBP"))
d.FramedFn(int64(riffLength-4)*8, func(d *decode.D) {
p := d.PeekBytes(4)
// TODO: VP8X
switch {
case bytes.Equal(p, []byte("VP8 ")):
d.FieldStruct("image", func(d *decode.D) {
decodeChunk(d, "VP8", func(d *decode.D) {
d.Format(&vp8FrameGroup, nil)
})
})
case bytes.Equal(p, []byte("VP8L")):
d.FieldStruct("image", func(d *decode.D) {
decodeChunk(d, "VP8L", func(d *decode.D) {
// TODO
})
})
default:
d.Fatalf("could not find VP8 or VP8L chunk")
}
})
return nil
}