update
This commit is contained in:
parent
8e14c48c2a
commit
790569a35a
16
aacenc.go
16
aacenc.go
@ -17,7 +17,7 @@ import (
|
|||||||
} aacenc_t ;
|
} aacenc_t ;
|
||||||
|
|
||||||
static int aacenc_new(aacenc_t *m) {
|
static int aacenc_new(aacenc_t *m) {
|
||||||
m->c = avcodec_find_encoder(CODEC_ID_AAC);
|
m->c = avcodec_find_encoder_by_name("aac");
|
||||||
m->ctx = avcodec_alloc_context3(m->c);
|
m->ctx = avcodec_alloc_context3(m->c);
|
||||||
m->ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
m->ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
||||||
m->ctx->sample_rate = m->samplerate;
|
m->ctx->sample_rate = m->samplerate;
|
||||||
@ -26,7 +26,7 @@ import (
|
|||||||
m->ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
|
m->ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
|
||||||
m->f = av_frame_alloc();
|
m->f = av_frame_alloc();
|
||||||
int r = avcodec_open2(m->ctx, m->c, 0);
|
int r = avcodec_open2(m->ctx, m->c, 0);
|
||||||
av_log(m->ctx, AV_LOG_DEBUG, "extra %d\n", m->ctx->extradata_size);
|
//av_log(m->ctx, AV_LOG_DEBUG, "extra %d\n", m->ctx->extradata_size);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +37,8 @@ import (
|
|||||||
pkt.size = sizeof(m->buf);
|
pkt.size = sizeof(m->buf);
|
||||||
m->f->nb_samples = 1024;
|
m->f->nb_samples = 1024;
|
||||||
m->f->extended_data = m->f->data;
|
m->f->extended_data = m->f->data;
|
||||||
m->f->linesize[0] = 4096;
|
m->f->linesize[0] = 1024*4;
|
||||||
|
//m->f->linesize[1] = 1024*4;
|
||||||
avcodec_encode_audio2(m->ctx, &pkt, m->f, &m->got);
|
avcodec_encode_audio2(m->ctx, &pkt, m->f, &m->got);
|
||||||
av_log(m->ctx, AV_LOG_DEBUG, "got %d size %d\n", m->got, pkt.size);
|
av_log(m->ctx, AV_LOG_DEBUG, "got %d size %d\n", m->got, pkt.size);
|
||||||
m->size = pkt.size;
|
m->size = pkt.size;
|
||||||
@ -53,12 +54,12 @@ type AACEncoder struct {
|
|||||||
Header []byte
|
Header []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// only supported fltp,stereo,44100khz. If you need other config, it's easy to modify code
|
// only supported fltp,stereo,44100HZ. If you need other config, it's easy to modify code
|
||||||
func NewAACEncoder() (m *AACEncoder, err error) {
|
func NewAACEncoder() (m *AACEncoder, err error) {
|
||||||
m = &AACEncoder{}
|
m = &AACEncoder{}
|
||||||
m.m.samplerate = 44100
|
m.m.samplerate = 44100
|
||||||
m.m.bitrate = 50000
|
m.m.bitrate = 50000
|
||||||
m.m.channels = 2
|
m.m.channels = 1
|
||||||
r := C.aacenc_new(&m.m)
|
r := C.aacenc_new(&m.m)
|
||||||
if int(r) != 0 {
|
if int(r) != 0 {
|
||||||
err = errors.New("open codec failed")
|
err = errors.New("open codec failed")
|
||||||
@ -67,7 +68,7 @@ func NewAACEncoder() (m *AACEncoder, err error) {
|
|||||||
m.Header = make([]byte, (int)(m.m.ctx.extradata_size))
|
m.Header = make([]byte, (int)(m.m.ctx.extradata_size))
|
||||||
C.memcpy(
|
C.memcpy(
|
||||||
unsafe.Pointer(&m.Header[0]),
|
unsafe.Pointer(&m.Header[0]),
|
||||||
unsafe.Pointer(&m.m.ctx.extradata),
|
unsafe.Pointer(m.m.ctx.extradata),
|
||||||
(C.size_t)(len(m.Header)),
|
(C.size_t)(len(m.Header)),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@ -75,7 +76,7 @@ func NewAACEncoder() (m *AACEncoder, err error) {
|
|||||||
|
|
||||||
func (m *AACEncoder) Encode(sample []byte) (ret []byte, err error) {
|
func (m *AACEncoder) Encode(sample []byte) (ret []byte, err error) {
|
||||||
m.m.f.data[0] = (*C.uint8_t)(unsafe.Pointer(&sample[0]))
|
m.m.f.data[0] = (*C.uint8_t)(unsafe.Pointer(&sample[0]))
|
||||||
m.m.f.data[1] = (*C.uint8_t)(unsafe.Pointer(&sample[4096]))
|
//m.m.f.data[1] = (*C.uint8_t)(unsafe.Pointer(&sample[1024*4]))
|
||||||
C.aacenc_encode(&m.m)
|
C.aacenc_encode(&m.m)
|
||||||
if int(m.m.got) == 0 {
|
if int(m.m.got) == 0 {
|
||||||
err = errors.New("no data")
|
err = errors.New("no data")
|
||||||
@ -89,3 +90,4 @@ func (m *AACEncoder) Encode(sample []byte) (ret []byte, err error) {
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package aacparser
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nareix/bits"
|
"github.com/nareix/bits"
|
||||||
|
"github.com/nareix/av"
|
||||||
"fmt"
|
"fmt"
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
@ -247,6 +248,16 @@ func (self MPEG4AudioConfig) Complete() (config MPEG4AudioConfig) {
|
|||||||
return
|
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 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()
|
||||||
br := &bits.Reader{R: r}
|
br := &bits.Reader{R: r}
|
||||||
@ -298,17 +309,51 @@ func WriteMPEG4AudioConfig(w io.Writer, config MPEG4AudioConfig) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type CodecInfo struct {
|
type CodecData struct {
|
||||||
MPEG4AudioConfig
|
Config []byte
|
||||||
|
ConfigInfo MPEG4AudioConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseCodecData(config []byte) (info CodecInfo, err error) {
|
func (self CodecData) IsVideo() bool {
|
||||||
r := bytes.NewReader(config)
|
return false
|
||||||
if info.MPEG4AudioConfig, err = ReadMPEG4AudioConfig(r); err != nil {
|
}
|
||||||
err = fmt.Errorf("CodecData invalid: parse MPEG4AudioConfig failed(%s)", err)
|
|
||||||
|
func (self CodecData) IsAudio() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) Type() int {
|
||||||
|
return av.AAC
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) MPEG4AudioConfigBytes() []byte {
|
||||||
|
return self.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) ChannelCount() int {
|
||||||
|
return self.ConfigInfo.ChannelCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) SampleRate() int {
|
||||||
|
return self.ConfigInfo.SampleRate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) SampleFormat() av.SampleFormat {
|
||||||
|
return av.FLTP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) MakeADTSHeader(samples int, payloadLength int) []byte {
|
||||||
|
return MakeADTSHeader(self.ConfigInfo, samples, payloadLength)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCodecDataFromMPEG4AudioConfigBytes(config []byte) (codec av.AACCodecData, err error) {
|
||||||
|
self := CodecData{}
|
||||||
|
self.Config = config
|
||||||
|
if self.ConfigInfo, err = ParseMPEG4AudioConfig(config); err != nil {
|
||||||
|
err = fmt.Errorf("parse MPEG4AudioConfig failed(%s)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
info.MPEG4AudioConfig = info.MPEG4AudioConfig.Complete()
|
codec = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
package h264parser
|
package h264parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/nareix/av"
|
||||||
"github.com/nareix/bits"
|
"github.com/nareix/bits"
|
||||||
"io"
|
"io"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -492,25 +493,6 @@ func ParseSPS(data []byte) (self SPSInfo, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
func MakeAVCDecoderConfRecord(
|
|
||||||
SPS []byte,
|
|
||||||
PPS []byte,
|
|
||||||
) (self AVCDecoderConfRecord, err error) {
|
|
||||||
if len(SPS) < 4 {
|
|
||||||
err = fmt.Errorf("invalid SPS data")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.AVCProfileIndication = int(SPS[1])
|
|
||||||
self.ProfileCompatibility = int(SPS[2])
|
|
||||||
self.AVCLevelIndication = int(SPS[3])
|
|
||||||
self.SPS = [][]byte{SPS}
|
|
||||||
self.PPS = [][]byte{PPS}
|
|
||||||
self.LengthSizeMinusOne = 3
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func WriteAVCDecoderConfRecord(w io.Writer, self AVCDecoderConfRecord) (err error) {
|
func WriteAVCDecoderConfRecord(w io.Writer, self AVCDecoderConfRecord) (err error) {
|
||||||
if err = bits.WriteUIntBE(w, 1, 8); err != nil {
|
if err = bits.WriteUIntBE(w, 1, 8); err != nil {
|
||||||
return
|
return
|
||||||
@ -555,42 +537,85 @@ func WriteAVCDecoderConfRecord(w io.Writer, self AVCDecoderConfRecord) (err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type CodecInfo struct {
|
type CodecData struct {
|
||||||
Record AVCDecoderConfRecord
|
Record []byte
|
||||||
|
RecordInfo AVCDecoderConfRecord
|
||||||
SPSInfo SPSInfo
|
SPSInfo SPSInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// CodecData is AVCDecoderConfRecord
|
func (self CodecData) Type() int {
|
||||||
func ParseCodecData(config []byte) (info CodecInfo, err error) {
|
return av.H264
|
||||||
if info.Record, err = ParseAVCDecoderConfRecord(config); err != nil {
|
}
|
||||||
|
|
||||||
|
func (self CodecData) IsVideo() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) AVCDecoderConfRecordBytes() []byte {
|
||||||
|
return self.Record
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) SPS() []byte {
|
||||||
|
return self.RecordInfo.SPS[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) PPS() []byte {
|
||||||
|
return self.RecordInfo.PPS[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) IsAudio() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) Width() int {
|
||||||
|
return int(self.SPSInfo.Width)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self CodecData) Height() int {
|
||||||
|
return int(self.SPSInfo.Height)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCodecDataFromAVCDecoderConfRecord(record []byte) (codec av.H264CodecData, err error) {
|
||||||
|
self := CodecData{}
|
||||||
|
self.Record = record
|
||||||
|
if self.RecordInfo, err = ParseAVCDecoderConfRecord(record); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(info.Record.SPS) < 1 {
|
if len(self.RecordInfo.SPS) == 0 {
|
||||||
err = fmt.Errorf("CodecData invalid: no SPS found in AVCDecoderConfRecord")
|
err = fmt.Errorf("no SPS found in AVCDecoderConfRecord")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if info.SPSInfo, err = ParseSPS(info.Record.SPS[0]); err != nil {
|
if len(self.RecordInfo.PPS) == 0 {
|
||||||
err = fmt.Errorf("CodecData invalid: parse SPS failed(%s)", err)
|
err = fmt.Errorf("no PPS found in AVCDecoderConfRecord")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if self.SPSInfo, err = ParseSPS(self.RecordInfo.SPS[0]); err != nil {
|
||||||
|
err = fmt.Errorf("parse SPS failed(%s)", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
codec = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateCodecDataBySPSAndPPS(SPS, PPS []byte) (codecData []byte, err error) {
|
func NewCodecDataFromSPSAndPPS(sps, pps []byte) (codec av.H264CodecData, err error) {
|
||||||
self := AVCDecoderConfRecord{}
|
recordinfo := AVCDecoderConfRecord{}
|
||||||
self.AVCProfileIndication = uint(SPS[1])
|
recordinfo.AVCProfileIndication = uint(sps[1])
|
||||||
self.ProfileCompatibility = uint(SPS[2])
|
recordinfo.ProfileCompatibility = uint(sps[2])
|
||||||
self.AVCLevelIndication = uint(SPS[3])
|
recordinfo.AVCLevelIndication = uint(sps[3])
|
||||||
self.SPS = [][]byte{SPS}
|
recordinfo.SPS = [][]byte{sps}
|
||||||
self.PPS = [][]byte{PPS}
|
recordinfo.PPS = [][]byte{pps}
|
||||||
self.LengthSizeMinusOne = 3
|
recordinfo.LengthSizeMinusOne = 3
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
if err = WriteAVCDecoderConfRecord(buf, self); err != nil {
|
if err = WriteAVCDecoderConfRecord(buf, recordinfo); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
codecData = buf.Bytes()
|
self := CodecData{}
|
||||||
|
self.RecordInfo = recordinfo
|
||||||
|
self.Record = buf.Bytes()
|
||||||
|
if self.SPSInfo, err = ParseSPS(sps); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
codec = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,3 +751,43 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
type CodecInfo struct {
|
||||||
|
Record AVCDecoderConfRecord
|
||||||
|
SPSInfo SPSInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseCodecData(config []byte) (info CodecInfo, err error) {
|
||||||
|
if info.Record, err = ParseAVCDecoderConfRecord(config); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(info.Record.SPS) < 1 {
|
||||||
|
err = fmt.Errorf("CodecData invalid: no SPS found in AVCDecoderConfRecord")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if info.SPSInfo, err = ParseSPS(info.Record.SPS[0]); err != nil {
|
||||||
|
err = fmt.Errorf("CodecData invalid: parse SPS failed(%s)", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateCodecDataBySPSAndPPS(SPS, PPS []byte) (codecData []byte, err error) {
|
||||||
|
self := AVCDecoderConfRecord{}
|
||||||
|
self.AVCProfileIndication = uint(SPS[1])
|
||||||
|
self.ProfileCompatibility = uint(SPS[2])
|
||||||
|
self.AVCLevelIndication = uint(SPS[3])
|
||||||
|
self.SPS = [][]byte{SPS}
|
||||||
|
self.PPS = [][]byte{PPS}
|
||||||
|
self.LengthSizeMinusOne = 3
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
if err = WriteAVCDecoderConfRecord(buf, self); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
codecData = buf.Bytes()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user