You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/aac/aac.go

213 lines
6.1 KiB
Go

// Copyright 2019, Chef. All rights reserved.
// https://github.com/q191201771/lal
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package aac
import (
"errors"
"github.com/q191201771/naza/pkg/nazabits"
"github.com/q191201771/naza/pkg/nazalog"
)
// AudioSpecificConfig(asc)
// keywords: Seq Header,
// e.g. rtmp, flv
//
// ADTS(Audio Data Transport Stream)
// e.g. es, ts
//
// StreamMuxConfig
//
var ErrAac = errors.New("lal.aac: fxxk")
const (
AdtsHeaderLength = 7
AscSamplingFrequencyIndex48000 = 3
AscSamplingFrequencyIndex44100 = 4
)
const (
minAscLength = 2
)
// <ISO_IEC_14496-3.pdf>
// <1.6.2.1 AudioSpecificConfig>, <page 33/110>
// <1.5.1.1 Audio Object type definition>, <page 23/110>
// <1.6.3.3 samplingFrequencyIndex>, <page 35/110>
// <1.6.3.4 channelConfiguration>
// --------------------------------------------------------
// audio object type [5b] 1=AAC MAIN 2=AAC LC
// samplingFrequencyIndex [4b] 3=48000 4=44100 6=24000 5=32000 11=11025
// channelConfiguration [4b] 1=center front speaker 2=left, right front speakers
type AscContext struct {
AudioObjectType uint8 // [5b]
SamplingFrequencyIndex uint8 // [4b]
ChannelConfiguration uint8 // [4b]
}
func NewAscContext(asc []byte) (*AscContext, error) {
var ascCtx AscContext
if err := ascCtx.Unpack(asc); err != nil {
return nil, err
}
return &ascCtx, nil
}
// @param asc: 2字节的AAC Audio Specifc Config
// 注意如果是rtmp/flv的message/tag应去除Seq Header头部的2个字节
// 函数调用结束后,内部不持有该内存块
//
func (ascCtx *AscContext) Unpack(asc []byte) error {
if len(asc) < minAscLength {
nazalog.Warnf("aac seq header length invalid. len=%d", len(asc))
return ErrAac
}
br := nazabits.NewBitReader(asc)
ascCtx.AudioObjectType, _ = br.ReadBits8(5)
ascCtx.SamplingFrequencyIndex, _ = br.ReadBits8(4)
ascCtx.ChannelConfiguration, _ = br.ReadBits8(4)
return nil
}
// @return asc: 内存块为独立新申请;函数调用结束后,内部不持有该内存块
//
func (ascCtx *AscContext) Pack() (asc []byte) {
asc = make([]byte, minAscLength)
bw := nazabits.NewBitWriter(asc)
bw.WriteBits8(5, ascCtx.AudioObjectType)
bw.WriteBits8(4, ascCtx.SamplingFrequencyIndex)
bw.WriteBits8(4, ascCtx.ChannelConfiguration)
return
}
// 获取ADTS头由于ADTS头中的字段依赖包的长度而每个包的长度可能不同所以每个包的ADTS头都需要独立生成
//
// @param frameLength: raw aac frame的大小
// 注意如果是rtmp/flv的message/tag应去除Seq Header头部的2个字节
//
// @return h: 内存块为独立新申请;函数调用结束后,内部不持有该内存块
//
func (ascCtx *AscContext) PackAdtsHeader(frameLength int) (out []byte) {
out = make([]byte, AdtsHeaderLength)
_ = ascCtx.PackToAdtsHeader(out, frameLength)
return
}
// @param out: 函数调用结束后,内部不持有该内存块
//
func (ascCtx *AscContext) PackToAdtsHeader(out []byte, frameLength int) error {
if len(out) < AdtsHeaderLength {
return ErrAac
}
// <ISO_IEC_14496-3.pdf>
// <1.A.2.2.1 Fixed Header of ADTS>, <page 75/110>
// <1.A.2.2.2 Variable Header of ADTS>, <page 76/110>
// <1.A.3.2.1 Definitions: Bitstream elements for ADTS>
// ----------------------------------------------------
// Syncword [12b] '1111 1111 1111'
// ID [1b] 1=MPEG-2 AAC 0=MPEG-4
// Layer [2b]
// protection_absent [1b] 1=no crc check
// Profile_ObjectType [2b]
// sampling_frequency_index [4b]
// private_bit [1b]
// channel_configuration [3b]
// origin/copy [1b]
// home [1b]
// Emphasis???
// ------------------------------------
// copyright_identification_bit [1b]
// copyright_identification_start [1b]
// aac_frame_length [13b]
// adts_buffer_fullness [11b]
// no_raw_data_blocks_in_frame [2b]
bw := nazabits.NewBitWriter(out)
// Syncword 0(8) 1(4)
bw.WriteBits16(12, 0xFFF)
// ID, Layer, protection_absent 1(4)
bw.WriteBits8(4, 0x1)
// 2(2)
bw.WriteBits8(2, ascCtx.AudioObjectType-1)
// 2(4)
bw.WriteBits8(4, ascCtx.SamplingFrequencyIndex)
// private_bit 2(1)
bw.WriteBits8(1, 0)
// 2(1) 3(2)
bw.WriteBits8(3, ascCtx.ChannelConfiguration)
// origin/copy, home, copyright_identification_bit, copyright_identification_start 3(4)
bw.WriteBits8(4, 0)
// 3(2) 4(8) 5(3)
bw.WriteBits16(13, uint16(frameLength+AdtsHeaderLength))
// adts_buffer_fullness 5(5) 6(6)
bw.WriteBits16(11, 0x7FF)
// no_raw_data_blocks_in_frame 6(2)
bw.WriteBits8(2, 0)
return nil
}
func (ascCtx *AscContext) GetSamplingFrequency() (int, error) {
switch ascCtx.SamplingFrequencyIndex {
case AscSamplingFrequencyIndex48000:
return 48000, nil
case AscSamplingFrequencyIndex44100:
return 44100, nil
}
return -1, ErrAac
}
type AdtsHeaderContext struct {
AscCtx AscContext
AdtsLength uint16 // 字段中的值包含了adts header + adts frame
}
func NewAdtsHeaderContext(adtsHeader []byte) (*AdtsHeaderContext, error) {
var ctx AdtsHeaderContext
if err := ctx.Unpack(adtsHeader); err != nil {
return nil, err
}
return &ctx, nil
}
// @param adtsHeader: 函数调用结束后,内部不持有该内存块
//
func (ctx *AdtsHeaderContext) Unpack(adtsHeader []byte) error {
if len(adtsHeader) < AdtsHeaderLength {
return ErrAac
}
br := nazabits.NewBitReader(adtsHeader)
_ = br.SkipBits(16)
v, _ := br.ReadBits8(2)
ctx.AscCtx.AudioObjectType = v + 1
ctx.AscCtx.SamplingFrequencyIndex, _ = br.ReadBits8(4)
_ = br.SkipBits(1)
ctx.AscCtx.ChannelConfiguration, _ = br.ReadBits8(3)
_ = br.SkipBits(4)
ctx.AdtsLength, _ = br.ReadBits16(13)
return nil
}
// @param adtsHeader: 函数调用结束后,内部不持有该内存块
//
// @return asc: 内存块为独立新申请;函数调用结束后,内部不持有该内存块
//
func MakeAscWithAdtsHeader(adtsHeader []byte) (asc []byte, err error) {
var ctx *AdtsHeaderContext
if ctx, err = NewAdtsHeaderContext(adtsHeader); err != nil {
return nil, err
}
return ctx.AscCtx.Pack(), nil
}