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

267 lines
8.3 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 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 (
"github.com/q191201771/naza/pkg/nazaerrors"
"github.com/q191201771/naza/pkg/nazalog"
"github.com/q191201771/lal/pkg/base"
"github.com/q191201771/naza/pkg/nazabits"
)
// AudioSpecificConfig(asc)
// keywords: Seq Header,
// e.g. rtmp, flv
//
// ADTS(Audio Data Transport Stream)
// e.g. es, ts
//
// StreamMuxConfig
//
const (
AdtsHeaderLength = 7
AscSamplingFrequencyIndex96000 = 0
AscSamplingFrequencyIndex88200 = 1
AscSamplingFrequencyIndex64000 = 2
AscSamplingFrequencyIndex48000 = 3
AscSamplingFrequencyIndex44100 = 4
AscSamplingFrequencyIndex32000 = 5
AscSamplingFrequencyIndex24000 = 6
AscSamplingFrequencyIndex22050 = 7
AscSamplingFrequencyIndex16000 = 8
AscSamplingFrequencyIndex12000 = 9
AscSamplingFrequencyIndex11025 = 10
AscSamplingFrequencyIndex8000 = 11
AscSamplingFrequencyIndex7350 = 12
)
const (
minAscLength = 2
)
// AscContext
//
// <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] 0=96000, 1=88200, 2=64000, 3=48000, 4=44100, 5=32000, 6=24000, 7=22050, 8=16000, 9=12000, 10=11025, 11=11025, 12=7350
// 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
}
// Unpack
//
// @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 {
return nazaerrors.Wrap(base.ErrShortBuffer)
}
br := nazabits.NewBitReader(asc)
ascCtx.AudioObjectType, _ = br.ReadBits8(5)
ascCtx.SamplingFrequencyIndex, _ = br.ReadBits8(4)
ascCtx.ChannelConfiguration, _ = br.ReadBits8(4)
return nil
}
// Pack
//
// @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
}
// PackAdtsHeader
//
// 获取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
}
// PackToAdtsHeader
//
// @param out: 函数调用结束后,内部不持有该内存块
func (ascCtx *AscContext) PackToAdtsHeader(out []byte, frameLength int) error {
if len(out) < AdtsHeaderLength {
return nazaerrors.Wrap(base.ErrShortBuffer)
}
// <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)
// <ISO_IEC_14496-3.pdf>
// profile_ObjectType: The interpretation of this bitstream element depends on the value of the ID bit. If ID is
// equal to 1 this field holds the same information as the profile field in the ADTS stream defined in ISO/IEC
// 13818-7. If ID is equal to 0 this element denotes the MPEG-4 Audio Object Type according to the table
// defined in subclause 5.1.1.
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 AscSamplingFrequencyIndex96000:
return 96000, nil
case AscSamplingFrequencyIndex88200:
return 88200, nil
case AscSamplingFrequencyIndex64000:
return 64000, nil
case AscSamplingFrequencyIndex48000:
return 48000, nil
case AscSamplingFrequencyIndex44100:
return 44100, nil
case AscSamplingFrequencyIndex32000:
return 32000, nil
case AscSamplingFrequencyIndex24000:
return 24000, nil
case AscSamplingFrequencyIndex22050:
return 22050, nil
case AscSamplingFrequencyIndex16000:
return 16000, nil
case AscSamplingFrequencyIndex12000:
return 12000, nil
case AscSamplingFrequencyIndex11025:
return 11025, nil
case AscSamplingFrequencyIndex8000:
return 8000, nil
case AscSamplingFrequencyIndex7350:
return 7350, nil
}
nazalog.Warnf("GetSamplingFrequency failed. err=%+v, ascCtx=%+v", base.ErrSamplingFrequencyIndex, ascCtx)
return -1, base.ErrSamplingFrequencyIndex
}
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
}
// Unpack
//
// @param adtsHeader: 函数调用结束后,内部不持有该内存块
func (ctx *AdtsHeaderContext) Unpack(adtsHeader []byte) error {
if len(adtsHeader) < AdtsHeaderLength {
return nazaerrors.Wrap(base.ErrShortBuffer)
}
br := nazabits.NewBitReader(adtsHeader)
_ = br.SkipBits(16)
v, _ := br.ReadBits8(2)
// <ISO_IEC_14496-3.pdf>
// profile_ObjectType: The interpretation of this bitstream element depends on the value of the ID bit. If ID is
// equal to 1 this field holds the same information as the profile field in the ADTS stream defined in ISO/IEC
// 13818-7. If ID is equal to 0 this element denotes the MPEG-4 Audio Object Type according to the table
// defined in subclause 5.1.1.
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
}
// MakeAscWithAdtsHeader
//
// @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
}