aacparser: adjust func ParseADTSHeader FillADTSHeader
This commit is contained in:
parent
929adb2829
commit
6536e6f784
@ -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,
|
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 {
|
func ParseADTSHeader(frame []byte) (config MPEG4AudioConfig, hdrlen int, framelen int, samples int, err error) {
|
||||||
return len(frames) > 7 && frames[0] == 0xff && frames[1]&0xf0 == 0xf0
|
if frame[0] != 0xff || frame[1]&0xf6 != 0xf0 {
|
||||||
}
|
err = fmt.Errorf("not adts header")
|
||||||
|
|
||||||
func ReadADTSFrame(frame []byte) (config MPEG4AudioConfig, payload []byte, samples int, framelen int, err error) {
|
|
||||||
if !IsADTSFrame(frame) {
|
|
||||||
err = fmt.Errorf("not adts frame")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
config.ObjectType = uint(frame[2]>>6) + 1
|
config.ObjectType = uint(frame[2]>>6) + 1
|
||||||
config.SampleRateIndex = uint(frame[2] >> 2 & 0xf)
|
config.SampleRateIndex = uint(frame[2] >> 2 & 0xf)
|
||||||
config.ChannelConfig = uint(frame[2]<<2&0x4 | frame[3]>>6&0x3)
|
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)
|
framelen = int(frame[3]&0x3)<<11 | int(frame[4])<<3 | int(frame[5]>>5)
|
||||||
samples = (int(frame[6]&0x3) + 1) * 1024
|
samples = (int(frame[6]&0x3) + 1) * 1024
|
||||||
hdrlen := 7
|
hdrlen = 7
|
||||||
if frame[1]&0x1 == 0 {
|
if frame[1]&0x1 == 0 {
|
||||||
hdrlen = 9
|
hdrlen = 9
|
||||||
}
|
}
|
||||||
if framelen < hdrlen || len(frame) < framelen {
|
if framelen < hdrlen {
|
||||||
err = fmt.Errorf("invalid adts header length")
|
err = fmt.Errorf("adts framelen < hdrlen")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
payload = frame[hdrlen:framelen]
|
|
||||||
return
|
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
|
payloadLength += 7
|
||||||
//AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP (QQQQQQQQ QQQQQQQQ)
|
//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.ObjectType = uint(frames[2]>>6)+1
|
||||||
//config.SampleRateIndex = uint(frames[2]>>2&0xf)
|
//config.SampleRateIndex = uint(frames[2]>>2&0xf)
|
||||||
//config.ChannelConfig = uint(frames[2]<<2&0x4|frames[3]>>6&0x3)
|
//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
|
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) {
|
func readObjectType(r *bits.Reader) (objectType uint, err error) {
|
||||||
if objectType, err = r.ReadBits(5); err != nil {
|
if objectType, err = r.ReadBits(5); err != nil {
|
||||||
return
|
return
|
||||||
@ -209,8 +199,7 @@ func (self MPEG4AudioConfig) IsValid() bool {
|
|||||||
return self.ObjectType > 0
|
return self.ObjectType > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self MPEG4AudioConfig) Complete() (config MPEG4AudioConfig) {
|
func (self *MPEG4AudioConfig) Complete() (config MPEG4AudioConfig) {
|
||||||
config = self
|
|
||||||
if int(config.SampleRateIndex) < len(sampleRateTable) {
|
if int(config.SampleRateIndex) < len(sampleRateTable) {
|
||||||
config.SampleRate = sampleRateTable[config.SampleRateIndex]
|
config.SampleRate = sampleRateTable[config.SampleRateIndex]
|
||||||
}
|
}
|
||||||
@ -220,20 +209,10 @@ func (self MPEG4AudioConfig) Complete() (config MPEG4AudioConfig) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseMPEG4AudioConfig(data []byte) (config MPEG4AudioConfig, err error) {
|
func ParseMPEG4AudioConfigBytes(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) {
|
|
||||||
// copied from libavcodec/mpeg4audio.c avpriv_mpeg4audio_get_config()
|
// copied from libavcodec/mpeg4audio.c avpriv_mpeg4audio_get_config()
|
||||||
|
r := bytes.NewReader(data)
|
||||||
br := &bits.Reader{R: r}
|
br := &bits.Reader{R: r}
|
||||||
|
|
||||||
if config.ObjectType, err = readObjectType(br); err != nil {
|
if config.ObjectType, err = readObjectType(br); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -243,12 +222,12 @@ func ReadMPEG4AudioConfig(r io.Reader) (config MPEG4AudioConfig, err error) {
|
|||||||
if config.ChannelConfig, err = br.ReadBits(4); err != nil {
|
if config.ChannelConfig, err = br.ReadBits(4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
config = config.Complete()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteMPEG4AudioConfig(w io.Writer, config MPEG4AudioConfig) (err error) {
|
func WriteMPEG4AudioConfig(w io.Writer, config MPEG4AudioConfig) (err error) {
|
||||||
bw := &bits.Writer{W: w}
|
bw := &bits.Writer{W: w}
|
||||||
|
|
||||||
if err = writeObjectType(bw, config.ObjectType); err != nil {
|
if err = writeObjectType(bw, config.ObjectType); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -311,9 +290,15 @@ func (self CodecData) PacketDuration(data []byte) (dur time.Duration, err error)
|
|||||||
return
|
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) {
|
func NewCodecDataFromMPEG4AudioConfigBytes(config []byte) (self CodecData, err error) {
|
||||||
self.ConfigBytes = config
|
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)
|
err = fmt.Errorf("parse MPEG4AudioConfig failed(%s)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1059,12 +1059,20 @@ func (self *Stream) handleRtpPacket(packet []byte) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case av.AAC:
|
case av.AAC:
|
||||||
if len(payload) < 4 {
|
if len(payload) < 4+7 {
|
||||||
err = fmt.Errorf("rtp: aac packet too short")
|
err = fmt.Errorf("rtp: aac packet too short")
|
||||||
return
|
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.gotpkt = true
|
||||||
self.pkt.Data = payload[4+7:] // TODO: remove this hack
|
self.pkt.Data = payload[hdrlen:framelen]
|
||||||
self.timestamp = timestamp
|
self.timestamp = timestamp
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -171,30 +171,26 @@ func (self *Stream) payloadEnd() (err error) {
|
|||||||
switch self.streamType {
|
switch self.streamType {
|
||||||
case ElementaryStreamTypeAdtsAAC:
|
case ElementaryStreamTypeAdtsAAC:
|
||||||
var config aacparser.MPEG4AudioConfig
|
var config aacparser.MPEG4AudioConfig
|
||||||
var packets [][]byte
|
if config, _, _, _, err = aacparser.ParseADTSHeader(payload); err != nil {
|
||||||
var totsamples int
|
err = fmt.Errorf("ts: aac invalid: %s", err)
|
||||||
if config, packets, totsamples, err = aacparser.SplitADTSFrames(payload); err != nil {
|
|
||||||
err = fmt.Errorf("ts: demuxer: SplitADTSFrames failed: %s", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
config = config.Complete()
|
|
||||||
|
|
||||||
if self.CodecData == nil {
|
if self.CodecData == nil {
|
||||||
bw := &bytes.Buffer{}
|
if self.CodecData, err = aacparser.NewCodecDataFromMPEG4AudioConfig(config); err != nil {
|
||||||
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 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frametime := time.Duration(totsamples / len(packets)) * time.Second / time.Duration(config.SampleRate)
|
delta := time.Duration(0)
|
||||||
timedelta := time.Duration(0)
|
for len(payload) > 0 {
|
||||||
for _, packet := range packets {
|
var hdrlen, framelen, samples int
|
||||||
self.addPacket(packet, timedelta)
|
if _, hdrlen, framelen, samples, err = aacparser.ParseADTSHeader(payload); err != nil {
|
||||||
timedelta += frametime
|
return
|
||||||
|
}
|
||||||
|
self.addPacket(payload[hdrlen:framelen], delta)
|
||||||
|
delta += time.Duration(samples) * time.Second / time.Duration(config.SampleRate)
|
||||||
|
payload = payload[:framelen]
|
||||||
}
|
}
|
||||||
|
|
||||||
case ElementaryStreamTypeH264:
|
case ElementaryStreamTypeH264:
|
||||||
|
@ -145,16 +145,17 @@ func (self *Muxer) writePacket(pkt av.Packet) (err error) {
|
|||||||
switch stream.Type() {
|
switch stream.Type() {
|
||||||
case av.AAC:
|
case av.AAC:
|
||||||
codec := stream.CodecData.(aacparser.CodecData)
|
codec := stream.CodecData.(aacparser.CodecData)
|
||||||
data := pkt.Data
|
adtshdr := make([]byte, aacparser.ADTSHeaderLength)
|
||||||
data = append(aacparser.MakeADTSHeader(codec.Config, 1024, len(data)), data...)
|
aacparser.FillADTSHeader(adtshdr, codec.Config, 1024, len(pkt.Data))
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
pes := PESHeader{
|
pes := PESHeader{
|
||||||
StreamId: StreamIdAAC,
|
StreamId: StreamIdAAC,
|
||||||
PTS: timeToPesTs(pkt.Time),
|
PTS: timeToPesTs(pkt.Time),
|
||||||
}
|
}
|
||||||
WritePESHeader(buf, pes, len(data))
|
WritePESHeader(buf, pes, len(pkt.Data)+len(adtshdr))
|
||||||
buf.Write(data)
|
buf.Write(adtshdr)
|
||||||
|
buf.Write(pkt.Data)
|
||||||
|
|
||||||
stream.tsw.RandomAccessIndicator = true
|
stream.tsw.RandomAccessIndicator = true
|
||||||
stream.tsw.PCR = timeToPCR(pkt.Time)
|
stream.tsw.PCR = timeToPCR(pkt.Time)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user