Mon Oct 8 12:39:22 2012

Asterisk developer's documentation


format_ogg_vorbis.c File Reference

OGG/Vorbis streams. More...

#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_frameogg_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_infoast_module_info = &__mod_info
static ov_callbacks OV_CALLBACKS_NOCLOSE
static struct ast_format vorbis_f


Detailed Description

OGG/Vorbis streams.

Definition in file format_ogg_vorbis.c.


Define Documentation

#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.


Function Documentation

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]

Definition at line 88 of file format_ogg_vorbis.c.

00089 {
00090    if (f == NULL) {
00091       return -1;
00092    }
00093    return fseek(f, off, whence);
00094 }

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.

Parameters:
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.

Parameters:
s File that points to on disk storage of the OGG/Vorbis data.
Returns:
The new filestream.

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.

Parameters:
fs The filestream.
whennext Number of sample times to schedule the next call.
Returns:
A pointer to a frame containing audio data or NULL ifthere is no more audio data.

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       &current_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.

Parameters:
s File pointer that points to on-disk storage.
comment Comment that should be embedded in the OGG/Vorbis file.
Returns:
A new filestream.

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.

Parameters:
s The filestream to take action on.
sample_offset New position for the filestream, measured in 8KHz samples.
whence Location to measure
Returns:
0 on success, -1 on failure.

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.

Parameters:
s The filestream to take action on.
Returns:
0 or greater with the position measured in samples, or -1 for false.

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.

Parameters:
s The filestream to truncate.
Returns:
0 on success, -1 on failure.

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.

Parameters:
fs An OGG/Vorbis filestream.
f A frame containing audio to be written to the filestream.
Returns:
-1 if there was an error, 0 on success.

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.

Parameters:
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 }


Variable Documentation

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().


Generated on Mon Oct 8 12:39:22 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7