|
|
|
@ -4,6 +4,10 @@ |
|
|
|
#include <libavfilter/avfilter.h> |
|
|
|
#include <libavutil/opt.h> |
|
|
|
#include <glib.h> |
|
|
|
#ifdef HAVE_BCG729 |
|
|
|
#include <bcg729/encoder.h> |
|
|
|
#include <bcg729/decoder.h> |
|
|
|
#endif |
|
|
|
#include "str.h" |
|
|
|
#include "log.h" |
|
|
|
#include "loglib.h" |
|
|
|
@ -34,7 +38,7 @@ static packetizer_f packetizer_samplestream; // flat stream of samples |
|
|
|
static format_init_f opus_init; |
|
|
|
static set_options_f opus_set_options; |
|
|
|
|
|
|
|
static void avc_def_init(codec_def_t *, int); |
|
|
|
static void avc_def_init(codec_def_t *); |
|
|
|
static const char *avc_decoder_init(decoder_t *); |
|
|
|
static int avc_decoder_input(decoder_t *dec, const str *data, GQueue *out); |
|
|
|
static void avc_decoder_close(decoder_t *); |
|
|
|
@ -55,6 +59,26 @@ static const codec_type_t codec_type_avcodec = { |
|
|
|
.encoder_close = avc_encoder_close, |
|
|
|
}; |
|
|
|
|
|
|
|
#ifdef HAVE_BCG729 |
|
|
|
static void bcg729_def_init(codec_def_t *); |
|
|
|
static const char *bcg729_decoder_init(decoder_t *); |
|
|
|
static int bcg729_decoder_input(decoder_t *dec, const str *data, GQueue *out); |
|
|
|
static void bcg729_decoder_close(decoder_t *); |
|
|
|
static const char *bcg729_encoder_init(encoder_t *enc); |
|
|
|
static int bcg729_encoder_input(encoder_t *enc, AVFrame **frame); |
|
|
|
static void bcg729_encoder_close(encoder_t *enc); |
|
|
|
|
|
|
|
static const codec_type_t codec_type_bcg729 = { |
|
|
|
.def_init = bcg729_def_init, |
|
|
|
.decoder_init = bcg729_decoder_init, |
|
|
|
.decoder_input = bcg729_decoder_input, |
|
|
|
.decoder_close = bcg729_decoder_close, |
|
|
|
.encoder_init = bcg729_encoder_init, |
|
|
|
.encoder_input = bcg729_encoder_input, |
|
|
|
.encoder_close = bcg729_encoder_close, |
|
|
|
}; |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static codec_def_t __codec_defs[] = { |
|
|
|
@ -115,17 +139,31 @@ static codec_def_t __codec_defs[] = { |
|
|
|
.media_type = MT_AUDIO, |
|
|
|
.codec_type = &codec_type_avcodec, |
|
|
|
}, |
|
|
|
#ifndef HAVE_BCG729 |
|
|
|
{ |
|
|
|
.rtpname = "G729", |
|
|
|
.avcodec_id = AV_CODEC_ID_G729, |
|
|
|
.clockrate_mult = 1, |
|
|
|
.default_clockrate = 8000, |
|
|
|
.default_channels = 1, |
|
|
|
.default_ptime = 20, |
|
|
|
.default_ptime = 10, |
|
|
|
.packetizer = packetizer_passthrough, |
|
|
|
.media_type = MT_AUDIO, |
|
|
|
.codec_type = &codec_type_avcodec, |
|
|
|
}, |
|
|
|
#else |
|
|
|
{ |
|
|
|
.rtpname = "G729", |
|
|
|
.avcodec_id = -1, |
|
|
|
.clockrate_mult = 1, |
|
|
|
.default_clockrate = 8000, |
|
|
|
.default_channels = 1, |
|
|
|
.default_ptime = 10, |
|
|
|
.packetizer = packetizer_passthrough, |
|
|
|
.media_type = MT_AUDIO, |
|
|
|
.codec_type = &codec_type_bcg729, |
|
|
|
}, |
|
|
|
#endif |
|
|
|
{ |
|
|
|
.rtpname = "speex", |
|
|
|
.avcodec_id = AV_CODEC_ID_SPEEX, |
|
|
|
@ -276,6 +314,7 @@ static codec_def_t __codec_defs[] = { |
|
|
|
.avcodec_name = NULL, |
|
|
|
.packetizer = packetizer_passthrough, |
|
|
|
.media_type = MT_AUDIO, |
|
|
|
.pseudocodec = 1, |
|
|
|
}, |
|
|
|
// for file writing |
|
|
|
{ |
|
|
|
@ -600,7 +639,7 @@ static void avlog_ilog(void *ptr, int loglevel, const char *fmt, va_list ap) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void avc_def_init(codec_def_t *def, int print) { |
|
|
|
static void avc_def_init(codec_def_t *def) { |
|
|
|
// look up AVCodec structs |
|
|
|
if (def->avcodec_name) { |
|
|
|
def->encoder = avcodec_find_encoder_by_name(def->avcodec_name); |
|
|
|
@ -614,28 +653,10 @@ static void avc_def_init(codec_def_t *def, int print) { |
|
|
|
} |
|
|
|
// check if we have support if we are supposed to |
|
|
|
if (def->avcodec_name || def->avcodec_id >= 0) { |
|
|
|
if (print) { |
|
|
|
if (def->encoder && def->decoder) |
|
|
|
printf("%20s: fully supported\n", def->rtpname); |
|
|
|
else if (def->decoder) |
|
|
|
printf("%20s: supported for decoding only\n", def->rtpname); |
|
|
|
else if (def->encoder) |
|
|
|
printf("%20s: supported for encoding only\n", def->rtpname); |
|
|
|
else |
|
|
|
printf("%20s: not supported\n", def->rtpname); |
|
|
|
} |
|
|
|
else { |
|
|
|
if (!def->encoder && !def->decoder) |
|
|
|
ilog(LOG_DEBUG, "Codec %s is not supported by codec library", |
|
|
|
def->rtpname); |
|
|
|
else if (!def->encoder) { |
|
|
|
ilog(LOG_DEBUG, "Codec %s is only supported for decoding " |
|
|
|
"by codec library", def->rtpname); |
|
|
|
} |
|
|
|
else if (!def->decoder) |
|
|
|
ilog(LOG_DEBUG, "Codec %s is only supported for encoding " |
|
|
|
"by codec library", def->rtpname); |
|
|
|
} |
|
|
|
if (def->encoder) |
|
|
|
def->support_encoding = 1; |
|
|
|
if (def->decoder) |
|
|
|
def->support_decoding = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -673,7 +694,33 @@ void codeclib_init(int print) { |
|
|
|
def->rfc_payload_type = -1; |
|
|
|
|
|
|
|
if (def->codec_type && def->codec_type->def_init) |
|
|
|
def->codec_type->def_init(def, print); |
|
|
|
def->codec_type->def_init(def); |
|
|
|
|
|
|
|
if (def->pseudocodec) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (print) { |
|
|
|
if (def->support_encoding && def->support_decoding) |
|
|
|
printf("%20s: fully supported\n", def->rtpname); |
|
|
|
else if (def->support_decoding) |
|
|
|
printf("%20s: supported for decoding only\n", def->rtpname); |
|
|
|
else if (def->support_encoding) |
|
|
|
printf("%20s: supported for encoding only\n", def->rtpname); |
|
|
|
else |
|
|
|
printf("%20s: not supported\n", def->rtpname); |
|
|
|
} |
|
|
|
else { |
|
|
|
if (!def->support_encoding && !def->support_decoding) |
|
|
|
ilog(LOG_DEBUG, "Codec %s is not supported by codec library", |
|
|
|
def->rtpname); |
|
|
|
else if (!def->support_encoding) { |
|
|
|
ilog(LOG_DEBUG, "Codec %s is only supported for decoding " |
|
|
|
"by codec library", def->rtpname); |
|
|
|
} |
|
|
|
else if (!def->support_decoding) |
|
|
|
ilog(LOG_DEBUG, "Codec %s is only supported for encoding " |
|
|
|
"by codec library", def->rtpname); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -856,6 +903,7 @@ static const char *avc_encoder_init(encoder_t *enc) { |
|
|
|
enc->u.avc.avcctx->sample_fmt = enc->actual_format.format; |
|
|
|
enc->u.avc.avcctx->time_base = (AVRational){1,enc->actual_format.clockrate}; |
|
|
|
enc->u.avc.avcctx->bit_rate = enc->bitrate; |
|
|
|
|
|
|
|
enc->samples_per_frame = enc->actual_format.clockrate * enc->ptime / 1000; |
|
|
|
if (enc->u.avc.avcctx->frame_size) |
|
|
|
enc->samples_per_frame = enc->u.avc.avcctx->frame_size; |
|
|
|
@ -1026,10 +1074,10 @@ int encoder_input_data(encoder_t *enc, AVFrame *frame, |
|
|
|
if (ret < 0) |
|
|
|
return -1; |
|
|
|
|
|
|
|
//av_write_frame(output->fmtctx, &output->avpkt); |
|
|
|
callback(enc, u1, u2); |
|
|
|
|
|
|
|
if (enc->avpkt.size) { |
|
|
|
//av_write_frame(output->fmtctx, &output->avpkt); |
|
|
|
callback(enc, u1, u2); |
|
|
|
|
|
|
|
//output->fifo_pts += output->frame->nb_samples; |
|
|
|
enc->mux_dts = enc->avpkt.dts + 1; // min next expected dts |
|
|
|
|
|
|
|
@ -1168,3 +1216,94 @@ static void opus_set_options(encoder_t *enc) { |
|
|
|
ilog(LOG_WARN, "Failed to set Opus frame_duration option (error code %i)", ret); |
|
|
|
// XXX additional opus options |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_BCG729 |
|
|
|
static void bcg729_def_init(codec_def_t *def) { |
|
|
|
// test init |
|
|
|
bcg729EncoderChannelContextStruct *e = initBcg729EncoderChannel(0); |
|
|
|
bcg729DecoderChannelContextStruct *d = initBcg729DecoderChannel(); |
|
|
|
if (e) { |
|
|
|
def->support_encoding = 1; |
|
|
|
closeBcg729EncoderChannel(e); |
|
|
|
} |
|
|
|
if (d) { |
|
|
|
def->support_decoding = 1; |
|
|
|
closeBcg729DecoderChannel(d); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static const char *bcg729_decoder_init(decoder_t *dec) { |
|
|
|
dec->u.bcg729 = initBcg729DecoderChannel(); |
|
|
|
if (!dec->u.bcg729) |
|
|
|
return "failed to initialize bcg729"; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static int bcg729_decoder_input(decoder_t *dec, const str *data, GQueue *out) { |
|
|
|
AVFrame *frame = av_frame_alloc(); |
|
|
|
frame->nb_samples = 80; |
|
|
|
frame->format = AV_SAMPLE_FMT_S16; |
|
|
|
frame->sample_rate = dec->in_format.clockrate; // 8000 |
|
|
|
frame->channel_layout = av_get_default_channel_layout(dec->in_format.channels); // 1 channel |
|
|
|
if (av_frame_get_buffer(frame, 0) < 0) |
|
|
|
abort(); |
|
|
|
|
|
|
|
// XXX handle lost packets and comfort noise |
|
|
|
bcg729Decoder(dec->u.bcg729, (void *) data->s, data->len, 0, 0, 0, (void *) frame->extended_data[0]); |
|
|
|
|
|
|
|
g_queue_push_tail(out, frame); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void bcg729_decoder_close(decoder_t *dec) { |
|
|
|
if (dec->u.bcg729) |
|
|
|
closeBcg729DecoderChannel(dec->u.bcg729); |
|
|
|
dec->u.bcg729 = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static const char *bcg729_encoder_init(encoder_t *enc) { |
|
|
|
enc->u.bcg729 = initBcg729EncoderChannel(0); // no VAD |
|
|
|
if (!enc->u.bcg729) |
|
|
|
return "failed to initialize bcg729"; |
|
|
|
|
|
|
|
enc->actual_format.format = AV_SAMPLE_FMT_S16; |
|
|
|
enc->actual_format.channels = 1; |
|
|
|
enc->actual_format.clockrate = 8000; |
|
|
|
enc->samples_per_frame = 80; |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static int bcg729_encoder_input(encoder_t *enc, AVFrame **frame) { |
|
|
|
if (!*frame) |
|
|
|
return 0; |
|
|
|
|
|
|
|
if ((*frame)->nb_samples != 80) { |
|
|
|
ilog(LOG_ERR, "bcg729: input %u samples instead of 80", (*frame)->nb_samples); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
av_new_packet(&enc->avpkt, 10); |
|
|
|
unsigned char len = 0; |
|
|
|
|
|
|
|
bcg729Encoder(enc->u.bcg729, (void *) (*frame)->extended_data[0], enc->avpkt.data, &len); |
|
|
|
if (!len) { |
|
|
|
av_packet_unref(&enc->avpkt); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
enc->avpkt.size = len; |
|
|
|
enc->avpkt.pts = (*frame)->pts; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void bcg729_encoder_close(encoder_t *enc) { |
|
|
|
if (enc->u.bcg729) |
|
|
|
closeBcg729EncoderChannel(enc->u.bcg729); |
|
|
|
enc->u.bcg729 = NULL; |
|
|
|
} |
|
|
|
#endif |