#include "asterisk.h"
#include <vorbis/codec.h>
#include <vorbis/vorbisenc.h>
#include <vorbis/vorbisfile.h>
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
Go to the source code of this file.
Data Structures | |
struct | ogg_vorbis_desc |
Defines | |
#define | BLOCK_SIZE 4096 |
#define | BUF_SIZE (2*SAMPLES_MAX) |
#define | SAMPLES_MAX 512 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | _ov_header_fseek_wrap (FILE *f, ogg_int64_t off, int whence) |
static int | load_module (void) |
static void | ogg_vorbis_close (struct ast_filestream *fs) |
Close a OGG/Vorbis filestream. | |
static int | ogg_vorbis_open (struct ast_filestream *s) |
Create a new OGG/Vorbis filestream and set it up for reading. | |
static struct ast_frame * | ogg_vorbis_read (struct ast_filestream *fs, int *whennext) |
Read a frame full of audio data from the filestream. | |
static int | ogg_vorbis_rewrite (struct ast_filestream *s, const char *comment) |
Create a new OGG/Vorbis filestream and set it up for writing. | |
static int | ogg_vorbis_seek (struct ast_filestream *fs, off_t sample_offset, int whence) |
Seek to a specific position in an OGG/Vorbis filestream. | |
static off_t | ogg_vorbis_tell (struct ast_filestream *fs) |
Tell the current position in OGG/Vorbis filestream measured in pcms. | |
static int | ogg_vorbis_trunc (struct ast_filestream *fs) |
Trucate an OGG/Vorbis filestream. | |
static int | ogg_vorbis_write (struct ast_filestream *fs, struct ast_frame *f) |
Write audio data from a frame to an OGG/Vorbis filestream. | |
static int | unload_module (void) |
static void | write_stream (struct ogg_vorbis_desc *s, FILE *f) |
Write out any pending encoded data. | |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "OGG/Vorbis audio" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static ov_callbacks | OV_CALLBACKS_NOCLOSE |
static struct ast_format | vorbis_f |
Definition in file format_ogg_vorbis.c.
#define BLOCK_SIZE 4096 |
Definition at line 56 of file format_ogg_vorbis.c.
#define BUF_SIZE (2*SAMPLES_MAX) |
Definition at line 54 of file format_ogg_vorbis.c.
#define SAMPLES_MAX 512 |
Definition at line 53 of file format_ogg_vorbis.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 453 of file format_ogg_vorbis.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 453 of file format_ogg_vorbis.c.
static int _ov_header_fseek_wrap | ( | FILE * | f, | |
ogg_int64_t | off, | |||
int | whence | |||
) | [static] |
static int load_module | ( | void | ) | [static] |
Definition at line 437 of file format_ogg_vorbis.c.
References ast_format_register, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, and vorbis_f.
00438 { 00439 if (ast_format_register(&vorbis_f)) 00440 return AST_MODULE_LOAD_FAILURE; 00441 return AST_MODULE_LOAD_SUCCESS; 00442 }
static void ogg_vorbis_close | ( | struct ast_filestream * | fs | ) | [static] |
Close a OGG/Vorbis filestream.
fs | A OGG/Vorbis filestream. |
Definition at line 278 of file format_ogg_vorbis.c.
References ast_filestream::_private, ast_filestream::f, ogg_vorbis_desc::ov_f, ogg_vorbis_desc::vd, write_stream(), and ogg_vorbis_desc::writing.
00279 { 00280 struct ogg_vorbis_desc *s = (struct ogg_vorbis_desc *) fs->_private; 00281 00282 if (s->writing) { 00283 /* Tell the Vorbis encoder that the stream is finished 00284 * and write out the rest of the data */ 00285 vorbis_analysis_wrote(&s->vd, 0); 00286 write_stream(s, fs->f); 00287 } else { 00288 /* clear OggVorbis_File handle */ 00289 ov_clear(&s->ov_f); 00290 } 00291 }
static int ogg_vorbis_open | ( | struct ast_filestream * | s | ) | [static] |
Create a new OGG/Vorbis filestream and set it up for reading.
s | File that points to on disk storage of the OGG/Vorbis data. |
Definition at line 109 of file format_ogg_vorbis.c.
References ast_filestream::_private, ast_log(), DEFAULT_SAMPLE_RATE, desc, ast_filestream::f, and LOG_ERROR.
00110 { 00111 int result; 00112 struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) s->_private; 00113 00114 /* initialize private description block */ 00115 memset(desc, 0, sizeof(struct ogg_vorbis_desc)); 00116 desc->writing = 0; 00117 00118 /* actually open file */ 00119 result = ov_open_callbacks(s->f, &desc->ov_f, NULL, 0, OV_CALLBACKS_NOCLOSE); 00120 if (result != 0) { 00121 ast_log(LOG_ERROR, "Error opening Ogg/Vorbis file stream.\n"); 00122 return -1; 00123 } 00124 00125 /* check stream(s) type */ 00126 if (desc->ov_f.vi->channels != 1) { 00127 ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n"); 00128 ov_clear(&desc->ov_f); 00129 return -1; 00130 } 00131 00132 if (desc->ov_f.vi->rate != DEFAULT_SAMPLE_RATE) { 00133 ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n"); 00134 ov_clear(&desc->ov_f); 00135 return -1; 00136 } 00137 00138 return 0; 00139 }
static struct ast_frame* ogg_vorbis_read | ( | struct ast_filestream * | fs, | |
int * | whennext | |||
) | [static] |
Read a frame full of audio data from the filestream.
fs | The filestream. | |
whennext | Number of sample times to schedule the next call. |
Definition at line 299 of file format_ogg_vorbis.c.
References __BIG_ENDIAN, ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_filestream::buf, BUF_SIZE, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, desc, ast_filestream::fr, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ast_frame::ptr, ast_frame::samples, and ast_frame::subclass.
00301 { 00302 struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private; 00303 int current_bitstream = -10; 00304 char *out_buf; 00305 long bytes_read; 00306 00307 if (desc->writing) { 00308 ast_log(LOG_WARNING, "Reading is not suport on OGG/Vorbis on write files.\n"); 00309 return NULL; 00310 } 00311 00312 /* initialize frame */ 00313 fs->fr.frametype = AST_FRAME_VOICE; 00314 fs->fr.subclass.codec = AST_FORMAT_SLINEAR; 00315 fs->fr.mallocd = 0; 00316 AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); 00317 out_buf = (char *) (fs->fr.data.ptr); /* SLIN data buffer */ 00318 00319 /* read samples from OV interface */ 00320 bytes_read = ov_read( 00321 &desc->ov_f, 00322 out_buf, /* Buffer to write data */ 00323 BUF_SIZE, /* Size of buffer */ 00324 (__BYTE_ORDER == __BIG_ENDIAN), /* Endianes (0 for little) */ 00325 2, /* 1 = 8bit, 2 = 16bit */ 00326 1, /* 0 = unsigned, 1 = signed */ 00327 ¤t_bitstream /* Returns the current bitstream section */ 00328 ); 00329 00330 /* check returned data */ 00331 if (bytes_read <= 0) { 00332 /* End of stream */ 00333 return NULL; 00334 } 00335 00336 /* Return decoded bytes */ 00337 fs->fr.datalen = bytes_read; 00338 fs->fr.samples = bytes_read / 2; 00339 *whennext = fs->fr.samples; 00340 return &fs->fr; 00341 }
static int ogg_vorbis_rewrite | ( | struct ast_filestream * | s, | |
const char * | comment | |||
) | [static] |
Create a new OGG/Vorbis filestream and set it up for writing.
s | File pointer that points to on-disk storage. | |
comment | Comment that should be embedded in the OGG/Vorbis file. |
Definition at line 147 of file format_ogg_vorbis.c.
References ast_filestream::_private, ast_log(), ast_random(), DEFAULT_SAMPLE_RATE, ogg_vorbis_desc::eos, errno, ast_filestream::f, LOG_ERROR, LOG_WARNING, ogg_vorbis_desc::og, ogg_vorbis_desc::os, ogg_vorbis_desc::vb, ogg_vorbis_desc::vc, ogg_vorbis_desc::vd, ogg_vorbis_desc::vi, ogg_vorbis_desc::writing, and ogg_vorbis_desc::writing_pcm_pos.
00149 { 00150 ogg_packet header; 00151 ogg_packet header_comm; 00152 ogg_packet header_code; 00153 struct ogg_vorbis_desc *tmp = (struct ogg_vorbis_desc *) s->_private; 00154 00155 tmp->writing = 1; 00156 tmp->writing_pcm_pos = 0; 00157 00158 vorbis_info_init(&tmp->vi); 00159 00160 if (vorbis_encode_init_vbr(&tmp->vi, 1, DEFAULT_SAMPLE_RATE, 0.4)) { 00161 ast_log(LOG_ERROR, "Unable to initialize Vorbis encoder!\n"); 00162 return -1; 00163 } 00164 00165 vorbis_comment_init(&tmp->vc); 00166 vorbis_comment_add_tag(&tmp->vc, "ENCODER", "Asterisk PBX"); 00167 if (comment) 00168 vorbis_comment_add_tag(&tmp->vc, "COMMENT", (char *) comment); 00169 00170 vorbis_analysis_init(&tmp->vd, &tmp->vi); 00171 vorbis_block_init(&tmp->vd, &tmp->vb); 00172 00173 ogg_stream_init(&tmp->os, ast_random()); 00174 00175 vorbis_analysis_headerout(&tmp->vd, &tmp->vc, &header, &header_comm, 00176 &header_code); 00177 ogg_stream_packetin(&tmp->os, &header); 00178 ogg_stream_packetin(&tmp->os, &header_comm); 00179 ogg_stream_packetin(&tmp->os, &header_code); 00180 00181 while (!tmp->eos) { 00182 if (ogg_stream_flush(&tmp->os, &tmp->og) == 0) 00183 break; 00184 if (!fwrite(tmp->og.header, 1, tmp->og.header_len, s->f)) { 00185 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00186 } 00187 if (!fwrite(tmp->og.body, 1, tmp->og.body_len, s->f)) { 00188 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00189 } 00190 if (ogg_page_eos(&tmp->og)) 00191 tmp->eos = 1; 00192 } 00193 00194 return 0; 00195 }
static int ogg_vorbis_seek | ( | struct ast_filestream * | fs, | |
off_t | sample_offset, | |||
int | whence | |||
) | [static] |
Seek to a specific position in an OGG/Vorbis filestream.
s | The filestream to take action on. | |
sample_offset | New position for the filestream, measured in 8KHz samples. | |
whence | Location to measure |
Definition at line 382 of file format_ogg_vorbis.c.
References ast_filestream::_private, ast_log(), desc, LOG_WARNING, and ogg_vorbis_tell().
00383 { 00384 int seek_result = -1; 00385 off_t relative_pcm_pos; 00386 struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private; 00387 00388 if (desc->writing) { 00389 ast_log(LOG_WARNING, "Seeking is not supported on OGG/Vorbis streams in writing mode!\n"); 00390 return -1; 00391 } 00392 00393 /* ov_pcm_seek support seeking only from begining (SEEK_SET), the rest must be emulated */ 00394 switch (whence) { 00395 case SEEK_SET: 00396 seek_result = ov_pcm_seek(&desc->ov_f, sample_offset); 00397 break; 00398 case SEEK_CUR: 00399 if ((relative_pcm_pos = ogg_vorbis_tell(fs)) < 0) { 00400 seek_result = -1; 00401 break; 00402 } 00403 seek_result = ov_pcm_seek(&desc->ov_f, relative_pcm_pos + sample_offset); 00404 break; 00405 case SEEK_END: 00406 if ((relative_pcm_pos = ov_pcm_total(&desc->ov_f, -1)) < 0) { 00407 seek_result = -1; 00408 break; 00409 } 00410 seek_result = ov_pcm_seek(&desc->ov_f, relative_pcm_pos - sample_offset); 00411 break; 00412 default: 00413 ast_log(LOG_WARNING, "Unknown *whence* to seek on OGG/Vorbis streams!\n"); 00414 break; 00415 } 00416 00417 /* normalize error value to -1,0 */ 00418 return (seek_result == 0) ? 0 : -1; 00419 }
static off_t ogg_vorbis_tell | ( | struct ast_filestream * | fs | ) | [static] |
Tell the current position in OGG/Vorbis filestream measured in pcms.
s | The filestream to take action on. |
Definition at line 360 of file format_ogg_vorbis.c.
References ast_filestream::_private, and desc.
Referenced by ogg_vorbis_seek().
00361 { 00362 off_t pos; 00363 struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private; 00364 00365 if (desc->writing) { 00366 return desc->writing_pcm_pos; 00367 } 00368 00369 if ((pos = ov_pcm_tell(&desc->ov_f)) < 0) { 00370 return -1; 00371 } 00372 return pos; 00373 }
static int ogg_vorbis_trunc | ( | struct ast_filestream * | fs | ) | [static] |
Trucate an OGG/Vorbis filestream.
s | The filestream to truncate. |
Definition at line 349 of file format_ogg_vorbis.c.
References ast_log(), and LOG_WARNING.
00350 { 00351 ast_log(LOG_WARNING, "Truncation is not supported on OGG/Vorbis streams!\n"); 00352 return -1; 00353 }
static int ogg_vorbis_write | ( | struct ast_filestream * | fs, | |
struct ast_frame * | f | |||
) | [static] |
Write audio data from a frame to an OGG/Vorbis filestream.
fs | An OGG/Vorbis filestream. | |
f | A frame containing audio to be written to the filestream. |
Definition at line 234 of file format_ogg_vorbis.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_filestream::f, f, LOG_ERROR, LOG_WARNING, ogg_vorbis_desc::vd, write_stream(), ogg_vorbis_desc::writing, and ogg_vorbis_desc::writing_pcm_pos.
00235 { 00236 int i; 00237 float **buffer; 00238 short *data; 00239 struct ogg_vorbis_desc *s = (struct ogg_vorbis_desc *) fs->_private; 00240 00241 if (!s->writing) { 00242 ast_log(LOG_ERROR, "This stream is not set up for writing!\n"); 00243 return -1; 00244 } 00245 00246 if (f->frametype != AST_FRAME_VOICE) { 00247 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00248 return -1; 00249 } 00250 if (f->subclass.codec != AST_FORMAT_SLINEAR) { 00251 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%s)!\n", 00252 ast_getformatname(f->subclass.codec)); 00253 return -1; 00254 } 00255 if (!f->datalen) 00256 return -1; 00257 00258 data = (short *) f->data.ptr; 00259 00260 buffer = vorbis_analysis_buffer(&s->vd, f->samples); 00261 00262 for (i = 0; i < f->samples; i++) 00263 buffer[0][i] = (double)data[i] / 32768.0; 00264 00265 vorbis_analysis_wrote(&s->vd, f->samples); 00266 00267 write_stream(s, fs->f); 00268 00269 s->writing_pcm_pos += f->samples; 00270 00271 return 0; 00272 }
static int unload_module | ( | void | ) | [static] |
Definition at line 444 of file format_ogg_vorbis.c.
References ast_format_unregister(), ast_format::name, and vorbis_f.
00445 { 00446 return ast_format_unregister(vorbis_f.name); 00447 }
static void write_stream | ( | struct ogg_vorbis_desc * | s, | |
FILE * | f | |||
) | [static] |
Write out any pending encoded data.
s | An OGG/Vorbis filestream. | |
f | The file to write to. |
Definition at line 202 of file format_ogg_vorbis.c.
References ast_log(), ogg_vorbis_desc::eos, errno, LOG_WARNING, ogg_vorbis_desc::og, ogg_vorbis_desc::op, ogg_vorbis_desc::os, ogg_vorbis_desc::vb, and ogg_vorbis_desc::vd.
Referenced by ogg_vorbis_close(), and ogg_vorbis_write().
00203 { 00204 while (vorbis_analysis_blockout(&s->vd, &s->vb) == 1) { 00205 vorbis_analysis(&s->vb, NULL); 00206 vorbis_bitrate_addblock(&s->vb); 00207 00208 while (vorbis_bitrate_flushpacket(&s->vd, &s->op)) { 00209 ogg_stream_packetin(&s->os, &s->op); 00210 while (!s->eos) { 00211 if (ogg_stream_pageout(&s->os, &s->og) == 0) { 00212 break; 00213 } 00214 if (!fwrite(s->og.header, 1, s->og.header_len, f)) { 00215 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00216 } 00217 if (!fwrite(s->og.body, 1, s->og.body_len, f)) { 00218 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00219 } 00220 if (ogg_page_eos(&s->og)) { 00221 s->eos = 1; 00222 } 00223 } 00224 } 00225 } 00226 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "OGG/Vorbis audio" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } [static] |
Definition at line 453 of file format_ogg_vorbis.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 453 of file format_ogg_vorbis.c.
ov_callbacks OV_CALLBACKS_NOCLOSE [static] |
Definition at line 96 of file format_ogg_vorbis.c.
struct ast_format vorbis_f [static] |
Definition at line 421 of file format_ogg_vorbis.c.
Referenced by load_module(), and unload_module().