opencore_amr.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. /*
  2. * Copyright (C) 2011-2013 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2011 Dan Arrhenius <dan@keystream.se>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. /*
  20. * AMR codec implementation with OpenCORE AMR library
  21. */
  22. #include <pjmedia-codec/g722.h>
  23. #include <pjmedia-codec/amr_sdp_match.h>
  24. #include <pjmedia/codec.h>
  25. #include <pjmedia/errno.h>
  26. #include <pjmedia/endpoint.h>
  27. #include <pjmedia/plc.h>
  28. #include <pjmedia/port.h>
  29. #include <pjmedia/silencedet.h>
  30. #include <pj/assert.h>
  31. #include <pj/log.h>
  32. #include <pj/pool.h>
  33. #include <pj/string.h>
  34. #include <pj/os.h>
  35. #include <pj/math.h>
  36. #if defined(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC) && \
  37. (PJMEDIA_HAS_OPENCORE_AMRNB_CODEC != 0)
  38. #define USE_AMRNB
  39. #endif
  40. #if defined(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC) && \
  41. (PJMEDIA_HAS_OPENCORE_AMRWB_CODEC != 0)
  42. #define USE_AMRWB
  43. #endif
  44. #if defined(USE_AMRNB) || defined(USE_AMRWB)
  45. #ifdef USE_AMRNB
  46. #include <opencore-amrnb/interf_enc.h>
  47. #include <opencore-amrnb/interf_dec.h>
  48. #endif
  49. #ifdef USE_AMRWB
  50. #include <vo-amrwbenc/enc_if.h>
  51. #include <opencore-amrwb/dec_if.h>
  52. #endif
  53. #include <pjmedia-codec/amr_helper.h>
  54. #include <pjmedia-codec/opencore_amr.h>
  55. #define THIS_FILE "opencore_amr.c"
  56. /* Tracing */
  57. #define PJ_TRACE 0
  58. #if PJ_TRACE
  59. # define TRACE_(expr) PJ_LOG(4,expr)
  60. #else
  61. # define TRACE_(expr)
  62. #endif
  63. /* Use PJMEDIA PLC */
  64. #define USE_PJMEDIA_PLC 1
  65. #define FRAME_LENGTH_MS 20
  66. /* Prototypes for AMR factory */
  67. static pj_status_t amr_test_alloc(pjmedia_codec_factory *factory,
  68. const pjmedia_codec_info *id );
  69. static pj_status_t amr_default_attr(pjmedia_codec_factory *factory,
  70. const pjmedia_codec_info *id,
  71. pjmedia_codec_param *attr );
  72. static pj_status_t amr_enum_codecs(pjmedia_codec_factory *factory,
  73. unsigned *count,
  74. pjmedia_codec_info codecs[]);
  75. static pj_status_t amr_alloc_codec(pjmedia_codec_factory *factory,
  76. const pjmedia_codec_info *id,
  77. pjmedia_codec **p_codec);
  78. static pj_status_t amr_dealloc_codec(pjmedia_codec_factory *factory,
  79. pjmedia_codec *codec );
  80. /* Prototypes for AMR implementation. */
  81. static pj_status_t amr_codec_init(pjmedia_codec *codec,
  82. pj_pool_t *pool );
  83. static pj_status_t amr_codec_open(pjmedia_codec *codec,
  84. pjmedia_codec_param *attr );
  85. static pj_status_t amr_codec_close(pjmedia_codec *codec );
  86. static pj_status_t amr_codec_modify(pjmedia_codec *codec,
  87. const pjmedia_codec_param *attr );
  88. static pj_status_t amr_codec_parse(pjmedia_codec *codec,
  89. void *pkt,
  90. pj_size_t pkt_size,
  91. const pj_timestamp *ts,
  92. unsigned *frame_cnt,
  93. pjmedia_frame frames[]);
  94. static pj_status_t amr_codec_encode(pjmedia_codec *codec,
  95. const struct pjmedia_frame *input,
  96. unsigned output_buf_len,
  97. struct pjmedia_frame *output);
  98. static pj_status_t amr_codec_decode(pjmedia_codec *codec,
  99. const struct pjmedia_frame *input,
  100. unsigned output_buf_len,
  101. struct pjmedia_frame *output);
  102. static pj_status_t amr_codec_recover(pjmedia_codec *codec,
  103. unsigned output_buf_len,
  104. struct pjmedia_frame *output);
  105. /* Definition for AMR codec operations. */
  106. static pjmedia_codec_op amr_op =
  107. {
  108. &amr_codec_init,
  109. &amr_codec_open,
  110. &amr_codec_close,
  111. &amr_codec_modify,
  112. &amr_codec_parse,
  113. &amr_codec_encode,
  114. &amr_codec_decode,
  115. &amr_codec_recover
  116. };
  117. /* Definition for AMR codec factory operations. */
  118. static pjmedia_codec_factory_op amr_factory_op =
  119. {
  120. &amr_test_alloc,
  121. &amr_default_attr,
  122. &amr_enum_codecs,
  123. &amr_alloc_codec,
  124. &amr_dealloc_codec,
  125. &pjmedia_codec_opencore_amr_deinit
  126. };
  127. /* AMR factory */
  128. static struct amr_codec_factory
  129. {
  130. pjmedia_codec_factory base;
  131. pjmedia_endpt *endpt;
  132. pj_pool_t *pool;
  133. pj_bool_t init[2];
  134. } amr_codec_factory;
  135. /* AMR codec private data. */
  136. struct amr_data
  137. {
  138. pj_pool_t *pool;
  139. unsigned clock_rate;
  140. void *encoder;
  141. void *decoder;
  142. pj_bool_t plc_enabled;
  143. pj_bool_t vad_enabled;
  144. int enc_mode;
  145. pjmedia_codec_amr_pack_setting enc_setting;
  146. pjmedia_codec_amr_pack_setting dec_setting;
  147. #if USE_PJMEDIA_PLC
  148. pjmedia_plc *plc;
  149. #endif
  150. pj_timestamp last_tx;
  151. };
  152. /* Index for AMR tables. */
  153. enum
  154. {
  155. IDX_AMR_NB, /* Index for narrowband. */
  156. IDX_AMR_WB /* Index for wideband. */
  157. };
  158. static pjmedia_codec_amr_config def_config[2] =
  159. {{ /* AMR-NB */
  160. PJ_FALSE, /* octet align */
  161. 5900 /* bitrate */
  162. },
  163. { /* AMR-WB */
  164. PJ_FALSE, /* octet align */
  165. 12650 /* bitrate */
  166. }};
  167. static const pj_uint16_t* amr_bitrates[2] =
  168. {pjmedia_codec_amrnb_bitrates, pjmedia_codec_amrwb_bitrates};
  169. static const unsigned amr_bitrates_size[2] =
  170. {
  171. PJ_ARRAY_SIZE(pjmedia_codec_amrnb_bitrates),
  172. PJ_ARRAY_SIZE(pjmedia_codec_amrwb_bitrates)
  173. };
  174. /*
  175. * Initialize and register AMR codec factory to pjmedia endpoint.
  176. */
  177. PJ_DEF(pj_status_t) pjmedia_codec_opencore_amr_init( pjmedia_endpt *endpt,
  178. unsigned options)
  179. {
  180. pjmedia_codec_mgr *codec_mgr;
  181. pj_str_t codec_name;
  182. pj_status_t status;
  183. if (amr_codec_factory.pool != NULL)
  184. return PJ_SUCCESS;
  185. /* Create AMR codec factory. */
  186. amr_codec_factory.base.op = &amr_factory_op;
  187. amr_codec_factory.base.factory_data = NULL;
  188. amr_codec_factory.endpt = endpt;
  189. #ifdef USE_AMRNB
  190. amr_codec_factory.init[IDX_AMR_NB] = ((options & PJMEDIA_AMR_NO_NB) == 0);
  191. #else
  192. amr_codec_factory.init[IDX_AMR_NB] = PJ_FALSE;
  193. #endif
  194. #ifdef USE_AMRWB
  195. amr_codec_factory.init[IDX_AMR_WB] = ((options & PJMEDIA_AMR_NO_WB) == 0);
  196. #else
  197. amr_codec_factory.init[IDX_AMR_WB] = PJ_FALSE;
  198. #endif
  199. amr_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "amr", 1000,
  200. 1000);
  201. if (!amr_codec_factory.pool)
  202. return PJ_ENOMEM;
  203. /* Get the codec manager. */
  204. codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
  205. if (!codec_mgr) {
  206. status = PJ_EINVALIDOP;
  207. goto on_error;
  208. }
  209. /* Register format match callback. */
  210. #ifdef USE_AMRNB
  211. if ((options & PJMEDIA_AMR_NO_NB) == 0) {
  212. pj_cstr(&codec_name, "AMR");
  213. status = pjmedia_sdp_neg_register_fmt_match_cb(
  214. &codec_name,
  215. &pjmedia_codec_amr_match_sdp);
  216. if (status != PJ_SUCCESS)
  217. goto on_error;
  218. }
  219. #endif
  220. #ifdef USE_AMRWB
  221. if ((options & PJMEDIA_AMR_NO_WB) == 0) {
  222. pj_cstr(&codec_name, "AMR-WB");
  223. status = pjmedia_sdp_neg_register_fmt_match_cb(
  224. &codec_name,
  225. &pjmedia_codec_amr_match_sdp);
  226. if (status != PJ_SUCCESS)
  227. goto on_error;
  228. }
  229. #endif
  230. /* Register codec factory to endpoint. */
  231. status = pjmedia_codec_mgr_register_factory(codec_mgr,
  232. &amr_codec_factory.base);
  233. if (status != PJ_SUCCESS)
  234. goto on_error;
  235. /* Done. */
  236. return PJ_SUCCESS;
  237. on_error:
  238. pj_pool_release(amr_codec_factory.pool);
  239. amr_codec_factory.pool = NULL;
  240. return status;
  241. }
  242. PJ_DEF(pj_status_t)
  243. pjmedia_codec_opencore_amr_init_default( pjmedia_endpt *endpt )
  244. {
  245. return pjmedia_codec_opencore_amr_init(endpt, 0);
  246. }
  247. PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_init( pjmedia_endpt *endpt )
  248. {
  249. return pjmedia_codec_opencore_amr_init(endpt, PJMEDIA_AMR_NO_WB);
  250. }
  251. /*
  252. * Unregister AMR codec factory from pjmedia endpoint and deinitialize
  253. * the AMR codec library.
  254. */
  255. PJ_DEF(pj_status_t) pjmedia_codec_opencore_amr_deinit(void)
  256. {
  257. pjmedia_codec_mgr *codec_mgr;
  258. pj_status_t status;
  259. amr_codec_factory.init[IDX_AMR_NB] = PJ_FALSE;
  260. amr_codec_factory.init[IDX_AMR_WB] = PJ_FALSE;
  261. if (amr_codec_factory.pool == NULL)
  262. return PJ_SUCCESS;
  263. /* Get the codec manager. */
  264. codec_mgr = pjmedia_endpt_get_codec_mgr(amr_codec_factory.endpt);
  265. if (!codec_mgr) {
  266. pj_pool_release(amr_codec_factory.pool);
  267. amr_codec_factory.pool = NULL;
  268. return PJ_EINVALIDOP;
  269. }
  270. /* Unregister AMR codec factory. */
  271. status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
  272. &amr_codec_factory.base);
  273. /* Destroy pool. */
  274. pj_pool_release(amr_codec_factory.pool);
  275. amr_codec_factory.pool = NULL;
  276. return status;
  277. }
  278. PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void)
  279. {
  280. if (amr_codec_factory.init[IDX_AMR_NB] &&
  281. amr_codec_factory.init[IDX_AMR_WB])
  282. {
  283. PJ_LOG(4, (THIS_FILE, "Should call "
  284. "pjmedia_codec_opencore_amr_deinit() instead"));
  285. return PJ_EINVALIDOP;
  286. }
  287. return pjmedia_codec_opencore_amr_deinit();
  288. }
  289. static pj_status_t
  290. amr_set_config(unsigned idx, const pjmedia_codec_amr_config *config)
  291. {
  292. unsigned nbitrates;
  293. def_config[idx] = *config;
  294. /* Normalize bitrate. */
  295. nbitrates = amr_bitrates_size[idx];
  296. if (def_config[idx].bitrate < amr_bitrates[idx][0]) {
  297. def_config[idx].bitrate = amr_bitrates[idx][0];
  298. } else if (def_config[idx].bitrate > amr_bitrates[idx][nbitrates-1]) {
  299. def_config[idx].bitrate = amr_bitrates[idx][nbitrates-1];
  300. } else
  301. {
  302. unsigned i;
  303. for (i = 0; i < nbitrates; ++i) {
  304. if (def_config[idx].bitrate <= amr_bitrates[idx][i])
  305. break;
  306. }
  307. def_config[idx].bitrate = amr_bitrates[idx][i];
  308. }
  309. return PJ_SUCCESS;
  310. }
  311. PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_set_config(
  312. const pjmedia_codec_amrnb_config *config)
  313. {
  314. return amr_set_config(IDX_AMR_NB, (const pjmedia_codec_amr_config *)config);
  315. }
  316. PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrwb_set_config(
  317. const pjmedia_codec_amrwb_config *config)
  318. {
  319. return amr_set_config(IDX_AMR_WB, (const pjmedia_codec_amr_config *)config);
  320. }
  321. /*
  322. * Check if factory can allocate the specified codec.
  323. */
  324. static pj_status_t amr_test_alloc( pjmedia_codec_factory *factory,
  325. const pjmedia_codec_info *info )
  326. {
  327. const pj_str_t amr_tag = { "AMR", 3};
  328. const pj_str_t amrwb_tag = { "AMR-WB", 6};
  329. PJ_UNUSED_ARG(factory);
  330. /* Type MUST be audio. */
  331. if (info->type != PJMEDIA_TYPE_AUDIO)
  332. return PJMEDIA_CODEC_EUNSUP;
  333. /* Check payload type. */
  334. if (info->pt != PJMEDIA_RTP_PT_AMR && info->pt != PJMEDIA_RTP_PT_AMRWB)
  335. return PJMEDIA_CODEC_EUNSUP;
  336. /* Check encoding name. */
  337. if (pj_stricmp(&info->encoding_name, &amr_tag) != 0 &&
  338. pj_stricmp(&info->encoding_name, &amrwb_tag) != 0)
  339. {
  340. return PJMEDIA_CODEC_EUNSUP;
  341. }
  342. /* Check clock-rate */
  343. if ((info->clock_rate == 8000 && amr_codec_factory.init[IDX_AMR_NB]) ||
  344. (info->clock_rate == 16000 && amr_codec_factory.init[IDX_AMR_WB]))
  345. {
  346. return PJ_SUCCESS;
  347. }
  348. /* Unsupported or disabled. */
  349. return PJMEDIA_CODEC_EUNSUP;
  350. }
  351. /*
  352. * Generate default attribute.
  353. */
  354. static pj_status_t amr_default_attr( pjmedia_codec_factory *factory,
  355. const pjmedia_codec_info *id,
  356. pjmedia_codec_param *attr )
  357. {
  358. unsigned idx;
  359. PJ_UNUSED_ARG(factory);
  360. idx = (id->clock_rate <= 8000? IDX_AMR_NB: IDX_AMR_WB);
  361. pj_bzero(attr, sizeof(pjmedia_codec_param));
  362. attr->info.clock_rate = (id->clock_rate <= 8000? 8000: 16000);
  363. attr->info.channel_cnt = 1;
  364. attr->info.avg_bps = def_config[idx].bitrate;
  365. attr->info.max_bps = amr_bitrates[idx][amr_bitrates_size[idx]-1];
  366. attr->info.pcm_bits_per_sample = 16;
  367. attr->info.frm_ptime = 20;
  368. attr->info.pt = (pj_uint8_t)id->pt;
  369. attr->setting.frm_per_pkt = 1;
  370. attr->setting.vad = 1;
  371. attr->setting.plc = 1;
  372. if (def_config[idx].octet_align) {
  373. attr->setting.dec_fmtp.cnt = 1;
  374. attr->setting.dec_fmtp.param[0].name = pj_str("octet-align");
  375. attr->setting.dec_fmtp.param[0].val = pj_str("1");
  376. }
  377. /* Default all other flag bits disabled. */
  378. return PJ_SUCCESS;
  379. }
  380. /*
  381. * Enum codecs supported by this factory (i.e. AMR-NB and AMR-WB).
  382. */
  383. static pj_status_t amr_enum_codecs( pjmedia_codec_factory *factory,
  384. unsigned *count,
  385. pjmedia_codec_info codecs[])
  386. {
  387. PJ_UNUSED_ARG(factory);
  388. PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
  389. *count = 0;
  390. if (amr_codec_factory.init[IDX_AMR_NB]) {
  391. pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
  392. codecs[*count].encoding_name = pj_str("AMR");
  393. codecs[*count].pt = PJMEDIA_RTP_PT_AMR;
  394. codecs[*count].type = PJMEDIA_TYPE_AUDIO;
  395. codecs[*count].clock_rate = 8000;
  396. codecs[*count].channel_cnt = 1;
  397. (*count)++;
  398. }
  399. if (amr_codec_factory.init[IDX_AMR_WB]) {
  400. pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
  401. codecs[*count].encoding_name = pj_str("AMR-WB");
  402. codecs[*count].pt = PJMEDIA_RTP_PT_AMRWB;
  403. codecs[*count].type = PJMEDIA_TYPE_AUDIO;
  404. codecs[*count].clock_rate = 16000;
  405. codecs[*count].channel_cnt = 1;
  406. (*count)++;
  407. }
  408. return PJ_SUCCESS;
  409. }
  410. /*
  411. * Allocate a new AMR codec instance.
  412. */
  413. static pj_status_t amr_alloc_codec( pjmedia_codec_factory *factory,
  414. const pjmedia_codec_info *id,
  415. pjmedia_codec **p_codec)
  416. {
  417. pj_pool_t *pool;
  418. pjmedia_codec *codec;
  419. struct amr_data *amr_data;
  420. pj_status_t status;
  421. PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
  422. PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
  423. pool = pjmedia_endpt_create_pool(amr_codec_factory.endpt, "amr-inst",
  424. 512, 512);
  425. codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
  426. PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
  427. codec->op = &amr_op;
  428. codec->factory = factory;
  429. amr_data = PJ_POOL_ZALLOC_T(pool, struct amr_data);
  430. codec->codec_data = amr_data;
  431. amr_data->pool = pool;
  432. #if USE_PJMEDIA_PLC
  433. /* Create PLC */
  434. status = pjmedia_plc_create(pool, id->clock_rate,
  435. id->clock_rate * FRAME_LENGTH_MS / 1000, 0,
  436. &amr_data->plc);
  437. if (status != PJ_SUCCESS) {
  438. return status;
  439. }
  440. #else
  441. PJ_UNUSED_ARG(status);
  442. #endif
  443. *p_codec = codec;
  444. return PJ_SUCCESS;
  445. }
  446. /*
  447. * Free codec.
  448. */
  449. static pj_status_t amr_dealloc_codec( pjmedia_codec_factory *factory,
  450. pjmedia_codec *codec )
  451. {
  452. struct amr_data *amr_data;
  453. PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
  454. PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
  455. amr_data = (struct amr_data*) codec->codec_data;
  456. /* Close codec, if it's not closed. */
  457. amr_codec_close(codec);
  458. pj_pool_release(amr_data->pool);
  459. amr_data = NULL;
  460. return PJ_SUCCESS;
  461. }
  462. /*
  463. * Init codec.
  464. */
  465. static pj_status_t amr_codec_init( pjmedia_codec *codec,
  466. pj_pool_t *pool )
  467. {
  468. PJ_UNUSED_ARG(codec);
  469. PJ_UNUSED_ARG(pool);
  470. return PJ_SUCCESS;
  471. }
  472. /*
  473. * Open codec.
  474. */
  475. static pj_status_t amr_codec_open( pjmedia_codec *codec,
  476. pjmedia_codec_param *attr )
  477. {
  478. struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
  479. pjmedia_codec_amr_pack_setting *setting;
  480. unsigned i;
  481. pj_uint8_t octet_align = 0;
  482. pj_int8_t enc_mode;
  483. const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
  484. unsigned idx;
  485. PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
  486. PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
  487. idx = (attr->info.clock_rate <= 8000? IDX_AMR_NB: IDX_AMR_WB);
  488. enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps);
  489. pj_assert(enc_mode >= 0 && (unsigned)enc_mode < amr_bitrates_size[idx]);
  490. /* Check octet-align */
  491. for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
  492. if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name,
  493. &STR_FMTP_OCTET_ALIGN) == 0)
  494. {
  495. octet_align = (pj_uint8_t)
  496. (pj_strtoul(&attr->setting.dec_fmtp.param[i].val));
  497. break;
  498. }
  499. }
  500. /* Check mode-set */
  501. for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
  502. const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8};
  503. if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name,
  504. &STR_FMTP_MODE_SET) == 0)
  505. {
  506. const char *p;
  507. pj_size_t l;
  508. pj_int8_t diff = 99;
  509. /* Encoding mode is chosen based on local default mode setting:
  510. * - if local default mode is included in the mode-set, use it
  511. * - otherwise, find the closest mode to local default mode;
  512. * if there are two closest modes, prefer to use the higher
  513. * one, e.g: local default mode is 4, the mode-set param
  514. * contains '2,3,5,6', then 5 will be chosen.
  515. */
  516. p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val);
  517. l = pj_strlen(&attr->setting.enc_fmtp.param[i].val);
  518. while (l--) {
  519. if (*p>='0' && (unsigned)*p<=('0'+amr_bitrates_size[idx]-1)) {
  520. pj_int8_t tmp = *p - '0' - enc_mode;
  521. if (PJ_ABS(diff) > PJ_ABS(tmp) ||
  522. (PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff))
  523. {
  524. diff = tmp;
  525. if (diff == 0) break;
  526. }
  527. }
  528. ++p;
  529. }
  530. PJ_ASSERT_RETURN(diff != 99, PJMEDIA_CODEC_EFAILED);
  531. enc_mode = enc_mode + diff;
  532. break;
  533. }
  534. }
  535. amr_data->clock_rate = attr->info.clock_rate;
  536. amr_data->vad_enabled = (attr->setting.vad != 0);
  537. amr_data->plc_enabled = (attr->setting.plc != 0);
  538. amr_data->enc_mode = enc_mode;
  539. if (idx == IDX_AMR_NB) {
  540. #ifdef USE_AMRNB
  541. amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
  542. #endif
  543. } else {
  544. #ifdef USE_AMRWB
  545. amr_data->encoder = E_IF_init();
  546. #endif
  547. }
  548. if (amr_data->encoder == NULL) {
  549. TRACE_((THIS_FILE, "Encoder initialization failed"));
  550. amr_codec_close(codec);
  551. return PJMEDIA_CODEC_EFAILED;
  552. }
  553. setting = &amr_data->enc_setting;
  554. pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
  555. setting->amr_nb = (idx == IDX_AMR_NB? 1: 0);
  556. setting->reorder = 0;
  557. setting->octet_aligned = octet_align;
  558. setting->cmr = 15;
  559. if (idx == IDX_AMR_NB) {
  560. #ifdef USE_AMRNB
  561. amr_data->decoder = Decoder_Interface_init();
  562. #endif
  563. } else {
  564. #ifdef USE_AMRWB
  565. amr_data->decoder = D_IF_init();
  566. #endif
  567. }
  568. if (amr_data->decoder == NULL) {
  569. TRACE_((THIS_FILE, "Decoder initialization failed"));
  570. amr_codec_close(codec);
  571. return PJMEDIA_CODEC_EFAILED;
  572. }
  573. setting = &amr_data->dec_setting;
  574. pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
  575. setting->amr_nb = (idx == IDX_AMR_NB? 1: 0);
  576. setting->reorder = 0;
  577. setting->octet_aligned = octet_align;
  578. TRACE_((THIS_FILE, "AMR codec allocated: clockrate=%d vad=%d, plc=%d,"
  579. " bitrate=%d", amr_data->clock_rate,
  580. amr_data->vad_enabled, amr_data->plc_enabled,
  581. amr_bitrates[idx][amr_data->enc_mode]));
  582. return PJ_SUCCESS;
  583. }
  584. /*
  585. * Close codec.
  586. */
  587. static pj_status_t amr_codec_close( pjmedia_codec *codec )
  588. {
  589. struct amr_data *amr_data;
  590. PJ_ASSERT_RETURN(codec, PJ_EINVAL);
  591. amr_data = (struct amr_data*) codec->codec_data;
  592. PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
  593. if (amr_data->encoder) {
  594. if (amr_data->enc_setting.amr_nb) {
  595. #ifdef USE_AMRNB
  596. Encoder_Interface_exit(amr_data->encoder);
  597. #endif
  598. } else {
  599. #ifdef USE_AMRWB
  600. E_IF_exit(amr_data->encoder);
  601. #endif
  602. }
  603. amr_data->encoder = NULL;
  604. }
  605. if (amr_data->decoder) {
  606. if (amr_data->dec_setting.amr_nb) {
  607. #ifdef USE_AMRNB
  608. Decoder_Interface_exit(amr_data->decoder);
  609. #endif
  610. } else {
  611. #ifdef USE_AMRWB
  612. D_IF_exit(amr_data->decoder);
  613. #endif
  614. }
  615. amr_data->decoder = NULL;
  616. }
  617. TRACE_((THIS_FILE, "AMR codec closed"));
  618. return PJ_SUCCESS;
  619. }
  620. /*
  621. * Modify codec settings.
  622. */
  623. static pj_status_t amr_codec_modify( pjmedia_codec *codec,
  624. const pjmedia_codec_param *attr )
  625. {
  626. struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
  627. pj_bool_t prev_vad_state;
  628. pj_assert(amr_data != NULL);
  629. pj_assert(amr_data->encoder != NULL && amr_data->decoder != NULL);
  630. prev_vad_state = amr_data->vad_enabled;
  631. amr_data->vad_enabled = (attr->setting.vad != 0);
  632. amr_data->plc_enabled = (attr->setting.plc != 0);
  633. if (amr_data->enc_setting.amr_nb &&
  634. prev_vad_state != amr_data->vad_enabled)
  635. {
  636. /* Reinit AMR encoder to update VAD setting */
  637. TRACE_((THIS_FILE, "Reiniting AMR encoder to update VAD setting."));
  638. #ifdef USE_AMRNB
  639. Encoder_Interface_exit(amr_data->encoder);
  640. amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
  641. #endif
  642. if (amr_data->encoder == NULL) {
  643. TRACE_((THIS_FILE, "Encoder_Interface_init() failed"));
  644. amr_codec_close(codec);
  645. return PJMEDIA_CODEC_EFAILED;
  646. }
  647. }
  648. TRACE_((THIS_FILE, "AMR codec modified: vad=%d, plc=%d",
  649. amr_data->vad_enabled, amr_data->plc_enabled));
  650. return PJ_SUCCESS;
  651. }
  652. /*
  653. * Get frames in the packet.
  654. */
  655. static pj_status_t amr_codec_parse( pjmedia_codec *codec,
  656. void *pkt,
  657. pj_size_t pkt_size,
  658. const pj_timestamp *ts,
  659. unsigned *frame_cnt,
  660. pjmedia_frame frames[])
  661. {
  662. struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
  663. pj_uint8_t cmr;
  664. pj_status_t status;
  665. unsigned idx = (amr_data->enc_setting.amr_nb? 0: 1);
  666. status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, &amr_data->dec_setting,
  667. frames, frame_cnt, &cmr);
  668. if (status != PJ_SUCCESS)
  669. return status;
  670. /* Check for Change Mode Request. */
  671. if (cmr < amr_bitrates_size[idx] && amr_data->enc_mode != cmr) {
  672. amr_data->enc_mode = cmr;
  673. TRACE_((THIS_FILE, "AMR encoder switched mode to %d (%dbps)",
  674. amr_data->enc_mode,
  675. amr_bitrates[idx][amr_data->enc_mode]));
  676. }
  677. return PJ_SUCCESS;
  678. }
  679. /*
  680. * Encode frame.
  681. */
  682. static pj_status_t amr_codec_encode( pjmedia_codec *codec,
  683. const struct pjmedia_frame *input,
  684. unsigned output_buf_len,
  685. struct pjmedia_frame *output)
  686. {
  687. struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
  688. unsigned char *bitstream;
  689. pj_int16_t *speech;
  690. unsigned nsamples, samples_per_frame;
  691. enum {MAX_FRAMES_PER_PACKET = 16};
  692. pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
  693. pj_uint8_t *p;
  694. unsigned i, out_size = 0, nframes = 0;
  695. pj_size_t payload_len;
  696. unsigned dtx_cnt, sid_cnt;
  697. pj_status_t status;
  698. pj_assert(amr_data != NULL);
  699. PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
  700. nsamples = input->size >> 1;
  701. samples_per_frame = amr_data->clock_rate * FRAME_LENGTH_MS / 1000;
  702. PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0,
  703. PJMEDIA_CODEC_EPCMFRMINLEN);
  704. nframes = nsamples / samples_per_frame;
  705. PJ_ASSERT_RETURN(nframes <= MAX_FRAMES_PER_PACKET,
  706. PJMEDIA_CODEC_EFRMTOOSHORT);
  707. /* Encode the frames */
  708. speech = (pj_int16_t*)input->buf;
  709. bitstream = (unsigned char*)output->buf;
  710. while (nsamples >= samples_per_frame) {
  711. int size;
  712. if (amr_data->enc_setting.amr_nb) {
  713. #ifdef USE_AMRNB
  714. size = Encoder_Interface_Encode (amr_data->encoder,
  715. amr_data->enc_mode,
  716. speech, bitstream, 0);
  717. #else
  718. size = 0;
  719. #endif
  720. } else {
  721. #ifdef USE_AMRWB
  722. size = E_IF_encode (amr_data->encoder, amr_data->enc_mode,
  723. speech, bitstream, 0);
  724. #else
  725. size = 0;
  726. #endif
  727. }
  728. if (size == 0) {
  729. output->size = 0;
  730. output->buf = NULL;
  731. output->type = PJMEDIA_FRAME_TYPE_NONE;
  732. TRACE_((THIS_FILE, "AMR encode() failed"));
  733. return PJMEDIA_CODEC_EFAILED;
  734. }
  735. nsamples -= samples_per_frame;
  736. speech += samples_per_frame;
  737. bitstream += size;
  738. out_size += size;
  739. TRACE_((THIS_FILE, "AMR encode(): mode=%d, size=%d",
  740. amr_data->enc_mode, out_size));
  741. }
  742. /* Pack payload */
  743. p = (pj_uint8_t*)output->buf + output_buf_len - out_size;
  744. pj_memmove(p, output->buf, out_size);
  745. dtx_cnt = sid_cnt = 0;
  746. for (i = 0; i < nframes; ++i) {
  747. pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*)
  748. &frames[i].bit_info;
  749. info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F);
  750. info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01);
  751. info->mode = (pj_int8_t)amr_data->enc_mode;
  752. info->start_bit = 0;
  753. frames[i].buf = p + 1;
  754. if (amr_data->enc_setting.amr_nb) {
  755. frames[i].size = (info->frame_type <= 8)?
  756. pjmedia_codec_amrnb_framelen[info->frame_type] : 0;
  757. } else {
  758. frames[i].size = (info->frame_type <= 9)?
  759. pjmedia_codec_amrwb_framelen[info->frame_type] : 0;
  760. }
  761. p += frames[i].size + 1;
  762. /* Count the number of SID and DTX frames */
  763. if (info->frame_type == 15) /* DTX*/
  764. ++dtx_cnt;
  765. else if (info->frame_type == 8 && amr_data->enc_setting.amr_nb) /* SID */
  766. ++sid_cnt;
  767. else if (info->frame_type == 9 && !amr_data->enc_setting.amr_nb) /* SID */
  768. ++sid_cnt;
  769. }
  770. /* VA generates DTX frames as DTX+SID frames switching quickly and it
  771. * seems that the SID frames occur too often (assuming the purpose is
  772. * only for keeping NAT alive?). So let's modify the behavior a bit.
  773. * Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD
  774. * milliseconds.
  775. */
  776. if (sid_cnt + dtx_cnt == nframes) {
  777. pj_int32_t dtx_duration;
  778. dtx_duration = pj_timestamp_diff32(&amr_data->last_tx,
  779. &input->timestamp);
  780. if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
  781. dtx_duration < (int)(PJMEDIA_CODEC_MAX_SILENCE_PERIOD*
  782. amr_data->clock_rate/1000))
  783. {
  784. output->size = 0;
  785. output->type = PJMEDIA_FRAME_TYPE_NONE;
  786. output->timestamp = input->timestamp;
  787. return PJ_SUCCESS;
  788. }
  789. }
  790. payload_len = output_buf_len;
  791. status = pjmedia_codec_amr_pack(frames, nframes, &amr_data->enc_setting,
  792. output->buf, &payload_len);
  793. if (status != PJ_SUCCESS) {
  794. output->size = 0;
  795. output->buf = NULL;
  796. output->type = PJMEDIA_FRAME_TYPE_NONE;
  797. TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status));
  798. return status;
  799. }
  800. output->size = payload_len;
  801. output->type = PJMEDIA_FRAME_TYPE_AUDIO;
  802. output->timestamp = input->timestamp;
  803. amr_data->last_tx = input->timestamp;
  804. return PJ_SUCCESS;
  805. }
  806. /*
  807. * Decode frame.
  808. */
  809. static pj_status_t amr_codec_decode( pjmedia_codec *codec,
  810. const struct pjmedia_frame *input,
  811. unsigned output_buf_len,
  812. struct pjmedia_frame *output)
  813. {
  814. struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
  815. pjmedia_frame input_;
  816. pjmedia_codec_amr_bit_info *info;
  817. unsigned out_size;
  818. /* AMR decoding buffer: AMR max frame size + 1 byte header. */
  819. unsigned char bitstream[61];
  820. pj_assert(amr_data != NULL);
  821. PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
  822. out_size = amr_data->clock_rate * FRAME_LENGTH_MS / 1000 * 2;
  823. if (output_buf_len < out_size)
  824. return PJMEDIA_CODEC_EPCMTOOSHORT;
  825. input_.buf = &bitstream[1];
  826. /* AMR max frame size */
  827. input_.size = (amr_data->dec_setting.amr_nb? 31: 60);
  828. pjmedia_codec_amr_predecode(input, &amr_data->dec_setting, &input_);
  829. info = (pjmedia_codec_amr_bit_info*)&input_.bit_info;
  830. /* VA AMR decoder requires frame info in the first byte. */
  831. bitstream[0] = (info->frame_type << 3) | (info->good_quality << 2);
  832. TRACE_((THIS_FILE, "AMR decode(): mode=%d, ft=%d, size=%d",
  833. info->mode, info->frame_type, input_.size));
  834. /* Decode */
  835. if (amr_data->dec_setting.amr_nb) {
  836. #ifdef USE_AMRNB
  837. Decoder_Interface_Decode(amr_data->decoder, bitstream,
  838. (pj_int16_t*)output->buf, 0);
  839. #endif
  840. } else {
  841. #ifdef USE_AMRWB
  842. D_IF_decode(amr_data->decoder, bitstream,
  843. (pj_int16_t*)output->buf, 0);
  844. #endif
  845. }
  846. output->size = out_size;
  847. output->type = PJMEDIA_FRAME_TYPE_AUDIO;
  848. output->timestamp = input->timestamp;
  849. #if USE_PJMEDIA_PLC
  850. if (amr_data->plc_enabled)
  851. pjmedia_plc_save(amr_data->plc, (pj_int16_t*)output->buf);
  852. #endif
  853. return PJ_SUCCESS;
  854. }
  855. /*
  856. * Recover lost frame.
  857. */
  858. #if USE_PJMEDIA_PLC
  859. /*
  860. * Recover lost frame.
  861. */
  862. static pj_status_t amr_codec_recover( pjmedia_codec *codec,
  863. unsigned output_buf_len,
  864. struct pjmedia_frame *output)
  865. {
  866. struct amr_data *amr_data = codec->codec_data;
  867. unsigned out_size = amr_data->clock_rate * FRAME_LENGTH_MS / 1000 * 2;
  868. TRACE_((THIS_FILE, "amr_codec_recover"));
  869. PJ_ASSERT_RETURN(amr_data->plc_enabled, PJ_EINVALIDOP);
  870. PJ_ASSERT_RETURN(output_buf_len >= out_size, PJMEDIA_CODEC_EPCMTOOSHORT);
  871. pjmedia_plc_generate(amr_data->plc, (pj_int16_t*)output->buf);
  872. output->size = out_size;
  873. output->type = PJMEDIA_FRAME_TYPE_AUDIO;
  874. return PJ_SUCCESS;
  875. }
  876. #endif
  877. #if defined(_MSC_VER) && PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS
  878. # if PJMEDIA_OPENCORE_AMR_BUILT_WITH_GCC
  879. # ifdef USE_AMRNB
  880. # pragma comment( lib, "libopencore-amrnb.a")
  881. # endif
  882. # ifdef USE_AMRWB
  883. # pragma comment( lib, "libopencore-amrwb.a")
  884. # pragma comment( lib, "libvo-amrwbenc.a")
  885. # endif
  886. # else
  887. # error Unsupported OpenCORE AMR library, fix here
  888. # endif
  889. #endif
  890. #endif