Sat Apr 26 2014 22:02:50

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"
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 /* used internally in the vorbis routines */
#define BUF_SIZE   (2*SAMPLES_MAX)
#define SAMPLES_MAX   512

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_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, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_format_def vorbis_f

Detailed Description

OGG/Vorbis streams.

  • File name extension: ogg

Definition in file format_ogg_vorbis.c.


Define Documentation

#define BLOCK_SIZE   4096 /* used internally in the vorbis routines */

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.

Referenced by ogg_vorbis_read().

#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 void ogg_vorbis_close ( struct ast_filestream fs) [static]

Close a OGG/Vorbis filestream.

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

{
   struct ogg_vorbis_desc *s = (struct ogg_vorbis_desc *) fs->_private;

   if (s->writing) {
      /* Tell the Vorbis encoder that the stream is finished
       * and write out the rest of the data */
      vorbis_analysis_wrote(&s->vd, 0);
      write_stream(s, fs->f);
   } else {
      /* clear OggVorbis_File handle */
      ov_clear(&s->ov_f);
   }
}
static int ogg_vorbis_open ( struct ast_filestream s) [static]

Create a new OGG/Vorbis filestream and set it up for reading.

Parameters:
sFile 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, LOG_ERROR, ogg_vorbis_desc::ov_f, and ogg_vorbis_desc::writing.

{
   int result;
   struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) s->_private;

   /* initialize private description block */
   memset(desc, 0, sizeof(struct ogg_vorbis_desc));
   desc->writing = 0;

   /* actually open file */
   result = ov_open_callbacks(s->f, &desc->ov_f, NULL, 0, OV_CALLBACKS_NOCLOSE);
   if (result != 0) {
      ast_log(LOG_ERROR, "Error opening Ogg/Vorbis file stream.\n");
      return -1;
   }

   /* check stream(s) type */
   if (desc->ov_f.vi->channels != 1) {
      ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
      ov_clear(&desc->ov_f);
      return -1;
   }

   if (desc->ov_f.vi->rate != DEFAULT_SAMPLE_RATE) {
      ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
      ov_clear(&desc->ov_f);
      return -1;
   }

   return 0;
}
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:
fsThe filestream.
whennextNumber 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 ast_filestream::_private, ast_format_set(), 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, desc, ast_frame_subclass::format, ast_filestream::fr, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ogg_vorbis_desc::ov_f, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, and ogg_vorbis_desc::writing.

{
   struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private;
   int current_bitstream = -10;
   char *out_buf;
   long bytes_read;

   if (desc->writing) {
      ast_log(LOG_WARNING, "Reading is not supported on OGG/Vorbis on write files.\n");
      return NULL;
   }

   /* initialize frame */
   fs->fr.frametype = AST_FRAME_VOICE;
   ast_format_set(&fs->fr.subclass.format, AST_FORMAT_SLINEAR, 0);
   fs->fr.mallocd = 0;
   AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
   out_buf = (char *) (fs->fr.data.ptr);  /* SLIN data buffer */

   /* read samples from OV interface */
   bytes_read = ov_read(
      &desc->ov_f,
      out_buf,                /* Buffer to write data */
      BUF_SIZE,                  /* Size of buffer */
      (__BYTE_ORDER == __BIG_ENDIAN),  /* Endianes (0 for little) */
      2,                      /* 1 = 8bit, 2 = 16bit */
      1,                      /* 0 = unsigned, 1 = signed */
      &current_bitstream            /* Returns the current bitstream section */
   );

   /* check returned data */
   if (bytes_read <= 0) {
      /* End of stream */
      return NULL;
   }

   /* Return decoded bytes */
   fs->fr.datalen = bytes_read;
   fs->fr.samples = bytes_read / 2;
   *whennext = fs->fr.samples;
   return &fs->fr;
}
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:
sFile pointer that points to on-disk storage.
commentComment 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.

{
   ogg_packet header;
   ogg_packet header_comm;
   ogg_packet header_code;
   struct ogg_vorbis_desc *tmp = (struct ogg_vorbis_desc *) s->_private;

   tmp->writing = 1;
   tmp->writing_pcm_pos = 0;

   vorbis_info_init(&tmp->vi);

   if (vorbis_encode_init_vbr(&tmp->vi, 1, DEFAULT_SAMPLE_RATE, 0.4)) {
      ast_log(LOG_ERROR, "Unable to initialize Vorbis encoder!\n");
      return -1;
   }

   vorbis_comment_init(&tmp->vc);
   vorbis_comment_add_tag(&tmp->vc, "ENCODER", "Asterisk PBX");
   if (comment)
      vorbis_comment_add_tag(&tmp->vc, "COMMENT", (char *) comment);

   vorbis_analysis_init(&tmp->vd, &tmp->vi);
   vorbis_block_init(&tmp->vd, &tmp->vb);

   ogg_stream_init(&tmp->os, ast_random());

   vorbis_analysis_headerout(&tmp->vd, &tmp->vc, &header, &header_comm,
              &header_code);
   ogg_stream_packetin(&tmp->os, &header);
   ogg_stream_packetin(&tmp->os, &header_comm);
   ogg_stream_packetin(&tmp->os, &header_code);

   while (!tmp->eos) {
      if (ogg_stream_flush(&tmp->os, &tmp->og) == 0)
         break;
      if (!fwrite(tmp->og.header, 1, tmp->og.header_len, s->f)) {
         ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
      }
      if (!fwrite(tmp->og.body, 1, tmp->og.body_len, s->f)) {
         ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
      }
      if (ogg_page_eos(&tmp->og))
         tmp->eos = 1;
   }

   return 0;
}
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:
sThe filestream to take action on.
sample_offsetNew position for the filestream, measured in 8KHz samples.
whenceLocation 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, ogg_vorbis_tell(), ogg_vorbis_desc::ov_f, and ogg_vorbis_desc::writing.

{
   int seek_result = -1;
   off_t relative_pcm_pos;
   struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private;

   if (desc->writing) {
      ast_log(LOG_WARNING, "Seeking is not supported on OGG/Vorbis streams in writing mode!\n");
      return -1;
   }

   /* ov_pcm_seek support seeking only from begining (SEEK_SET), the rest must be emulated */
   switch (whence) {
   case SEEK_SET:
      seek_result = ov_pcm_seek(&desc->ov_f, sample_offset);
      break;
   case SEEK_CUR:
      if ((relative_pcm_pos = ogg_vorbis_tell(fs)) < 0) {
         seek_result = -1;
         break;
      }
      seek_result = ov_pcm_seek(&desc->ov_f, relative_pcm_pos + sample_offset);
      break;
   case SEEK_END:
      if ((relative_pcm_pos = ov_pcm_total(&desc->ov_f, -1)) < 0) {
         seek_result = -1;
         break;
      }
      seek_result = ov_pcm_seek(&desc->ov_f, relative_pcm_pos - sample_offset);
      break;
   default:
      ast_log(LOG_WARNING, "Unknown *whence* to seek on OGG/Vorbis streams!\n");
      break;
   }

   /* normalize error value to -1,0 */
   return (seek_result == 0) ? 0 : -1;
}
static off_t ogg_vorbis_tell ( struct ast_filestream fs) [static]

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

Parameters:
sThe 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, desc, ogg_vorbis_desc::ov_f, ogg_vorbis_desc::writing, and ogg_vorbis_desc::writing_pcm_pos.

Referenced by ogg_vorbis_seek().

{
   off_t pos;
   struct ogg_vorbis_desc *desc = (struct ogg_vorbis_desc *) fs->_private;

   if (desc->writing) {
      return desc->writing_pcm_pos;
   }

   if ((pos = ov_pcm_tell(&desc->ov_f)) < 0) {
      return -1;
   }
   return pos;
}
static int ogg_vorbis_trunc ( struct ast_filestream fs) [static]

Trucate an OGG/Vorbis filestream.

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

{
   ast_log(LOG_WARNING, "Truncation is not supported on OGG/Vorbis streams!\n");
   return -1;
}
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:
fsAn OGG/Vorbis filestream.
fA 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_frame::data, ast_frame::datalen, ast_filestream::f, ast_frame_subclass::format, ast_frame::frametype, ast_format::id, LOG_ERROR, LOG_WARNING, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, ogg_vorbis_desc::vd, write_stream(), ogg_vorbis_desc::writing, and ogg_vorbis_desc::writing_pcm_pos.

{
   int i;
   float **buffer;
   short *data;
   struct ogg_vorbis_desc *s = (struct ogg_vorbis_desc *) fs->_private;

   if (!s->writing) {
      ast_log(LOG_ERROR, "This stream is not set up for writing!\n");
      return -1;
   }

   if (f->frametype != AST_FRAME_VOICE) {
      ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
      return -1;
   }
   if (f->subclass.format.id != AST_FORMAT_SLINEAR) {
      ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%s)!\n",
         ast_getformatname(&f->subclass.format));
      return -1;
   }
   if (!f->datalen)
      return -1;

   data = (short *) f->data.ptr;

   buffer = vorbis_analysis_buffer(&s->vd, f->samples);

   for (i = 0; i < f->samples; i++)
      buffer[0][i] = (double)data[i] / 32768.0;

   vorbis_analysis_wrote(&s->vd, f->samples);

   write_stream(s, fs->f);

   s->writing_pcm_pos +=  f->samples;

   return 0;
}
static int unload_module ( void  ) [static]
static void write_stream ( struct ogg_vorbis_desc s,
FILE *  f 
) [static]

Write out any pending encoded data.

Parameters:
sAn OGG/Vorbis filestream.
fThe 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 ast_monitor_stop(), ast_write(), ogg_vorbis_close(), and ogg_vorbis_write().

{
   while (vorbis_analysis_blockout(&s->vd, &s->vb) == 1) {
      vorbis_analysis(&s->vb, NULL);
      vorbis_bitrate_addblock(&s->vb);

      while (vorbis_bitrate_flushpacket(&s->vd, &s->op)) {
         ogg_stream_packetin(&s->os, &s->op);
         while (!s->eos) {
            if (ogg_stream_pageout(&s->os, &s->og) == 0) {
               break;
            }
            if (!fwrite(s->og.header, 1, s->og.header_len, f)) {
            ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
            }
            if (!fwrite(s->og.body, 1, s->og.body_len, f)) {
               ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
            }
            if (ogg_page_eos(&s->og)) {
               s->eos = 1;
            }
         }
      }
   }
}

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

Definition at line 453 of file format_ogg_vorbis.c.

Definition at line 453 of file format_ogg_vorbis.c.

struct ast_format_def vorbis_f [static]

Definition at line 421 of file format_ogg_vorbis.c.