Code refactorization

Should even work if the subatoms of "----" are out of order
This commit is contained in:
Xavier Henner 2015-05-25 08:45:31 +02:00
parent be3da62488
commit a931bf6e30

134
mp4.go
View File

@ -6,6 +6,7 @@ package tag
import (
"encoding/binary"
"errors"
"fmt"
"io"
"os"
@ -69,10 +70,62 @@ func ReadAtoms(r io.ReadSeeker) (Metadata, error) {
return m, err
}
func readCustomAtom(r io.ReadSeeker, size uint32) (string, uint32, error) {
var datasize uint32
var datapos int64
var name string
var mean string
for size > 8 {
var subsize uint32
err := binary.Read(r, binary.BigEndian, &subsize)
if err != nil {
return "----", size - 4, err
}
subname, err := readString(r, 4)
if err != nil {
return "----", size - 8, err
}
b, err := readBytes(r, int(subsize-8))
if err != nil {
return "----", size - subsize, err
}
// Remove the size of the mean atom from the size counter
size -= subsize
switch string(subname) {
case "mean":
mean = string(b[4:])
case "name":
name = string(b[4:])
case "data":
datapos, err = r.Seek(0, os.SEEK_CUR)
if err != nil {
return "----", size, err
}
datasize = subsize
datapos -= int64(subsize)
}
}
// there should remain only the header size
if size != 8 {
return "----", size, errors.New("---- atom out of bound")
}
if mean == "com.apple.iTunes" && datasize != 0 && name != "" {
// we jump just before the data subatom
_, err := r.Seek(datapos, os.SEEK_SET)
if err != nil {
return "----", size, err
}
return name, datasize + 8, nil
}
return "----", size, nil
}
func (m metadataMP4) readAtoms(r io.ReadSeeker) error {
for {
var size uint32
var subname string
ok := false
err := binary.Read(r, binary.BigEndian, &size)
if err != nil {
if err == io.EOF {
@ -109,69 +162,20 @@ func (m metadataMP4) readAtoms(r io.ReadSeeker) error {
}
continue
case "----":
/* Generic atom.
Should have 3 sub atoms : mean, name and data.
We check that mean=="com.apple.iTunes" and we use the subname as
the name, and move to the data atom if anything goes wrong, we jump
at the end of the "----" atom. */
// let's read the mean atom
var subsize uint32
err := binary.Read(r, binary.BigEndian, &subsize)
// Generic atom.
// Should have 3 sub atoms : mean, name and data.
// We check that mean=="com.apple.iTunes" and we use the subname as
// the name, and move to the data atom if anything goes wrong,
// we jump at the end of the "----" atom.
name, size, err = readCustomAtom(r, size)
if err != nil {
return err
}
sub, err := readString(r, 4)
if err != nil {
return err
if name != "----" {
ok = true
}
if sub != "mean" {
// Something's wrong. Remove 8 read bytes from the size counter
// since "----" is not a known atom name, the whole data will
// be skipped
size -= 8
break
}
mean, err := readBytes(r, int(subsize-8))
if err != nil {
return err
}
// Remove the size of the mean atom from the size counter
size -= subsize
if string(mean[4:]) != "com.apple.iTunes" {
// Something's wrong, skip this atom
break
}
// Let's read the name atom
err = binary.Read(r, binary.BigEndian, &subsize)
if err != nil {
return err
}
sub, err = readString(r, 4)
if err != nil {
return err
}
if sub != "name" {
// Something's wrong
size -= 8
break
}
b, err := readBytes(r, int(subsize-8))
if err != nil {
return err
}
/* Remove the size of the name atom from the size counter.
We should now be at the start of the data subatom and size should
be equal to the size of the data atom and its header */
size -= subsize
subname = string(b[4:])
default:
_, ok = atoms[name]
}
b, err := readBytes(r, int(size-8))
@ -179,14 +183,8 @@ func (m metadataMP4) readAtoms(r io.ReadSeeker) error {
return err
}
// Allow all known atoms and the valid "----" atoms
_, ok := atoms[name]
switch {
case name == "----" && subname == "":
continue
case name == "----":
name = subname
case !ok:
// At this point, we allow all known atoms and the valid "----" atoms
if !ok {
continue
}