123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942 |
- /*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2014, Digium, Inc.
- *
- * Joshua Colp <jcolp@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
- /*! \file
- *
- * \brief Built-in supported codecs
- *
- * \author Joshua Colp <jcolp@digium.com>
- */
- /*** MODULEINFO
- <support_level>core</support_level>
- ***/
- #include "asterisk.h"
- ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
- #include "asterisk/logger.h"
- #include "asterisk/astobj2.h"
- #include "asterisk/codec.h"
- #include "asterisk/format.h"
- #include "asterisk/format_cache.h"
- #include "asterisk/frame.h"
- #include "asterisk/smoother.h"
- int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name,
- struct ast_module *mod);
- enum frame_type {
- TYPE_HIGH, /* 0x0 */
- TYPE_LOW, /* 0x1 */
- TYPE_SILENCE, /* 0x2 */
- TYPE_DONTSEND /* 0x3 */
- };
- #define TYPE_MASK 0x3
- static int g723_len(unsigned char buf)
- {
- enum frame_type type = buf & TYPE_MASK;
- switch(type) {
- case TYPE_DONTSEND:
- return 0;
- break;
- case TYPE_SILENCE:
- return 4;
- break;
- case TYPE_HIGH:
- return 24;
- break;
- case TYPE_LOW:
- return 20;
- break;
- default:
- ast_log(LOG_WARNING, "Badly encoded frame (%u)\n", type);
- }
- return -1;
- }
- static int g723_samples(struct ast_frame *frame)
- {
- unsigned char *buf = frame->data.ptr;
- int pos = 0, samples = 0, res;
- while(pos < frame->datalen) {
- res = g723_len(buf[pos]);
- if (res <= 0)
- break;
- samples += 240;
- pos += res;
- }
- return samples;
- }
- static int g723_length(unsigned int samples)
- {
- return (samples / 240) * 20;
- }
- static struct ast_codec g723 = {
- .name = "g723",
- .description = "G.723.1",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 30,
- .maximum_ms = 300,
- .default_ms = 30,
- .minimum_bytes = 20,
- .samples_count = g723_samples,
- .get_length = g723_length,
- };
- static int none_samples(struct ast_frame *frame)
- {
- return frame->datalen;
- }
- static int none_length(unsigned int samples) {
- return samples;
- }
- static struct ast_codec none = {
- .name = "none",
- .description = "<Null> codec",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000, /* This must have some sample rate to prevent divide by 0 */
- .minimum_ms = 10,
- .maximum_ms = 150,
- .default_ms = 20,
- .minimum_bytes = 20,
- .samples_count = none_samples,
- .get_length = none_length,
- };
- static int ulaw_samples(struct ast_frame *frame)
- {
- return frame->datalen;
- }
- static int ulaw_length(unsigned int samples)
- {
- return samples;
- }
- static struct ast_codec ulaw = {
- .name = "ulaw",
- .description = "G.711 u-law",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 150,
- .default_ms = 20,
- .minimum_bytes = 80,
- .samples_count = ulaw_samples,
- .get_length = ulaw_length,
- .smooth = 1,
- };
- static struct ast_codec alaw = {
- .name = "alaw",
- .description = "G.711 a-law",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 150,
- .default_ms = 20,
- .minimum_bytes = 80,
- .samples_count = ulaw_samples,
- .get_length = ulaw_length,
- .smooth = 1,
- };
- static int gsm_samples(struct ast_frame *frame)
- {
- return 160 * (frame->datalen / 33);
- }
- static int gsm_length(unsigned int samples)
- {
- return (samples / 160) * 33;
- }
- static struct ast_codec gsm = {
- .name = "gsm",
- .description = "GSM",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 20,
- .maximum_ms = 300,
- .default_ms = 20,
- .minimum_bytes = 33,
- .samples_count = gsm_samples,
- .get_length = gsm_length,
- .smooth = 1,
- };
- static int g726_samples(struct ast_frame *frame)
- {
- return frame->datalen * 2;
- }
- static int g726_length(unsigned int samples)
- {
- return samples / 2;
- }
- static struct ast_codec g726rfc3551 = {
- .name = "g726",
- .description = "G.726 RFC3551",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 300,
- .default_ms = 20,
- .minimum_bytes = 40,
- .samples_count = g726_samples,
- .get_length = g726_length,
- .smooth = 1,
- };
- static struct ast_codec g726aal2 = {
- .name = "g726aal2",
- .description = "G.726 AAL2",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 300,
- .default_ms = 20,
- .minimum_bytes = 40,
- .samples_count = g726_samples,
- .get_length = g726_length,
- .smooth = 1,
- };
- static struct ast_codec adpcm = {
- .name = "adpcm",
- .description = "Dialogic ADPCM",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 300,
- .default_ms = 20,
- .minimum_bytes = 40,
- .samples_count = g726_samples,
- .get_length = g726_length,
- .smooth = 1,
- };
- static int slin_samples(struct ast_frame *frame)
- {
- return frame->datalen / 2;
- }
- static int slin_length(unsigned int samples)
- {
- return samples * 2;
- }
- static struct ast_codec slin8 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 160,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static struct ast_codec slin12 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM (12kHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 12000,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 240,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static struct ast_codec slin16 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM (16kHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 16000,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 320,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static struct ast_codec slin24 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM (24kHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 24000,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 480,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static struct ast_codec slin32 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM (32kHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 32000,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 640,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static struct ast_codec slin44 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM (44kHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 44100,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 882,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static struct ast_codec slin48 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM (48kHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 48000,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 960,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static struct ast_codec slin96 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM (96kHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 96000,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 1920,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static struct ast_codec slin192 = {
- .name = "slin",
- .description = "16 bit Signed Linear PCM (192kHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 192000,
- .minimum_ms = 10,
- .maximum_ms = 70,
- .default_ms = 20,
- .minimum_bytes = 3840,
- .samples_count = slin_samples,
- .get_length = slin_length,
- .smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
- };
- static int lpc10_samples(struct ast_frame *frame)
- {
- int samples = 22 * 8;
- /* assumes that the RTP packet contains one LPC10 frame */
- samples += (((char *)(frame->data.ptr))[7] & 0x1) * 8;
- return samples;
- }
- static struct ast_codec lpc10 = {
- .name = "lpc10",
- .description = "LPC10",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 20,
- .maximum_ms = 20,
- .default_ms = 20,
- .minimum_bytes = 7,
- .samples_count = lpc10_samples,
- .smooth = 1,
- };
- static int g729_samples(struct ast_frame *frame)
- {
- return frame->datalen * 8;
- }
- static int g729_length(unsigned int samples)
- {
- return samples / 8;
- }
- static struct ast_codec g729a = {
- .name = "g729",
- .description = "G.729A",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 230,
- .default_ms = 20,
- .minimum_bytes = 10,
- .samples_count = g729_samples,
- .get_length = g729_length,
- .smooth = 1,
- };
- static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
- {
- int byte = bit / 8; /* byte containing first bit */
- int rem = 8 - (bit % 8); /* remaining bits in first byte */
- unsigned char ret = 0;
- if (n <= 0 || n > 8)
- return 0;
- if (rem < n) {
- ret = (data[byte] << (n - rem));
- ret |= (data[byte + 1] >> (8 - n + rem));
- } else {
- ret = (data[byte] >> (rem - n));
- }
- return (ret & (0xff >> (8 - n)));
- }
- static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
- {
- static const int SpeexWBSubModeSz[] = {
- 4, 36, 112, 192,
- 352, 0, 0, 0 };
- int off = bit;
- unsigned char c;
- /* skip up to two wideband frames */
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- c = get_n_bits_at(data, 3, off + 1);
- off += SpeexWBSubModeSz[c];
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- c = get_n_bits_at(data, 3, off + 1);
- off += SpeexWBSubModeSz[c];
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
- return -1;
- }
- }
- }
- return off - bit;
- }
- static int speex_samples(unsigned char *data, int len)
- {
- static const int SpeexSubModeSz[] = {
- 5, 43, 119, 160,
- 220, 300, 364, 492,
- 79, 0, 0, 0,
- 0, 0, 0, 0 };
- static const int SpeexInBandSz[] = {
- 1, 1, 4, 4,
- 4, 4, 4, 4,
- 8, 8, 16, 16,
- 32, 32, 64, 64 };
- int bit = 0;
- int cnt = 0;
- int off;
- unsigned char c;
- while ((len * 8 - bit) >= 5) {
- /* skip wideband frames */
- off = speex_get_wb_sz_at(data, len, bit);
- if (off < 0) {
- ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
- break;
- }
- bit += off;
- if ((len * 8 - bit) < 5)
- break;
- /* get control bits */
- c = get_n_bits_at(data, 5, bit);
- bit += 5;
- if (c == 15) {
- /* terminator */
- break;
- } else if (c == 14) {
- /* in-band signal; next 4 bits contain signal id */
- c = get_n_bits_at(data, 4, bit);
- bit += 4;
- bit += SpeexInBandSz[c];
- } else if (c == 13) {
- /* user in-band; next 4 bits contain msg len */
- c = get_n_bits_at(data, 4, bit);
- bit += 4;
- /* after which it's 5-bit signal id + c bytes of data */
- bit += 5 + c * 8;
- } else if (c > 8) {
- /* unknown */
- ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
- break;
- } else {
- /* skip number bits for submode (less the 5 control bits) */
- bit += SpeexSubModeSz[c] - 5;
- cnt += 160; /* new frame */
- }
- }
- return cnt;
- }
- static int speex8_samples(struct ast_frame *frame)
- {
- return speex_samples(frame->data.ptr, frame->datalen);
- }
- static struct ast_codec speex8 = {
- .name = "speex",
- .description = "SpeeX",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 60,
- .default_ms = 20,
- .minimum_bytes = 10,
- .samples_count = speex8_samples,
- };
- static int speex16_samples(struct ast_frame *frame)
- {
- return 2 * speex_samples(frame->data.ptr, frame->datalen);
- }
- static struct ast_codec speex16 = {
- .name = "speex",
- .description = "SpeeX 16khz",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 16000,
- .minimum_ms = 10,
- .maximum_ms = 60,
- .default_ms = 20,
- .minimum_bytes = 10,
- .samples_count = speex16_samples,
- };
- static int speex32_samples(struct ast_frame *frame)
- {
- return 4 * speex_samples(frame->data.ptr, frame->datalen);
- }
- static struct ast_codec speex32 = {
- .name = "speex",
- .description = "SpeeX 32khz",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 32000,
- .minimum_ms = 10,
- .maximum_ms = 60,
- .default_ms = 20,
- .minimum_bytes = 10,
- .samples_count = speex32_samples,
- };
- static int ilbc_samples(struct ast_frame *frame)
- {
- return 240 * (frame->datalen / 50);
- }
- static struct ast_codec ilbc = {
- .name = "ilbc",
- .description = "iLBC",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 30,
- .maximum_ms = 300,
- .default_ms = 30,
- .minimum_bytes = 50,
- .samples_count = ilbc_samples,
- .smooth = 1,
- };
- static struct ast_codec g722 = {
- .name = "g722",
- .description = "G722",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 16000,
- .minimum_ms = 10,
- .maximum_ms = 150,
- .default_ms = 20,
- .minimum_bytes = 80,
- .samples_count = g726_samples,
- .get_length = g726_length,
- .smooth = 1,
- };
- static int siren7_samples(struct ast_frame *frame)
- {
- return frame->datalen * (16000 / 4000);
- }
- static int siren7_length(unsigned int samples)
- {
- return samples / (16000 / 4000);
- }
- static struct ast_codec siren7 = {
- .name = "siren7",
- .description = "ITU G.722.1 (Siren7, licensed from Polycom)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 16000,
- .minimum_ms = 20,
- .maximum_ms = 80,
- .default_ms = 20,
- .minimum_bytes = 80,
- .samples_count = siren7_samples,
- .get_length = siren7_length,
- };
- static int siren14_samples(struct ast_frame *frame)
- {
- return (int) frame->datalen * ((float) 32000 / 6000);
- }
- static int siren14_length(unsigned int samples)
- {
- return (int) samples / ((float) 32000 / 6000);;
- }
- static struct ast_codec siren14 = {
- .name = "siren14",
- .description = "ITU G.722.1 Annex C, (Siren14, licensed from Polycom)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 32000,
- .minimum_ms = 20,
- .maximum_ms = 80,
- .default_ms = 20,
- .minimum_bytes = 120,
- .samples_count = siren14_samples,
- .get_length = siren14_length,
- };
- static struct ast_codec testlaw = {
- .name = "testlaw",
- .description = "G.711 test-law",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 10,
- .maximum_ms = 150,
- .default_ms = 20,
- .minimum_bytes = 80,
- .samples_count = ulaw_samples,
- .get_length = ulaw_length,
- .smooth = 1,
- };
- static int g719_samples(struct ast_frame *frame)
- {
- return (int) frame->datalen * ((float) 48000 / 8000);
- }
- static int g719_length(unsigned int samples)
- {
- return (int) samples / ((float) 48000 / 8000);
- }
- static struct ast_codec g719 = {
- .name = "g719",
- .description = "ITU G.719",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 48000,
- .minimum_ms = 20,
- .maximum_ms = 80,
- .default_ms = 20,
- .minimum_bytes = 160,
- .samples_count = g719_samples,
- .get_length = g719_length,
- };
- static int opus_samples(struct ast_frame *frame)
- {
- /*
- * XXX This is likely not at all what's intended from this
- * callback. If you have codec_opus.so loaded then this
- * function is overridden anyway. However, since opus is
- * variable bit rate and I cannot extract the calculation code
- * from the opus library, I am going to punt and assume 20ms
- * worth of samples. In testing, this has worked just fine.
- * Pass through support doesn't seem to care about the value
- * returned anyway.
- */
- return ast_format_get_sample_rate(frame->subclass.format) / 50;
- }
- static struct ast_codec opus = {
- .name = "opus",
- .description = "Opus Codec",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 48000,
- .minimum_ms = 20,
- .maximum_ms = 60,
- .default_ms = 20,
- .samples_count = opus_samples,
- .minimum_bytes = 10,
- };
- static struct ast_codec jpeg = {
- .name = "jpeg",
- .description = "JPEG image",
- .type = AST_MEDIA_TYPE_IMAGE,
- };
- static struct ast_codec png = {
- .name = "png",
- .description = "PNG Image",
- .type = AST_MEDIA_TYPE_IMAGE,
- };
- static struct ast_codec h261 = {
- .name = "h261",
- .description = "H.261 video",
- .type = AST_MEDIA_TYPE_VIDEO,
- .sample_rate = 1000,
- };
- static struct ast_codec h263 = {
- .name = "h263",
- .description = "H.263 video",
- .type = AST_MEDIA_TYPE_VIDEO,
- .sample_rate = 1000,
- };
- static struct ast_codec h263p = {
- .name = "h263p",
- .description = "H.263+ video",
- .type = AST_MEDIA_TYPE_VIDEO,
- .sample_rate = 1000,
- };
- static struct ast_codec h264 = {
- .name = "h264",
- .description = "H.264 video",
- .type = AST_MEDIA_TYPE_VIDEO,
- .sample_rate = 1000,
- };
- static struct ast_codec mpeg4 = {
- .name = "mpeg4",
- .description = "MPEG4 video",
- .type = AST_MEDIA_TYPE_VIDEO,
- .sample_rate = 1000,
- };
- static struct ast_codec vp8 = {
- .name = "vp8",
- .description = "VP8 video",
- .type = AST_MEDIA_TYPE_VIDEO,
- .sample_rate = 1000,
- };
- static struct ast_codec vp9 = {
- .name = "vp9",
- .description = "VP9 video",
- .type = AST_MEDIA_TYPE_VIDEO,
- .sample_rate = 1000,
- };
- static struct ast_codec t140red = {
- .name = "red",
- .description = "T.140 Realtime Text with redundancy",
- .type = AST_MEDIA_TYPE_TEXT,
- };
- static struct ast_codec t140 = {
- .name = "t140",
- .description = "Passthrough T.140 Realtime Text",
- .type = AST_MEDIA_TYPE_TEXT,
- };
- static int silk_samples(struct ast_frame *frame)
- {
- /* XXX This is likely not at all what's intended from this callback. However,
- * since SILK is variable bit rate, I have no idea how to take a frame of data
- * and determine the number of samples present. Instead, we base this on the
- * sample rate of the codec and the expected number of samples to receive in 20ms.
- * In testing, this has worked just fine.
- */
- return ast_format_get_sample_rate(frame->subclass.format) / 50;
- }
- static struct ast_codec silk8 = {
- .name = "silk",
- .description = "SILK Codec (8 KHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 8000,
- .minimum_ms = 20,
- .maximum_ms = 100,
- .default_ms = 20,
- .minimum_bytes = 160,
- .samples_count = silk_samples
- };
- static struct ast_codec silk12 = {
- .name = "silk",
- .description = "SILK Codec (12 KHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 12000,
- .minimum_ms = 20,
- .maximum_ms = 100,
- .default_ms = 20,
- .minimum_bytes = 240,
- .samples_count = silk_samples
- };
- static struct ast_codec silk16 = {
- .name = "silk",
- .description = "SILK Codec (16 KHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 16000,
- .minimum_ms = 20,
- .maximum_ms = 100,
- .default_ms = 20,
- .minimum_bytes = 320,
- .samples_count = silk_samples
- };
- static struct ast_codec silk24 = {
- .name = "silk",
- .description = "SILK Codec (24 KHz)",
- .type = AST_MEDIA_TYPE_AUDIO,
- .sample_rate = 24000,
- .minimum_ms = 20,
- .maximum_ms = 100,
- .default_ms = 20,
- .minimum_bytes = 480,
- .samples_count = silk_samples
- };
- #define CODEC_REGISTER_AND_CACHE(codec) \
- ({ \
- int __res_ ## __LINE__ = 0; \
- struct ast_format *__fmt_ ## __LINE__; \
- struct ast_codec *__codec_ ## __LINE__; \
- res |= __ast_codec_register_with_format(&(codec), (codec).name, NULL); \
- __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
- __fmt_ ## __LINE__ = __codec_ ## __LINE__ ? ast_format_create(__codec_ ## __LINE__) : NULL; \
- res |= ast_format_cache_set(__fmt_ ## __LINE__); \
- ao2_ref(__fmt_ ## __LINE__, -1); \
- ao2_ref(__codec_ ## __LINE__, -1); \
- __res_ ## __LINE__; \
- })
- #define CODEC_REGISTER_AND_CACHE_NAMED(fmt_name, codec) \
- ({ \
- int __res_ ## __LINE__ = 0; \
- struct ast_format *__fmt_ ## __LINE__; \
- struct ast_codec *__codec_ ## __LINE__; \
- res |= __ast_codec_register_with_format(&(codec), fmt_name, NULL); \
- __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
- __fmt_ ## __LINE__ = ast_format_create_named((fmt_name), __codec_ ## __LINE__); \
- res |= ast_format_cache_set(__fmt_ ## __LINE__); \
- ao2_ref(__fmt_ ## __LINE__, -1); \
- ao2_ref(__codec_ ## __LINE__, -1); \
- __res_ ## __LINE__; \
- })
- int ast_codec_builtin_init(void)
- {
- int res = 0;
- res |= CODEC_REGISTER_AND_CACHE(g723);
- res |= CODEC_REGISTER_AND_CACHE(ulaw);
- res |= CODEC_REGISTER_AND_CACHE(alaw);
- res |= CODEC_REGISTER_AND_CACHE(gsm);
- res |= CODEC_REGISTER_AND_CACHE(g726rfc3551);
- res |= CODEC_REGISTER_AND_CACHE(g726aal2);
- res |= CODEC_REGISTER_AND_CACHE(adpcm);
- res |= CODEC_REGISTER_AND_CACHE(slin8);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("slin12", slin12);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("slin16", slin16);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("slin24", slin24);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("slin32", slin32);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("slin44", slin44);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("slin48", slin48);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("slin96", slin96);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("slin192", slin192);
- res |= CODEC_REGISTER_AND_CACHE(lpc10);
- res |= CODEC_REGISTER_AND_CACHE(g729a);
- res |= CODEC_REGISTER_AND_CACHE(speex8);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("speex16", speex16);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("speex32", speex32);
- res |= CODEC_REGISTER_AND_CACHE(ilbc);
- res |= CODEC_REGISTER_AND_CACHE(g722);
- res |= CODEC_REGISTER_AND_CACHE(siren7);
- res |= CODEC_REGISTER_AND_CACHE(siren14);
- res |= CODEC_REGISTER_AND_CACHE(testlaw);
- res |= CODEC_REGISTER_AND_CACHE(g719);
- res |= CODEC_REGISTER_AND_CACHE(opus);
- res |= CODEC_REGISTER_AND_CACHE(jpeg);
- res |= CODEC_REGISTER_AND_CACHE(png);
- res |= CODEC_REGISTER_AND_CACHE(h261);
- res |= CODEC_REGISTER_AND_CACHE(h263);
- res |= CODEC_REGISTER_AND_CACHE(h263p);
- res |= CODEC_REGISTER_AND_CACHE(h264);
- res |= CODEC_REGISTER_AND_CACHE(mpeg4);
- res |= CODEC_REGISTER_AND_CACHE(vp8);
- res |= CODEC_REGISTER_AND_CACHE(vp9);
- res |= CODEC_REGISTER_AND_CACHE(t140red);
- res |= CODEC_REGISTER_AND_CACHE(t140);
- res |= CODEC_REGISTER_AND_CACHE(none);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("silk8", silk8);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("silk12", silk12);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("silk16", silk16);
- res |= CODEC_REGISTER_AND_CACHE_NAMED("silk24", silk24);
- return res;
- }
|