format_g726.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. * Headerless G.726 (16/24/32/40kbps) data format for Asterisk.
  3. *
  4. * Copyright (c) 2004, inAccess Networks
  5. *
  6. * Michael Manousos <manousos@inaccessnetworks.com>
  7. *
  8. * This program is free software, distributed under the terms of
  9. * the GNU General Public License
  10. */
  11. #include <asterisk/lock.h>
  12. #include <asterisk/options.h>
  13. #include <asterisk/channel.h>
  14. #include <asterisk/file.h>
  15. #include <asterisk/logger.h>
  16. #include <asterisk/sched.h>
  17. #include <asterisk/module.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #include <stdlib.h>
  21. #include <sys/time.h>
  22. #include <stdio.h>
  23. #include <unistd.h>
  24. #include <errno.h>
  25. #include <string.h>
  26. #include "asterisk/endian.h"
  27. #define RATE_40 0
  28. #define RATE_32 1
  29. #define RATE_24 2
  30. #define RATE_16 3
  31. /* We can only read/write chunks of FRAME_TIME ms G.726 data */
  32. #define FRAME_TIME 10 /* 10 ms size */
  33. /* Frame sizes in bytes */
  34. static int frame_size[4] = {
  35. FRAME_TIME * 5,
  36. FRAME_TIME * 4,
  37. FRAME_TIME * 3,
  38. FRAME_TIME * 2
  39. };
  40. struct ast_filestream {
  41. /* Do not place anything before "reserved" */
  42. void *reserved[AST_RESERVED_POINTERS];
  43. /* This is what a filestream means to us */
  44. int fd; /* Open file descriptor */
  45. int rate; /* RATE_* defines */
  46. struct ast_frame fr; /* Frame information */
  47. char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
  48. char empty; /* Empty character */
  49. unsigned char g726[FRAME_TIME * 5]; /* G.726 encoded voice */
  50. };
  51. AST_MUTEX_DEFINE_STATIC(g726_lock);
  52. static int glistcnt = 0;
  53. static char *desc = "Raw G.726 (16/24/32/40kbps) data";
  54. static char *name40 = "g726-40";
  55. static char *name32 = "g726-32";
  56. static char *name24 = "g726-24";
  57. static char *name16 = "g726-16";
  58. static char *exts40 = "g726-40";
  59. static char *exts32 = "g726-32";
  60. static char *exts24 = "g726-24";
  61. static char *exts16 = "g726-16";
  62. /*
  63. * Rate dependant format functions (open, rewrite)
  64. */
  65. static struct ast_filestream *g726_40_open(int fd)
  66. {
  67. /* We don't have any header to read or anything really, but
  68. if we did, it would go here. We also might want to check
  69. and be sure it's a valid file. */
  70. struct ast_filestream *tmp;
  71. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  72. memset(tmp, 0, sizeof(struct ast_filestream));
  73. if (ast_mutex_lock(&g726_lock)) {
  74. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  75. free(tmp);
  76. return NULL;
  77. }
  78. tmp->fd = fd;
  79. tmp->rate = RATE_40;
  80. tmp->fr.data = tmp->g726;
  81. tmp->fr.frametype = AST_FRAME_VOICE;
  82. tmp->fr.subclass = AST_FORMAT_G726;
  83. /* datalen will vary for each frame */
  84. tmp->fr.src = name40;
  85. tmp->fr.mallocd = 0;
  86. glistcnt++;
  87. if (option_debug)
  88. ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
  89. 40 - tmp->rate * 8);
  90. ast_mutex_unlock(&g726_lock);
  91. ast_update_use_count();
  92. }
  93. return tmp;
  94. }
  95. static struct ast_filestream *g726_32_open(int fd)
  96. {
  97. /* We don't have any header to read or anything really, but
  98. if we did, it would go here. We also might want to check
  99. and be sure it's a valid file. */
  100. struct ast_filestream *tmp;
  101. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  102. memset(tmp, 0, sizeof(struct ast_filestream));
  103. if (ast_mutex_lock(&g726_lock)) {
  104. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  105. free(tmp);
  106. return NULL;
  107. }
  108. tmp->fd = fd;
  109. tmp->rate = RATE_32;
  110. tmp->fr.data = tmp->g726;
  111. tmp->fr.frametype = AST_FRAME_VOICE;
  112. tmp->fr.subclass = AST_FORMAT_G726;
  113. /* datalen will vary for each frame */
  114. tmp->fr.src = name32;
  115. tmp->fr.mallocd = 0;
  116. glistcnt++;
  117. if (option_debug)
  118. ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
  119. 40 - tmp->rate * 8);
  120. ast_mutex_unlock(&g726_lock);
  121. ast_update_use_count();
  122. }
  123. return tmp;
  124. }
  125. static struct ast_filestream *g726_24_open(int fd)
  126. {
  127. /* We don't have any header to read or anything really, but
  128. if we did, it would go here. We also might want to check
  129. and be sure it's a valid file. */
  130. struct ast_filestream *tmp;
  131. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  132. memset(tmp, 0, sizeof(struct ast_filestream));
  133. if (ast_mutex_lock(&g726_lock)) {
  134. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  135. free(tmp);
  136. return NULL;
  137. }
  138. tmp->fd = fd;
  139. tmp->rate = RATE_24;
  140. tmp->fr.data = tmp->g726;
  141. tmp->fr.frametype = AST_FRAME_VOICE;
  142. tmp->fr.subclass = AST_FORMAT_G726;
  143. /* datalen will vary for each frame */
  144. tmp->fr.src = name24;
  145. tmp->fr.mallocd = 0;
  146. glistcnt++;
  147. if (option_debug)
  148. ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
  149. 40 - tmp->rate * 8);
  150. ast_mutex_unlock(&g726_lock);
  151. ast_update_use_count();
  152. }
  153. return tmp;
  154. }
  155. static struct ast_filestream *g726_16_open(int fd)
  156. {
  157. /* We don't have any header to read or anything really, but
  158. if we did, it would go here. We also might want to check
  159. and be sure it's a valid file. */
  160. struct ast_filestream *tmp;
  161. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  162. memset(tmp, 0, sizeof(struct ast_filestream));
  163. if (ast_mutex_lock(&g726_lock)) {
  164. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  165. free(tmp);
  166. return NULL;
  167. }
  168. tmp->fd = fd;
  169. tmp->rate = RATE_16;
  170. tmp->fr.data = tmp->g726;
  171. tmp->fr.frametype = AST_FRAME_VOICE;
  172. tmp->fr.subclass = AST_FORMAT_G726;
  173. /* datalen will vary for each frame */
  174. tmp->fr.src = name16;
  175. tmp->fr.mallocd = 0;
  176. glistcnt++;
  177. if (option_debug)
  178. ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
  179. 40 - tmp->rate * 8);
  180. ast_mutex_unlock(&g726_lock);
  181. ast_update_use_count();
  182. }
  183. return tmp;
  184. }
  185. static struct ast_filestream *g726_40_rewrite(int fd, char *comment)
  186. {
  187. /* We don't have any header to read or anything really, but
  188. if we did, it would go here. We also might want to check
  189. and be sure it's a valid file. */
  190. struct ast_filestream *tmp;
  191. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  192. memset(tmp, 0, sizeof(struct ast_filestream));
  193. if (ast_mutex_lock(&g726_lock)) {
  194. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  195. free(tmp);
  196. return NULL;
  197. }
  198. tmp->fd = fd;
  199. tmp->rate = RATE_40;
  200. glistcnt++;
  201. if (option_debug)
  202. ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
  203. 40 - tmp->rate * 8);
  204. ast_mutex_unlock(&g726_lock);
  205. ast_update_use_count();
  206. } else
  207. ast_log(LOG_WARNING, "Out of memory\n");
  208. return tmp;
  209. }
  210. static struct ast_filestream *g726_32_rewrite(int fd, char *comment)
  211. {
  212. /* We don't have any header to read or anything really, but
  213. if we did, it would go here. We also might want to check
  214. and be sure it's a valid file. */
  215. struct ast_filestream *tmp;
  216. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  217. memset(tmp, 0, sizeof(struct ast_filestream));
  218. if (ast_mutex_lock(&g726_lock)) {
  219. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  220. free(tmp);
  221. return NULL;
  222. }
  223. tmp->fd = fd;
  224. tmp->rate = RATE_32;
  225. glistcnt++;
  226. if (option_debug)
  227. ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
  228. 40 - tmp->rate * 8);
  229. ast_mutex_unlock(&g726_lock);
  230. ast_update_use_count();
  231. } else
  232. ast_log(LOG_WARNING, "Out of memory\n");
  233. return tmp;
  234. }
  235. static struct ast_filestream *g726_24_rewrite(int fd, char *comment)
  236. {
  237. /* We don't have any header to read or anything really, but
  238. if we did, it would go here. We also might want to check
  239. and be sure it's a valid file. */
  240. struct ast_filestream *tmp;
  241. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  242. memset(tmp, 0, sizeof(struct ast_filestream));
  243. if (ast_mutex_lock(&g726_lock)) {
  244. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  245. free(tmp);
  246. return NULL;
  247. }
  248. tmp->fd = fd;
  249. tmp->rate = RATE_24;
  250. glistcnt++;
  251. if (option_debug)
  252. ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
  253. 40 - tmp->rate * 8);
  254. ast_mutex_unlock(&g726_lock);
  255. ast_update_use_count();
  256. } else
  257. ast_log(LOG_WARNING, "Out of memory\n");
  258. return tmp;
  259. }
  260. static struct ast_filestream *g726_16_rewrite(int fd, char *comment)
  261. {
  262. /* We don't have any header to read or anything really, but
  263. if we did, it would go here. We also might want to check
  264. and be sure it's a valid file. */
  265. struct ast_filestream *tmp;
  266. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  267. memset(tmp, 0, sizeof(struct ast_filestream));
  268. if (ast_mutex_lock(&g726_lock)) {
  269. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  270. free(tmp);
  271. return NULL;
  272. }
  273. tmp->fd = fd;
  274. tmp->rate = RATE_16;
  275. glistcnt++;
  276. if (option_debug)
  277. ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
  278. 40 - tmp->rate * 8);
  279. ast_mutex_unlock(&g726_lock);
  280. ast_update_use_count();
  281. } else
  282. ast_log(LOG_WARNING, "Out of memory\n");
  283. return tmp;
  284. }
  285. /*
  286. * Rate independent format functions (close, read, write)
  287. */
  288. static void g726_close(struct ast_filestream *s)
  289. {
  290. if (ast_mutex_lock(&g726_lock)) {
  291. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  292. return;
  293. }
  294. glistcnt--;
  295. if (option_debug)
  296. ast_log(LOG_DEBUG, "Closed filestream G.726-%dk.\n", 40 - s->rate * 8);
  297. ast_mutex_unlock(&g726_lock);
  298. ast_update_use_count();
  299. close(s->fd);
  300. free(s);
  301. s = NULL;
  302. }
  303. static struct ast_frame *g726_read(struct ast_filestream *s, int *whennext)
  304. {
  305. int res;
  306. /* Send a frame from the file to the appropriate channel */
  307. s->fr.frametype = AST_FRAME_VOICE;
  308. s->fr.subclass = AST_FORMAT_G726;
  309. s->fr.offset = AST_FRIENDLY_OFFSET;
  310. s->fr.samples = 8 * FRAME_TIME;
  311. s->fr.datalen = frame_size[s->rate];
  312. s->fr.mallocd = 0;
  313. s->fr.data = s->g726;
  314. if ((res = read(s->fd, s->g726, s->fr.datalen)) != s->fr.datalen) {
  315. if (res)
  316. ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
  317. return NULL;
  318. }
  319. *whennext = s->fr.samples;
  320. return &s->fr;
  321. }
  322. static int g726_write(struct ast_filestream *fs, struct ast_frame *f)
  323. {
  324. int res;
  325. if (f->frametype != AST_FRAME_VOICE) {
  326. ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
  327. return -1;
  328. }
  329. if (f->subclass != AST_FORMAT_G726) {
  330. ast_log(LOG_WARNING, "Asked to write non-G726 frame (%d)!\n",
  331. f->subclass);
  332. return -1;
  333. }
  334. if (f->datalen % frame_size[fs->rate]) {
  335. ast_log(LOG_WARNING, "Invalid data length %d, should be multiple of %d\n",
  336. f->datalen, frame_size[fs->rate]);
  337. return -1;
  338. }
  339. if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) {
  340. ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n",
  341. res, frame_size[fs->rate], strerror(errno));
  342. return -1;
  343. }
  344. return 0;
  345. }
  346. static char *g726_getcomment(struct ast_filestream *s)
  347. {
  348. return NULL;
  349. }
  350. static int g726_seek(struct ast_filestream *fs, long sample_offset, int whence)
  351. {
  352. return -1;
  353. }
  354. static int g726_trunc(struct ast_filestream *fs)
  355. {
  356. return -1;
  357. }
  358. static long g726_tell(struct ast_filestream *fs)
  359. {
  360. return -1;
  361. }
  362. /*
  363. * Module interface (load_module, unload_module, usecount, description, key)
  364. */
  365. int load_module()
  366. {
  367. int res;
  368. res = ast_format_register(name40, exts40, AST_FORMAT_G726,
  369. g726_40_open,
  370. g726_40_rewrite,
  371. g726_write,
  372. g726_seek,
  373. g726_trunc,
  374. g726_tell,
  375. g726_read,
  376. g726_close,
  377. g726_getcomment);
  378. if (res) {
  379. ast_log(LOG_WARNING, "Failed to register format %s.\n", name40);
  380. return(-1);
  381. }
  382. res = ast_format_register(name32, exts32, AST_FORMAT_G726,
  383. g726_32_open,
  384. g726_32_rewrite,
  385. g726_write,
  386. g726_seek,
  387. g726_trunc,
  388. g726_tell,
  389. g726_read,
  390. g726_close,
  391. g726_getcomment);
  392. if (res) {
  393. ast_log(LOG_WARNING, "Failed to register format %s.\n", name32);
  394. return(-1);
  395. }
  396. res = ast_format_register(name24, exts24, AST_FORMAT_G726,
  397. g726_24_open,
  398. g726_24_rewrite,
  399. g726_write,
  400. g726_seek,
  401. g726_trunc,
  402. g726_tell,
  403. g726_read,
  404. g726_close,
  405. g726_getcomment);
  406. if (res) {
  407. ast_log(LOG_WARNING, "Failed to register format %s.\n", name24);
  408. return(-1);
  409. }
  410. res = ast_format_register(name16, exts16, AST_FORMAT_G726,
  411. g726_16_open,
  412. g726_16_rewrite,
  413. g726_write,
  414. g726_seek,
  415. g726_trunc,
  416. g726_tell,
  417. g726_read,
  418. g726_close,
  419. g726_getcomment);
  420. if (res) {
  421. ast_log(LOG_WARNING, "Failed to register format %s.\n", name16);
  422. return(-1);
  423. }
  424. return(0);
  425. }
  426. int unload_module()
  427. {
  428. int res;
  429. res = ast_format_unregister(name16);
  430. if (res) {
  431. ast_log(LOG_WARNING, "Failed to unregister format %s.\n", name16);
  432. return(-1);
  433. }
  434. res = ast_format_unregister(name24);
  435. if (res) {
  436. ast_log(LOG_WARNING, "Failed to unregister format %s.\n", name24);
  437. return(-1);
  438. }
  439. res = ast_format_unregister(name32);
  440. if (res) {
  441. ast_log(LOG_WARNING, "Failed to unregister format %s.\n", name32);
  442. return(-1);
  443. }
  444. res = ast_format_unregister(name40);
  445. if (res) {
  446. ast_log(LOG_WARNING, "Failed to unregister format %s.\n", name40);
  447. return(-1);
  448. }
  449. return(0);
  450. }
  451. int usecount()
  452. {
  453. int res;
  454. if (ast_mutex_lock(&g726_lock)) {
  455. ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
  456. return -1;
  457. }
  458. res = glistcnt;
  459. ast_mutex_unlock(&g726_lock);
  460. return res;
  461. }
  462. char *description()
  463. {
  464. return desc;
  465. }
  466. char *key()
  467. {
  468. return ASTERISK_GPL_KEY;
  469. }