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"
#include "asterisk/format_cache.h"

Include dependency graph for format_ogg_vorbis.c:

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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .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_def vorbis_f


Detailed Description

OGG/Vorbis streams.

Definition in file format_ogg_vorbis.c.


Define Documentation

#define BLOCK_SIZE   4096

Definition at line 57 of file format_ogg_vorbis.c.

#define BUF_SIZE   (2*SAMPLES_MAX)

Definition at line 55 of file format_ogg_vorbis.c.

#define SAMPLES_MAX   512

Definition at line 54 of file format_ogg_vorbis.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 442 of file format_ogg_vorbis.c.

static void __unreg_module ( void   )  [static]

Definition at line 442 of file format_ogg_vorbis.c.

static int _ov_header_fseek_wrap ( FILE *  f,
ogg_int64_t  off,
int  whence 
) [static]

Definition at line 89 of file format_ogg_vorbis.c.

References NULL.

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

static int load_module ( void   )  [static]

static void ogg_vorbis_close ( struct ast_filestream fs  )  [static]

Close a OGG/Vorbis filestream.

Parameters:
fs A OGG/Vorbis filestream.

Definition at line 269 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.

00270 {
00271    struct ogg_vorbis_desc *s = (struct ogg_vorbis_desc *) fs->_private;
00272 
00273    if (s->writing) {
00274       /* Tell the Vorbis encoder that the stream is finished
00275        * and write out the rest of the data */
00276       vorbis_analysis_wrote(&s->vd, 0);
00277       write_stream(s, fs->f);
00278    } else {
00279       /* clear OggVorbis_File handle */
00280       ov_clear(&s->ov_f);
00281    }
00282 }

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 110 of file format_ogg_vorbis.c.

References ast_filestream::_private, ast_log, DEFAULT_SAMPLE_RATE, desc, ast_filestream::f, LOG_ERROR, NULL, ogg_vorbis_desc::ov_f, result, and ogg_vorbis_desc::writing.

00111 {
00112    int result;
00113    struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) s->_private;
00114 
00115    /* initialize private description block */
00116    memset(desc, 0, sizeof(struct ogg_vorbis_desc));
00117    desc->writing = 0;
00118 
00119    /* actually open file */
00120    result = ov_open_callbacks(s->f, &desc->ov_f, NULL, 0, OV_CALLBACKS_NOCLOSE);
00121    if (result != 0) {
00122       ast_log(LOG_ERROR, "Error opening Ogg/Vorbis file stream.\n");
00123       return -1;
00124    }
00125 
00126    /* check stream(s) type */
00127    if (desc->ov_f.vi->channels != 1) {
00128       ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
00129       ov_clear(&desc->ov_f);
00130       return -1;
00131    }
00132 
00133    if (desc->ov_f.vi->rate != DEFAULT_SAMPLE_RATE) {
00134       ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
00135       ov_clear(&desc->ov_f);
00136       return -1;
00137    }
00138 
00139    return 0;
00140 }

static struct ast_frame* ogg_vorbis_read ( struct ast_filestream fs,
int *  whennext 
) [static, read]

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 290 of file format_ogg_vorbis.c.

References __BIG_ENDIAN, __BYTE_ORDER, ast_filestream::_private, AST_FRAME_SET_BUFFER, AST_FRIENDLY_OFFSET, ast_log, ast_filestream::buf, BUF_SIZE, ast_frame::data, ast_frame::datalen, desc, ast_filestream::fr, LOG_WARNING, NULL, ogg_vorbis_desc::ov_f, ast_frame::ptr, ast_frame::samples, and ogg_vorbis_desc::writing.

00292 {
00293    struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private;
00294    int current_bitstream = -10;
00295    char *out_buf;
00296    long bytes_read;
00297 
00298    if (desc->writing) {
00299       ast_log(LOG_WARNING, "Reading is not supported on OGG/Vorbis on write files.\n");
00300       return NULL;
00301    }
00302 
00303    /* initialize frame */
00304    AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
00305    out_buf = (char *) (fs->fr.data.ptr);  /* SLIN data buffer */
00306 
00307    /* read samples from OV interface */
00308    bytes_read = ov_read(
00309       &desc->ov_f,
00310       out_buf,                /* Buffer to write data */
00311       BUF_SIZE,                  /* Size of buffer */
00312       (__BYTE_ORDER == __BIG_ENDIAN),  /* Endianes (0 for little) */
00313       2,                      /* 1 = 8bit, 2 = 16bit */
00314       1,                      /* 0 = unsigned, 1 = signed */
00315       &current_bitstream            /* Returns the current bitstream section */
00316    );
00317 
00318    /* check returned data */
00319    if (bytes_read <= 0) {
00320       /* End of stream */
00321       return NULL;
00322    }
00323 
00324    /* Return decoded bytes */
00325    fs->fr.datalen = bytes_read;
00326    fs->fr.samples = bytes_read / 2;
00327    *whennext = fs->fr.samples;
00328    return &fs->fr;
00329 }

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 148 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, tmp(), 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.

00150 {
00151    ogg_packet header;
00152    ogg_packet header_comm;
00153    ogg_packet header_code;
00154    struct ogg_vorbis_desc *tmp = (struct ogg_vorbis_desc *) s->_private;
00155 
00156    tmp->writing = 1;
00157    tmp->writing_pcm_pos = 0;
00158 
00159    vorbis_info_init(&tmp->vi);
00160 
00161    if (vorbis_encode_init_vbr(&tmp->vi, 1, DEFAULT_SAMPLE_RATE, 0.4)) {
00162       ast_log(LOG_ERROR, "Unable to initialize Vorbis encoder!\n");
00163       return -1;
00164    }
00165 
00166    vorbis_comment_init(&tmp->vc);
00167    vorbis_comment_add_tag(&tmp->vc, "ENCODER", "Asterisk PBX");
00168    if (comment)
00169       vorbis_comment_add_tag(&tmp->vc, "COMMENT", (char *) comment);
00170 
00171    vorbis_analysis_init(&tmp->vd, &tmp->vi);
00172    vorbis_block_init(&tmp->vd, &tmp->vb);
00173 
00174    ogg_stream_init(&tmp->os, ast_random());
00175 
00176    vorbis_analysis_headerout(&tmp->vd, &tmp->vc, &header, &header_comm,
00177               &header_code);
00178    ogg_stream_packetin(&tmp->os, &header);
00179    ogg_stream_packetin(&tmp->os, &header_comm);
00180    ogg_stream_packetin(&tmp->os, &header_code);
00181 
00182    while (!tmp->eos) {
00183       if (ogg_stream_flush(&tmp->os, &tmp->og) == 0)
00184          break;
00185       if (!fwrite(tmp->og.header, 1, tmp->og.header_len, s->f)) {
00186          ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00187       }
00188       if (!fwrite(tmp->og.body, 1, tmp->og.body_len, s->f)) {
00189          ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00190       }
00191       if (ogg_page_eos(&tmp->og))
00192          tmp->eos = 1;
00193    }
00194 
00195    return 0;
00196 }

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:
fs 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 370 of file format_ogg_vorbis.c.

References ast_filestream::_private, ast_log, desc, LOG_WARNING, ogg_vorbis_tell(), ogg_vorbis_desc::ov_f, and ogg_vorbis_desc::writing.

00371 {
00372    int seek_result = -1;
00373    off_t relative_pcm_pos;
00374    struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private;
00375 
00376    if (desc->writing) {
00377       ast_log(LOG_WARNING, "Seeking is not supported on OGG/Vorbis streams in writing mode!\n");
00378       return -1;
00379    }
00380 
00381    /* ov_pcm_seek support seeking only from begining (SEEK_SET), the rest must be emulated */
00382    switch (whence) {
00383    case SEEK_SET:
00384       seek_result = ov_pcm_seek(&desc->ov_f, sample_offset);
00385       break;
00386    case SEEK_CUR:
00387       if ((relative_pcm_pos = ogg_vorbis_tell(fs)) < 0) {
00388          seek_result = -1;
00389          break;
00390       }
00391       seek_result = ov_pcm_seek(&desc->ov_f, relative_pcm_pos + sample_offset);
00392       break;
00393    case SEEK_END:
00394       if ((relative_pcm_pos = ov_pcm_total(&desc->ov_f, -1)) < 0) {
00395          seek_result = -1;
00396          break;
00397       }
00398       seek_result = ov_pcm_seek(&desc->ov_f, relative_pcm_pos - sample_offset);
00399       break;
00400    default:
00401       ast_log(LOG_WARNING, "Unknown *whence* to seek on OGG/Vorbis streams!\n");
00402       break;
00403    }
00404 
00405    /* normalize error value to -1,0 */
00406    return (seek_result == 0) ? 0 : -1;
00407 }

static off_t ogg_vorbis_tell ( struct ast_filestream fs  )  [static]

Tell the current position in OGG/Vorbis filestream measured in pcms.

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

Definition at line 348 of file format_ogg_vorbis.c.

References ast_filestream::_private, desc, ogg_vorbis_desc::ov_f, ogg_vorbis_desc::writing, and ogg_vorbis_desc::writing_pcm_pos.

Referenced by ogg_vorbis_seek().

00349 {
00350    off_t pos;
00351    struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private;
00352 
00353    if (desc->writing) {
00354       return desc->writing_pcm_pos;
00355    }
00356 
00357    if ((pos = ov_pcm_tell(&desc->ov_f)) < 0) {
00358       return -1;
00359    }
00360    return pos;
00361 }

static int ogg_vorbis_trunc ( struct ast_filestream fs  )  [static]

Trucate an OGG/Vorbis filestream.

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

Definition at line 337 of file format_ogg_vorbis.c.

References ast_log, and LOG_WARNING.

00338 {
00339    ast_log(LOG_WARNING, "Truncation is not supported on OGG/Vorbis streams!\n");
00340    return -1;
00341 }

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 235 of file format_ogg_vorbis.c.

References ast_filestream::_private, ast_log, ast_frame::data, ast_frame::datalen, ast_filestream::f, LOG_ERROR, ast_frame::ptr, ast_frame::samples, ogg_vorbis_desc::vd, write_stream(), ogg_vorbis_desc::writing, and ogg_vorbis_desc::writing_pcm_pos.

00236 {
00237    int i;
00238    float **buffer;
00239    short *data;
00240    struct ogg_vorbis_desc *s = (struct ogg_vorbis_desc *) fs->_private;
00241 
00242    if (!s->writing) {
00243       ast_log(LOG_ERROR, "This stream is not set up for writing!\n");
00244       return -1;
00245    }
00246    if (!f->datalen)
00247       return -1;
00248 
00249    data = (short *) f->data.ptr;
00250 
00251    buffer = vorbis_analysis_buffer(&s->vd, f->samples);
00252 
00253    for (i = 0; i < f->samples; i++)
00254       buffer[0][i] = (double)data[i] / 32768.0;
00255 
00256    vorbis_analysis_wrote(&s->vd, f->samples);
00257 
00258    write_stream(s, fs->f);
00259 
00260    s->writing_pcm_pos +=  f->samples;
00261 
00262    return 0;
00263 }

static int unload_module ( void   )  [static]

Definition at line 432 of file format_ogg_vorbis.c.

References ast_format_def_unregister(), and ast_format_def::name.

00433 {
00434    return ast_format_def_unregister(vorbis_f.name);
00435 }

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 203 of file format_ogg_vorbis.c.

References ast_log, ogg_vorbis_desc::eos, errno, LOG_WARNING, NULL, ogg_vorbis_desc::og, ogg_vorbis_desc::op, ogg_vorbis_desc::os, ogg_vorbis_desc::vb, and ogg_vorbis_desc::vd.

Referenced by ast_monitor_stop(), ast_write(), ogg_vorbis_close(), and ogg_vorbis_write().

00204 {
00205    while (vorbis_analysis_blockout(&s->vd, &s->vb) == 1) {
00206       vorbis_analysis(&s->vb, NULL);
00207       vorbis_bitrate_addblock(&s->vb);
00208 
00209       while (vorbis_bitrate_flushpacket(&s->vd, &s->op)) {
00210          ogg_stream_packetin(&s->os, &s->op);
00211          while (!s->eos) {
00212             if (ogg_stream_pageout(&s->os, &s->og) == 0) {
00213                break;
00214             }
00215             if (!fwrite(s->og.header, 1, s->og.header_len, f)) {
00216             ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00217             }
00218             if (!fwrite(s->og.body, 1, s->og.body_len, f)) {
00219                ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00220             }
00221             if (ogg_page_eos(&s->og)) {
00222                s->eos = 1;
00223             }
00224          }
00225       }
00226    }
00227 }


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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } [static]

Definition at line 442 of file format_ogg_vorbis.c.

Definition at line 442 of file format_ogg_vorbis.c.

ov_callbacks OV_CALLBACKS_NOCLOSE [static]

Definition at line 97 of file format_ogg_vorbis.c.

struct ast_format_def vorbis_f [static]

Definition at line 409 of file format_ogg_vorbis.c.


Generated on Thu Apr 16 06:31:07 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6