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: {
cc4: 'avcC',
fields: [
['data', '[]byte'],
['record', 'AVCDecoderConfRecord'],
],
},

View File

@ -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
}

View File

@ -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 {

13
mp4.go
View File

@ -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 {