#include "asterisk.h"
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisenc.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
Go to the source code of this file.
Data Structures | |
struct | vorbis_desc |
Defines | |
#define | BLOCK_SIZE 4096 |
#define | BUF_SIZE (2*SAMPLES_MAX) |
#define | SAMPLES_MAX 160 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
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 *s, 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 *s) |
static int | ogg_vorbis_trunc (struct ast_filestream *s) |
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 | read_samples (struct ast_filestream *fs, float ***pcm) |
Get audio data. | |
static int | unload_module (void) |
static void | write_stream (struct 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_FIRST | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_format | vorbis_f |
Definition in file format_ogg_vorbis.c.
#define BLOCK_SIZE 4096 |
Definition at line 68 of file format_ogg_vorbis.c.
Referenced by ogg_vorbis_open(), and read_samples().
#define BUF_SIZE (2*SAMPLES_MAX) |
Definition at line 66 of file format_ogg_vorbis.c.
#define SAMPLES_MAX 160 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 574 of file format_ogg_vorbis.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 574 of file format_ogg_vorbis.c.
static int load_module | ( | void | ) | [static] |
Definition at line 561 of file format_ogg_vorbis.c.
References ast_format_register, and vorbis_f.
00562 { 00563 return ast_format_register(&vorbis_f); 00564 }
static void ogg_vorbis_close | ( | struct ast_filestream * | fs | ) | [static] |
Close a OGG/Vorbis filestream.
fs | A OGG/Vorbis filestream. |
Definition at line 334 of file format_ogg_vorbis.c.
References ast_filestream::_private, ast_filestream::f, s, and write_stream().
00335 { 00336 struct vorbis_desc *s = (struct vorbis_desc *)fs->_private; 00337 00338 if (s->writing) { 00339 /* Tell the Vorbis encoder that the stream is finished 00340 * and write out the rest of the data */ 00341 vorbis_analysis_wrote(&s->vd, 0); 00342 write_stream(s, fs->f); 00343 } 00344 00345 ogg_stream_clear(&s->os); 00346 vorbis_block_clear(&s->vb); 00347 vorbis_dsp_clear(&s->vd); 00348 vorbis_comment_clear(&s->vc); 00349 vorbis_info_clear(&s->vi); 00350 00351 if (s->writing) { 00352 ogg_sync_clear(&s->oy); 00353 } 00354 }
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 95 of file format_ogg_vorbis.c.
References ast_log(), BLOCK_SIZE, LOG_ERROR, vorbis_desc::og, vorbis_desc::op, vorbis_desc::os, vorbis_desc::oy, s, vorbis_desc::vc, vorbis_desc::vi, and vorbis_desc::writing.
00096 { 00097 int i; 00098 int bytes; 00099 int result; 00100 char **ptr; 00101 char *buffer; 00102 struct vorbis_desc *tmp = (struct vorbis_desc *)s->_private; 00103 00104 tmp->writing = 0; 00105 00106 ogg_sync_init(&tmp->oy); 00107 00108 buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE); 00109 bytes = fread(buffer, 1, BLOCK_SIZE, s->f); 00110 ogg_sync_wrote(&tmp->oy, bytes); 00111 00112 result = ogg_sync_pageout(&tmp->oy, &tmp->og); 00113 if (result != 1) { 00114 if(bytes < BLOCK_SIZE) { 00115 ast_log(LOG_ERROR, "Run out of data...\n"); 00116 } else { 00117 ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n"); 00118 } 00119 ogg_sync_clear(&tmp->oy); 00120 return -1; 00121 } 00122 00123 ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og)); 00124 vorbis_info_init(&tmp->vi); 00125 vorbis_comment_init(&tmp->vc); 00126 00127 if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0) { 00128 ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n"); 00129 error: 00130 ogg_stream_clear(&tmp->os); 00131 vorbis_comment_clear(&tmp->vc); 00132 vorbis_info_clear(&tmp->vi); 00133 ogg_sync_clear(&tmp->oy); 00134 return -1; 00135 } 00136 00137 if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1) { 00138 ast_log(LOG_ERROR, "Error reading initial header packet.\n"); 00139 goto error; 00140 } 00141 00142 if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0) { 00143 ast_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n"); 00144 goto error; 00145 } 00146 00147 for (i = 0; i < 2 ; ) { 00148 while (i < 2) { 00149 result = ogg_sync_pageout(&tmp->oy, &tmp->og); 00150 if (result == 0) 00151 break; 00152 if (result == 1) { 00153 ogg_stream_pagein(&tmp->os, &tmp->og); 00154 while(i < 2) { 00155 result = ogg_stream_packetout(&tmp->os,&tmp->op); 00156 if(result == 0) 00157 break; 00158 if(result < 0) { 00159 ast_log(LOG_ERROR, "Corrupt secondary header. Exiting.\n"); 00160 goto error; 00161 } 00162 vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op); 00163 i++; 00164 } 00165 } 00166 } 00167 00168 buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE); 00169 bytes = fread(buffer, 1, BLOCK_SIZE, s->f); 00170 if (bytes == 0 && i < 2) { 00171 ast_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n"); 00172 goto error; 00173 } 00174 ogg_sync_wrote(&tmp->oy, bytes); 00175 } 00176 00177 for (ptr = tmp->vc.user_comments; *ptr; ptr++) 00178 ast_log(LOG_DEBUG, "OGG/Vorbis comment: %s\n", *ptr); 00179 ast_log(LOG_DEBUG, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate); 00180 ast_log(LOG_DEBUG, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor); 00181 00182 if (tmp->vi.channels != 1) { 00183 ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n"); 00184 goto error; 00185 } 00186 00187 if (tmp->vi.rate != DEFAULT_SAMPLE_RATE) { 00188 ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n"); 00189 vorbis_block_clear(&tmp->vb); 00190 vorbis_dsp_clear(&tmp->vd); 00191 goto error; 00192 } 00193 00194 vorbis_synthesis_init(&tmp->vd, &tmp->vi); 00195 vorbis_block_init(&tmp->vd, &tmp->vb); 00196 00197 return 0; 00198 }
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 441 of file format_ogg_vorbis.c.
References 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::data, ast_frame::datalen, ast_filestream::fr, ast_frame::frametype, len(), LOG_WARNING, ast_frame::mallocd, read_samples(), s, ast_frame::samples, SAMPLES_MAX, and ast_frame::subclass.
00443 { 00444 int clipflag = 0; 00445 int i; 00446 int j; 00447 double accumulator[SAMPLES_MAX]; 00448 int val; 00449 int samples_in; 00450 int samples_out = 0; 00451 struct vorbis_desc *s = (struct vorbis_desc *)fs->_private; 00452 short *buf; /* SLIN data buffer */ 00453 00454 fs->fr.frametype = AST_FRAME_VOICE; 00455 fs->fr.subclass = AST_FORMAT_SLINEAR; 00456 fs->fr.mallocd = 0; 00457 AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); 00458 buf = (short *)(fs->fr.data); /* SLIN data buffer */ 00459 00460 while (samples_out != SAMPLES_MAX) { 00461 float **pcm; 00462 int len = SAMPLES_MAX - samples_out; 00463 00464 /* See ifVorbis decoder has some audio data for us ... */ 00465 samples_in = read_samples(fs, &pcm); 00466 if (samples_in <= 0) 00467 break; 00468 00469 /* Got some audio data from Vorbis... */ 00470 /* Convert the float audio data to 16-bit signed linear */ 00471 00472 clipflag = 0; 00473 if (samples_in > len) 00474 samples_in = len; 00475 for (j = 0; j < samples_in; j++) 00476 accumulator[j] = 0.0; 00477 00478 for (i = 0; i < s->vi.channels; i++) { 00479 float *mono = pcm[i]; 00480 for (j = 0; j < samples_in; j++) 00481 accumulator[j] += mono[j]; 00482 } 00483 00484 for (j = 0; j < samples_in; j++) { 00485 val = accumulator[j] * 32767.0 / s->vi.channels; 00486 if (val > 32767) { 00487 val = 32767; 00488 clipflag = 1; 00489 } else if (val < -32768) { 00490 val = -32768; 00491 clipflag = 1; 00492 } 00493 buf[samples_out + j] = val; 00494 } 00495 00496 if (clipflag) 00497 ast_log(LOG_WARNING, "Clipping in frame %ld\n", (long) (s->vd.sequence)); 00498 /* Tell the Vorbis decoder how many samples we actually used. */ 00499 vorbis_synthesis_read(&s->vd, samples_in); 00500 samples_out += samples_in; 00501 } 00502 00503 if (samples_out > 0) { 00504 fs->fr.datalen = samples_out * 2; 00505 fs->fr.samples = samples_out; 00506 *whennext = samples_out; 00507 00508 return &fs->fr; 00509 } else { 00510 return NULL; 00511 } 00512 }
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 206 of file format_ogg_vorbis.c.
References ast_log(), ast_random(), DEFAULT_SAMPLE_RATE, vorbis_desc::eos, errno, LOG_ERROR, LOG_WARNING, vorbis_desc::og, vorbis_desc::os, s, vorbis_desc::vb, vorbis_desc::vc, vorbis_desc::vd, vorbis_desc::vi, and vorbis_desc::writing.
00208 { 00209 ogg_packet header; 00210 ogg_packet header_comm; 00211 ogg_packet header_code; 00212 struct vorbis_desc *tmp = (struct vorbis_desc *)s->_private; 00213 00214 tmp->writing = 1; 00215 00216 vorbis_info_init(&tmp->vi); 00217 00218 if (vorbis_encode_init_vbr(&tmp->vi, 1, DEFAULT_SAMPLE_RATE, 0.4)) { 00219 ast_log(LOG_ERROR, "Unable to initialize Vorbis encoder!\n"); 00220 return -1; 00221 } 00222 00223 vorbis_comment_init(&tmp->vc); 00224 vorbis_comment_add_tag(&tmp->vc, "ENCODER", "Asterisk PBX"); 00225 if (comment) 00226 vorbis_comment_add_tag(&tmp->vc, "COMMENT", (char *) comment); 00227 00228 vorbis_analysis_init(&tmp->vd, &tmp->vi); 00229 vorbis_block_init(&tmp->vd, &tmp->vb); 00230 00231 ogg_stream_init(&tmp->os, ast_random()); 00232 00233 vorbis_analysis_headerout(&tmp->vd, &tmp->vc, &header, &header_comm, 00234 &header_code); 00235 ogg_stream_packetin(&tmp->os, &header); 00236 ogg_stream_packetin(&tmp->os, &header_comm); 00237 ogg_stream_packetin(&tmp->os, &header_code); 00238 00239 while (!tmp->eos) { 00240 if (ogg_stream_flush(&tmp->os, &tmp->og) == 0) 00241 break; 00242 if (!fwrite(tmp->og.header, 1, tmp->og.header_len, s->f)) { 00243 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00244 } 00245 if (!fwrite(tmp->og.body, 1, tmp->og.body_len, s->f)) { 00246 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00247 } 00248 if (ogg_page_eos(&tmp->og)) 00249 tmp->eos = 1; 00250 } 00251 00252 return 0; 00253 }
static int ogg_vorbis_seek | ( | struct ast_filestream * | s, | |
off_t | sample_offset, | |||
int | whence | |||
) | [static] |
Seek to a specific position in an OGG/Vorbis filestream.
s | The filestream to truncate. | |
sample_offset | New position for the filestream, measured in 8KHz samples. | |
whence | Location to measure |
Definition at line 533 of file format_ogg_vorbis.c.
References ast_log(), and LOG_WARNING.
00534 { 00535 ast_log(LOG_WARNING, "Seeking is not supported on OGG/Vorbis streams!\n"); 00536 return -1; 00537 }
static off_t ogg_vorbis_tell | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 539 of file format_ogg_vorbis.c.
References ast_log(), and LOG_WARNING.
00540 { 00541 ast_log(LOG_WARNING, "Telling is not supported on OGG/Vorbis streams!\n"); 00542 return -1; 00543 }
static int ogg_vorbis_trunc | ( | struct ast_filestream * | s | ) | [static] |
Trucate an OGG/Vorbis filestream.
s | The filestream to truncate. |
Definition at line 520 of file format_ogg_vorbis.c.
References ast_log(), and LOG_WARNING.
00521 { 00522 ast_log(LOG_WARNING, "Truncation is not supported on OGG/Vorbis streams!\n"); 00523 return -1; 00524 }
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 292 of file format_ogg_vorbis.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_filestream::f, f, LOG_ERROR, LOG_WARNING, s, and write_stream().
00293 { 00294 int i; 00295 float **buffer; 00296 short *data; 00297 struct vorbis_desc *s = (struct vorbis_desc *)fs->_private; 00298 00299 if (!s->writing) { 00300 ast_log(LOG_ERROR, "This stream is not set up for writing!\n"); 00301 return -1; 00302 } 00303 00304 if (f->frametype != AST_FRAME_VOICE) { 00305 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00306 return -1; 00307 } 00308 if (f->subclass != AST_FORMAT_SLINEAR) { 00309 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", 00310 f->subclass); 00311 return -1; 00312 } 00313 if (!f->datalen) 00314 return -1; 00315 00316 data = (short *) f->data; 00317 00318 buffer = vorbis_analysis_buffer(&s->vd, f->samples); 00319 00320 for (i = 0; i < f->samples; i++) 00321 buffer[0][i] = (double)data[i] / 32768.0; 00322 00323 vorbis_analysis_wrote(&s->vd, f->samples); 00324 00325 write_stream(s, fs->f); 00326 00327 return 0; 00328 }
static int read_samples | ( | struct ast_filestream * | fs, | |
float *** | pcm | |||
) | [static] |
Get audio data.
fs | An OGG/Vorbis filestream. | |
pcm | Pointer to a buffere to store audio data in. |
Definition at line 362 of file format_ogg_vorbis.c.
References ast_filestream::_private, ast_log(), BLOCK_SIZE, ast_filestream::f, LOG_WARNING, and s.
Referenced by ogg_vorbis_read().
00363 { 00364 int samples_in; 00365 int result; 00366 char *buffer; 00367 int bytes; 00368 struct vorbis_desc *s = (struct vorbis_desc *)fs->_private; 00369 00370 while (1) { 00371 samples_in = vorbis_synthesis_pcmout(&s->vd, pcm); 00372 if (samples_in > 0) { 00373 return samples_in; 00374 } 00375 00376 /* The Vorbis decoder needs more data... */ 00377 /* See ifOGG has any packets in the current page for the Vorbis decoder. */ 00378 result = ogg_stream_packetout(&s->os, &s->op); 00379 if (result > 0) { 00380 /* Yes OGG had some more packets for the Vorbis decoder. */ 00381 if (vorbis_synthesis(&s->vb, &s->op) == 0) { 00382 vorbis_synthesis_blockin(&s->vd, &s->vb); 00383 } 00384 00385 continue; 00386 } 00387 00388 if (result < 0) 00389 ast_log(LOG_WARNING, 00390 "Corrupt or missing data at this page position; continuing...\n"); 00391 00392 /* No more packets left in the current page... */ 00393 00394 if (s->eos) { 00395 /* No more pages left in the stream */ 00396 return -1; 00397 } 00398 00399 while (!s->eos) { 00400 /* See ifOGG has any pages in it's internal buffers */ 00401 result = ogg_sync_pageout(&s->oy, &s->og); 00402 if (result > 0) { 00403 /* Yes, OGG has more pages in it's internal buffers, 00404 add the page to the stream state */ 00405 result = ogg_stream_pagein(&s->os, &s->og); 00406 if (result == 0) { 00407 /* Yes, got a new,valid page */ 00408 if (ogg_page_eos(&s->og)) { 00409 s->eos = 1; 00410 } 00411 break; 00412 } 00413 ast_log(LOG_WARNING, 00414 "Invalid page in the bitstream; continuing...\n"); 00415 } 00416 00417 if (result < 0) 00418 ast_log(LOG_WARNING, 00419 "Corrupt or missing data in bitstream; continuing...\n"); 00420 00421 /* No, we need to read more data from the file descrptor */ 00422 /* get a buffer from OGG to read the data into */ 00423 buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE); 00424 /* read more data from the file descriptor */ 00425 bytes = fread(buffer, 1, BLOCK_SIZE, fs->f); 00426 /* Tell OGG how many bytes we actually read into the buffer */ 00427 ogg_sync_wrote(&s->oy, bytes); 00428 if (bytes == 0) { 00429 s->eos = 1; 00430 } 00431 } 00432 } 00433 }
static int unload_module | ( | void | ) | [static] |
Definition at line 566 of file format_ogg_vorbis.c.
References ast_format_unregister(), ast_format::name, and vorbis_f.
00567 { 00568 return ast_format_unregister(vorbis_f.name); 00569 }
static void write_stream | ( | struct 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 260 of file format_ogg_vorbis.c.
References ast_log(), errno, LOG_WARNING, and s.
Referenced by ogg_vorbis_close(), and ogg_vorbis_write().
00261 { 00262 while (vorbis_analysis_blockout(&s->vd, &s->vb) == 1) { 00263 vorbis_analysis(&s->vb, NULL); 00264 vorbis_bitrate_addblock(&s->vb); 00265 00266 while (vorbis_bitrate_flushpacket(&s->vd, &s->op)) { 00267 ogg_stream_packetin(&s->os, &s->op); 00268 while (!s->eos) { 00269 if (ogg_stream_pageout(&s->os, &s->og) == 0) { 00270 break; 00271 } 00272 if (!fwrite(s->og.header, 1, s->og.header_len, f)) { 00273 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00274 } 00275 if (!fwrite(s->og.body, 1, s->og.body_len, f)) { 00276 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00277 } 00278 if (ogg_page_eos(&s->og)) { 00279 s->eos = 1; 00280 } 00281 } 00282 } 00283 } 00284 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_FIRST | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 574 of file format_ogg_vorbis.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 574 of file format_ogg_vorbis.c.
struct ast_format vorbis_f [static] |
Definition at line 545 of file format_ogg_vorbis.c.
Referenced by load_module(), and unload_module().