From 6536e6f784362e8b03899a3a524b30f0e7617ff7 Mon Sep 17 00:00:00 2001 From: nareix Date: Sun, 3 Jul 2016 22:46:28 +0800 Subject: [PATCH] aacparser: adjust func ParseADTSHeader FillADTSHeader --- codec/aacparser/parser.go | 71 +++++++++++++++------------------------ format/rtsp/client.go | 12 +++++-- format/ts/demuxer.go | 28 +++++++-------- format/ts/muxer.go | 9 ++--- 4 files changed, 55 insertions(+), 65 deletions(-) diff --git a/codec/aacparser/parser.go b/codec/aacparser/parser.go index db3c5d3..79724b4 100644 --- a/codec/aacparser/parser.go +++ b/codec/aacparser/parser.go @@ -91,36 +91,40 @@ var chanConfigTable = []av.ChannelLayout{ av.CH_FRONT_CENTER|av.CH_FRONT_LEFT|av.CH_FRONT_RIGHT|av.CH_SIDE_LEFT|av.CH_SIDE_RIGHT|av.CH_BACK_LEFT|av.CH_BACK_RIGHT|av.CH_LOW_FREQ, } -func IsADTSFrame(frames []byte) bool { - return len(frames) > 7 && frames[0] == 0xff && frames[1]&0xf0 == 0xf0 -} - -func ReadADTSFrame(frame []byte) (config MPEG4AudioConfig, payload []byte, samples int, framelen int, err error) { - if !IsADTSFrame(frame) { - err = fmt.Errorf("not adts frame") +func ParseADTSHeader(frame []byte) (config MPEG4AudioConfig, hdrlen int, framelen int, samples int, err error) { + if frame[0] != 0xff || frame[1]&0xf6 != 0xf0 { + err = fmt.Errorf("not adts header") return } config.ObjectType = uint(frame[2]>>6) + 1 config.SampleRateIndex = uint(frame[2] >> 2 & 0xf) config.ChannelConfig = uint(frame[2]<<2&0x4 | frame[3]>>6&0x3) + config = config.Complete() framelen = int(frame[3]&0x3)<<11 | int(frame[4])<<3 | int(frame[5]>>5) samples = (int(frame[6]&0x3) + 1) * 1024 - hdrlen := 7 + hdrlen = 7 if frame[1]&0x1 == 0 { hdrlen = 9 } - if framelen < hdrlen || len(frame) < framelen { - err = fmt.Errorf("invalid adts header length") + if framelen < hdrlen { + err = fmt.Errorf("adts framelen < hdrlen") return } - payload = frame[hdrlen:framelen] return } -func MakeADTSHeader(config MPEG4AudioConfig, samples int, payloadLength int) (header []byte) { +const ADTSHeaderLength = 7 + +func FillADTSHeader(header []byte, config MPEG4AudioConfig, samples int, payloadLength int) { payloadLength += 7 //AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP (QQQQQQQQ QQQQQQQQ) - header = []byte{0xff, 0xf1, 0x50, 0x80, 0x043, 0xff, 0xcd} + header[0] = 0xff + header[1] = 0xf1 + header[2] = 0x50 + header[3] = 0x80 + header[4] = 0x43 + header[5] = 0xff + header[6] = 0xcd //config.ObjectType = uint(frames[2]>>6)+1 //config.SampleRateIndex = uint(frames[2]>>2&0xf) //config.ChannelConfig = uint(frames[2]<<2&0x4|frames[3]>>6&0x3) @@ -133,20 +137,6 @@ func MakeADTSHeader(config MPEG4AudioConfig, samples int, payloadLength int) (he return } -func SplitADTSFrames(frames []byte) (config MPEG4AudioConfig, payload [][]byte, samples int, err error) { - for len(frames) > 0 { - var n, framelen int - var _payload []byte - if config, _payload, n, framelen, err = ReadADTSFrame(frames); err != nil { - return - } - payload = append(payload, _payload) - frames = frames[framelen:] - samples += n - } - return -} - func readObjectType(r *bits.Reader) (objectType uint, err error) { if objectType, err = r.ReadBits(5); err != nil { return @@ -209,8 +199,7 @@ func (self MPEG4AudioConfig) IsValid() bool { return self.ObjectType > 0 } -func (self MPEG4AudioConfig) Complete() (config MPEG4AudioConfig) { - config = self +func (self *MPEG4AudioConfig) Complete() (config MPEG4AudioConfig) { if int(config.SampleRateIndex) < len(sampleRateTable) { config.SampleRate = sampleRateTable[config.SampleRateIndex] } @@ -220,20 +209,10 @@ func (self MPEG4AudioConfig) Complete() (config MPEG4AudioConfig) { return } -func ParseMPEG4AudioConfig(data []byte) (config MPEG4AudioConfig, err error) { - r := bytes.NewReader(data) - if config, err = ReadMPEG4AudioConfig(r); err != nil { - err = fmt.Errorf("CodecData invalid: parse MPEG4AudioConfig failed(%s)", err) - return - } - config = config.Complete() - return -} - -func ReadMPEG4AudioConfig(r io.Reader) (config MPEG4AudioConfig, err error) { +func ParseMPEG4AudioConfigBytes(data []byte) (config MPEG4AudioConfig, err error) { // copied from libavcodec/mpeg4audio.c avpriv_mpeg4audio_get_config() + r := bytes.NewReader(data) br := &bits.Reader{R: r} - if config.ObjectType, err = readObjectType(br); err != nil { return } @@ -243,12 +222,12 @@ func ReadMPEG4AudioConfig(r io.Reader) (config MPEG4AudioConfig, err error) { if config.ChannelConfig, err = br.ReadBits(4); err != nil { return } + config = config.Complete() return } func WriteMPEG4AudioConfig(w io.Writer, config MPEG4AudioConfig) (err error) { bw := &bits.Writer{W: w} - if err = writeObjectType(bw, config.ObjectType); err != nil { return } @@ -311,9 +290,15 @@ func (self CodecData) PacketDuration(data []byte) (dur time.Duration, err error) return } +func NewCodecDataFromMPEG4AudioConfig(config MPEG4AudioConfig) (self CodecData, err error) { + b := &bytes.Buffer{} + WriteMPEG4AudioConfig(b, config) + return NewCodecDataFromMPEG4AudioConfigBytes(b.Bytes()) +} + func NewCodecDataFromMPEG4AudioConfigBytes(config []byte) (self CodecData, err error) { self.ConfigBytes = config - if self.Config, err = ParseMPEG4AudioConfig(config); err != nil { + if self.Config, err = ParseMPEG4AudioConfigBytes(config); err != nil { err = fmt.Errorf("parse MPEG4AudioConfig failed(%s)", err) return } diff --git a/format/rtsp/client.go b/format/rtsp/client.go index fa292ed..e6a0abc 100644 --- a/format/rtsp/client.go +++ b/format/rtsp/client.go @@ -1059,12 +1059,20 @@ func (self *Stream) handleRtpPacket(packet []byte) (err error) { } case av.AAC: - if len(payload) < 4 { + if len(payload) < 4+7 { err = fmt.Errorf("rtp: aac packet too short") return } + payload = payload[4:] // TODO: remove this hack + + var hdrlen, framelen int + if _, hdrlen, framelen, _, err = aacparser.ParseADTSHeader(payload); err != nil { + err = fmt.Errorf("rtsp: aac invalid: %s", err) + return + } + self.gotpkt = true - self.pkt.Data = payload[4+7:] // TODO: remove this hack + self.pkt.Data = payload[hdrlen:framelen] self.timestamp = timestamp default: diff --git a/format/ts/demuxer.go b/format/ts/demuxer.go index 9c1db17..869afad 100644 --- a/format/ts/demuxer.go +++ b/format/ts/demuxer.go @@ -171,30 +171,26 @@ func (self *Stream) payloadEnd() (err error) { switch self.streamType { case ElementaryStreamTypeAdtsAAC: var config aacparser.MPEG4AudioConfig - var packets [][]byte - var totsamples int - if config, packets, totsamples, err = aacparser.SplitADTSFrames(payload); err != nil { - err = fmt.Errorf("ts: demuxer: SplitADTSFrames failed: %s", err) + if config, _, _, _, err = aacparser.ParseADTSHeader(payload); err != nil { + err = fmt.Errorf("ts: aac invalid: %s", err) return } - config = config.Complete() if self.CodecData == nil { - bw := &bytes.Buffer{} - if err = aacparser.WriteMPEG4AudioConfig(bw, config); err != nil { - err = fmt.Errorf("WriteMPEG4AudioConfig failed: %s", err) - return - } - if self.CodecData, err = aacparser.NewCodecDataFromMPEG4AudioConfigBytes(bw.Bytes()); err != nil { + if self.CodecData, err = aacparser.NewCodecDataFromMPEG4AudioConfig(config); err != nil { return } } - frametime := time.Duration(totsamples / len(packets)) * time.Second / time.Duration(config.SampleRate) - timedelta := time.Duration(0) - for _, packet := range packets { - self.addPacket(packet, timedelta) - timedelta += frametime + delta := time.Duration(0) + for len(payload) > 0 { + var hdrlen, framelen, samples int + if _, hdrlen, framelen, samples, err = aacparser.ParseADTSHeader(payload); err != nil { + return + } + self.addPacket(payload[hdrlen:framelen], delta) + delta += time.Duration(samples) * time.Second / time.Duration(config.SampleRate) + payload = payload[:framelen] } case ElementaryStreamTypeH264: diff --git a/format/ts/muxer.go b/format/ts/muxer.go index 11cf77a..2bef01a 100644 --- a/format/ts/muxer.go +++ b/format/ts/muxer.go @@ -145,16 +145,17 @@ func (self *Muxer) writePacket(pkt av.Packet) (err error) { switch stream.Type() { case av.AAC: codec := stream.CodecData.(aacparser.CodecData) - data := pkt.Data - data = append(aacparser.MakeADTSHeader(codec.Config, 1024, len(data)), data...) + adtshdr := make([]byte, aacparser.ADTSHeaderLength) + aacparser.FillADTSHeader(adtshdr, codec.Config, 1024, len(pkt.Data)) buf := &bytes.Buffer{} pes := PESHeader{ StreamId: StreamIdAAC, PTS: timeToPesTs(pkt.Time), } - WritePESHeader(buf, pes, len(data)) - buf.Write(data) + WritePESHeader(buf, pes, len(pkt.Data)+len(adtshdr)) + buf.Write(adtshdr) + buf.Write(pkt.Data) stream.tsw.RandomAccessIndicator = true stream.tsw.PCR = timeToPCR(pkt.Time)