From a3cf8aea9b050bb7e5106bd54b3e31adc8c242ae Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Fri, 1 May 2026 13:30:06 -0400 Subject: [PATCH] MT#55283 add G.726 codec type The ffmpeg G.726 encoder operates on fixed frame sizes which don't reflect the expected frame size on the wire. Add an encoder init wrapper to set the correct frame size. Change-Id: I4d635e52b6c3bd4f924d1b295ec1bf4c56ef22bc --- lib/codeclib.c | 205 ++++++++++++++++++++++++++++--------------------- 1 file changed, 117 insertions(+), 88 deletions(-) diff --git a/lib/codeclib.c b/lib/codeclib.c index 034e420a4..0aef8488d 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -73,6 +73,8 @@ static const char *avc_encoder_init(encoder_t *enc, const str *); static int avc_encoder_input(encoder_t *enc, AVFrame **frame); static void avc_encoder_close(encoder_t *enc); +static const char *g726_encoder_init(encoder_t *enc, const str *); + static int amr_decoder_input(decoder_t *dec, const str *data, GQueue *out); static void amr_encoder_got_packet(encoder_t *enc); static int ilbc_decoder_input(decoder_t *dec, const str *data, GQueue *out); @@ -243,6 +245,15 @@ static const codec_type_t codec_type_avcodec = { .encoder_input = avc_encoder_input, .encoder_close = avc_encoder_close, }; +static const codec_type_t codec_type_g726 = { + .def_init = avc_def_init, + .decoder_init = avc_decoder_init, + .decoder_input = avc_decoder_input, + .decoder_close = avc_decoder_close, + .encoder_init = g726_encoder_init, + .encoder_input = avc_encoder_input, + .encoder_close = avc_encoder_close, +}; static const codec_type_t codec_type_libopus = { .decoder_init = libopus_decoder_init, .decoder_input = libopus_decoder_input, @@ -773,94 +784,102 @@ static struct codec_def_s __codec_defs[] = { .format_cmp = format_cmp_ignore, .codec_type = &codec_type_cn, }, - { - .rtpname = "G726-16", - .avcodec_id = AV_CODEC_ID_ADPCM_G726, - .default_clockrate = 8000, - .default_channels = 1, - .default_ptime = 20, - .minimum_ptime = 20, - .default_bitrate = 16000, - .packetizer = packetizer_passthrough, - .media_type = MT_AUDIO, - .codec_type = &codec_type_avcodec, - .dtx_methods = { - [DTX_SILENCE] = &dtx_method_silence, - [DTX_CN] = &dtx_method_cn, - }, - }, - { - .rtpname = "G726-24", - .avcodec_id = AV_CODEC_ID_ADPCM_G726, - .default_clockrate = 8000, - .default_channels = 1, - .default_ptime = 20, - .minimum_ptime = 20, - .default_bitrate = 24000, - .packetizer = packetizer_passthrough, - .media_type = MT_AUDIO, - .codec_type = &codec_type_avcodec, - .dtx_methods = { - [DTX_SILENCE] = &dtx_method_silence, - [DTX_CN] = &dtx_method_cn, - }, - }, - { - .rtpname = "G726-32", - .avcodec_id = AV_CODEC_ID_ADPCM_G726, - .default_clockrate = 8000, - .default_channels = 1, - .default_ptime = 20, - .minimum_ptime = 20, - .default_bitrate = 32000, - .packetizer = packetizer_passthrough, - .media_type = MT_AUDIO, - .codec_type = &codec_type_avcodec, - .dtx_methods = { - [DTX_SILENCE] = &dtx_method_silence, - [DTX_CN] = &dtx_method_cn, - }, - }, - { - .rtpname = "G726-40", - .avcodec_id = AV_CODEC_ID_ADPCM_G726, - .default_clockrate = 8000, - .default_channels = 1, - .default_ptime = 20, - .minimum_ptime = 20, - .default_bitrate = 40000, - .packetizer = packetizer_passthrough, - .media_type = MT_AUDIO, - .codec_type = &codec_type_avcodec, - .dtx_methods = { - [DTX_SILENCE] = &dtx_method_silence, - [DTX_CN] = &dtx_method_cn, - }, - }, - { - .rtpname = "L16", - .avcodec_id = AV_CODEC_ID_PCM_S16BE, - .default_clockrate = 44100, - .default_channels = 1, - .default_ptime = 20, - .minimum_ptime = 20, - .bits_per_sample = 16, - .packetizer = packetizer_passthrough, - .media_type = MT_AUDIO, - .codec_type = &codec_type_avcodec, - }, - { - .rtpname = "X-L16", - .avcodec_id = AV_CODEC_ID_PCM_S16LE, - .default_clockrate = 44100, - .default_channels = 1, - .default_ptime = 20, - .minimum_ptime = 20, - .bits_per_sample = 16, - .packetizer = packetizer_passthrough, - .media_type = MT_AUDIO, - .codec_type = &codec_type_avcodec, - }, + { + .rtpname = "G726-16", + .avcodec_id = AV_CODEC_ID_ADPCM_G726, + .default_clockrate = 8000, + .default_channels = 1, + .default_ptime = 20, + .minimum_ptime = 20, + .default_bitrate = 16000, + .packetizer = packetizer_samplestream, + .bits_per_sample = 2, + .media_type = MT_AUDIO, + .codec_type = &codec_type_g726, + .dtx_methods = { + [DTX_SILENCE] = &dtx_method_silence, + [DTX_CN] = &dtx_method_cn, + }, + .fixed_sizes = 1, + }, + { + .rtpname = "G726-24", + .avcodec_id = AV_CODEC_ID_ADPCM_G726, + .default_clockrate = 8000, + .default_channels = 1, + .default_ptime = 20, + .minimum_ptime = 20, + .default_bitrate = 24000, + .packetizer = packetizer_samplestream, + .bits_per_sample = 3, + .media_type = MT_AUDIO, + .codec_type = &codec_type_g726, + .dtx_methods = { + [DTX_SILENCE] = &dtx_method_silence, + [DTX_CN] = &dtx_method_cn, + }, + .fixed_sizes = 1, + }, + { + .rtpname = "G726-32", + .avcodec_id = AV_CODEC_ID_ADPCM_G726, + .default_clockrate = 8000, + .default_channels = 1, + .default_ptime = 20, + .minimum_ptime = 20, + .default_bitrate = 32000, + .packetizer = packetizer_samplestream, + .bits_per_sample = 4, + .media_type = MT_AUDIO, + .codec_type = &codec_type_g726, + .dtx_methods = { + [DTX_SILENCE] = &dtx_method_silence, + [DTX_CN] = &dtx_method_cn, + }, + .fixed_sizes = 1, + }, + { + .rtpname = "G726-40", + .avcodec_id = AV_CODEC_ID_ADPCM_G726, + .default_clockrate = 8000, + .default_channels = 1, + .default_ptime = 20, + .minimum_ptime = 20, + .default_bitrate = 40000, + .packetizer = packetizer_samplestream, + .bits_per_sample = 5, + .media_type = MT_AUDIO, + .codec_type = &codec_type_g726, + .dtx_methods = { + [DTX_SILENCE] = &dtx_method_silence, + [DTX_CN] = &dtx_method_cn, + }, + .fixed_sizes = 1, + }, + { + .rtpname = "L16", + .avcodec_id = AV_CODEC_ID_PCM_S16BE, + .default_clockrate = 44100, + .default_channels = 1, + .default_ptime = 20, + .minimum_ptime = 20, + .bits_per_sample = 16, + .packetizer = packetizer_passthrough, + .media_type = MT_AUDIO, + .codec_type = &codec_type_avcodec, + }, + { + .rtpname = "X-L16", + .avcodec_id = AV_CODEC_ID_PCM_S16LE, + .default_clockrate = 44100, + .default_channels = 1, + .default_ptime = 20, + .minimum_ptime = 20, + .bits_per_sample = 16, + .packetizer = packetizer_passthrough, + .media_type = MT_AUDIO, + .codec_type = &codec_type_avcodec, + }, // for file reading and writing { .rtpname = "PCM-U8", @@ -1891,6 +1910,16 @@ static const char *avc_encoder_init(encoder_t *enc, const str *extra_opts) { return NULL; } +static const char *g726_encoder_init(encoder_t *enc, const str *extra_opts) { + const char *err = avc_encoder_init(enc, extra_opts); + if (err) + return err; + + enc->samples_per_packet = enc->ptime * 8; + + return NULL; +} + int encoder_config(encoder_t *enc, codec_def_t *def, int bitrate, int ptime, const format_t *requested_format, format_t *actual_format) {