voaac-go/aacenc/aacenc.go
2020-04-08 10:00:16 +03:00

361 lines
9.8 KiB
Go

package aacenc
// Package aacenc implements cgo bindings for [VisualOn AAC encoder library](https://github.com/mstorsjo/vo-aacenc) library.
//#include "voAAC.h"
// VO_U32 encode(VO_HANDLE hCodec,void *pcm, int pcmlen, void *aac, int aacBufferSize, VO_U32 *err);
import "C"
import (
"errors"
"unsafe"
)
// Constants.
const (
// AAC Param ID
VoPidAacMdoule = 0x42211000
VoPidAacEncparam = VoPidAacMdoule | 0x0040
// AAC decoder error ID
VoErrAacMdoule = 0x82210000
VoErrAacUnsfileformat = (VoErrAacMdoule | 0xF001)
VoErrAacUnsprofile = (VoErrAacMdoule | 0xF002)
// The base param ID for AUDIO codec
VoPidAudioBase = 0x42000000
// The format data of audio in track
VoPidAudioFormat = (VoPidAudioBase | 0x0001)
// The sample rate of audio
VoPidAudioSampleRate = (VoPidAudioBase | 0x0002)
// The channel of audio
VoPidAudioChannels = (VoPidAudioBase | 0x0003)
// The bit rate of audio
VoPidAudioBitrate = (VoPidAudioBase | 0x0004)
// The channel mode of audio
VoPidAudioChannelmode = (VoPidAudioBase | 0x0005)
// The base of common param ID
VoPidCommonBase = 0x40000000
// Query the memory needed; Reserved
VoPidCommonQueryMem = (VoPidCommonBase | 0)
// Set or get the input buffer type
VoPidCommonInputType = (VoPidCommonBase | 0)
// Query it has resource to be used
VoPidCommonHasResource = (VoPidCommonBase | 0)
// Decoder track header data
VoPidCommonHeadData = (VoPidCommonBase | 0)
// VoPidCommonFlush as defined in include/voIndex.h:182
VoPidCommonFlush = (VoPidCommonBase | 0)
)
// Error codes.
const (
VoErrNone = 0x00000000
VoErrFinish = 0x00000001
VoErrFailed = 0x80000001
VoErrOutofMemory = 0x80000002
VoErrNotImplement = 0x80000003
VoErrInvalidArg = 0x80000004
VoErrInputBufferSmall = 0x80000005
VoErrOutputBufferSmall = 0x80000006
VoErrWrongStatus = 0x80000007
VoErrWrongParamId = 0x80000008
VoErrLicenseError = 0x80000009
VoErrAudioBase = 0x82000000
VoErrAudioUnsChannel = VoErrAudioBase | 0x0001
VoErrAudioUnsSampleRate = VoErrAudioBase | 0x0002
VoErrAudioUnsFeature = VoErrAudioBase | 0x0003
)
// Enumeration used to define the possible audio coding formats.
const (
// Placeholder value when coding is N/A
VoAudioCodingUnused int32 = iota
// Any variant of PCM coding
VoAudioCodingPcm
// Any variant of ADPCM encoded data
VoAudioCodingAdpcm
// Any variant of AMR encoded data
VoAudioCodingAmrnb
// Any variant of AMR encoded data
VoAudioCodingAmrwb
// Any variant of AMR encoded data
VoAudioCodingAmrwbp
// Any variant of QCELP 13kbps encoded data
VoAudioCodingQcelp13
// Any variant of EVRC encoded data
VoAudioCodingEvrc
// Any variant of AAC encoded data, 0xA106 - ISO/MPEG-4 AAC, 0xFF - AAC
VoAudioCodingAac
// Any variant of AC3 encoded data
VoAudioCodingAc3
// Any variant of FLAC encoded data
VoAudioCodingFlac
// Any variant of MP1 encoded data
VoAudioCodingMp1
// Any variant of MP3 encoded data
VoAudioCodingMp3
// Any variant of OGG encoded data
VoAudioCodingOgg
// Any variant of WMA encoded data
VoAudioCodingWma
// Any variant of RA encoded data
VoAudioCodingRa
// Any variant of MIDI encoded data
VoAudioCodingMidi
// Any variant of dra encoded data
VoAudioCodingDra
// Any variant of dra encoded data
VoAudioCodingG729
)
// The frame type that the decoder supports.
const (
// Contains only raw aac data in a frame
VoAacRawdata int32 = iota
// Contains ADTS header + raw AAC data in a frame
VoAacAdts
)
// The channel type value.
const (
// Center channel
VoChannelCenter int32 = 1
// Front left channel
VoChannelFrontLeft = 1 << 1
// Front right channel
VoChannelFrontRight = 1 << 2
// Side left channel
VoChannelSideLeft = 1 << 3
// Side right channel
VoChannelSideRight = 1 << 4
// Back left channel
VoChannelBackLeft = 1 << 5
// Back right channel
VoChannelBackRight = 1 << 6
// Back center channel
VoChannelBackCenter = 1 << 7
// Low-frequency effects bass channel
VoChannelLfeBass = 1 << 8
// Include all channels (default)
VoChannelAll = 0xffff
)
// Input stream format, Frame or Stream.
const (
// Input contains completely frame(s) data
VoInputFrame int32 = iota + 1
// Input is stream data.
VoInputStream
)
// VoAudioFormat - general audio format info.
type VoAudioFormat struct {
// Sample rate
SampleRate int
// Channel count
Channels int
// Bits per sample
SampleBits int
}
// cptr return C pointer.
func (v *VoAudioFormat) cptr() *C.VO_AUDIO_FORMAT {
return (*C.VO_AUDIO_FORMAT)(unsafe.Pointer(v))
}
// VoAudioOutputinfo - general audio output info.
type VoAudioOutputinfo struct {
// Sample rate
Format VoAudioFormat
// Channel count
InputUsed uint
// Reserved
Reserve uint
}
// cptr return C pointer.
func (v *VoAudioOutputinfo) cptr() *C.VO_AUDIO_OUTPUTINFO {
return (*C.VO_AUDIO_OUTPUTINFO)(unsafe.Pointer(v))
}
// VoCodecBuffer - general data buffer, used as input or output.
type VoCodecBuffer struct {
// Buffer pointer
Buffer unsafe.Pointer
// Buffer size in byte
Length uint64
// The time of the buffer
Time int64
}
// cptr return C pointer.
func (v *VoCodecBuffer) cptr() *C.VO_CODECBUFFER {
return (*C.VO_CODECBUFFER)(unsafe.Pointer(v))
}
// AacencParam - the structure for AAC encoder input parameter.
type AacencParam struct {
// Audio file sample rate
SampleRate int32
// Encoder bit rate in bits/sec
BitRate int32
// Number of channels on input (1,2)
NChannels int16
// Whether write adts header
AdtsUsed int16
}
// Encoder Thread-safe
type Encoder struct {
handle C.VO_HANDLE
outbuff [20480]byte
blockSize int // size of block for encoding
}
// Errors.
var (
ErrFinish = errors.New("aac: error finish")
ErrFailed = errors.New("aac: process data failed")
ErrOutOfMemory = errors.New("aac: out of memory")
ErrNotImplement = errors.New("aac: feature not implemented")
ErrInvalidArg = errors.New("aac: invalid argument")
ErrInputBufferSmall = errors.New("aac: input buffer data too small")
ErrOutputBufferSmall = errors.New("aac: output buffer size too small")
ErrWrongStatus = errors.New("aac: wrong encoder run-time status")
ErrWrongParamId = errors.New("aac: wrong parameter id")
ErrLicenseError = errors.New("aac: license error")
ErrAudioBase = errors.New("aac: error audio base")
ErrAudioUnsChannel = errors.New("aac: unsupported number of channel")
ErrAudioUnsSampleRate = errors.New("aac: unsupported sample rate")
ErrAudioUnsFeature = errors.New("aac: unsupported feature")
)
// ErrorFromResult returns error for result code
func ErrorFromResult(r uint) error {
switch r {
case VoErrNone:
return nil
case VoErrFinish:
return ErrFinish
case VoErrFailed:
return ErrFailed
case VoErrOutofMemory:
return ErrOutOfMemory
case VoErrNotImplement:
return ErrNotImplement
case VoErrInvalidArg:
return ErrInvalidArg
case VoErrInputBufferSmall:
return ErrInputBufferSmall
case VoErrOutputBufferSmall:
return ErrOutputBufferSmall
case VoErrWrongStatus:
return ErrWrongStatus
case VoErrWrongParamId:
return ErrWrongParamId
case VoErrLicenseError:
return ErrLicenseError
case VoErrAudioBase:
return ErrAudioBase
case VoErrAudioUnsChannel:
return ErrAudioUnsChannel
case VoErrAudioUnsSampleRate:
return ErrAudioUnsSampleRate
case VoErrAudioUnsFeature:
return ErrAudioUnsFeature
default:
return nil
}
}
// New encoder
func New() *Encoder {
return &Encoder{}
}
// Init - init the audio codec module and return codec handle.
func (e *Encoder) Init(vtype int32) uint {
cvtype := (C.VO_AUDIO_CODINGTYPE)(vtype)
ret := C.voAACEncInit(&e.handle, cvtype, nil)
v := (uint)(ret)
return v
}
// SetInputData - set input audio data.
func (e *Encoder) SetInputData(pinput *VoCodecBuffer) uint {
cpinput := pinput.cptr()
ret := C.voAACEncSetInputData(e.handle, cpinput)
v := (uint)(ret)
return v
}
// GetOutputData - get the outut audio data.
func (e *Encoder) GetOutputData(poutbuffer *VoCodecBuffer, poutinfo *VoAudioOutputinfo) uint {
cpoutbuffer := poutbuffer.cptr()
cpoutinfo := poutinfo.cptr()
ret := C.voAACEncGetOutputData(e.handle, cpoutbuffer, cpoutinfo)
v := (uint)(ret)
return v
}
// SetParam - set the parameter for the specified param ID.
func (e *Encoder) SetParam(uparamid int, pdata unsafe.Pointer) uint {
cuparamid := (C.VO_S32)(uparamid)
cpdata := (C.VO_PTR)(pdata)
ret := C.voAACEncSetParam(e.handle, cuparamid, cpdata)
v := (uint)(ret)
return v
}
// GetParam - get the parameter for the specified param ID.
func (e *Encoder) GetParam(uparamid int, pdata unsafe.Pointer) uint {
cuparamid := (C.VO_S32)(uparamid)
cpdata := (C.VO_PTR)(pdata)
ret := C.voAACEncGetParam(e.handle, cuparamid, cpdata)
v := (uint)(ret)
return v
}
// Uninit - uninit the Codec.
func (e *Encoder) Uninit() uint {
ret := C.voAACEncUninit(e.handle)
v := (uint)(ret)
return v
}
// EncodePcmBlock - Encodes single interleaved block 1024 * numchannels
// if buffer size is wrong returns VoErrInvalidArg
func (e *Encoder) EncodePcmBlock(inPcm []int16) (aac []byte, err uint) {
if len(inPcm) != e.blockSize {
return nil, VoErrInvalidArg
}
var ret C.VO_U32
len := C.encode(e.handle,
unsafe.Pointer(&inPcm[0]),
C.int(len(inPcm)*2), // int16
unsafe.Pointer(&e.outbuff[0]),
C.int(len(e.outbuff)),
&ret)
err = uint(ret)
if err != VoErrNone { // error
return nil, err
}
return e.outbuff[:len], err
}
// SetParamAac set Samplerate & numchannels for AAC encoding
func (e *Encoder) SetParamAac(aacSamplerate, nChannels int) (err uint) {
e.blockSize = 1024 * nChannels
setParametersBlock := C.AACENC_PARAM{
sampleRate: C.int(aacSamplerate), /*! audio file sample rate */
bitRate: 64000, /*! encoder bit rate in bits/sec */
nChannels: C.short(nChannels), /*! number of channels on input (1,2) */
adtsUsed: 1, /*! whether write adts header */
}
return uint(C.voAACEncSetParam(e.handle, VoPidAacEncparam, C.VO_PTR(&setParametersBlock)))
}