ilbc.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  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. #include <pjmedia-codec/ilbc.h>
  20. #include <pjmedia-codec/types.h>
  21. #include <pjmedia/codec.h>
  22. #include <pjmedia/errno.h>
  23. #include <pjmedia/endpoint.h>
  24. #include <pjmedia/plc.h>
  25. #include <pjmedia/port.h>
  26. #include <pjmedia/silencedet.h>
  27. #include <pj/assert.h>
  28. #include <pj/log.h>
  29. #include <pj/pool.h>
  30. #include <pj/string.h>
  31. #include <pj/os.h>
  32. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  33. #include <AudioToolbox/AudioToolbox.h>
  34. #define iLBC_Enc_Inst_t AudioConverterRef
  35. #define iLBC_Dec_Inst_t AudioConverterRef
  36. #define BLOCKL_MAX 1
  37. #else
  38. #include "../../third_party/ilbc/iLBC_encode.h"
  39. #include "../../third_party/ilbc/iLBC_decode.h"
  40. #endif
  41. /*
  42. * Only build this file if PJMEDIA_HAS_ILBC_CODEC != 0
  43. */
  44. #if defined(PJMEDIA_HAS_ILBC_CODEC) && PJMEDIA_HAS_ILBC_CODEC != 0
  45. #define THIS_FILE "ilbc.c"
  46. #define CLOCK_RATE 8000
  47. #define DEFAULT_MODE 30
  48. /* Prototypes for iLBC factory */
  49. static pj_status_t ilbc_test_alloc(pjmedia_codec_factory *factory,
  50. const pjmedia_codec_info *id );
  51. static pj_status_t ilbc_default_attr(pjmedia_codec_factory *factory,
  52. const pjmedia_codec_info *id,
  53. pjmedia_codec_param *attr );
  54. static pj_status_t ilbc_enum_codecs(pjmedia_codec_factory *factory,
  55. unsigned *count,
  56. pjmedia_codec_info codecs[]);
  57. static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory,
  58. const pjmedia_codec_info *id,
  59. pjmedia_codec **p_codec);
  60. static pj_status_t ilbc_dealloc_codec(pjmedia_codec_factory *factory,
  61. pjmedia_codec *codec );
  62. /* Prototypes for iLBC implementation. */
  63. static pj_status_t ilbc_codec_init(pjmedia_codec *codec,
  64. pj_pool_t *pool );
  65. static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
  66. pjmedia_codec_param *attr );
  67. static pj_status_t ilbc_codec_close(pjmedia_codec *codec );
  68. static pj_status_t ilbc_codec_modify(pjmedia_codec *codec,
  69. const pjmedia_codec_param *attr );
  70. static pj_status_t ilbc_codec_parse(pjmedia_codec *codec,
  71. void *pkt,
  72. pj_size_t pkt_size,
  73. const pj_timestamp *ts,
  74. unsigned *frame_cnt,
  75. pjmedia_frame frames[]);
  76. static pj_status_t ilbc_codec_encode(pjmedia_codec *codec,
  77. const struct pjmedia_frame *input,
  78. unsigned output_buf_len,
  79. struct pjmedia_frame *output);
  80. static pj_status_t ilbc_codec_decode(pjmedia_codec *codec,
  81. const struct pjmedia_frame *input,
  82. unsigned output_buf_len,
  83. struct pjmedia_frame *output);
  84. static pj_status_t ilbc_codec_recover(pjmedia_codec *codec,
  85. unsigned output_buf_len,
  86. struct pjmedia_frame *output);
  87. /* Definition for iLBC codec operations. */
  88. static pjmedia_codec_op ilbc_op =
  89. {
  90. &ilbc_codec_init,
  91. &ilbc_codec_open,
  92. &ilbc_codec_close,
  93. &ilbc_codec_modify,
  94. &ilbc_codec_parse,
  95. &ilbc_codec_encode,
  96. &ilbc_codec_decode,
  97. &ilbc_codec_recover
  98. };
  99. /* Definition for iLBC codec factory operations. */
  100. static pjmedia_codec_factory_op ilbc_factory_op =
  101. {
  102. &ilbc_test_alloc,
  103. &ilbc_default_attr,
  104. &ilbc_enum_codecs,
  105. &ilbc_alloc_codec,
  106. &ilbc_dealloc_codec,
  107. &pjmedia_codec_ilbc_deinit
  108. };
  109. /* iLBC factory */
  110. static struct ilbc_factory
  111. {
  112. pjmedia_codec_factory base;
  113. pjmedia_endpt *endpt;
  114. int mode;
  115. int bps;
  116. } ilbc_factory;
  117. /* iLBC codec private data. */
  118. struct ilbc_codec
  119. {
  120. pjmedia_codec base;
  121. pj_pool_t *pool;
  122. char obj_name[PJ_MAX_OBJ_NAME];
  123. pjmedia_silence_det *vad;
  124. pj_bool_t vad_enabled;
  125. pj_bool_t plc_enabled;
  126. pj_timestamp last_tx;
  127. pj_bool_t enc_ready;
  128. iLBC_Enc_Inst_t enc;
  129. unsigned enc_frame_size;
  130. unsigned enc_samples_per_frame;
  131. float enc_block[BLOCKL_MAX];
  132. pj_bool_t dec_ready;
  133. iLBC_Dec_Inst_t dec;
  134. unsigned dec_frame_size;
  135. unsigned dec_samples_per_frame;
  136. float dec_block[BLOCKL_MAX];
  137. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  138. unsigned enc_total_packets;
  139. char *enc_buffer;
  140. unsigned enc_buffer_offset;
  141. unsigned dec_total_packets;
  142. char *dec_buffer;
  143. unsigned dec_buffer_offset;
  144. #endif
  145. };
  146. static pj_str_t STR_MODE = {"mode", 4};
  147. /*
  148. * Initialize and register iLBC codec factory to pjmedia endpoint.
  149. */
  150. PJ_DEF(pj_status_t) pjmedia_codec_ilbc_init( pjmedia_endpt *endpt,
  151. int mode )
  152. {
  153. pjmedia_codec_mgr *codec_mgr;
  154. pj_status_t status;
  155. PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
  156. PJ_ASSERT_RETURN(mode==0 || mode==20 || mode==30, PJ_EINVAL);
  157. if (ilbc_factory.endpt != NULL) {
  158. /* Already initialized. */
  159. return PJ_SUCCESS;
  160. }
  161. /* Create iLBC codec factory. */
  162. ilbc_factory.base.op = &ilbc_factory_op;
  163. ilbc_factory.base.factory_data = NULL;
  164. ilbc_factory.endpt = endpt;
  165. if (mode == 0)
  166. mode = DEFAULT_MODE;
  167. ilbc_factory.mode = mode;
  168. if (mode == 20) {
  169. ilbc_factory.bps = 15200;
  170. } else {
  171. ilbc_factory.bps = 13333;
  172. }
  173. /* Get the codec manager. */
  174. codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
  175. if (!codec_mgr) {
  176. ilbc_factory.endpt = NULL;
  177. return PJ_EINVALIDOP;
  178. }
  179. /* Register codec factory to endpoint. */
  180. status = pjmedia_codec_mgr_register_factory(codec_mgr,
  181. &ilbc_factory.base);
  182. if (status != PJ_SUCCESS) {
  183. ilbc_factory.endpt = NULL;
  184. return status;
  185. }
  186. /* Done. */
  187. return PJ_SUCCESS;
  188. }
  189. /*
  190. * Unregister iLBC codec factory from pjmedia endpoint and deinitialize
  191. * the iLBC codec library.
  192. */
  193. PJ_DEF(pj_status_t) pjmedia_codec_ilbc_deinit(void)
  194. {
  195. pjmedia_codec_mgr *codec_mgr;
  196. pj_status_t status;
  197. if (ilbc_factory.endpt == NULL) {
  198. /* Not registered. */
  199. return PJ_SUCCESS;
  200. }
  201. /* Get the codec manager. */
  202. codec_mgr = pjmedia_endpt_get_codec_mgr(ilbc_factory.endpt);
  203. if (!codec_mgr)
  204. return PJ_EINVALIDOP;
  205. /* Unregister iLBC codec factory. */
  206. status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
  207. &ilbc_factory.base);
  208. ilbc_factory.endpt = NULL;
  209. return status;
  210. }
  211. /*
  212. * Check if factory can allocate the specified codec.
  213. */
  214. static pj_status_t ilbc_test_alloc( pjmedia_codec_factory *factory,
  215. const pjmedia_codec_info *info )
  216. {
  217. const pj_str_t ilbc_tag = { "iLBC", 4};
  218. PJ_UNUSED_ARG(factory);
  219. PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
  220. /* Type MUST be audio. */
  221. if (info->type != PJMEDIA_TYPE_AUDIO)
  222. return PJMEDIA_CODEC_EUNSUP;
  223. /* Check encoding name. */
  224. if (pj_stricmp(&info->encoding_name, &ilbc_tag) != 0)
  225. return PJMEDIA_CODEC_EUNSUP;
  226. /* Check clock-rate */
  227. if (info->clock_rate != CLOCK_RATE)
  228. return PJMEDIA_CODEC_EUNSUP;
  229. /* Channel count must be one */
  230. if (info->channel_cnt != 1)
  231. return PJMEDIA_CODEC_EUNSUP;
  232. /* Yes, this should be iLBC! */
  233. return PJ_SUCCESS;
  234. }
  235. /*
  236. * Generate default attribute.
  237. */
  238. static pj_status_t ilbc_default_attr (pjmedia_codec_factory *factory,
  239. const pjmedia_codec_info *id,
  240. pjmedia_codec_param *attr )
  241. {
  242. PJ_UNUSED_ARG(factory);
  243. PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
  244. PJ_UNUSED_ARG(id);
  245. PJ_ASSERT_RETURN(pj_stricmp2(&id->encoding_name, "iLBC")==0, PJ_EINVAL);
  246. pj_bzero(attr, sizeof(pjmedia_codec_param));
  247. attr->info.clock_rate = CLOCK_RATE;
  248. attr->info.channel_cnt = 1;
  249. attr->info.avg_bps = ilbc_factory.bps;
  250. attr->info.max_bps = 15200;
  251. attr->info.pcm_bits_per_sample = 16;
  252. attr->info.frm_ptime = (short)ilbc_factory.mode;
  253. attr->info.pt = PJMEDIA_RTP_PT_ILBC;
  254. attr->setting.frm_per_pkt = 1;
  255. attr->setting.vad = 1;
  256. attr->setting.plc = 1;
  257. attr->setting.penh = 1;
  258. attr->setting.dec_fmtp.cnt = 1;
  259. attr->setting.dec_fmtp.param[0].name = STR_MODE;
  260. if (ilbc_factory.mode == 30)
  261. attr->setting.dec_fmtp.param[0].val = pj_str("30");
  262. else
  263. attr->setting.dec_fmtp.param[0].val = pj_str("20");
  264. return PJ_SUCCESS;
  265. }
  266. /*
  267. * Enum codecs supported by this factory (i.e. only iLBC!).
  268. */
  269. static pj_status_t ilbc_enum_codecs(pjmedia_codec_factory *factory,
  270. unsigned *count,
  271. pjmedia_codec_info codecs[])
  272. {
  273. PJ_UNUSED_ARG(factory);
  274. PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
  275. PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
  276. pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
  277. codecs[0].encoding_name = pj_str("iLBC");
  278. codecs[0].pt = PJMEDIA_RTP_PT_ILBC;
  279. codecs[0].type = PJMEDIA_TYPE_AUDIO;
  280. codecs[0].clock_rate = 8000;
  281. codecs[0].channel_cnt = 1;
  282. *count = 1;
  283. return PJ_SUCCESS;
  284. }
  285. /*
  286. * Allocate a new iLBC codec instance.
  287. */
  288. static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory,
  289. const pjmedia_codec_info *id,
  290. pjmedia_codec **p_codec)
  291. {
  292. pj_pool_t *pool;
  293. struct ilbc_codec *codec;
  294. PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
  295. PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
  296. pool = pjmedia_endpt_create_pool(ilbc_factory.endpt, "iLBC%p",
  297. 2000, 2000);
  298. PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
  299. codec = PJ_POOL_ZALLOC_T(pool, struct ilbc_codec);
  300. codec->base.op = &ilbc_op;
  301. codec->base.factory = factory;
  302. codec->pool = pool;
  303. pj_ansi_snprintf(codec->obj_name, sizeof(codec->obj_name),
  304. "ilbc%p", codec);
  305. *p_codec = &codec->base;
  306. return PJ_SUCCESS;
  307. }
  308. /*
  309. * Free codec.
  310. */
  311. static pj_status_t ilbc_dealloc_codec( pjmedia_codec_factory *factory,
  312. pjmedia_codec *codec )
  313. {
  314. struct ilbc_codec *ilbc_codec;
  315. PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
  316. PJ_UNUSED_ARG(factory);
  317. PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
  318. ilbc_codec = (struct ilbc_codec*) codec;
  319. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  320. if (ilbc_codec->enc) {
  321. AudioConverterDispose(ilbc_codec->enc);
  322. ilbc_codec->enc = NULL;
  323. }
  324. if (ilbc_codec->dec) {
  325. AudioConverterDispose(ilbc_codec->dec);
  326. ilbc_codec->dec = NULL;
  327. }
  328. #endif
  329. pj_pool_release(ilbc_codec->pool);
  330. return PJ_SUCCESS;
  331. }
  332. /*
  333. * Init codec.
  334. */
  335. static pj_status_t ilbc_codec_init(pjmedia_codec *codec,
  336. pj_pool_t *pool )
  337. {
  338. PJ_UNUSED_ARG(codec);
  339. PJ_UNUSED_ARG(pool);
  340. return PJ_SUCCESS;
  341. }
  342. /*
  343. * Open codec.
  344. */
  345. static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
  346. pjmedia_codec_param *attr )
  347. {
  348. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
  349. pj_status_t status;
  350. unsigned i;
  351. pj_uint16_t dec_fmtp_mode = DEFAULT_MODE,
  352. enc_fmtp_mode = DEFAULT_MODE;
  353. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  354. AudioStreamBasicDescription srcFormat, dstFormat;
  355. UInt32 size;
  356. srcFormat.mSampleRate = attr->info.clock_rate;
  357. srcFormat.mFormatID = kAudioFormatLinearPCM;
  358. srcFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger
  359. | kLinearPCMFormatFlagIsPacked;
  360. srcFormat.mBitsPerChannel = attr->info.pcm_bits_per_sample;
  361. srcFormat.mChannelsPerFrame = attr->info.channel_cnt;
  362. srcFormat.mBytesPerFrame = srcFormat.mChannelsPerFrame
  363. * srcFormat.mBitsPerChannel >> 3;
  364. srcFormat.mFramesPerPacket = 1;
  365. srcFormat.mBytesPerPacket = srcFormat.mBytesPerFrame *
  366. srcFormat.mFramesPerPacket;
  367. memset(&dstFormat, 0, sizeof(dstFormat));
  368. dstFormat.mSampleRate = attr->info.clock_rate;
  369. dstFormat.mFormatID = kAudioFormatiLBC;
  370. dstFormat.mChannelsPerFrame = attr->info.channel_cnt;
  371. #endif
  372. pj_assert(ilbc_codec != NULL);
  373. pj_assert(ilbc_codec->enc_ready == PJ_FALSE &&
  374. ilbc_codec->dec_ready == PJ_FALSE);
  375. /* Get decoder mode */
  376. for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
  377. if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_MODE) == 0)
  378. {
  379. dec_fmtp_mode = (pj_uint16_t)
  380. pj_strtoul(&attr->setting.dec_fmtp.param[i].val);
  381. break;
  382. }
  383. }
  384. /* Decoder mode must be set */
  385. PJ_ASSERT_RETURN(dec_fmtp_mode == 20 || dec_fmtp_mode == 30,
  386. PJMEDIA_CODEC_EINMODE);
  387. /* Get encoder mode */
  388. for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
  389. if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_MODE) == 0)
  390. {
  391. enc_fmtp_mode = (pj_uint16_t)
  392. pj_strtoul(&attr->setting.enc_fmtp.param[i].val);
  393. break;
  394. }
  395. }
  396. PJ_ASSERT_RETURN(enc_fmtp_mode==20 || enc_fmtp_mode==30,
  397. PJMEDIA_CODEC_EINMODE);
  398. /* Both sides of a bi-directional session MUST use the same "mode" value.
  399. * In this point, possible values are only 20 or 30, so when encoder and
  400. * decoder modes are not same, just use the default mode, it is 30.
  401. */
  402. if (enc_fmtp_mode != dec_fmtp_mode) {
  403. enc_fmtp_mode = dec_fmtp_mode = DEFAULT_MODE;
  404. PJ_LOG(4,(ilbc_codec->obj_name,
  405. "Normalized iLBC encoder and decoder modes to %d",
  406. DEFAULT_MODE));
  407. }
  408. /* Update some attributes based on negotiated mode. */
  409. attr->info.avg_bps = (dec_fmtp_mode == 30? 13333 : 15200);
  410. attr->info.frm_ptime = dec_fmtp_mode;
  411. /* Create encoder */
  412. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  413. dstFormat.mFramesPerPacket = CLOCK_RATE * enc_fmtp_mode / 1000;
  414. dstFormat.mBytesPerPacket = (enc_fmtp_mode == 20? 38 : 50);
  415. /* Use AudioFormat API to fill out the rest of the description */
  416. size = sizeof(dstFormat);
  417. AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
  418. 0, NULL, &size, &dstFormat);
  419. if (AudioConverterNew(&srcFormat, &dstFormat, &ilbc_codec->enc) != noErr)
  420. return PJMEDIA_CODEC_EFAILED;
  421. ilbc_codec->enc_frame_size = (enc_fmtp_mode == 20? 38 : 50);
  422. #else
  423. ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc, enc_fmtp_mode);
  424. #endif
  425. ilbc_codec->enc_samples_per_frame = CLOCK_RATE * enc_fmtp_mode / 1000;
  426. ilbc_codec->enc_ready = PJ_TRUE;
  427. /* Create decoder */
  428. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  429. if (AudioConverterNew(&dstFormat, &srcFormat, &ilbc_codec->dec) != noErr)
  430. return PJMEDIA_CODEC_EFAILED;
  431. ilbc_codec->dec_samples_per_frame = CLOCK_RATE * dec_fmtp_mode / 1000;
  432. #else
  433. ilbc_codec->dec_samples_per_frame = initDecode(&ilbc_codec->dec,
  434. dec_fmtp_mode,
  435. attr->setting.penh);
  436. #endif
  437. ilbc_codec->dec_frame_size = (dec_fmtp_mode == 20? 38 : 50);
  438. ilbc_codec->dec_ready = PJ_TRUE;
  439. /* Save plc flags */
  440. ilbc_codec->plc_enabled = (attr->setting.plc != 0);
  441. /* Create silence detector. */
  442. ilbc_codec->vad_enabled = (attr->setting.vad != 0);
  443. status = pjmedia_silence_det_create(ilbc_codec->pool, CLOCK_RATE,
  444. ilbc_codec->enc_samples_per_frame,
  445. &ilbc_codec->vad);
  446. if (status != PJ_SUCCESS)
  447. return status;
  448. /* Init last_tx (not necessary because of zalloc, but better
  449. * be safe in case someone remove zalloc later.
  450. */
  451. pj_set_timestamp32(&ilbc_codec->last_tx, 0, 0);
  452. PJ_LOG(4,(ilbc_codec->obj_name,
  453. "iLBC codec opened, mode=%d", dec_fmtp_mode));
  454. return PJ_SUCCESS;
  455. }
  456. /*
  457. * Close codec.
  458. */
  459. static pj_status_t ilbc_codec_close( pjmedia_codec *codec )
  460. {
  461. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
  462. PJ_UNUSED_ARG(codec);
  463. PJ_LOG(5,(ilbc_codec->obj_name, "iLBC codec closed"));
  464. return PJ_SUCCESS;
  465. }
  466. /*
  467. * Modify codec settings.
  468. */
  469. static pj_status_t ilbc_codec_modify(pjmedia_codec *codec,
  470. const pjmedia_codec_param *attr )
  471. {
  472. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
  473. ilbc_codec->plc_enabled = (attr->setting.plc != 0);
  474. ilbc_codec->vad_enabled = (attr->setting.vad != 0);
  475. return PJ_SUCCESS;
  476. }
  477. /*
  478. * Get frames in the packet.
  479. */
  480. static pj_status_t ilbc_codec_parse( pjmedia_codec *codec,
  481. void *pkt,
  482. pj_size_t pkt_size,
  483. const pj_timestamp *ts,
  484. unsigned *frame_cnt,
  485. pjmedia_frame frames[])
  486. {
  487. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
  488. unsigned count;
  489. PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
  490. count = 0;
  491. while (pkt_size >= ilbc_codec->dec_frame_size && count < *frame_cnt) {
  492. frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
  493. frames[count].buf = pkt;
  494. frames[count].size = ilbc_codec->dec_frame_size;
  495. frames[count].timestamp.u64 = ts->u64 + (pj_uint64_t)count *
  496. ilbc_codec->dec_samples_per_frame;
  497. pkt = ((char*)pkt) + ilbc_codec->dec_frame_size;
  498. pkt_size -= ilbc_codec->dec_frame_size;
  499. ++count;
  500. }
  501. *frame_cnt = count;
  502. return PJ_SUCCESS;
  503. }
  504. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  505. static OSStatus encodeDataProc (
  506. AudioConverterRef inAudioConverter,
  507. UInt32 *ioNumberDataPackets,
  508. AudioBufferList *ioData,
  509. AudioStreamPacketDescription **outDataPacketDescription,
  510. void *inUserData
  511. )
  512. {
  513. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData;
  514. /* Initialize in case of failure */
  515. ioData->mBuffers[0].mData = NULL;
  516. ioData->mBuffers[0].mDataByteSize = 0;
  517. if (ilbc_codec->enc_total_packets < *ioNumberDataPackets) {
  518. *ioNumberDataPackets = ilbc_codec->enc_total_packets;
  519. }
  520. if (*ioNumberDataPackets) {
  521. ioData->mBuffers[0].mData = ilbc_codec->enc_buffer +
  522. ilbc_codec->enc_buffer_offset;
  523. ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets *
  524. ilbc_codec->enc_samples_per_frame
  525. << 1;
  526. ilbc_codec->enc_buffer_offset += ioData->mBuffers[0].mDataByteSize;
  527. }
  528. ilbc_codec->enc_total_packets -= *ioNumberDataPackets;
  529. return noErr;
  530. }
  531. static OSStatus decodeDataProc (
  532. AudioConverterRef inAudioConverter,
  533. UInt32 *ioNumberDataPackets,
  534. AudioBufferList *ioData,
  535. AudioStreamPacketDescription **outDataPacketDescription,
  536. void *inUserData
  537. )
  538. {
  539. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData;
  540. /* Initialize in case of failure */
  541. ioData->mBuffers[0].mData = NULL;
  542. ioData->mBuffers[0].mDataByteSize = 0;
  543. if (ilbc_codec->dec_total_packets < *ioNumberDataPackets) {
  544. *ioNumberDataPackets = ilbc_codec->dec_total_packets;
  545. }
  546. if (*ioNumberDataPackets) {
  547. ioData->mBuffers[0].mData = ilbc_codec->dec_buffer +
  548. ilbc_codec->dec_buffer_offset;
  549. ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets *
  550. ilbc_codec->dec_frame_size;
  551. ilbc_codec->dec_buffer_offset += ioData->mBuffers[0].mDataByteSize;
  552. }
  553. ilbc_codec->dec_total_packets -= *ioNumberDataPackets;
  554. return noErr;
  555. }
  556. #endif
  557. /*
  558. * Encode frame.
  559. */
  560. static pj_status_t ilbc_codec_encode(pjmedia_codec *codec,
  561. const struct pjmedia_frame *input,
  562. unsigned output_buf_len,
  563. struct pjmedia_frame *output)
  564. {
  565. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
  566. pj_int16_t *pcm_in;
  567. pj_size_t nsamples;
  568. pj_assert(ilbc_codec && input && output);
  569. pcm_in = (pj_int16_t*)input->buf;
  570. nsamples = input->size >> 1;
  571. PJ_ASSERT_RETURN(nsamples % ilbc_codec->enc_samples_per_frame == 0,
  572. PJMEDIA_CODEC_EPCMFRMINLEN);
  573. PJ_ASSERT_RETURN(output_buf_len >= ilbc_codec->enc_frame_size * nsamples /
  574. ilbc_codec->enc_samples_per_frame,
  575. PJMEDIA_CODEC_EFRMTOOSHORT);
  576. /* Detect silence */
  577. if (ilbc_codec->vad_enabled) {
  578. pj_bool_t is_silence;
  579. pj_int32_t silence_period;
  580. silence_period = pj_timestamp_diff32(&ilbc_codec->last_tx,
  581. &input->timestamp);
  582. is_silence = pjmedia_silence_det_detect(ilbc_codec->vad,
  583. (const pj_int16_t*)input->buf,
  584. (input->size >> 1),
  585. NULL);
  586. if (is_silence &&
  587. (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
  588. silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000))
  589. {
  590. output->type = PJMEDIA_FRAME_TYPE_NONE;
  591. output->buf = NULL;
  592. output->size = 0;
  593. output->timestamp = input->timestamp;
  594. return PJ_SUCCESS;
  595. } else {
  596. ilbc_codec->last_tx = input->timestamp;
  597. }
  598. }
  599. /* Encode */
  600. output->size = 0;
  601. while (nsamples >= ilbc_codec->enc_samples_per_frame) {
  602. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  603. OSStatus err;
  604. AudioBufferList theABL;
  605. UInt32 npackets = 1;
  606. theABL.mNumberBuffers = 1;
  607. theABL.mBuffers[0].mNumberChannels = 1;
  608. theABL.mBuffers[0].mDataByteSize = output_buf_len;
  609. theABL.mBuffers[0].mData = output->buf + output->size;
  610. ilbc_codec->enc_total_packets = 1;
  611. ilbc_codec->enc_buffer = (char *)pcm_in;
  612. ilbc_codec->enc_buffer_offset = input->size - (nsamples << 1);
  613. err = AudioConverterFillComplexBuffer(ilbc_codec->enc, encodeDataProc,
  614. ilbc_codec, &npackets,
  615. &theABL, NULL);
  616. if (err == noErr && npackets) {
  617. output->size += npackets * ilbc_codec->enc_frame_size;
  618. }
  619. #else
  620. unsigned i;
  621. /* Convert to float */
  622. for (i=0; i<ilbc_codec->enc_samples_per_frame; ++i) {
  623. ilbc_codec->enc_block[i] = (float) (*pcm_in++);
  624. }
  625. iLBC_encode((unsigned char *)output->buf + output->size,
  626. ilbc_codec->enc_block,
  627. &ilbc_codec->enc);
  628. output->size += ilbc_codec->enc.no_of_bytes;
  629. #endif
  630. nsamples -= ilbc_codec->enc_samples_per_frame;
  631. }
  632. output->type = PJMEDIA_FRAME_TYPE_AUDIO;
  633. output->timestamp = input->timestamp;
  634. return PJ_SUCCESS;
  635. }
  636. /*
  637. * Decode frame.
  638. */
  639. static pj_status_t ilbc_codec_decode(pjmedia_codec *codec,
  640. const struct pjmedia_frame *input,
  641. unsigned output_buf_len,
  642. struct pjmedia_frame *output)
  643. {
  644. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
  645. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  646. UInt32 npackets;
  647. OSStatus err;
  648. AudioBufferList theABL;
  649. #else
  650. unsigned i;
  651. #endif
  652. pj_assert(ilbc_codec != NULL);
  653. PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
  654. if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
  655. return PJMEDIA_CODEC_EPCMTOOSHORT;
  656. if (input->size != ilbc_codec->dec_frame_size)
  657. return PJMEDIA_CODEC_EFRMINLEN;
  658. /* Decode to temporary buffer */
  659. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  660. npackets = input->size / ilbc_codec->dec_frame_size *
  661. ilbc_codec->dec_samples_per_frame;
  662. theABL.mNumberBuffers = 1;
  663. theABL.mBuffers[0].mNumberChannels = 1;
  664. theABL.mBuffers[0].mDataByteSize = output_buf_len;
  665. theABL.mBuffers[0].mData = output->buf;
  666. ilbc_codec->dec_total_packets = npackets;
  667. ilbc_codec->dec_buffer = (char *)input->buf;
  668. ilbc_codec->dec_buffer_offset = 0;
  669. err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc,
  670. ilbc_codec, &npackets,
  671. &theABL, NULL);
  672. if (err == noErr) {
  673. output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1);
  674. }
  675. #else
  676. iLBC_decode(ilbc_codec->dec_block, (unsigned char*) input->buf,
  677. &ilbc_codec->dec, 1);
  678. /* Convert decodec samples from float to short */
  679. for (i=0; i<ilbc_codec->dec_samples_per_frame; ++i) {
  680. ((short*)output->buf)[i] = (short)ilbc_codec->dec_block[i];
  681. }
  682. output->size = (ilbc_codec->dec_samples_per_frame << 1);
  683. #endif
  684. output->type = PJMEDIA_FRAME_TYPE_AUDIO;
  685. output->timestamp = input->timestamp;
  686. return PJ_SUCCESS;
  687. }
  688. /*
  689. * Recover lost frame.
  690. */
  691. static pj_status_t ilbc_codec_recover(pjmedia_codec *codec,
  692. unsigned output_buf_len,
  693. struct pjmedia_frame *output)
  694. {
  695. struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
  696. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  697. UInt32 npackets;
  698. OSStatus err;
  699. AudioBufferList theABL;
  700. #else
  701. unsigned i;
  702. #endif
  703. pj_assert(ilbc_codec != NULL);
  704. PJ_ASSERT_RETURN(output, PJ_EINVAL);
  705. if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
  706. return PJMEDIA_CODEC_EPCMTOOSHORT;
  707. /* Decode to temporary buffer */
  708. #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
  709. npackets = 1;
  710. theABL.mNumberBuffers = 1;
  711. theABL.mBuffers[0].mNumberChannels = 1;
  712. theABL.mBuffers[0].mDataByteSize = output_buf_len;
  713. theABL.mBuffers[0].mData = output->buf;
  714. ilbc_codec->dec_total_packets = npackets;
  715. ilbc_codec->dec_buffer_offset = 0;
  716. if (ilbc_codec->dec_buffer) {
  717. err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc,
  718. ilbc_codec, &npackets,
  719. &theABL, NULL);
  720. if (err == noErr) {
  721. output->size = npackets *
  722. (ilbc_codec->dec_samples_per_frame << 1);
  723. }
  724. } else {
  725. output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1);
  726. pj_bzero(output->buf, output->size);
  727. }
  728. #else
  729. iLBC_decode(ilbc_codec->dec_block, NULL, &ilbc_codec->dec, 0);
  730. /* Convert decodec samples from float to short */
  731. for (i=0; i<ilbc_codec->dec_samples_per_frame; ++i) {
  732. ((short*)output->buf)[i] = (short)ilbc_codec->dec_block[i];
  733. }
  734. output->size = (ilbc_codec->dec_samples_per_frame << 1);
  735. #endif
  736. output->type = PJMEDIA_FRAME_TYPE_AUDIO;
  737. return PJ_SUCCESS;
  738. }
  739. #endif /* PJMEDIA_HAS_ILBC_CODEC */