format_ogg_vorbis.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2005, Jeff Ollie
  5. *
  6. * See http://www.asterisk.org for more information about
  7. * the Asterisk project. Please do not directly contact
  8. * any of the maintainers of this project for assistance;
  9. * the project provides a web site, mailing lists and IRC
  10. * channels for your use.
  11. *
  12. * This program is free software, distributed under the terms of
  13. * the GNU General Public License Version 2. See the LICENSE file
  14. * at the top of the source tree.
  15. */
  16. /*! \file
  17. *
  18. * \brief OGG/Vorbis streams.
  19. * \arg File name extension: ogg
  20. * \ingroup formats
  21. */
  22. /* the order of these dependencies is important... it also specifies
  23. the link order of the libraries during linking
  24. */
  25. /*** MODULEINFO
  26. <depend>vorbis</depend>
  27. <depend>ogg</depend>
  28. ***/
  29. #include "asterisk.h"
  30. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  31. #include <vorbis/codec.h>
  32. #include <vorbis/vorbisenc.h>
  33. #ifdef _WIN32
  34. #include <io.h>
  35. #endif
  36. #include "asterisk/mod_format.h"
  37. #include "asterisk/module.h"
  38. /*
  39. * this is the number of samples we deal with. Samples are converted
  40. * to SLINEAR so each one uses 2 bytes in the buffer.
  41. */
  42. #define SAMPLES_MAX 160
  43. #define BUF_SIZE (2*SAMPLES_MAX)
  44. #define BLOCK_SIZE 4096 /* used internally in the vorbis routines */
  45. struct vorbis_desc { /* format specific parameters */
  46. /* structures for handling the Ogg container */
  47. ogg_sync_state oy;
  48. ogg_stream_state os;
  49. ogg_page og;
  50. ogg_packet op;
  51. /* structures for handling Vorbis audio data */
  52. vorbis_info vi;
  53. vorbis_comment vc;
  54. vorbis_dsp_state vd;
  55. vorbis_block vb;
  56. /*! \brief Indicates whether this filestream is set up for reading or writing. */
  57. int writing;
  58. /*! \brief Indicates whether an End of Stream condition has been detected. */
  59. int eos;
  60. };
  61. /*!
  62. * \brief Create a new OGG/Vorbis filestream and set it up for reading.
  63. * \param s File that points to on disk storage of the OGG/Vorbis data.
  64. * \return The new filestream.
  65. */
  66. static int ogg_vorbis_open(struct ast_filestream *s)
  67. {
  68. int i;
  69. int bytes;
  70. int result;
  71. char **ptr;
  72. char *buffer;
  73. struct vorbis_desc *tmp = (struct vorbis_desc *)s->_private;
  74. tmp->writing = 0;
  75. ogg_sync_init(&tmp->oy);
  76. buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
  77. bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
  78. ogg_sync_wrote(&tmp->oy, bytes);
  79. result = ogg_sync_pageout(&tmp->oy, &tmp->og);
  80. if (result != 1) {
  81. if(bytes < BLOCK_SIZE) {
  82. ast_log(LOG_ERROR, "Run out of data...\n");
  83. } else {
  84. ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
  85. }
  86. ogg_sync_clear(&tmp->oy);
  87. return -1;
  88. }
  89. ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
  90. vorbis_info_init(&tmp->vi);
  91. vorbis_comment_init(&tmp->vc);
  92. if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0) {
  93. ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
  94. error:
  95. ogg_stream_clear(&tmp->os);
  96. vorbis_comment_clear(&tmp->vc);
  97. vorbis_info_clear(&tmp->vi);
  98. ogg_sync_clear(&tmp->oy);
  99. return -1;
  100. }
  101. if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1) {
  102. ast_log(LOG_ERROR, "Error reading initial header packet.\n");
  103. goto error;
  104. }
  105. if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0) {
  106. ast_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
  107. goto error;
  108. }
  109. for (i = 0; i < 2 ; ) {
  110. while (i < 2) {
  111. result = ogg_sync_pageout(&tmp->oy, &tmp->og);
  112. if (result == 0)
  113. break;
  114. if (result == 1) {
  115. ogg_stream_pagein(&tmp->os, &tmp->og);
  116. while(i < 2) {
  117. result = ogg_stream_packetout(&tmp->os,&tmp->op);
  118. if(result == 0)
  119. break;
  120. if(result < 0) {
  121. ast_log(LOG_ERROR, "Corrupt secondary header. Exiting.\n");
  122. goto error;
  123. }
  124. vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
  125. i++;
  126. }
  127. }
  128. }
  129. buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
  130. bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
  131. if (bytes == 0 && i < 2) {
  132. ast_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
  133. goto error;
  134. }
  135. ogg_sync_wrote(&tmp->oy, bytes);
  136. }
  137. for (ptr = tmp->vc.user_comments; *ptr; ptr++)
  138. ast_debug(1, "OGG/Vorbis comment: %s\n", *ptr);
  139. ast_debug(1, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
  140. ast_debug(1, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);
  141. if (tmp->vi.channels != 1) {
  142. ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
  143. goto error;
  144. }
  145. if (tmp->vi.rate != DEFAULT_SAMPLE_RATE) {
  146. ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
  147. vorbis_block_clear(&tmp->vb);
  148. vorbis_dsp_clear(&tmp->vd);
  149. goto error;
  150. }
  151. vorbis_synthesis_init(&tmp->vd, &tmp->vi);
  152. vorbis_block_init(&tmp->vd, &tmp->vb);
  153. return 0;
  154. }
  155. /*!
  156. * \brief Create a new OGG/Vorbis filestream and set it up for writing.
  157. * \param s File pointer that points to on-disk storage.
  158. * \param comment Comment that should be embedded in the OGG/Vorbis file.
  159. * \return A new filestream.
  160. */
  161. static int ogg_vorbis_rewrite(struct ast_filestream *s,
  162. const char *comment)
  163. {
  164. ogg_packet header;
  165. ogg_packet header_comm;
  166. ogg_packet header_code;
  167. struct vorbis_desc *tmp = (struct vorbis_desc *)s->_private;
  168. tmp->writing = 1;
  169. vorbis_info_init(&tmp->vi);
  170. if (vorbis_encode_init_vbr(&tmp->vi, 1, DEFAULT_SAMPLE_RATE, 0.4)) {
  171. ast_log(LOG_ERROR, "Unable to initialize Vorbis encoder!\n");
  172. return -1;
  173. }
  174. vorbis_comment_init(&tmp->vc);
  175. vorbis_comment_add_tag(&tmp->vc, "ENCODER", "Asterisk PBX");
  176. if (comment)
  177. vorbis_comment_add_tag(&tmp->vc, "COMMENT", (char *) comment);
  178. vorbis_analysis_init(&tmp->vd, &tmp->vi);
  179. vorbis_block_init(&tmp->vd, &tmp->vb);
  180. ogg_stream_init(&tmp->os, ast_random());
  181. vorbis_analysis_headerout(&tmp->vd, &tmp->vc, &header, &header_comm,
  182. &header_code);
  183. ogg_stream_packetin(&tmp->os, &header);
  184. ogg_stream_packetin(&tmp->os, &header_comm);
  185. ogg_stream_packetin(&tmp->os, &header_code);
  186. while (!tmp->eos) {
  187. if (ogg_stream_flush(&tmp->os, &tmp->og) == 0)
  188. break;
  189. if (!fwrite(tmp->og.header, 1, tmp->og.header_len, s->f)) {
  190. ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
  191. }
  192. if (!fwrite(tmp->og.body, 1, tmp->og.body_len, s->f)) {
  193. ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
  194. }
  195. if (ogg_page_eos(&tmp->og))
  196. tmp->eos = 1;
  197. }
  198. return 0;
  199. }
  200. /*!
  201. * \brief Write out any pending encoded data.
  202. * \param s An OGG/Vorbis filestream.
  203. * \param f The file to write to.
  204. */
  205. static void write_stream(struct vorbis_desc *s, FILE *f)
  206. {
  207. while (vorbis_analysis_blockout(&s->vd, &s->vb) == 1) {
  208. vorbis_analysis(&s->vb, NULL);
  209. vorbis_bitrate_addblock(&s->vb);
  210. while (vorbis_bitrate_flushpacket(&s->vd, &s->op)) {
  211. ogg_stream_packetin(&s->os, &s->op);
  212. while (!s->eos) {
  213. if (ogg_stream_pageout(&s->os, &s->og) == 0) {
  214. break;
  215. }
  216. if (!fwrite(s->og.header, 1, s->og.header_len, f)) {
  217. ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
  218. }
  219. if (!fwrite(s->og.body, 1, s->og.body_len, f)) {
  220. ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
  221. }
  222. if (ogg_page_eos(&s->og)) {
  223. s->eos = 1;
  224. }
  225. }
  226. }
  227. }
  228. }
  229. /*!
  230. * \brief Write audio data from a frame to an OGG/Vorbis filestream.
  231. * \param fs An OGG/Vorbis filestream.
  232. * \param f A frame containing audio to be written to the filestream.
  233. * \return -1 if there was an error, 0 on success.
  234. */
  235. static int ogg_vorbis_write(struct ast_filestream *fs, struct ast_frame *f)
  236. {
  237. int i;
  238. float **buffer;
  239. short *data;
  240. struct vorbis_desc *s = (struct vorbis_desc *)fs->_private;
  241. if (!s->writing) {
  242. ast_log(LOG_ERROR, "This stream is not set up for writing!\n");
  243. return -1;
  244. }
  245. if (f->frametype != AST_FRAME_VOICE) {
  246. ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
  247. return -1;
  248. }
  249. if (f->subclass != AST_FORMAT_SLINEAR) {
  250. ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n",
  251. f->subclass);
  252. return -1;
  253. }
  254. if (!f->datalen)
  255. return -1;
  256. data = (short *) f->data.ptr;
  257. buffer = vorbis_analysis_buffer(&s->vd, f->samples);
  258. for (i = 0; i < f->samples; i++)
  259. buffer[0][i] = (double)data[i] / 32768.0;
  260. vorbis_analysis_wrote(&s->vd, f->samples);
  261. write_stream(s, fs->f);
  262. return 0;
  263. }
  264. /*!
  265. * \brief Close a OGG/Vorbis filestream.
  266. * \param fs A OGG/Vorbis filestream.
  267. */
  268. static void ogg_vorbis_close(struct ast_filestream *fs)
  269. {
  270. struct vorbis_desc *s = (struct vorbis_desc *)fs->_private;
  271. if (s->writing) {
  272. /* Tell the Vorbis encoder that the stream is finished
  273. * and write out the rest of the data */
  274. vorbis_analysis_wrote(&s->vd, 0);
  275. write_stream(s, fs->f);
  276. }
  277. ogg_stream_clear(&s->os);
  278. vorbis_block_clear(&s->vb);
  279. vorbis_dsp_clear(&s->vd);
  280. vorbis_comment_clear(&s->vc);
  281. vorbis_info_clear(&s->vi);
  282. if (s->writing) {
  283. ogg_sync_clear(&s->oy);
  284. }
  285. }
  286. /*!
  287. * \brief Get audio data.
  288. * \param fs An OGG/Vorbis filestream.
  289. * \param pcm Pointer to a buffere to store audio data in.
  290. */
  291. static int read_samples(struct ast_filestream *fs, float ***pcm)
  292. {
  293. int samples_in;
  294. int result;
  295. char *buffer;
  296. int bytes;
  297. struct vorbis_desc *s = (struct vorbis_desc *)fs->_private;
  298. while (1) {
  299. samples_in = vorbis_synthesis_pcmout(&s->vd, pcm);
  300. if (samples_in > 0) {
  301. return samples_in;
  302. }
  303. /* The Vorbis decoder needs more data... */
  304. /* See ifOGG has any packets in the current page for the Vorbis decoder. */
  305. result = ogg_stream_packetout(&s->os, &s->op);
  306. if (result > 0) {
  307. /* Yes OGG had some more packets for the Vorbis decoder. */
  308. if (vorbis_synthesis(&s->vb, &s->op) == 0) {
  309. vorbis_synthesis_blockin(&s->vd, &s->vb);
  310. }
  311. continue;
  312. }
  313. if (result < 0)
  314. ast_log(LOG_WARNING,
  315. "Corrupt or missing data at this page position; continuing...\n");
  316. /* No more packets left in the current page... */
  317. if (s->eos) {
  318. /* No more pages left in the stream */
  319. return -1;
  320. }
  321. while (!s->eos) {
  322. /* See ifOGG has any pages in it's internal buffers */
  323. result = ogg_sync_pageout(&s->oy, &s->og);
  324. if (result > 0) {
  325. /* Yes, OGG has more pages in it's internal buffers,
  326. add the page to the stream state */
  327. result = ogg_stream_pagein(&s->os, &s->og);
  328. if (result == 0) {
  329. /* Yes, got a new,valid page */
  330. if (ogg_page_eos(&s->og)) {
  331. s->eos = 1;
  332. }
  333. break;
  334. }
  335. ast_log(LOG_WARNING,
  336. "Invalid page in the bitstream; continuing...\n");
  337. }
  338. if (result < 0)
  339. ast_log(LOG_WARNING,
  340. "Corrupt or missing data in bitstream; continuing...\n");
  341. /* No, we need to read more data from the file descrptor */
  342. /* get a buffer from OGG to read the data into */
  343. buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE);
  344. /* read more data from the file descriptor */
  345. bytes = fread(buffer, 1, BLOCK_SIZE, fs->f);
  346. /* Tell OGG how many bytes we actually read into the buffer */
  347. ogg_sync_wrote(&s->oy, bytes);
  348. if (bytes == 0) {
  349. s->eos = 1;
  350. }
  351. }
  352. }
  353. }
  354. /*!
  355. * \brief Read a frame full of audio data from the filestream.
  356. * \param fs The filestream.
  357. * \param whennext Number of sample times to schedule the next call.
  358. * \return A pointer to a frame containing audio data or NULL ifthere is no more audio data.
  359. */
  360. static struct ast_frame *ogg_vorbis_read(struct ast_filestream *fs,
  361. int *whennext)
  362. {
  363. int clipflag = 0;
  364. int i;
  365. int j;
  366. double accumulator[SAMPLES_MAX];
  367. int val;
  368. int samples_in;
  369. int samples_out = 0;
  370. struct vorbis_desc *s = (struct vorbis_desc *)fs->_private;
  371. short *buf; /* SLIN data buffer */
  372. fs->fr.frametype = AST_FRAME_VOICE;
  373. fs->fr.subclass = AST_FORMAT_SLINEAR;
  374. fs->fr.mallocd = 0;
  375. AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
  376. buf = (short *)(fs->fr.data.ptr); /* SLIN data buffer */
  377. while (samples_out != SAMPLES_MAX) {
  378. float **pcm;
  379. int len = SAMPLES_MAX - samples_out;
  380. /* See ifVorbis decoder has some audio data for us ... */
  381. samples_in = read_samples(fs, &pcm);
  382. if (samples_in <= 0)
  383. break;
  384. /* Got some audio data from Vorbis... */
  385. /* Convert the float audio data to 16-bit signed linear */
  386. clipflag = 0;
  387. if (samples_in > len)
  388. samples_in = len;
  389. for (j = 0; j < samples_in; j++)
  390. accumulator[j] = 0.0;
  391. for (i = 0; i < s->vi.channels; i++) {
  392. float *mono = pcm[i];
  393. for (j = 0; j < samples_in; j++)
  394. accumulator[j] += mono[j];
  395. }
  396. for (j = 0; j < samples_in; j++) {
  397. val = accumulator[j] * 32767.0 / s->vi.channels;
  398. if (val > 32767) {
  399. val = 32767;
  400. clipflag = 1;
  401. } else if (val < -32768) {
  402. val = -32768;
  403. clipflag = 1;
  404. }
  405. buf[samples_out + j] = val;
  406. }
  407. if (clipflag)
  408. ast_log(LOG_WARNING, "Clipping in frame %ld\n", (long) (s->vd.sequence));
  409. /* Tell the Vorbis decoder how many samples we actually used. */
  410. vorbis_synthesis_read(&s->vd, samples_in);
  411. samples_out += samples_in;
  412. }
  413. if (samples_out > 0) {
  414. fs->fr.datalen = samples_out * 2;
  415. fs->fr.samples = samples_out;
  416. *whennext = samples_out;
  417. return &fs->fr;
  418. } else {
  419. return NULL;
  420. }
  421. }
  422. /*!
  423. * \brief Trucate an OGG/Vorbis filestream.
  424. * \param s The filestream to truncate.
  425. * \return 0 on success, -1 on failure.
  426. */
  427. static int ogg_vorbis_trunc(struct ast_filestream *s)
  428. {
  429. ast_log(LOG_WARNING, "Truncation is not supported on OGG/Vorbis streams!\n");
  430. return -1;
  431. }
  432. /*!
  433. * \brief Seek to a specific position in an OGG/Vorbis filestream.
  434. * \param s The filestream to truncate.
  435. * \param sample_offset New position for the filestream, measured in 8KHz samples.
  436. * \param whence Location to measure
  437. * \return 0 on success, -1 on failure.
  438. */
  439. static int ogg_vorbis_seek(struct ast_filestream *s, off_t sample_offset, int whence)
  440. {
  441. ast_log(LOG_WARNING, "Seeking is not supported on OGG/Vorbis streams!\n");
  442. return -1;
  443. }
  444. static off_t ogg_vorbis_tell(struct ast_filestream *s)
  445. {
  446. ast_log(LOG_WARNING, "Telling is not supported on OGG/Vorbis streams!\n");
  447. return -1;
  448. }
  449. static const struct ast_format vorbis_f = {
  450. .name = "ogg_vorbis",
  451. .exts = "ogg",
  452. .format = AST_FORMAT_SLINEAR,
  453. .open = ogg_vorbis_open,
  454. .rewrite = ogg_vorbis_rewrite,
  455. .write = ogg_vorbis_write,
  456. .seek = ogg_vorbis_seek,
  457. .trunc = ogg_vorbis_trunc,
  458. .tell = ogg_vorbis_tell,
  459. .read = ogg_vorbis_read,
  460. .close = ogg_vorbis_close,
  461. .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
  462. .desc_size = sizeof(struct vorbis_desc),
  463. };
  464. static int load_module(void)
  465. {
  466. if (ast_format_register(&vorbis_f))
  467. return AST_MODULE_LOAD_FAILURE;
  468. return AST_MODULE_LOAD_SUCCESS;
  469. }
  470. static int unload_module(void)
  471. {
  472. return ast_format_unregister(vorbis_f.name);
  473. }
  474. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "OGG/Vorbis audio",
  475. .load = load_module,
  476. .unload = unload_module,
  477. .load_pri = 10,
  478. );