Read/Write AVCDecoderConfRecord

This commit is contained in:
nareix 2015-11-24 16:25:40 +08:00
parent 3f60565c66
commit 2ba72a94e8
4 changed files with 117 additions and 41 deletions

View File

@ -220,7 +220,7 @@ var atoms = {
avc1Conf: { avc1Conf: {
cc4: 'avcC', cc4: 'avcC',
fields: [ fields: [
['data', '[]byte'], ['record', 'AVCDecoderConfRecord'],
], ],
}, },

View File

@ -2,52 +2,125 @@
package atom package atom
import ( import (
_"io" "io"
_"bytes" "fmt"
_"log"
_"encoding/hex"
) )
/* type AVCDecoderConfRecord struct {
type VideoSampleDesc struct { AVCProfileIndication int
VideoSampleDescHeader ProfileCompatibility int
AVCDecoderConf []byte AVCLevelIndication int
LengthSizeMinusOne int
SeqenceParamSet [][]byte
PictureParamSet [][]byte
} }
func ReadVideoSampleDesc(r *io.LimitedReader) (res *VideoSampleDesc, err error) { func CreateAVCDecoderConfRecord(
self := &VideoSampleDesc{} 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 return
} }
for r.N > 0 { if err = WriteInt(w, len(self.SeqenceParamSet) | 0xe0, 1); err != nil {
var cc4 string return
var ar *io.LimitedReader }
if ar, cc4, err = ReadAtomHeader(r, ""); err != nil { for _, data := range self.SeqenceParamSet {
if err = WriteInt(w, len(data), 2); err != nil {
return return
} }
if err = WriteBytes(w, data, len(data)); err != nil {
if false { return
log.Println("VideoSampleDesc:", cc4, ar.N) }
//log.Println("VideoSampleDesc:", "avcC", len(self.AVCDecoderConf)) }
}
if err = WriteInt(w, len(self.PictureParamSet), 1); err != nil {
switch cc4 { return
case "avcC": { }
if self.AVCDecoderConf, err = ReadBytes(ar, int(ar.N)); err != nil { for _, data := range self.PictureParamSet {
return if err = WriteInt(w, len(data), 2); err != nil {
} return
} }
} if err = WriteBytes(w, data, len(data)); err != nil {
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
return return
} }
} }
res = self
return 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
}

View File

@ -1292,13 +1292,13 @@ func WriteAvc1Desc(w io.WriteSeeker, self *Avc1Desc) (err error) {
} }
type Avc1Conf struct { type Avc1Conf struct {
Data []byte Record AVCDecoderConfRecord
} }
func ReadAvc1Conf(r *io.LimitedReader) (res *Avc1Conf, err error) { func ReadAvc1Conf(r *io.LimitedReader) (res *Avc1Conf, err error) {
self := &Avc1Conf{} self := &Avc1Conf{}
if self.Data, err = ReadBytes(r, int(r.N)); err != nil { if self.Record, err = ReadAVCDecoderConfRecord(r); err != nil {
return return
} }
res = self res = self
@ -1311,7 +1311,7 @@ func WriteAvc1Conf(w io.WriteSeeker, self *Avc1Conf) (err error) {
return return
} }
w = aw w = aw
if err = WriteBytes(w, self.Data, len(self.Data)); err != nil { if err = WriteAVCDecoderConfRecord(w, self.Record); err != nil {
return return
} }
if err = aw.Close(); err != nil { if err = aw.Close(); err != nil {

13
mp4.go
View File

@ -106,8 +106,10 @@ func changeMoov(moov *atom.Movie) {
if avc1Desc := desc.Avc1Desc; avc1Desc != nil { if avc1Desc := desc.Avc1Desc; avc1Desc != nil {
if conf := avc1Desc.Conf; conf != nil { if conf := avc1Desc.Conf; conf != nil {
if true { if true {
log.Println("avc1", hex.Dump(conf.Data)) //log.Println("avc1", hex.Dump(conf.Data))
log.Println("avc1desc", avc1Desc) 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) sampleCh := make(chan Sample)
go readSamples(vsample, mdat, sampleCh) go readSamples(vsample, mdat, sampleCh)
log.Println("avc1Desc.conf", vsample.SampleDesc.Avc1Desc.Conf)
newsample := &atom.SampleTable{ newsample := &atom.SampleTable{
SampleDesc: &atom.SampleDesc{ SampleDesc: &atom.SampleDesc{
Avc1Desc: &atom.Avc1Desc{ Avc1Desc: &atom.Avc1Desc{
@ -311,8 +315,8 @@ func rewrite(moov *atom.Movie, mdat io.ReadSeeker, outfile io.WriteSeeker) (err
Duration: vtrack.Header.Duration, Duration: vtrack.Header.Duration,
Volume: vtrack.Header.Volume, Volume: vtrack.Header.Volume,
Matrix: [9]int{0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000}, Matrix: [9]int{0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000},
TrackWidth: vtrack.Header.TrackWidth, //TrackWidth: vtrack.Header.TrackWidth,
TrackHeight: vtrack.Header.TrackHeight, //TrackHeight: vtrack.Header.TrackHeight,
TrackId: 1, TrackId: 1,
}, },
@ -401,7 +405,6 @@ func TestRewrite(filename string) (file *File, err error) {
return return
} }
func TestConvert(filename string) (file *File, err error) { func TestConvert(filename string) (file *File, err error) {
var osfile *os.File var osfile *os.File
if osfile, err = os.Open(filename); err != nil { if osfile, err = os.Open(filename); err != nil {