diff options
Diffstat (limited to 'vendor/github.com/abema/go-mp4/box_info.go')
-rw-r--r-- | vendor/github.com/abema/go-mp4/box_info.go | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/vendor/github.com/abema/go-mp4/box_info.go b/vendor/github.com/abema/go-mp4/box_info.go new file mode 100644 index 000000000..b5c587fd9 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/box_info.go @@ -0,0 +1,155 @@ +package mp4 + +import ( + "bytes" + "encoding/binary" + "io" + "math" +) + +type Context struct { + // IsQuickTimeCompatible represents whether ftyp.compatible_brands contains "qt ". + IsQuickTimeCompatible bool + + // UnderWave represents whether current box is under the wave box. + UnderWave bool + + // UnderIlst represents whether current box is under the ilst box. + UnderIlst bool + + // UnderIlstMeta represents whether current box is under the metadata box under the ilst box. + UnderIlstMeta bool + + // UnderIlstFreeMeta represents whether current box is under "----" box. + UnderIlstFreeMeta bool + + // UnderUdta represents whether current box is under the udta box. + UnderUdta bool +} + +// BoxInfo has common infomations of box +type BoxInfo struct { + // Offset specifies an offset of the box in a file. + Offset uint64 + + // Size specifies size(bytes) of box. + Size uint64 + + // HeaderSize specifies size(bytes) of common fields which are defined as "Box" class member at ISO/IEC 14496-12. + HeaderSize uint64 + + // Type specifies box type which is represented by 4 characters. + Type BoxType + + // ExtendToEOF is set true when Box.size is zero. It means that end of box equals to end of file. + ExtendToEOF bool + + // Context would be set by ReadBoxStructure, not ReadBoxInfo. + Context +} + +func (bi *BoxInfo) IsSupportedType() bool { + return bi.Type.IsSupported(bi.Context) +} + +const ( + SmallHeaderSize = 8 + LargeHeaderSize = 16 +) + +// WriteBoxInfo writes common fields which are defined as "Box" class member at ISO/IEC 14496-12. +// This function ignores bi.Offset and returns BoxInfo which contains real Offset and recalculated Size/HeaderSize. +func WriteBoxInfo(w io.WriteSeeker, bi *BoxInfo) (*BoxInfo, error) { + offset, err := w.Seek(0, io.SeekCurrent) + if err != nil { + return nil, err + } + + var data []byte + if bi.ExtendToEOF { + data = make([]byte, SmallHeaderSize) + } else if bi.Size <= math.MaxUint32 && bi.HeaderSize != LargeHeaderSize { + data = make([]byte, SmallHeaderSize) + binary.BigEndian.PutUint32(data, uint32(bi.Size)) + } else { + data = make([]byte, LargeHeaderSize) + binary.BigEndian.PutUint32(data, 1) + binary.BigEndian.PutUint64(data[SmallHeaderSize:], bi.Size) + } + data[4] = bi.Type[0] + data[5] = bi.Type[1] + data[6] = bi.Type[2] + data[7] = bi.Type[3] + + if _, err := w.Write(data); err != nil { + return nil, err + } + + return &BoxInfo{ + Offset: uint64(offset), + Size: bi.Size - bi.HeaderSize + uint64(len(data)), + HeaderSize: uint64(len(data)), + Type: bi.Type, + ExtendToEOF: bi.ExtendToEOF, + }, nil +} + +// ReadBoxInfo reads common fields which are defined as "Box" class member at ISO/IEC 14496-12. +func ReadBoxInfo(r io.ReadSeeker) (*BoxInfo, error) { + offset, err := r.Seek(0, io.SeekCurrent) + if err != nil { + return nil, err + } + + bi := &BoxInfo{ + Offset: uint64(offset), + } + + // read 8 bytes + buf := bytes.NewBuffer(make([]byte, 0, SmallHeaderSize)) + if _, err := io.CopyN(buf, r, SmallHeaderSize); err != nil { + return nil, err + } + bi.HeaderSize += SmallHeaderSize + + // pick size and type + data := buf.Bytes() + bi.Size = uint64(binary.BigEndian.Uint32(data)) + bi.Type = BoxType{data[4], data[5], data[6], data[7]} + + if bi.Size == 0 { + // box extends to end of file + offsetEOF, err := r.Seek(0, io.SeekEnd) + if err != nil { + return nil, err + } + bi.Size = uint64(offsetEOF) - bi.Offset + bi.ExtendToEOF = true + if _, err := bi.SeekToPayload(r); err != nil { + return nil, err + } + + } else if bi.Size == 1 { + // read more 8 bytes + buf.Reset() + if _, err := io.CopyN(buf, r, LargeHeaderSize-SmallHeaderSize); err != nil { + return nil, err + } + bi.HeaderSize += LargeHeaderSize - SmallHeaderSize + bi.Size = binary.BigEndian.Uint64(buf.Bytes()) + } + + return bi, nil +} + +func (bi *BoxInfo) SeekToStart(s io.Seeker) (int64, error) { + return s.Seek(int64(bi.Offset), io.SeekStart) +} + +func (bi *BoxInfo) SeekToPayload(s io.Seeker) (int64, error) { + return s.Seek(int64(bi.Offset+bi.HeaderSize), io.SeekStart) +} + +func (bi *BoxInfo) SeekToEnd(s io.Seeker) (int64, error) { + return s.Seek(int64(bi.Offset+bi.Size), io.SeekStart) +} |