From 0f6c9533ef18bb8645962e56c8d2ec1a3bc04f17 Mon Sep 17 00:00:00 2001 From: kondakovdmitry Date: Mon, 9 Dec 2019 16:21:46 +0300 Subject: [PATCH 1/4] Support for MP4 files without STCO atom --- format/mp4/demuxer.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/format/mp4/demuxer.go b/format/mp4/demuxer.go index b102c731..78e2a3be 100644 --- a/format/mp4/demuxer.go +++ b/format/mp4/demuxer.go @@ -50,6 +50,7 @@ func (self *Demuxer) probe() (err error) { } var moov *mp4io.Movie + var mdat *mp4io.Dummy var atoms []mp4io.Atom if atoms, err = mp4io.ReadFileAtoms(self.r); err != nil { @@ -62,6 +63,8 @@ func (self *Demuxer) probe() (err error) { for _, atom := range atoms { if atom.Tag() == mp4io.MOOV { moov = atom.(*mp4io.Movie) + } else if atom.Tag() == mp4io.MDAT { + mdat = atom.(*mp4io.Dummy) } } @@ -85,6 +88,10 @@ func (self *Demuxer) probe() (err error) { return } + if stream.sample.ChunkOffset == nil { + stream.restoreChunkOffsets(mdat) + } + if avc1 := atrack.GetAVC1Conf(); avc1 != nil { if stream.CodecData, err = h264parser.NewCodecDataFromAVCDecoderConfRecord(avc1.Data); err != nil { return @@ -102,6 +109,38 @@ func (self *Demuxer) probe() (err error) { return } +func (self *Stream) restoreChunkOffsets(mdat *mp4io.Dummy) { + var dataOffset uint32 + if mdat.Size == 1 { + dataOffset = uint32(mdat.Offset + 16) // account for extended size field + } else { + dataOffset = uint32(mdat.Offset + 8) + } + + offset := dataOffset + chunkGroupIndex := 0 + chunkOffsets := []uint32{offset} + chunkIndex := uint32(1) + sampleIndexInChunk := uint32(0) + for _, sampleSize := range self.sample.SampleSize.Entries { + offset += sampleSize + sampleIndexInChunk++ + if sampleIndexInChunk >= self.sample.SampleToChunk.Entries[chunkGroupIndex].SamplesPerChunk { + chunkOffsets = append(chunkOffsets, offset) + chunkIndex++ + sampleIndexInChunk = 0 + } + if chunkGroupIndex+1 < len(self.sample.SampleToChunk.Entries) && + chunkIndex == self.sample.SampleToChunk.Entries[chunkGroupIndex+1].FirstChunk { + chunkGroupIndex++ + } + } + + self.sample.ChunkOffset = &mp4io.ChunkOffset{ + Entries: chunkOffsets, + } +} + func (self *Stream) setSampleIndex(index int) (err error) { found := false start := 0 From 798fb5b6077fa196939ac9625bb00f0b0c2e421b Mon Sep 17 00:00:00 2001 From: kondakovdmitry Date: Thu, 12 Dec 2019 13:10:14 +0300 Subject: [PATCH 2/4] Support for CO64 atom --- format/mp4/demuxer.go | 12 +- format/mp4/mp4io/atoms.go | 518 ++++++++++++++++++++------------------ format/mp4/muxer.go | 24 +- 3 files changed, 296 insertions(+), 258 deletions(-) diff --git a/format/mp4/demuxer.go b/format/mp4/demuxer.go index 78e2a3be..84495969 100644 --- a/format/mp4/demuxer.go +++ b/format/mp4/demuxer.go @@ -110,20 +110,20 @@ func (self *Demuxer) probe() (err error) { } func (self *Stream) restoreChunkOffsets(mdat *mp4io.Dummy) { - var dataOffset uint32 + var dataOffset int64 if mdat.Size == 1 { - dataOffset = uint32(mdat.Offset + 16) // account for extended size field + dataOffset = int64(mdat.Offset + 16) // account for extended size field } else { - dataOffset = uint32(mdat.Offset + 8) + dataOffset = int64(mdat.Offset + 8) } offset := dataOffset chunkGroupIndex := 0 - chunkOffsets := []uint32{offset} + chunkOffsets := []int64{offset} chunkIndex := uint32(1) sampleIndexInChunk := uint32(0) for _, sampleSize := range self.sample.SampleSize.Entries { - offset += sampleSize + offset += int64(sampleSize) sampleIndexInChunk++ if sampleIndexInChunk >= self.sample.SampleToChunk.Entries[chunkGroupIndex].SamplesPerChunk { chunkOffsets = append(chunkOffsets, offset) @@ -410,7 +410,7 @@ func (self *Stream) readPacket() (pkt av.Packet, err error) { sampleSize = self.sample.SampleSize.Entries[self.sampleIndex] } - sampleOffset := int64(chunkOffset) + self.sampleOffsetInChunk + sampleOffset := chunkOffset + self.sampleOffsetInChunk pkt.Data = make([]byte, sampleSize) if err = self.demuxer.readat(sampleOffset, pkt.Data); err != nil { return diff --git a/format/mp4/mp4io/atoms.go b/format/mp4/mp4io/atoms.go index c90485cc..ef5d024a 100644 --- a/format/mp4/mp4io/atoms.go +++ b/format/mp4/mp4io/atoms.go @@ -21,7 +21,7 @@ func (self AVC1Desc) Tag() Tag { return AVC1 } -const URL = Tag(0x75726c20) +const URL = Tag(0x75726c20) func (self DataReferUrl) Tag() Tag { return URL @@ -106,8 +106,12 @@ func (self CompositionOffset) Tag() Tag { } const STCO = Tag(0x7374636f) +const CO64 = Tag(0x636f3634) func (self ChunkOffset) Tag() Tag { + if self.Is64bit { + return CO64 + } return STCO } @@ -204,16 +208,16 @@ func (self SoundMediaInfo) Tag() Tag { const MDAT = Tag(0x6d646174) type Movie struct { - Header *MovieHeader - MovieExtend *MovieExtend - Tracks []*Track - Unknowns []Atom + Header *MovieHeader + MovieExtend *MovieExtend + Tracks []*Track + Unknowns []Atom AtomPos } func (self Movie) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MOOV)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -288,7 +292,7 @@ func (self *Movie) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -315,28 +319,28 @@ func (self Movie) Children() (r []Atom) { } type MovieHeader struct { - Version uint8 - Flags uint32 - CreateTime time.Time - ModifyTime time.Time - TimeScale int32 - Duration int32 - PreferredRate float64 - PreferredVolume float64 - Matrix [9]int32 - PreviewTime time.Time - PreviewDuration time.Time - PosterTime time.Time - SelectionTime time.Time - SelectionDuration time.Time - CurrentTime time.Time - NextTrackId int32 + Version uint8 + Flags uint32 + CreateTime time.Time + ModifyTime time.Time + TimeScale int32 + Duration int32 + PreferredRate float64 + PreferredVolume float64 + Matrix [9]int32 + PreviewTime time.Time + PreviewDuration time.Time + PosterTime time.Time + SelectionTime time.Time + SelectionDuration time.Time + CurrentTime time.Time + NextTrackId int32 AtomPos } func (self MovieHeader) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MVHD)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -389,7 +393,7 @@ func (self MovieHeader) Len() (n int) { n += 4 n += 2 n += 10 - n += 4*len(self.Matrix[:]) + n += 4 * len(self.Matrix[:]) n += 4 n += 4 n += 4 @@ -508,15 +512,15 @@ func (self MovieHeader) Children() (r []Atom) { } type Track struct { - Header *TrackHeader - Media *Media - Unknowns []Atom + Header *TrackHeader + Media *Media + Unknowns []Atom AtomPos } func (self Track) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(TRAK)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -576,7 +580,7 @@ func (self *Track) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -600,24 +604,24 @@ func (self Track) Children() (r []Atom) { } type TrackHeader struct { - Version uint8 - Flags uint32 - CreateTime time.Time - ModifyTime time.Time - TrackId int32 - Duration int32 - Layer int16 - AlternateGroup int16 - Volume float64 - Matrix [9]int32 - TrackWidth float64 - TrackHeight float64 + Version uint8 + Flags uint32 + CreateTime time.Time + ModifyTime time.Time + TrackId int32 + Duration int32 + Layer int16 + AlternateGroup int16 + Volume float64 + Matrix [9]int32 + TrackWidth float64 + TrackHeight float64 AtomPos } func (self TrackHeader) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(TKHD)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -667,7 +671,7 @@ func (self TrackHeader) Len() (n int) { n += 2 n += 2 n += 2 - n += 4*len(self.Matrix[:]) + n += 4 * len(self.Matrix[:]) n += 4 n += 4 return @@ -759,17 +763,17 @@ func (self TrackHeader) Children() (r []Atom) { } type HandlerRefer struct { - Version uint8 - Flags uint32 - Type [4]byte - SubType [4]byte - Name []byte + Version uint8 + Flags uint32 + Type [4]byte + SubType [4]byte + Name []byte AtomPos } func (self HandlerRefer) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(HDLR)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -831,16 +835,16 @@ func (self HandlerRefer) Children() (r []Atom) { } type Media struct { - Header *MediaHeader - Handler *HandlerRefer - Info *MediaInfo - Unknowns []Atom + Header *MediaHeader + Handler *HandlerRefer + Info *MediaInfo + Unknowns []Atom AtomPos } func (self Media) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MDIA)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -915,7 +919,7 @@ func (self *Media) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -942,20 +946,20 @@ func (self Media) Children() (r []Atom) { } type MediaHeader struct { - Version uint8 - Flags uint32 - CreateTime time.Time - ModifyTime time.Time - TimeScale int32 - Duration int32 - Language int16 - Quality int16 + Version uint8 + Flags uint32 + CreateTime time.Time + ModifyTime time.Time + TimeScale int32 + Duration int32 + Language int16 + Quality int16 AtomPos } func (self MediaHeader) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MDHD)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1048,17 +1052,17 @@ func (self MediaHeader) Children() (r []Atom) { } type MediaInfo struct { - Sound *SoundMediaInfo - Video *VideoMediaInfo - Data *DataInfo - Sample *SampleTable - Unknowns []Atom + Sound *SoundMediaInfo + Video *VideoMediaInfo + Data *DataInfo + Sample *SampleTable + Unknowns []Atom AtomPos } func (self MediaInfo) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MINF)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1148,7 +1152,7 @@ func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -1178,14 +1182,14 @@ func (self MediaInfo) Children() (r []Atom) { } type DataInfo struct { - Refer *DataRefer - Unknowns []Atom + Refer *DataRefer + Unknowns []Atom AtomPos } func (self DataInfo) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(DINF)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1230,7 +1234,7 @@ func (self *DataInfo) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -1251,15 +1255,15 @@ func (self DataInfo) Children() (r []Atom) { } type DataRefer struct { - Version uint8 - Flags uint32 - Url *DataReferUrl + Version uint8 + Flags uint32 + Url *DataReferUrl AtomPos } func (self DataRefer) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(DREF)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1313,7 +1317,7 @@ func (self *DataRefer) Unmarshal(b []byte, offset int) (n int, err error) { return } switch tag { - case URL : + case URL: { atom := &DataReferUrl{} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { @@ -1335,14 +1339,14 @@ func (self DataRefer) Children() (r []Atom) { } type DataReferUrl struct { - Version uint8 - Flags uint32 + Version uint8 + Flags uint32 AtomPos } func (self DataReferUrl) Marshal(b []byte) (n int) { - pio.PutU32BE(b[4:], uint32(URL )) - n += self.marshal(b[8:])+8 + pio.PutU32BE(b[4:], uint32(URL)) + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1381,15 +1385,15 @@ func (self DataReferUrl) Children() (r []Atom) { } type SoundMediaInfo struct { - Version uint8 - Flags uint32 - Balance int16 + Version uint8 + Flags uint32 + Balance int16 AtomPos } func (self SoundMediaInfo) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(SMHD)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1440,16 +1444,16 @@ func (self SoundMediaInfo) Children() (r []Atom) { } type VideoMediaInfo struct { - Version uint8 - Flags uint32 - GraphicsMode int16 - Opcolor [3]int16 + Version uint8 + Flags uint32 + GraphicsMode int16 + Opcolor [3]int16 AtomPos } func (self VideoMediaInfo) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(VMHD)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1471,7 +1475,7 @@ func (self VideoMediaInfo) Len() (n int) { n += 1 n += 3 n += 2 - n += 2*len(self.Opcolor[:]) + n += 2 * len(self.Opcolor[:]) return } func (self *VideoMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { @@ -1510,19 +1514,19 @@ func (self VideoMediaInfo) Children() (r []Atom) { } type SampleTable struct { - SampleDesc *SampleDesc - TimeToSample *TimeToSample - CompositionOffset *CompositionOffset - SampleToChunk *SampleToChunk - SyncSample *SyncSample - ChunkOffset *ChunkOffset - SampleSize *SampleSize + SampleDesc *SampleDesc + TimeToSample *TimeToSample + CompositionOffset *CompositionOffset + SampleToChunk *SampleToChunk + SyncSample *SyncSample + ChunkOffset *ChunkOffset + SampleSize *SampleSize AtomPos } func (self SampleTable) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(STBL)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1631,11 +1635,11 @@ func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { } self.SyncSample = atom } - case STCO: + case STCO, CO64: { atom := &ChunkOffset{} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("stco", n+offset, err) + err = parseErr(tag.String(), n+offset, err) return } self.ChunkOffset = atom @@ -1680,16 +1684,16 @@ func (self SampleTable) Children() (r []Atom) { } type SampleDesc struct { - Version uint8 - AVC1Desc *AVC1Desc - MP4ADesc *MP4ADesc - Unknowns []Atom + Version uint8 + AVC1Desc *AVC1Desc + MP4ADesc *MP4ADesc + Unknowns []Atom AtomPos } func (self SampleDesc) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(STSD)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1773,7 +1777,7 @@ func (self *SampleDesc) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -1797,22 +1801,22 @@ func (self SampleDesc) Children() (r []Atom) { } type MP4ADesc struct { - DataRefIdx int16 - Version int16 - RevisionLevel int16 - Vendor int32 - NumberOfChannels int16 - SampleSize int16 - CompressionId int16 - SampleRate float64 - Conf *ElemStreamDesc - Unknowns []Atom + DataRefIdx int16 + Version int16 + RevisionLevel int16 + Vendor int32 + NumberOfChannels int16 + SampleSize int16 + CompressionId int16 + SampleRate float64 + Conf *ElemStreamDesc + Unknowns []Atom AtomPos } func (self MP4ADesc) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MP4A)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -1935,7 +1939,7 @@ func (self *MP4ADesc) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -1956,28 +1960,28 @@ func (self MP4ADesc) Children() (r []Atom) { } type AVC1Desc struct { - DataRefIdx int16 - Version int16 - Revision int16 - Vendor int32 - TemporalQuality int32 - SpatialQuality int32 - Width int16 - Height int16 - HorizontalResolution float64 - VorizontalResolution float64 - FrameCount int16 - CompressorName [32]byte - Depth int16 - ColorTableId int16 - Conf *AVC1Conf - Unknowns []Atom + DataRefIdx int16 + Version int16 + Revision int16 + Vendor int32 + TemporalQuality int32 + SpatialQuality int32 + Width int16 + Height int16 + HorizontalResolution float64 + VorizontalResolution float64 + FrameCount int16 + CompressorName [32]byte + Depth int16 + ColorTableId int16 + Conf *AVC1Conf + Unknowns []Atom AtomPos } func (self AVC1Desc) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(AVC1)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2154,7 +2158,7 @@ func (self *AVC1Desc) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -2175,13 +2179,13 @@ func (self AVC1Desc) Children() (r []Atom) { } type AVC1Conf struct { - Data []byte + Data []byte AtomPos } func (self AVC1Conf) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(AVCC)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2207,15 +2211,15 @@ func (self AVC1Conf) Children() (r []Atom) { } type TimeToSample struct { - Version uint8 - Flags uint32 - Entries []TimeToSampleEntry + Version uint8 + Flags uint32 + Entries []TimeToSampleEntry AtomPos } func (self TimeToSample) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(STTS)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2237,7 +2241,7 @@ func (self TimeToSample) Len() (n int) { n += 1 n += 3 n += 4 - n += LenTimeToSampleEntry*len(self.Entries) + n += LenTimeToSampleEntry * len(self.Entries) return } func (self *TimeToSample) Unmarshal(b []byte, offset int) (n int, err error) { @@ -2274,8 +2278,8 @@ func (self TimeToSample) Children() (r []Atom) { } type TimeToSampleEntry struct { - Count uint32 - Duration uint32 + Count uint32 + Duration uint32 } func GetTimeToSampleEntry(b []byte) (self TimeToSampleEntry) { @@ -2291,15 +2295,15 @@ func PutTimeToSampleEntry(b []byte, self TimeToSampleEntry) { const LenTimeToSampleEntry = 8 type SampleToChunk struct { - Version uint8 - Flags uint32 - Entries []SampleToChunkEntry + Version uint8 + Flags uint32 + Entries []SampleToChunkEntry AtomPos } func (self SampleToChunk) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(STSC)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2321,7 +2325,7 @@ func (self SampleToChunk) Len() (n int) { n += 1 n += 3 n += 4 - n += LenSampleToChunkEntry*len(self.Entries) + n += LenSampleToChunkEntry * len(self.Entries) return } func (self *SampleToChunk) Unmarshal(b []byte, offset int) (n int, err error) { @@ -2358,9 +2362,9 @@ func (self SampleToChunk) Children() (r []Atom) { } type SampleToChunkEntry struct { - FirstChunk uint32 - SamplesPerChunk uint32 - SampleDescId uint32 + FirstChunk uint32 + SamplesPerChunk uint32 + SampleDescId uint32 } func GetSampleToChunkEntry(b []byte) (self SampleToChunkEntry) { @@ -2378,15 +2382,15 @@ func PutSampleToChunkEntry(b []byte, self SampleToChunkEntry) { const LenSampleToChunkEntry = 12 type CompositionOffset struct { - Version uint8 - Flags uint32 - Entries []CompositionOffsetEntry + Version uint8 + Flags uint32 + Entries []CompositionOffsetEntry AtomPos } func (self CompositionOffset) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(CTTS)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2408,7 +2412,7 @@ func (self CompositionOffset) Len() (n int) { n += 1 n += 3 n += 4 - n += LenCompositionOffsetEntry*len(self.Entries) + n += LenCompositionOffsetEntry * len(self.Entries) return } func (self *CompositionOffset) Unmarshal(b []byte, offset int) (n int, err error) { @@ -2445,8 +2449,8 @@ func (self CompositionOffset) Children() (r []Atom) { } type CompositionOffsetEntry struct { - Count uint32 - Offset uint32 + Count uint32 + Offset uint32 } func GetCompositionOffsetEntry(b []byte) (self CompositionOffsetEntry) { @@ -2462,15 +2466,15 @@ func PutCompositionOffsetEntry(b []byte, self CompositionOffsetEntry) { const LenCompositionOffsetEntry = 8 type SyncSample struct { - Version uint8 - Flags uint32 - Entries []uint32 + Version uint8 + Flags uint32 + Entries []uint32 AtomPos } func (self SyncSample) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(STSS)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2492,7 +2496,7 @@ func (self SyncSample) Len() (n int) { n += 1 n += 3 n += 4 - n += 4*len(self.Entries) + n += 4 * len(self.Entries) return } func (self *SyncSample) Unmarshal(b []byte, offset int) (n int, err error) { @@ -2529,15 +2533,20 @@ func (self SyncSample) Children() (r []Atom) { } type ChunkOffset struct { - Version uint8 - Flags uint32 - Entries []uint32 + Version uint8 + Flags uint32 + Is64bit bool + Entries []int64 AtomPos } func (self ChunkOffset) Marshal(b []byte) (n int) { - pio.PutU32BE(b[4:], uint32(STCO)) - n += self.marshal(b[8:])+8 + if self.Is64bit { + pio.PutU32BE(b[4:], uint32(CO64)) + } else { + pio.PutU32BE(b[4:], uint32(STCO)) + } + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2548,9 +2557,16 @@ func (self ChunkOffset) marshal(b []byte) (n int) { n += 3 pio.PutU32BE(b[n:], uint32(len(self.Entries))) n += 4 - for _, entry := range self.Entries { - pio.PutU32BE(b[n:], entry) - n += 4 + if self.Is64bit { + for _, entry := range self.Entries { + pio.PutI64BE(b[n:], entry) + n += 8 + } + } else { + for _, entry := range self.Entries { + pio.PutU32BE(b[n:], uint32(entry)) + n += 4 + } } return } @@ -2559,11 +2575,16 @@ func (self ChunkOffset) Len() (n int) { n += 1 n += 3 n += 4 - n += 4*len(self.Entries) + if self.Is64bit { + n += 8 * len(self.Entries) + } else { + n += 4 * len(self.Entries) + } return } func (self *ChunkOffset) Unmarshal(b []byte, offset int) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) + self.Is64bit = Tag(pio.U32BE(b[4:])) == CO64 n += 8 if len(b) < n+1 { err = parseErr("Version", n+offset, err) @@ -2580,14 +2601,31 @@ func (self *ChunkOffset) Unmarshal(b []byte, offset int) (n int, err error) { var _len_Entries uint32 _len_Entries = pio.U32BE(b[n:]) n += 4 - self.Entries = make([]uint32, _len_Entries) - if len(b) < n+4*len(self.Entries) { - err = parseErr("uint32", n+offset, err) + self.Entries = make([]int64, _len_Entries) + var entriesSize int + if self.Is64bit { + entriesSize = 8 * len(self.Entries) + } else { + entriesSize = 4 * len(self.Entries) + } + if len(b) < n+entriesSize { + if self.Is64bit { + err = parseErr("int64", n+offset, err) + } else { + err = parseErr("uint32", n+offset, err) + } return } - for i := range self.Entries { - self.Entries[i] = pio.U32BE(b[n:]) - n += 4 + if self.Is64bit { + for i := range self.Entries { + self.Entries[i] = pio.I64BE(b[n:]) + n += 8 + } + } else { + for i := range self.Entries { + self.Entries[i] = int64(pio.U32BE(b[n:])) + n += 4 + } } return } @@ -2596,15 +2634,15 @@ func (self ChunkOffset) Children() (r []Atom) { } type MovieFrag struct { - Header *MovieFragHeader - Tracks []*TrackFrag - Unknowns []Atom + Header *MovieFragHeader + Tracks []*TrackFrag + Unknowns []Atom AtomPos } func (self MovieFrag) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MOOF)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2664,7 +2702,7 @@ func (self *MovieFrag) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -2688,15 +2726,15 @@ func (self MovieFrag) Children() (r []Atom) { } type MovieFragHeader struct { - Version uint8 - Flags uint32 - Seqnum uint32 + Version uint8 + Flags uint32 + Seqnum uint32 AtomPos } func (self MovieFragHeader) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MFHD)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2744,16 +2782,16 @@ func (self MovieFragHeader) Children() (r []Atom) { } type TrackFrag struct { - Header *TrackFragHeader - DecodeTime *TrackFragDecodeTime - Run *TrackFragRun - Unknowns []Atom + Header *TrackFragHeader + DecodeTime *TrackFragDecodeTime + Run *TrackFragRun + Unknowns []Atom AtomPos } func (self TrackFrag) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(TRAF)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2828,7 +2866,7 @@ func (self *TrackFrag) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -2855,14 +2893,14 @@ func (self TrackFrag) Children() (r []Atom) { } type MovieExtend struct { - Tracks []*TrackExtend - Unknowns []Atom + Tracks []*TrackExtend + Unknowns []Atom AtomPos } func (self MovieExtend) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(MVEX)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -2907,7 +2945,7 @@ func (self *MovieExtend) Unmarshal(b []byte, offset int) (n int, err error) { } default: { - atom := &Dummy{Tag_: tag, Data: b[n:n+size]} + atom := &Dummy{Tag_: tag, Data: b[n : n+size]} if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { err = parseErr("", n+offset, err) return @@ -2928,19 +2966,19 @@ func (self MovieExtend) Children() (r []Atom) { } type TrackExtend struct { - Version uint8 - Flags uint32 - TrackId uint32 - DefaultSampleDescIdx uint32 - DefaultSampleDuration uint32 - DefaultSampleSize uint32 - DefaultSampleFlags uint32 + Version uint8 + Flags uint32 + TrackId uint32 + DefaultSampleDescIdx uint32 + DefaultSampleDuration uint32 + DefaultSampleSize uint32 + DefaultSampleFlags uint32 AtomPos } func (self TrackExtend) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(TREX)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -3024,16 +3062,16 @@ func (self TrackExtend) Children() (r []Atom) { } type SampleSize struct { - Version uint8 - Flags uint32 - SampleSize uint32 - Entries []uint32 + Version uint8 + Flags uint32 + SampleSize uint32 + Entries []uint32 AtomPos } func (self SampleSize) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(STSZ)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -3064,7 +3102,7 @@ func (self SampleSize) Len() (n int) { return } n += 4 - n += 4*len(self.Entries) + n += 4 * len(self.Entries) return } func (self *SampleSize) Unmarshal(b []byte, offset int) (n int, err error) { @@ -3110,17 +3148,17 @@ func (self SampleSize) Children() (r []Atom) { } type TrackFragRun struct { - Version uint8 - Flags uint32 - DataOffset uint32 - FirstSampleFlags uint32 - Entries []TrackFragRunEntry + Version uint8 + Flags uint32 + DataOffset uint32 + FirstSampleFlags uint32 + Entries []TrackFragRunEntry AtomPos } func (self TrackFragRun) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(TRUN)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -3280,10 +3318,10 @@ func (self TrackFragRun) Children() (r []Atom) { } type TrackFragRunEntry struct { - Duration uint32 - Size uint32 - Flags uint32 - Cts uint32 + Duration uint32 + Size uint32 + Flags uint32 + Cts uint32 } func GetTrackFragRunEntry(b []byte) (self TrackFragRunEntry) { @@ -3303,19 +3341,19 @@ func PutTrackFragRunEntry(b []byte, self TrackFragRunEntry) { const LenTrackFragRunEntry = 16 type TrackFragHeader struct { - Version uint8 - Flags uint32 - BaseDataOffset uint64 - StsdId uint32 - DefaultDuration uint32 - DefaultSize uint32 - DefaultFlags uint32 + Version uint8 + Flags uint32 + BaseDataOffset uint64 + StsdId uint32 + DefaultDuration uint32 + DefaultSize uint32 + DefaultFlags uint32 AtomPos } func (self TrackFragHeader) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(TFHD)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } @@ -3459,15 +3497,15 @@ func (self TrackFragHeader) Children() (r []Atom) { } type TrackFragDecodeTime struct { - Version uint8 - Flags uint32 - Time time.Time + Version uint8 + Flags uint32 + Time time.Time AtomPos } func (self TrackFragDecodeTime) Marshal(b []byte) (n int) { pio.PutU32BE(b[4:], uint32(TFDT)) - n += self.marshal(b[8:])+8 + n += self.marshal(b[8:]) + 8 pio.PutU32BE(b[0:], uint32(n)) return } diff --git a/format/mp4/muxer.go b/format/mp4/muxer.go index d1ef7e0c..3ad04ca4 100644 --- a/format/mp4/muxer.go +++ b/format/mp4/muxer.go @@ -1,27 +1,27 @@ package mp4 import ( + "bufio" "fmt" - "time" "github.com/nareix/joy4/av" "github.com/nareix/joy4/codec/aacparser" "github.com/nareix/joy4/codec/h264parser" "github.com/nareix/joy4/format/mp4/mp4io" "github.com/nareix/joy4/utils/bits/pio" "io" - "bufio" + "time" ) type Muxer struct { - w io.WriteSeeker - bufw *bufio.Writer - wpos int64 - streams []*Stream + w io.WriteSeeker + bufw *bufio.Writer + wpos int64 + streams []*Stream } func NewMuxer(w io.WriteSeeker) *Muxer { return &Muxer{ - w: w, + w: w, bufw: bufio.NewWriterSize(w, pio.RecommendBufioSize), } } @@ -49,12 +49,12 @@ func (self *Muxer) newStream(codec av.CodecData) (err error) { }, }, SampleSize: &mp4io.SampleSize{}, - ChunkOffset: &mp4io.ChunkOffset{}, + ChunkOffset: &mp4io.ChunkOffset{Is64bit: true}, } stream.trackAtom = &mp4io.Track{ Header: &mp4io.TrackHeader{ - TrackId: int32(len(self.streams)+1), + TrackId: int32(len(self.streams) + 1), Flags: 0x0003, // Track enabled | Track in movie Duration: 0, // fill later Matrix: [9]int32{0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000}, @@ -109,7 +109,7 @@ func (self *Stream) fillTrackAtom() (err error) { Conf: &mp4io.AVC1Conf{Data: codec.AVCDecoderConfRecordBytes()}, } self.trackAtom.Media.Handler = &mp4io.HandlerRefer{ - SubType: [4]byte{'v','i','d','e'}, + SubType: [4]byte{'v', 'i', 'd', 'e'}, Name: []byte("Video Media Handler"), } self.trackAtom.Media.Info.Video = &mp4io.VideoMediaInfo{ @@ -132,7 +132,7 @@ func (self *Stream) fillTrackAtom() (err error) { self.trackAtom.Header.Volume = 1 self.trackAtom.Header.AlternateGroup = 1 self.trackAtom.Media.Handler = &mp4io.HandlerRefer{ - SubType: [4]byte{'s','o','u','n'}, + SubType: [4]byte{'s', 'o', 'u', 'n'}, Name: []byte("Sound Handler"), } self.trackAtom.Media.Info.Sound = &mp4io.SoundMediaInfo{} @@ -211,7 +211,7 @@ func (self *Stream) writePacket(pkt av.Packet, rawdur time.Duration) (err error) self.duration += int64(duration) self.sampleIndex++ - self.sample.ChunkOffset.Entries = append(self.sample.ChunkOffset.Entries, uint32(self.muxer.wpos)) + self.sample.ChunkOffset.Entries = append(self.sample.ChunkOffset.Entries, self.muxer.wpos) self.sample.SampleSize.Entries = append(self.sample.SampleSize.Entries, uint32(len(pkt.Data))) self.muxer.wpos += int64(len(pkt.Data)) From 86e3ec33ae210926b5077d01fd50944bd3234275 Mon Sep 17 00:00:00 2001 From: kondakovdmitry Date: Wed, 6 May 2020 19:44:10 +0300 Subject: [PATCH 3/4] Support for reading MP4 files with wide atoms --- format/mp4/mp4io/atoms.go | 499 +++++++++++++++++++------------------- format/mp4/mp4io/mp4io.go | 120 ++++----- 2 files changed, 317 insertions(+), 302 deletions(-) diff --git a/format/mp4/mp4io/atoms.go b/format/mp4/mp4io/atoms.go index ef5d024a..799f4177 100644 --- a/format/mp4/mp4io/atoms.go +++ b/format/mp4/mp4io/atoms.go @@ -1,7 +1,10 @@ package mp4io -import "github.com/nareix/joy4/utils/bits/pio" -import "time" +import ( + "time" + + "github.com/nareix/joy4/utils/bits/pio" +) const MOOF = Tag(0x6d6f6f66) @@ -252,22 +255,22 @@ func (self Movie) Len() (n int) { } return } -func (self *Movie) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *Movie) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case MVHD: { atom := &MovieHeader{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("mvhd", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("mvhd", int64(n)+offset, err) return } self.Header = atom @@ -275,8 +278,8 @@ func (self *Movie) Unmarshal(b []byte, offset int) (n int, err error) { case MVEX: { atom := &MovieExtend{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("mvex", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("mvex", int64(n)+offset, err) return } self.MovieExtend = atom @@ -284,8 +287,8 @@ func (self *Movie) Unmarshal(b []byte, offset int) (n int, err error) { case TRAK: { atom := &Track{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("trak", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("trak", int64(n)+offset, err) return } self.Tracks = append(self.Tracks, atom) @@ -293,8 +296,8 @@ func (self *Movie) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -403,60 +406,60 @@ func (self MovieHeader) Len() (n int) { n += 4 return } -func (self *MovieHeader) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *MovieHeader) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+4 { - err = parseErr("CreateTime", n+offset, err) + err = parseErr("CreateTime", int64(n)+offset, err) return } self.CreateTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("ModifyTime", n+offset, err) + err = parseErr("ModifyTime", int64(n)+offset, err) return } self.ModifyTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("TimeScale", n+offset, err) + err = parseErr("TimeScale", int64(n)+offset, err) return } self.TimeScale = pio.I32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("Duration", n+offset, err) + err = parseErr("Duration", int64(n)+offset, err) return } self.Duration = pio.I32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("PreferredRate", n+offset, err) + err = parseErr("PreferredRate", int64(n)+offset, err) return } self.PreferredRate = GetFixed32(b[n:]) n += 4 if len(b) < n+2 { - err = parseErr("PreferredVolume", n+offset, err) + err = parseErr("PreferredVolume", int64(n)+offset, err) return } self.PreferredVolume = GetFixed16(b[n:]) n += 2 n += 10 if len(b) < n+4*len(self.Matrix) { - err = parseErr("Matrix", n+offset, err) + err = parseErr("Matrix", int64(n)+offset, err) return } for i := range self.Matrix { @@ -464,43 +467,43 @@ func (self *MovieHeader) Unmarshal(b []byte, offset int) (n int, err error) { n += 4 } if len(b) < n+4 { - err = parseErr("PreviewTime", n+offset, err) + err = parseErr("PreviewTime", int64(n)+offset, err) return } self.PreviewTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("PreviewDuration", n+offset, err) + err = parseErr("PreviewDuration", int64(n)+offset, err) return } self.PreviewDuration = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("PosterTime", n+offset, err) + err = parseErr("PosterTime", int64(n)+offset, err) return } self.PosterTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("SelectionTime", n+offset, err) + err = parseErr("SelectionTime", int64(n)+offset, err) return } self.SelectionTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("SelectionDuration", n+offset, err) + err = parseErr("SelectionDuration", int64(n)+offset, err) return } self.SelectionDuration = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("CurrentTime", n+offset, err) + err = parseErr("CurrentTime", int64(n)+offset, err) return } self.CurrentTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("NextTrackId", n+offset, err) + err = parseErr("NextTrackId", int64(n)+offset, err) return } self.NextTrackId = pio.I32BE(b[n:]) @@ -549,22 +552,22 @@ func (self Track) Len() (n int) { } return } -func (self *Track) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *Track) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case TKHD: { atom := &TrackHeader{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("tkhd", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("tkhd", int64(n)+offset, err) return } self.Header = atom @@ -572,8 +575,8 @@ func (self *Track) Unmarshal(b []byte, offset int) (n int, err error) { case MDIA: { atom := &Media{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("mdia", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("mdia", int64(n)+offset, err) return } self.Media = atom @@ -581,8 +584,8 @@ func (self *Track) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -676,68 +679,68 @@ func (self TrackHeader) Len() (n int) { n += 4 return } -func (self *TrackHeader) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *TrackHeader) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+4 { - err = parseErr("CreateTime", n+offset, err) + err = parseErr("CreateTime", int64(n)+offset, err) return } self.CreateTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("ModifyTime", n+offset, err) + err = parseErr("ModifyTime", int64(n)+offset, err) return } self.ModifyTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("TrackId", n+offset, err) + err = parseErr("TrackId", int64(n)+offset, err) return } self.TrackId = pio.I32BE(b[n:]) n += 4 n += 4 if len(b) < n+4 { - err = parseErr("Duration", n+offset, err) + err = parseErr("Duration", int64(n)+offset, err) return } self.Duration = pio.I32BE(b[n:]) n += 4 n += 8 if len(b) < n+2 { - err = parseErr("Layer", n+offset, err) + err = parseErr("Layer", int64(n)+offset, err) return } self.Layer = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("AlternateGroup", n+offset, err) + err = parseErr("AlternateGroup", int64(n)+offset, err) return } self.AlternateGroup = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("Volume", n+offset, err) + err = parseErr("Volume", int64(n)+offset, err) return } self.Volume = GetFixed16(b[n:]) n += 2 n += 2 if len(b) < n+4*len(self.Matrix) { - err = parseErr("Matrix", n+offset, err) + err = parseErr("Matrix", int64(n)+offset, err) return } for i := range self.Matrix { @@ -745,13 +748,13 @@ func (self *TrackHeader) Unmarshal(b []byte, offset int) (n int, err error) { n += 4 } if len(b) < n+4 { - err = parseErr("TrackWidth", n+offset, err) + err = parseErr("TrackWidth", int64(n)+offset, err) return } self.TrackWidth = GetFixed32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("TrackHeight", n+offset, err) + err = parseErr("TrackHeight", int64(n)+offset, err) return } self.TrackHeight = GetFixed32(b[n:]) @@ -799,29 +802,29 @@ func (self HandlerRefer) Len() (n int) { n += len(self.Name[:]) return } -func (self *HandlerRefer) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *HandlerRefer) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+len(self.Type) { - err = parseErr("Type", n+offset, err) + err = parseErr("Type", int64(n)+offset, err) return } copy(self.Type[:], b[n:]) n += len(self.Type) if len(b) < n+len(self.SubType) { - err = parseErr("SubType", n+offset, err) + err = parseErr("SubType", int64(n)+offset, err) return } copy(self.SubType[:], b[n:]) @@ -879,22 +882,22 @@ func (self Media) Len() (n int) { } return } -func (self *Media) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *Media) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case MDHD: { atom := &MediaHeader{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("mdhd", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("mdhd", int64(n)+offset, err) return } self.Header = atom @@ -902,8 +905,8 @@ func (self *Media) Unmarshal(b []byte, offset int) (n int, err error) { case HDLR: { atom := &HandlerRefer{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("hdlr", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("hdlr", int64(n)+offset, err) return } self.Handler = atom @@ -911,8 +914,8 @@ func (self *Media) Unmarshal(b []byte, offset int) (n int, err error) { case MINF: { atom := &MediaInfo{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("minf", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("minf", int64(n)+offset, err) return } self.Info = atom @@ -920,8 +923,8 @@ func (self *Media) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -994,53 +997,53 @@ func (self MediaHeader) Len() (n int) { n += 2 return } -func (self *MediaHeader) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *MediaHeader) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+4 { - err = parseErr("CreateTime", n+offset, err) + err = parseErr("CreateTime", int64(n)+offset, err) return } self.CreateTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("ModifyTime", n+offset, err) + err = parseErr("ModifyTime", int64(n)+offset, err) return } self.ModifyTime = GetTime32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("TimeScale", n+offset, err) + err = parseErr("TimeScale", int64(n)+offset, err) return } self.TimeScale = pio.I32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("Duration", n+offset, err) + err = parseErr("Duration", int64(n)+offset, err) return } self.Duration = pio.I32BE(b[n:]) n += 4 if len(b) < n+2 { - err = parseErr("Language", n+offset, err) + err = parseErr("Language", int64(n)+offset, err) return } self.Language = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("Quality", n+offset, err) + err = parseErr("Quality", int64(n)+offset, err) return } self.Quality = pio.I16BE(b[n:]) @@ -1103,22 +1106,22 @@ func (self MediaInfo) Len() (n int) { } return } -func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *MediaInfo) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case SMHD: { atom := &SoundMediaInfo{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("smhd", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("smhd", int64(n)+offset, err) return } self.Sound = atom @@ -1126,8 +1129,8 @@ func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { case VMHD: { atom := &VideoMediaInfo{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("vmhd", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("vmhd", int64(n)+offset, err) return } self.Video = atom @@ -1135,8 +1138,8 @@ func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { case DINF: { atom := &DataInfo{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("dinf", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("dinf", int64(n)+offset, err) return } self.Data = atom @@ -1144,8 +1147,8 @@ func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { case STBL: { atom := &SampleTable{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("stbl", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("stbl", int64(n)+offset, err) return } self.Sample = atom @@ -1153,8 +1156,8 @@ func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -1212,22 +1215,22 @@ func (self DataInfo) Len() (n int) { } return } -func (self *DataInfo) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *DataInfo) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case DREF: { atom := &DataRefer{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("dref", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("dref", int64(n)+offset, err) return } self.Refer = atom @@ -1235,8 +1238,8 @@ func (self *DataInfo) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -1293,17 +1296,17 @@ func (self DataRefer) Len() (n int) { } return } -func (self *DataRefer) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *DataRefer) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -1313,15 +1316,15 @@ func (self *DataRefer) Unmarshal(b []byte, offset int) (n int, err error) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case URL: { atom := &DataReferUrl{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("url ", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("url ", int64(n)+offset, err) return } self.Url = atom @@ -1363,17 +1366,17 @@ func (self DataReferUrl) Len() (n int) { n += 3 return } -func (self *DataReferUrl) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *DataReferUrl) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -1415,23 +1418,23 @@ func (self SoundMediaInfo) Len() (n int) { n += 2 return } -func (self *SoundMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *SoundMediaInfo) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+2 { - err = parseErr("Balance", n+offset, err) + err = parseErr("Balance", int64(n)+offset, err) return } self.Balance = pio.I16BE(b[n:]) @@ -1478,29 +1481,29 @@ func (self VideoMediaInfo) Len() (n int) { n += 2 * len(self.Opcolor[:]) return } -func (self *VideoMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *VideoMediaInfo) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+2 { - err = parseErr("GraphicsMode", n+offset, err) + err = parseErr("GraphicsMode", int64(n)+offset, err) return } self.GraphicsMode = pio.I16BE(b[n:]) n += 2 if len(b) < n+2*len(self.Opcolor) { - err = parseErr("Opcolor", n+offset, err) + err = parseErr("Opcolor", int64(n)+offset, err) return } for i := range self.Opcolor { @@ -1579,22 +1582,22 @@ func (self SampleTable) Len() (n int) { } return } -func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *SampleTable) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case STSD: { atom := &SampleDesc{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("stsd", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("stsd", int64(n)+offset, err) return } self.SampleDesc = atom @@ -1602,8 +1605,8 @@ func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { case STTS: { atom := &TimeToSample{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("stts", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("stts", int64(n)+offset, err) return } self.TimeToSample = atom @@ -1611,8 +1614,8 @@ func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { case CTTS: { atom := &CompositionOffset{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("ctts", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("ctts", int64(n)+offset, err) return } self.CompositionOffset = atom @@ -1620,8 +1623,8 @@ func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { case STSC: { atom := &SampleToChunk{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("stsc", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("stsc", int64(n)+offset, err) return } self.SampleToChunk = atom @@ -1629,8 +1632,8 @@ func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { case STSS: { atom := &SyncSample{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("stss", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("stss", int64(n)+offset, err) return } self.SyncSample = atom @@ -1638,8 +1641,8 @@ func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { case STCO, CO64: { atom := &ChunkOffset{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr(tag.String(), n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr(tag.String(), int64(n)+offset, err) return } self.ChunkOffset = atom @@ -1647,8 +1650,8 @@ func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { case STSZ: { atom := &SampleSize{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("stsz", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("stsz", int64(n)+offset, err) return } self.SampleSize = atom @@ -1738,11 +1741,11 @@ func (self SampleDesc) Len() (n int) { } return } -func (self *SampleDesc) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *SampleDesc) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) @@ -1753,15 +1756,15 @@ func (self *SampleDesc) Unmarshal(b []byte, offset int) (n int, err error) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case AVC1: { atom := &AVC1Desc{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("avc1", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("avc1", int64(n)+offset, err) return } self.AVC1Desc = atom @@ -1769,8 +1772,8 @@ func (self *SampleDesc) Unmarshal(b []byte, offset int) (n int, err error) { case MP4A: { atom := &MP4ADesc{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("mp4a", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("mp4a", int64(n)+offset, err) return } self.MP4ADesc = atom @@ -1778,8 +1781,8 @@ func (self *SampleDesc) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -1867,55 +1870,55 @@ func (self MP4ADesc) Len() (n int) { } return } -func (self *MP4ADesc) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *MP4ADesc) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 n += 6 if len(b) < n+2 { - err = parseErr("DataRefIdx", n+offset, err) + err = parseErr("DataRefIdx", int64(n)+offset, err) return } self.DataRefIdx = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("RevisionLevel", n+offset, err) + err = parseErr("RevisionLevel", int64(n)+offset, err) return } self.RevisionLevel = pio.I16BE(b[n:]) n += 2 if len(b) < n+4 { - err = parseErr("Vendor", n+offset, err) + err = parseErr("Vendor", int64(n)+offset, err) return } self.Vendor = pio.I32BE(b[n:]) n += 4 if len(b) < n+2 { - err = parseErr("NumberOfChannels", n+offset, err) + err = parseErr("NumberOfChannels", int64(n)+offset, err) return } self.NumberOfChannels = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("SampleSize", n+offset, err) + err = parseErr("SampleSize", int64(n)+offset, err) return } self.SampleSize = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("CompressionId", n+offset, err) + err = parseErr("CompressionId", int64(n)+offset, err) return } self.CompressionId = pio.I16BE(b[n:]) n += 2 n += 2 if len(b) < n+4 { - err = parseErr("SampleRate", n+offset, err) + err = parseErr("SampleRate", int64(n)+offset, err) return } self.SampleRate = GetFixed32(b[n:]) @@ -1924,15 +1927,15 @@ func (self *MP4ADesc) Unmarshal(b []byte, offset int) (n int, err error) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case ESDS: { atom := &ElemStreamDesc{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("esds", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("esds", int64(n)+offset, err) return } self.Conf = atom @@ -1940,8 +1943,8 @@ func (self *MP4ADesc) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -2050,91 +2053,91 @@ func (self AVC1Desc) Len() (n int) { } return } -func (self *AVC1Desc) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *AVC1Desc) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 n += 6 if len(b) < n+2 { - err = parseErr("DataRefIdx", n+offset, err) + err = parseErr("DataRefIdx", int64(n)+offset, err) return } self.DataRefIdx = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("Revision", n+offset, err) + err = parseErr("Revision", int64(n)+offset, err) return } self.Revision = pio.I16BE(b[n:]) n += 2 if len(b) < n+4 { - err = parseErr("Vendor", n+offset, err) + err = parseErr("Vendor", int64(n)+offset, err) return } self.Vendor = pio.I32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("TemporalQuality", n+offset, err) + err = parseErr("TemporalQuality", int64(n)+offset, err) return } self.TemporalQuality = pio.I32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("SpatialQuality", n+offset, err) + err = parseErr("SpatialQuality", int64(n)+offset, err) return } self.SpatialQuality = pio.I32BE(b[n:]) n += 4 if len(b) < n+2 { - err = parseErr("Width", n+offset, err) + err = parseErr("Width", int64(n)+offset, err) return } self.Width = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("Height", n+offset, err) + err = parseErr("Height", int64(n)+offset, err) return } self.Height = pio.I16BE(b[n:]) n += 2 if len(b) < n+4 { - err = parseErr("HorizontalResolution", n+offset, err) + err = parseErr("HorizontalResolution", int64(n)+offset, err) return } self.HorizontalResolution = GetFixed32(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("VorizontalResolution", n+offset, err) + err = parseErr("VorizontalResolution", int64(n)+offset, err) return } self.VorizontalResolution = GetFixed32(b[n:]) n += 4 n += 4 if len(b) < n+2 { - err = parseErr("FrameCount", n+offset, err) + err = parseErr("FrameCount", int64(n)+offset, err) return } self.FrameCount = pio.I16BE(b[n:]) n += 2 if len(b) < n+len(self.CompressorName) { - err = parseErr("CompressorName", n+offset, err) + err = parseErr("CompressorName", int64(n)+offset, err) return } copy(self.CompressorName[:], b[n:]) n += len(self.CompressorName) if len(b) < n+2 { - err = parseErr("Depth", n+offset, err) + err = parseErr("Depth", int64(n)+offset, err) return } self.Depth = pio.I16BE(b[n:]) n += 2 if len(b) < n+2 { - err = parseErr("ColorTableId", n+offset, err) + err = parseErr("ColorTableId", int64(n)+offset, err) return } self.ColorTableId = pio.I16BE(b[n:]) @@ -2143,15 +2146,15 @@ func (self *AVC1Desc) Unmarshal(b []byte, offset int) (n int, err error) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case AVCC: { atom := &AVC1Conf{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("avcC", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("avcC", int64(n)+offset, err) return } self.Conf = atom @@ -2159,8 +2162,8 @@ func (self *AVC1Desc) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -2199,7 +2202,7 @@ func (self AVC1Conf) Len() (n int) { n += len(self.Data[:]) return } -func (self *AVC1Conf) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *AVC1Conf) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 self.Data = b[n:] @@ -2244,17 +2247,17 @@ func (self TimeToSample) Len() (n int) { n += LenTimeToSampleEntry * len(self.Entries) return } -func (self *TimeToSample) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *TimeToSample) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -2264,7 +2267,7 @@ func (self *TimeToSample) Unmarshal(b []byte, offset int) (n int, err error) { n += 4 self.Entries = make([]TimeToSampleEntry, _len_Entries) if len(b) < n+LenTimeToSampleEntry*len(self.Entries) { - err = parseErr("TimeToSampleEntry", n+offset, err) + err = parseErr("TimeToSampleEntry", int64(n)+offset, err) return } for i := range self.Entries { @@ -2328,17 +2331,17 @@ func (self SampleToChunk) Len() (n int) { n += LenSampleToChunkEntry * len(self.Entries) return } -func (self *SampleToChunk) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *SampleToChunk) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -2348,7 +2351,7 @@ func (self *SampleToChunk) Unmarshal(b []byte, offset int) (n int, err error) { n += 4 self.Entries = make([]SampleToChunkEntry, _len_Entries) if len(b) < n+LenSampleToChunkEntry*len(self.Entries) { - err = parseErr("SampleToChunkEntry", n+offset, err) + err = parseErr("SampleToChunkEntry", int64(n)+offset, err) return } for i := range self.Entries { @@ -2415,17 +2418,17 @@ func (self CompositionOffset) Len() (n int) { n += LenCompositionOffsetEntry * len(self.Entries) return } -func (self *CompositionOffset) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *CompositionOffset) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -2435,7 +2438,7 @@ func (self *CompositionOffset) Unmarshal(b []byte, offset int) (n int, err error n += 4 self.Entries = make([]CompositionOffsetEntry, _len_Entries) if len(b) < n+LenCompositionOffsetEntry*len(self.Entries) { - err = parseErr("CompositionOffsetEntry", n+offset, err) + err = parseErr("CompositionOffsetEntry", int64(n)+offset, err) return } for i := range self.Entries { @@ -2499,17 +2502,17 @@ func (self SyncSample) Len() (n int) { n += 4 * len(self.Entries) return } -func (self *SyncSample) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *SyncSample) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -2519,7 +2522,7 @@ func (self *SyncSample) Unmarshal(b []byte, offset int) (n int, err error) { n += 4 self.Entries = make([]uint32, _len_Entries) if len(b) < n+4*len(self.Entries) { - err = parseErr("uint32", n+offset, err) + err = parseErr("uint32", int64(n)+offset, err) return } for i := range self.Entries { @@ -2582,18 +2585,18 @@ func (self ChunkOffset) Len() (n int) { } return } -func (self *ChunkOffset) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *ChunkOffset) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) self.Is64bit = Tag(pio.U32BE(b[4:])) == CO64 n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -2610,9 +2613,9 @@ func (self *ChunkOffset) Unmarshal(b []byte, offset int) (n int, err error) { } if len(b) < n+entriesSize { if self.Is64bit { - err = parseErr("int64", n+offset, err) + err = parseErr("int64", int64(n)+offset, err) } else { - err = parseErr("uint32", n+offset, err) + err = parseErr("uint32", int64(n)+offset, err) } return } @@ -2671,22 +2674,22 @@ func (self MovieFrag) Len() (n int) { } return } -func (self *MovieFrag) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *MovieFrag) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case MFHD: { atom := &MovieFragHeader{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("mfhd", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("mfhd", int64(n)+offset, err) return } self.Header = atom @@ -2694,8 +2697,8 @@ func (self *MovieFrag) Unmarshal(b []byte, offset int) (n int, err error) { case TRAF: { atom := &TrackFrag{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("traf", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("traf", int64(n)+offset, err) return } self.Tracks = append(self.Tracks, atom) @@ -2703,8 +2706,8 @@ func (self *MovieFrag) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -2754,23 +2757,23 @@ func (self MovieFragHeader) Len() (n int) { n += 4 return } -func (self *MovieFragHeader) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *MovieFragHeader) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+4 { - err = parseErr("Seqnum", n+offset, err) + err = parseErr("Seqnum", int64(n)+offset, err) return } self.Seqnum = pio.U32BE(b[n:]) @@ -2826,22 +2829,22 @@ func (self TrackFrag) Len() (n int) { } return } -func (self *TrackFrag) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *TrackFrag) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case TFHD: { atom := &TrackFragHeader{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("tfhd", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("tfhd", int64(n)+offset, err) return } self.Header = atom @@ -2849,8 +2852,8 @@ func (self *TrackFrag) Unmarshal(b []byte, offset int) (n int, err error) { case TFDT: { atom := &TrackFragDecodeTime{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("tfdt", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("tfdt", int64(n)+offset, err) return } self.DecodeTime = atom @@ -2858,8 +2861,8 @@ func (self *TrackFrag) Unmarshal(b []byte, offset int) (n int, err error) { case TRUN: { atom := &TrackFragRun{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("trun", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("trun", int64(n)+offset, err) return } self.Run = atom @@ -2867,8 +2870,8 @@ func (self *TrackFrag) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -2923,22 +2926,22 @@ func (self MovieExtend) Len() (n int) { } return } -func (self *MovieExtend) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *MovieExtend) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 for n+8 < len(b) { tag := Tag(pio.U32BE(b[n+4:])) size := int(pio.U32BE(b[n:])) if len(b) < n+size { - err = parseErr("TagSizeInvalid", n+offset, err) + err = parseErr("TagSizeInvalid", int64(n)+offset, err) return } switch tag { case TREX: { atom := &TrackExtend{} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("trex", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("trex", int64(n)+offset, err) return } self.Tracks = append(self.Tracks, atom) @@ -2946,8 +2949,8 @@ func (self *MovieExtend) Unmarshal(b []byte, offset int) (n int, err error) { default: { atom := &Dummy{Tag_: tag, Data: b[n : n+size]} - if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { - err = parseErr("", n+offset, err) + if _, err = atom.Unmarshal(b[n:n+size], offset+int64(n)); err != nil { + err = parseErr("", int64(n)+offset, err) return } self.Unknowns = append(self.Unknowns, atom) @@ -3010,47 +3013,47 @@ func (self TrackExtend) Len() (n int) { n += 4 return } -func (self *TrackExtend) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *TrackExtend) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+4 { - err = parseErr("TrackId", n+offset, err) + err = parseErr("TrackId", int64(n)+offset, err) return } self.TrackId = pio.U32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("DefaultSampleDescIdx", n+offset, err) + err = parseErr("DefaultSampleDescIdx", int64(n)+offset, err) return } self.DefaultSampleDescIdx = pio.U32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("DefaultSampleDuration", n+offset, err) + err = parseErr("DefaultSampleDuration", int64(n)+offset, err) return } self.DefaultSampleDuration = pio.U32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("DefaultSampleSize", n+offset, err) + err = parseErr("DefaultSampleSize", int64(n)+offset, err) return } self.DefaultSampleSize = pio.U32BE(b[n:]) n += 4 if len(b) < n+4 { - err = parseErr("DefaultSampleFlags", n+offset, err) + err = parseErr("DefaultSampleFlags", int64(n)+offset, err) return } self.DefaultSampleFlags = pio.U32BE(b[n:]) @@ -3105,23 +3108,23 @@ func (self SampleSize) Len() (n int) { n += 4 * len(self.Entries) return } -func (self *SampleSize) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *SampleSize) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) n += 3 if len(b) < n+4 { - err = parseErr("SampleSize", n+offset, err) + err = parseErr("SampleSize", int64(n)+offset, err) return } self.SampleSize = pio.U32BE(b[n:]) @@ -3134,7 +3137,7 @@ func (self *SampleSize) Unmarshal(b []byte, offset int) (n int, err error) { n += 4 self.Entries = make([]uint32, _len_Entries) if len(b) < n+4*len(self.Entries) { - err = parseErr("uint32", n+offset, err) + err = parseErr("uint32", int64(n)+offset, err) return } for i := range self.Entries { @@ -3246,17 +3249,17 @@ func (self TrackFragRun) Len() (n int) { } return } -func (self *TrackFragRun) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *TrackFragRun) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -3268,7 +3271,7 @@ func (self *TrackFragRun) Unmarshal(b []byte, offset int) (n int, err error) { if self.Flags&TRUN_DATA_OFFSET != 0 { { if len(b) < n+4 { - err = parseErr("DataOffset", n+offset, err) + err = parseErr("DataOffset", int64(n)+offset, err) return } self.DataOffset = pio.U32BE(b[n:]) @@ -3278,7 +3281,7 @@ func (self *TrackFragRun) Unmarshal(b []byte, offset int) (n int, err error) { if self.Flags&TRUN_FIRST_SAMPLE_FLAGS != 0 { { if len(b) < n+4 { - err = parseErr("FirstSampleFlags", n+offset, err) + err = parseErr("FirstSampleFlags", int64(n)+offset, err) return } self.FirstSampleFlags = pio.U32BE(b[n:]) @@ -3425,17 +3428,17 @@ func (self TrackFragHeader) Len() (n int) { } return } -func (self *TrackFragHeader) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *TrackFragHeader) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) @@ -3443,7 +3446,7 @@ func (self *TrackFragHeader) Unmarshal(b []byte, offset int) (n int, err error) if self.Flags&TFHD_BASE_DATA_OFFSET != 0 { { if len(b) < n+8 { - err = parseErr("BaseDataOffset", n+offset, err) + err = parseErr("BaseDataOffset", int64(n)+offset, err) return } self.BaseDataOffset = pio.U64BE(b[n:]) @@ -3453,7 +3456,7 @@ func (self *TrackFragHeader) Unmarshal(b []byte, offset int) (n int, err error) if self.Flags&TFHD_STSD_ID != 0 { { if len(b) < n+4 { - err = parseErr("StsdId", n+offset, err) + err = parseErr("StsdId", int64(n)+offset, err) return } self.StsdId = pio.U32BE(b[n:]) @@ -3463,7 +3466,7 @@ func (self *TrackFragHeader) Unmarshal(b []byte, offset int) (n int, err error) if self.Flags&TFHD_DEFAULT_DURATION != 0 { { if len(b) < n+4 { - err = parseErr("DefaultDuration", n+offset, err) + err = parseErr("DefaultDuration", int64(n)+offset, err) return } self.DefaultDuration = pio.U32BE(b[n:]) @@ -3473,7 +3476,7 @@ func (self *TrackFragHeader) Unmarshal(b []byte, offset int) (n int, err error) if self.Flags&TFHD_DEFAULT_SIZE != 0 { { if len(b) < n+4 { - err = parseErr("DefaultSize", n+offset, err) + err = parseErr("DefaultSize", int64(n)+offset, err) return } self.DefaultSize = pio.U32BE(b[n:]) @@ -3483,7 +3486,7 @@ func (self *TrackFragHeader) Unmarshal(b []byte, offset int) (n int, err error) if self.Flags&TFHD_DEFAULT_FLAGS != 0 { { if len(b) < n+4 { - err = parseErr("DefaultFlags", n+offset, err) + err = parseErr("DefaultFlags", int64(n)+offset, err) return } self.DefaultFlags = pio.U32BE(b[n:]) @@ -3536,17 +3539,17 @@ func (self TrackFragDecodeTime) Len() (n int) { } return } -func (self *TrackFragDecodeTime) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *TrackFragDecodeTime) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) n += 8 if len(b) < n+1 { - err = parseErr("Version", n+offset, err) + err = parseErr("Version", int64(n)+offset, err) return } self.Version = pio.U8(b[n:]) n += 1 if len(b) < n+3 { - err = parseErr("Flags", n+offset, err) + err = parseErr("Flags", int64(n)+offset, err) return } self.Flags = pio.U24BE(b[n:]) diff --git a/format/mp4/mp4io/mp4io.go b/format/mp4/mp4io/mp4io.go index 0227a843..0e0e08d0 100644 --- a/format/mp4/mp4io/mp4io.go +++ b/format/mp4/mp4io/mp4io.go @@ -1,20 +1,20 @@ - package mp4io import ( - "github.com/nareix/joy4/utils/bits/pio" - "os" - "io" "fmt" - "time" + "io" "math" + "os" "strings" + "time" + + "github.com/nareix/joy4/utils/bits/pio" ) type ParseError struct { - Debug string - Offset int - prev *ParseError + Debug string + Offset int64 + prev *ParseError } func (self *ParseError) Error() string { @@ -22,10 +22,10 @@ func (self *ParseError) Error() string { for p := self; p != nil; p = p.prev { s = append(s, fmt.Sprintf("%s:%d", p.Debug, p.Offset)) } - return "mp4io: parse error: "+strings.Join(s, ",") + return "mp4io: parse error: " + strings.Join(s, ",") } -func parseErr(debug string, offset int, prev error) (err error) { +func parseErr(debug string, offset int64, prev error) (err error) { _prev, _ := prev.(*ParseError) return &ParseError{Debug: debug, Offset: offset, prev: _prev} } @@ -33,37 +33,37 @@ func parseErr(debug string, offset int, prev error) (err error) { func GetTime32(b []byte) (t time.Time) { sec := pio.U32BE(b) t = time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC) - t = t.Add(time.Second*time.Duration(sec)) + t = t.Add(time.Second * time.Duration(sec)) return } func PutTime32(b []byte, t time.Time) { dur := t.Sub(time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC)) - sec := uint32(dur/time.Second) + sec := uint32(dur / time.Second) pio.PutU32BE(b, sec) } func GetTime64(b []byte) (t time.Time) { sec := pio.U64BE(b) t = time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC) - t = t.Add(time.Second*time.Duration(sec)) + t = t.Add(time.Second * time.Duration(sec)) return } func PutTime64(b []byte, t time.Time) { dur := t.Sub(time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC)) - sec := uint64(dur/time.Second) + sec := uint64(dur / time.Second) pio.PutU64BE(b, sec) } func PutFixed16(b []byte, f float64) { intpart, fracpart := math.Modf(f) b[0] = uint8(intpart) - b[1] = uint8(fracpart*256.0) + b[1] = uint8(fracpart * 256.0) } func GetFixed16(b []byte) float64 { - return float64(b[0])+float64(b[1])/256.0 + return float64(b[0]) + float64(b[1])/256.0 } func PutFixed32(b []byte, f float64) { @@ -73,7 +73,7 @@ func PutFixed32(b []byte, f float64) { } func GetFixed32(b []byte) float64 { - return float64(pio.U16BE(b[0:2]))+float64(pio.U16BE(b[2:4]))/65536.0 + return float64(pio.U16BE(b[0:2])) + float64(pio.U16BE(b[2:4]))/65536.0 } type Tag uint32 @@ -89,26 +89,26 @@ func (self Tag) String() string { return string(b[:]) } -type Atom interface{ - Pos() (int,int) +type Atom interface { + Pos() (int64, int64) Tag() Tag Marshal([]byte) int - Unmarshal([]byte, int) (int,error) + Unmarshal([]byte, int64) (int, error) Len() int Children() []Atom } type AtomPos struct { - Offset int - Size int + Offset int64 + Size int64 } -func (self AtomPos) Pos() (int,int) { +func (self AtomPos) Pos() (int64, int64) { return self.Offset, self.Size } -func (self *AtomPos) setPos(offset int, size int) { - self.Offset, self.Size = offset, size +func (self *AtomPos) setPos(offset int64, size int) { + self.Offset, self.Size = offset, int64(size) } type Dummy struct { @@ -134,7 +134,7 @@ func (self Dummy) Marshal(b []byte) int { return len(self.Data) } -func (self *Dummy) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *Dummy) Unmarshal(b []byte, offset int64) (n int, err error) { (&self.AtomPos).setPos(offset, len(b)) self.Data = b n = len(b) @@ -190,7 +190,7 @@ const ( type ElemStreamDesc struct { DecConfig []byte - TrackId uint16 + TrackId uint16 AtomPos } @@ -200,10 +200,10 @@ func (self ElemStreamDesc) Children() []Atom { func (self ElemStreamDesc) fillLength(b []byte, length int) (n int) { for i := 3; i > 0; i-- { - b[n] = uint8(length>>uint(7*i))&0x7f|0x80 + b[n] = uint8(length>>uint(7*i))&0x7f | 0x80 n++ } - b[n] = uint8(length&0x7f) + b[n] = uint8(length & 0x7f) n++ return } @@ -220,7 +220,7 @@ func (self ElemStreamDesc) fillDescHdr(b []byte, tag uint8, datalen int) (n int) } func (self ElemStreamDesc) lenESDescHdr() (n int) { - return self.lenDescHdr()+3 + return self.lenDescHdr() + 3 } func (self ElemStreamDesc) fillESDescHdr(b []byte, datalen int) (n int) { @@ -233,7 +233,7 @@ func (self ElemStreamDesc) fillESDescHdr(b []byte, datalen int) (n int) { } func (self ElemStreamDesc) lenDecConfigDescHdr() (n int) { - return self.lenDescHdr()+2+3+4+4+self.lenDescHdr() + return self.lenDescHdr() + 2 + 3 + 4 + 4 + self.lenDescHdr() } func (self ElemStreamDesc) fillDecConfigDescHdr(b []byte, datalen int) (n int) { @@ -256,7 +256,7 @@ func (self ElemStreamDesc) fillDecConfigDescHdr(b []byte, datalen int) (n int) { } func (self ElemStreamDesc) Len() (n int) { - return 8+4+self.lenESDescHdr()+self.lenDecConfigDescHdr()+len(self.DecConfig)+self.lenDescHdr()+1 + return 8 + 4 + self.lenESDescHdr() + self.lenDecConfigDescHdr() + len(self.DecConfig) + self.lenDescHdr() + 1 } // Version(4) @@ -292,18 +292,18 @@ func (self ElemStreamDesc) Marshal(b []byte) (n int) { return } -func (self *ElemStreamDesc) Unmarshal(b []byte, offset int) (n int, err error) { +func (self *ElemStreamDesc) Unmarshal(b []byte, offset int64) (n int, err error) { if len(b) < n+12 { - err = parseErr("hdr", offset+n, err) + err = parseErr("hdr", offset+int64(n), err) return } (&self.AtomPos).setPos(offset, len(b)) n += 8 n += 4 - return self.parseDesc(b[n:], offset+n) + return self.parseDesc(b[n:], offset+int64(n)) } -func (self *ElemStreamDesc) parseDesc(b []byte, offset int) (n int, err error) { +func (self *ElemStreamDesc) parseDesc(b []byte, offset int64) (n int, err error) { var hdrlen int var datalen int var tag uint8 @@ -313,27 +313,27 @@ func (self *ElemStreamDesc) parseDesc(b []byte, offset int) (n int, err error) { n += hdrlen if len(b) < n+datalen { - err = parseErr("datalen", offset+n, err) + err = parseErr("datalen", offset+int64(n), err) return } switch tag { case MP4ESDescrTag: if len(b) < n+3 { - err = parseErr("MP4ESDescrTag", offset+n, err) + err = parseErr("MP4ESDescrTag", offset+int64(n), err) return } - if _, err = self.parseDesc(b[n+3:], offset+n+3); err != nil { + if _, err = self.parseDesc(b[n+3:], offset+int64(n+3)); err != nil { return } case MP4DecConfigDescrTag: - const size = 2+3+4+4 + const size = 2 + 3 + 4 + 4 if len(b) < n+size { - err = parseErr("MP4DecSpecificDescrTag", offset+n, err) + err = parseErr("MP4DecSpecificDescrTag", offset+int64(n), err) return } - if _, err = self.parseDesc(b[n+size:], offset+n+size); err != nil { + if _, err = self.parseDesc(b[n+size:], offset+int64(n+size)); err != nil { return } @@ -345,15 +345,15 @@ func (self *ElemStreamDesc) parseDesc(b []byte, offset int) (n int, err error) { return } -func (self *ElemStreamDesc) parseLength(b []byte, offset int) (n int, length int, err error) { +func (self *ElemStreamDesc) parseLength(b []byte, offset int64) (n int, length int, err error) { for n < 4 { if len(b) < n+1 { - err = parseErr("len", offset+n, err) + err = parseErr("len", offset+int64(n), err) return } c := b[n] n++ - length = (length<<7)|(int(c)&0x7f) + length = (length << 7) | (int(c) & 0x7f) if c&0x80 == 0 { break } @@ -361,15 +361,15 @@ func (self *ElemStreamDesc) parseLength(b []byte, offset int) (n int, length int return } -func (self *ElemStreamDesc) parseDescHdr(b []byte, offset int) (n int, tag uint8, datalen int, err error) { +func (self *ElemStreamDesc) parseDescHdr(b []byte, offset int64) (n int, tag uint8, datalen int, err error) { if len(b) < n+1 { - err = parseErr("tag", offset+n, err) + err = parseErr("tag", offset+int64(n), err) return } tag = b[n] n++ var lenlen int - if lenlen, datalen, err = self.parseLength(b[n:], offset+n); err != nil { + if lenlen, datalen, err = self.parseLength(b[n:], offset+int64(n)); err != nil { return } n += lenlen @@ -378,7 +378,7 @@ func (self *ElemStreamDesc) parseDescHdr(b []byte, offset int) (n int, tag uint8 func ReadFileAtoms(r io.ReadSeeker) (atoms []Atom, err error) { for { - offset, _ := r.Seek(0, 1) + offset, _ := r.Seek(0, io.SeekCurrent) taghdr := make([]byte, 8) if _, err = io.ReadFull(r, taghdr); err != nil { if err == io.EOF { @@ -386,8 +386,18 @@ func ReadFileAtoms(r io.ReadSeeker) (atoms []Atom, err error) { } return } - size := pio.U32BE(taghdr[0:]) + size := int64(pio.U32BE(taghdr[0:])) tag := Tag(pio.U32BE(taghdr[4:])) + headerSize := 8 + + if size == 1 { // wide atom + var extendedSize [8]byte + if _, err = io.ReadFull(r, extendedSize[:]); err != nil { + return + } + size = pio.I64BE(extendedSize[:]) + headerSize += 8 + } var atom Atom switch tag { @@ -398,19 +408,22 @@ func ReadFileAtoms(r io.ReadSeeker) (atoms []Atom, err error) { } if atom != nil { + if headerSize > 8 { + err = fmt.Errorf("extended size not supported for atom '%s'", tag) + } b := make([]byte, int(size)) if _, err = io.ReadFull(r, b[8:]); err != nil { return } copy(b, taghdr) - if _, err = atom.Unmarshal(b, int(offset)); err != nil { + if _, err = atom.Unmarshal(b, offset); err != nil { return } atoms = append(atoms, atom) } else { dummy := &Dummy{Tag_: tag} - dummy.setPos(int(offset), int(size)) - if _, err = r.Seek(int64(size)-8, 1); err != nil { + dummy.Offset, dummy.Size = offset, size + if _, err = r.Seek(size-int64(headerSize), io.SeekCurrent); err != nil { return } atoms = append(atoms, dummy) @@ -500,4 +513,3 @@ func (self *Track) GetElemStreamDesc() (esds *ElemStreamDesc) { esds, _ = atom.(*ElemStreamDesc) return } - From 01b7a1dec0562a3e6fbe84e73f1415812863d99c Mon Sep 17 00:00:00 2001 From: Ilya Hrankouski Date: Mon, 6 Sep 2021 18:26:36 +0000 Subject: [PATCH 4/4] TLS config for RTMP server --- format/rtmp/rtmp.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/format/rtmp/rtmp.go b/format/rtmp/rtmp.go index 212ee06c..c934edea 100644 --- a/format/rtmp/rtmp.go +++ b/format/rtmp/rtmp.go @@ -6,18 +6,20 @@ import ( "crypto/hmac" "crypto/rand" "crypto/sha256" + "crypto/tls" "encoding/hex" "fmt" - "github.com/nareix/joy4/utils/bits/pio" - "github.com/nareix/joy4/av" - "github.com/nareix/joy4/av/avutil" - "github.com/nareix/joy4/format/flv" - "github.com/nareix/joy4/format/flv/flvio" "io" "net" "net/url" "strings" "time" + + "github.com/nareix/joy4/av" + "github.com/nareix/joy4/av/avutil" + "github.com/nareix/joy4/format/flv" + "github.com/nareix/joy4/format/flv/flvio" + "github.com/nareix/joy4/utils/bits/pio" ) var Debug bool @@ -58,6 +60,7 @@ type Server struct { HandlePublish func(*Conn) HandlePlay func(*Conn) HandleConn func(*Conn) + TLSConfig *tls.Config } func (self *Server) handleConn(conn *Conn) (err error) { @@ -93,11 +96,15 @@ func (self *Server) ListenAndServe() (err error) { return } - var listener *net.TCPListener + var listener net.Listener if listener, err = net.ListenTCP("tcp", tcpaddr); err != nil { return } + if self.TLSConfig != nil { + listener = tls.NewListener(listener, self.TLSConfig) + } + if Debug { fmt.Println("rtmp: server: listening on", addr) }