diff --git a/atom/genStruct.js b/atom/genStruct.js index 99628f8..b8abe8e 100644 --- a/atom/genStruct.js +++ b/atom/genStruct.js @@ -220,7 +220,7 @@ var atoms = { avc1Conf: { cc4: 'avcC', fields: [ - ['data', '[]byte'], + ['record', 'AVCDecoderConfRecord'], ], }, diff --git a/atom/otherStruct.go b/atom/otherStruct.go index ba68d30..d384b42 100644 --- a/atom/otherStruct.go +++ b/atom/otherStruct.go @@ -2,52 +2,125 @@ package atom import ( - _"io" - _"bytes" - _"log" - _"encoding/hex" + "io" + "fmt" ) -/* -type VideoSampleDesc struct { - VideoSampleDescHeader - AVCDecoderConf []byte +type AVCDecoderConfRecord struct { + AVCProfileIndication int + ProfileCompatibility int + AVCLevelIndication int + LengthSizeMinusOne int + SeqenceParamSet [][]byte + PictureParamSet [][]byte } -func ReadVideoSampleDesc(r *io.LimitedReader) (res *VideoSampleDesc, err error) { - self := &VideoSampleDesc{} +func CreateAVCDecoderConfRecord( + SeqenceParamSet []byte, + PictureParamSet []byte, +) (self AVCDecoderConfRecord, err error) { + if len(SeqenceParamSet) < 4 { + err = fmt.Errorf("invalid SeqenceParamSet") + return + } + self.AVCProfileIndication = int(SeqenceParamSet[1]) + self.AVCLevelIndication = int(SeqenceParamSet[3]) + self.LengthSizeMinusOne = 3 + return +} - if self.VideoSampleDescHeader, err = ReadVideoSampleDescHeader(r); err != nil { +func WriteAVCDecoderConfRecord(w io.Writer, self AVCDecoderConfRecord) (err error) { + if err = WriteInt(w, 1, 1); err != nil { + return + } + if err = WriteInt(w, self.AVCProfileIndication, 1); err != nil { + return + } + if err = WriteInt(w, self.ProfileCompatibility, 1); err != nil { + return + } + if err = WriteInt(w, self.AVCLevelIndication, 1); err != nil { + return + } + if err = WriteInt(w, self.LengthSizeMinusOne | 0xfc, 1); err != nil { return } - for r.N > 0 { - var cc4 string - var ar *io.LimitedReader - if ar, cc4, err = ReadAtomHeader(r, ""); err != nil { + if err = WriteInt(w, len(self.SeqenceParamSet) | 0xe0, 1); err != nil { + return + } + for _, data := range self.SeqenceParamSet { + if err = WriteInt(w, len(data), 2); err != nil { return } - - if false { - log.Println("VideoSampleDesc:", cc4, ar.N) - //log.Println("VideoSampleDesc:", "avcC", len(self.AVCDecoderConf)) - } - - switch cc4 { - case "avcC": { - if self.AVCDecoderConf, err = ReadBytes(ar, int(ar.N)); err != nil { - return - } - } - } - - if _, err = ReadDummy(ar, int(ar.N)); err != nil { + if err = WriteBytes(w, data, len(data)); err != nil { + return + } + } + + if err = WriteInt(w, len(self.PictureParamSet), 1); err != nil { + return + } + for _, data := range self.PictureParamSet { + if err = WriteInt(w, len(data), 2); err != nil { + return + } + if err = WriteBytes(w, data, len(data)); err != nil { return } } - res = self return } -*/ + +func ReadAVCDecoderConfRecord(r *io.LimitedReader) (self AVCDecoderConfRecord, err error) { + if _, err = ReadDummy(r, 1); err != nil { + return + } + if self.AVCProfileIndication, err = ReadInt(r, 1); err != nil { + return + } + if self.ProfileCompatibility, err = ReadInt(r, 1); err != nil { + return + } + if self.AVCLevelIndication, err = ReadInt(r, 1); err != nil { + return + } + if self.LengthSizeMinusOne, err = ReadInt(r, 1); err != nil { + return + } + self.LengthSizeMinusOne &= 0x03 + + var n, length int + var data []byte + + if n, err = ReadInt(r, 1); err != nil { + return + } + n &= 0x1f + for i := 0; i < n; i++ { + if length, err = ReadInt(r, 2); err != nil { + return + } + if data, err = ReadBytes(r, length); err != nil { + return + } + self.SeqenceParamSet = append(self.SeqenceParamSet, data) + } + + if n, err = ReadInt(r, 1); err != nil { + return + } + for i := 0; i < n; i++ { + if length, err = ReadInt(r, 2); err != nil { + return + } + if data, err = ReadBytes(r, length); err != nil { + return + } + self.PictureParamSet = append(self.PictureParamSet, data) + } + + return +} diff --git a/atom/struct.go b/atom/struct.go index 8eb422f..6606be2 100644 --- a/atom/struct.go +++ b/atom/struct.go @@ -1292,13 +1292,13 @@ func WriteAvc1Desc(w io.WriteSeeker, self *Avc1Desc) (err error) { } type Avc1Conf struct { - Data []byte + Record AVCDecoderConfRecord } func ReadAvc1Conf(r *io.LimitedReader) (res *Avc1Conf, err error) { self := &Avc1Conf{} - if self.Data, err = ReadBytes(r, int(r.N)); err != nil { + if self.Record, err = ReadAVCDecoderConfRecord(r); err != nil { return } res = self @@ -1311,7 +1311,7 @@ func WriteAvc1Conf(w io.WriteSeeker, self *Avc1Conf) (err error) { return } w = aw - if err = WriteBytes(w, self.Data, len(self.Data)); err != nil { + if err = WriteAVCDecoderConfRecord(w, self.Record); err != nil { return } if err = aw.Close(); err != nil { diff --git a/mp4.go b/mp4.go index bf9e258..723f798 100644 --- a/mp4.go +++ b/mp4.go @@ -106,8 +106,10 @@ func changeMoov(moov *atom.Movie) { if avc1Desc := desc.Avc1Desc; avc1Desc != nil { if conf := avc1Desc.Conf; conf != nil { if true { - log.Println("avc1", hex.Dump(conf.Data)) - log.Println("avc1desc", avc1Desc) + //log.Println("avc1", hex.Dump(conf.Data)) + log.Println("avc1desc", conf) + //avcconf, _ := atom.ReadAVCDecoderConfRecord(bytes.NewReader(conf.Data)) + //log.Println("avcconf", avcconf) } } } @@ -225,6 +227,8 @@ func rewrite(moov *atom.Movie, mdat io.ReadSeeker, outfile io.WriteSeeker) (err sampleCh := make(chan Sample) go readSamples(vsample, mdat, sampleCh) + log.Println("avc1Desc.conf", vsample.SampleDesc.Avc1Desc.Conf) + newsample := &atom.SampleTable{ SampleDesc: &atom.SampleDesc{ Avc1Desc: &atom.Avc1Desc{ @@ -311,8 +315,8 @@ func rewrite(moov *atom.Movie, mdat io.ReadSeeker, outfile io.WriteSeeker) (err Duration: vtrack.Header.Duration, Volume: vtrack.Header.Volume, Matrix: [9]int{0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000}, - TrackWidth: vtrack.Header.TrackWidth, - TrackHeight: vtrack.Header.TrackHeight, + //TrackWidth: vtrack.Header.TrackWidth, + //TrackHeight: vtrack.Header.TrackHeight, TrackId: 1, }, @@ -401,7 +405,6 @@ func TestRewrite(filename string) (file *File, err error) { return } - func TestConvert(filename string) (file *File, err error) { var osfile *os.File if osfile, err = os.Open(filename); err != nil {