diff --git a/format/mp4/boxes.go b/format/mp4/boxes.go index fb7207d9..84263175 100644 --- a/format/mp4/boxes.go +++ b/format/mp4/boxes.go @@ -1,7 +1,5 @@ package mp4 -// TODO: flags? - import ( "bytes" "encoding/binary" @@ -1639,9 +1637,41 @@ func decodeBox(ctx *decodeContext, d *decode.D, typ string) { } }) default: + // there are at least 3 ways to encode udta metadata in mov/mp4 files. + // + // mdta subtype: + // + // udta: + // meta + // hdlr with subtype "mdta" + // keys with 1-based to key namespace.name table + // ilst + // -box + // data box with value + // + // mdir subtype: + // + // udta + // meta + // hdlr with subtype "mdir" + // ilst + // © or similar + // data with value + // + // no-meta-box: + // + // udta + // © or similar + // data with length, language and value + if mb := ctx.currentMetaBox(); mb != nil && ctx.parent().typ == "ilst" { - // unknown type inside a metadata box with ilst as parent, decode item boxes + // unknown type under a meta box with ilst as parent, decode as boxes + // is probably one or more data boxes decodeBoxes(ctx, d) + } else if ctx.parent().typ == "udta" { + length := d.FieldU16("length") + d.FieldStrFn("language", decodeLang) + d.FieldUTF8("value", int(length)) } else { d.FieldRawLen("data", d.BitsLeft()) } diff --git a/format/mp4/desc.go b/format/mp4/desc.go index d0bef8f9..cdffd2c9 100644 --- a/format/mp4/desc.go +++ b/format/mp4/desc.go @@ -282,7 +282,53 @@ var boxDescriptions = scalar.StrMapDescription{ "tvnn": "Network", "©lyr": "Lyrics", + // some from ffmpeg libavformat/mov.c "©too": "Encoder", + "@PRM": "Premiere version", + "@PRQ": "QuickTime version", + "akID": "Account type", + "apID": "Account id", + "catg": "Category", + "cpil": "Compilation", + "disk": "Disc", + "egid": "Episode UID", + "FIRM": "Firmware", + "hdvd": "HD video", + "keyw": "Keywords", + "pcst": "Podcast", + "pgap": "Gapless playback", + "purd": "Purchase date", + "soaa": "Sort album artist", + "soal": "Sort album", + "soar": "Sort artist", + "soco": "Sort composer", + "sonm": "Sort name", + "sosn": "Sort show", + "stik": "Media type", + "©PRD": "Producer", + "©aut": "Artist", + "©chp": "Chapter", + "©com": "Composer", + "©dir": "Director", + "©dis": "Disclaimer", + "©ed1": "Edit date", + "©enc": "Encoder", + "©fmt": "Original format", + "©hst": "Host computer", + "©inf": "Comment", + "©mak": "Make", + "©mod": "Model", + "©ope": "Original artist", + "©prd": "Producer", + "©prf": "Performers", + "©req": "Playback requirements", + "©src": "Original source", + "©st3": "Subtitle", + "©swr": "Encoder", + "©trk": "Track", + "©url": "URL", + "©wrn": "Warning", + "©xyz": "Location", "\x00\x00\x00\x00": "Terminator Atom", } diff --git a/format/mp4/testdata/in24.fqtest b/format/mp4/testdata/in24.fqtest index de6be129..b79f76fc 100644 --- a/format/mp4/testdata/in24.fqtest +++ b/format/mp4/testdata/in24.fqtest @@ -279,8 +279,10 @@ $ fq dv in24.mp4 | | | boxes[0:1]: 0x3d3-0x3eb.7 (25) | | | [0]{}: box 0x3d3-0x3eb.7 (25) 0x3d0| 00 00 00 19 | .... | size: 25 0x3d3-0x3d6.7 (4) -0x3d0| a9 73 77 72 | .swr | type: "©swr" 0x3d7-0x3da.7 (4) -0x3d0| 00 0d 55 c4 4c| ..U.L| data: raw bits 0x3db-0x3eb.7 (17) +0x3d0| a9 73 77 72 | .swr | type: "©swr" (Encoder) 0x3d7-0x3da.7 (4) +0x3d0| 00 0d | .. | length: 13 0x3db-0x3dc.7 (2) +0x3d0| 55 c4 | U. | language: "und" 0x3dd-0x3de.7 (2) +0x3d0| 4c| L| value: "Lavf58.76.100" 0x3df-0x3eb.7 (13) 0x3e0|61 76 66 35 38 2e 37 36 2e 31 30 30| |avf58.76.100| | | | | tracks[0:1]: 0x3ec-NA (0) | | | [0]{}: track 0x3ec-NA (0) diff --git a/format/mp4/testdata/lpcm.fqtest b/format/mp4/testdata/lpcm.fqtest index cfe9ddb3..e9bfc3ef 100644 --- a/format/mp4/testdata/lpcm.fqtest +++ b/format/mp4/testdata/lpcm.fqtest @@ -269,9 +269,11 @@ $ fq dv lpcm.mp4 | | | boxes[0:1]: 0x4f9-0x511.7 (25) | | | [0]{}: box 0x4f9-0x511.7 (25) 0x4f0| 00 00 00 19 | .... | size: 25 0x4f9-0x4fc.7 (4) -0x4f0| a9 73 77| .sw| type: "©swr" 0x4fd-0x500.7 (4) +0x4f0| a9 73 77| .sw| type: "©swr" (Encoder) 0x4fd-0x500.7 (4) 0x500|72 |r | -0x500| 00 0d 55 c4 4c 61 76 66 35 38 2e 37 36 2e 31| ..U.Lavf58.76.1| data: raw bits 0x501-0x511.7 (17) +0x500| 00 0d | .. | length: 13 0x501-0x502.7 (2) +0x500| 55 c4 | U. | language: "und" 0x503-0x504.7 (2) +0x500| 4c 61 76 66 35 38 2e 37 36 2e 31| Lavf58.76.1| value: "Lavf58.76.100" 0x505-0x511.7 (13) 0x510|30 30| |00| | | | | tracks[0:1]: 0x512-NA (0) | | | [0]{}: track 0x512-NA (0) diff --git a/format/prores/testdata/prores_frame.fqtest b/format/prores/testdata/prores_frame.fqtest index f75dd54e..c4a0ec33 100644 --- a/format/prores/testdata/prores_frame.fqtest +++ b/format/prores/testdata/prores_frame.fqtest @@ -294,9 +294,10 @@ $ fq -d mp4 dv prores_frame.mov | | | boxes[0:1]: 0x6ee6-0x6efe.7 (25) | | | [0]{}: box 0x6ee6-0x6efe.7 (25) 0x6ee0| 00 00 00 19 | .... | size: 25 0x6ee6-0x6ee9.7 (4) -0x6ee0| a9 73 77 72 | .swr | type: "©swr" 0x6eea-0x6eed.7 (4) -0x6ee0| 00 0d| ..| data: raw bits 0x6eee-0x6efe.7 (17) -0x6ef0|55 c4 4c 61 76 66 35 39 2e 31 36 2e 31 30 30| |U.Lavf59.16.100|| +0x6ee0| a9 73 77 72 | .swr | type: "©swr" (Encoder) 0x6eea-0x6eed.7 (4) +0x6ee0| 00 0d| ..| length: 13 0x6eee-0x6eef.7 (2) +0x6ef0|55 c4 |U. | language: "und" 0x6ef0-0x6ef1.7 (2) +0x6ef0| 4c 61 76 66 35 39 2e 31 36 2e 31 30 30| | Lavf59.16.100|| value: "Lavf59.16.100" 0x6ef2-0x6efe.7 (13) | | | tracks[0:1]: 0x24-0x6efe.7 (28379) | | | [0]{}: track 0x24-0x6efe.7 (28379) | | | samples[0:1]: 0x24-0x6c3c.7 (27673)