Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:53 2009

## Asterisk developer's documentation

# format_ogg_vorbis.c File Reference

OGG/Vorbis streams. More...

`#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.h"`
`#include "asterisk/lock.h"`
`#include "asterisk/channel.h"`
`#include "asterisk/file.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/module.h"`

Include dependency graph for format_ogg_vorbis.c:

Go to the source code of this file.

## Data Structures

struct | ast_filestream

## Defines

#define | BLOCK_SIZE 4096
#define | SAMPLES_MAX 160

## Functions

| AST_MUTEX_DEFINE_STATIC (ogg_vorbis_lock)
char * | description ()
| Provides a description of the module.
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module ()
| Initialize the module.
static void | ogg_vorbis_close (struct ast_filestream *s)
| Close a OGG/Vorbis filestream.
static char * | ogg_vorbis_getcomment (struct ast_filestream *s)
static struct ast_filestream * | ogg_vorbis_open (FILE *f)
| Create a new OGG/Vorbis filestream and set it up for reading.
static struct ast_frame * | ogg_vorbis_read (struct ast_filestream *s, int *whennext)
| Read a frame full of audio data from the filestream.
static struct ast_filestream * | ogg_vorbis_rewrite (FILE *f, const char *comment)
| Create a new OGG/Vorbis filestream and set it up for writing.
static int | ogg_vorbis_seek (struct ast_filestream *s, long sample_offset, int whence)
| Seek to a specific position in an OGG/Vorbis filestream.
static long | 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 *s, struct ast_frame *f)
| Write audio data from a frame to an OGG/Vorbis filestream.
static int | read_samples (struct ast_filestream *s, float ***pcm)
| Get audio data.
int | unload_module ()
| Cleanup all module structures, sockets, etc.
int | usecount ()
| Provides a usecount.
static void | write_stream (struct ast_filestream *s)
| Write out any pending encoded data.

## Variables

static char * | desc = "OGG/Vorbis audio"
static char * | exts = "ogg"
static int | glistcnt = 0
static char * | name = "ogg_vorbis"

## Detailed Description

OGG/Vorbis streams.

- File name extension: ogg

Definition in file format_ogg_vorbis.c.

## Define Documentation

#define BLOCK_SIZE 4096

Definition at line 53 of file format_ogg_vorbis.c.

Referenced by ogg_vorbis_open(), and read_samples().

#define SAMPLES_MAX 160

Definition at line 52 of file format_ogg_vorbis.c.

Referenced by ogg_vorbis_read().

## Function Documentation

AST_MUTEX_DEFINE_STATIC | ( | ogg_vorbis_lock |  | ) |

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 660 of file format_ogg_vorbis.c.

    00661 {
    00662    return desc;
    00663 }

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 666 of file format_ogg_vorbis.c.

References ASTERISK_GPL_KEY.

    00667 {
    00668    return ASTERISK_GPL_KEY;
    00669 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
  int Always 0.

TE STUFF END

Definition at line 636 of file format_ogg_vorbis.c.

References ast_format_register(), AST_FORMAT_SLINEAR, ogg_vorbis_close(), ogg_vorbis_getcomment(), ogg_vorbis_open(), ogg_vorbis_read(), ogg_vorbis_rewrite(), ogg_vorbis_seek(), ogg_vorbis_tell(), ogg_vorbis_trunc(), and ogg_vorbis_write().

    00637 {
    00638    return ast_format_register(name, exts, AST_FORMAT_SLINEAR,
    00639                ogg_vorbis_open,
    00640                ogg_vorbis_rewrite,
    00641                ogg_vorbis_write,
    00642                ogg_vorbis_seek,
    00643                ogg_vorbis_trunc,
    00644                ogg_vorbis_tell,
    00645                ogg_vorbis_read,
    00646                ogg_vorbis_close,
    00647                ogg_vorbis_getcomment);
    00648 }

static void ogg_vorbis_close | ( | struct ast_filestream * | s | ) | `[static]`

Close a OGG/Vorbis filestream.

Parameters:

  | s | A OGG/Vorbis filestream.

Definition at line 412 of file format_ogg_vorbis.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), ast_filestream::f, free, LOG_WARNING, ast_filestream::os, ast_filestream::oy, ast_filestream::vb, ast_filestream::vc, ast_filestream::vd, ast_filestream::vi, write_stream(), and ast_filestream::writing.

Referenced by load_module().

    00413 {
    00414    if(ast_mutex_lock(&ogg_vorbis_lock)) {
    00415       ast_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
    00416       return;
    00417    }
    00418    glistcnt--;
    00419    ast_mutex_unlock(&ogg_vorbis_lock);
    00420    ast_update_use_count();
    00421
    00422    if(s->writing) {
    00423       /* Tell the Vorbis encoder that the stream is finished
    00424        * and write out the rest of the data */
    00425       vorbis_analysis_wrote(&s->vd, 0);
    00426       write_stream(s);
    00427    }
    00428
    00429    ogg_stream_clear(&s->os);
    00430    vorbis_block_clear(&s->vb);
    00431    vorbis_dsp_clear(&s->vd);
    00432    vorbis_comment_clear(&s->vc);
    00433    vorbis_info_clear(&s->vi);
    00434
    00435    if(s->writing) {
    00436       ogg_sync_clear(&s->oy);
    00437    }
    00438
    00439    fclose(s->f);
    00440    free(s);
    00441 }

static char* ogg_vorbis_getcomment | ( | struct ast_filestream * | s | ) | `[static]`

Definition at line 631 of file format_ogg_vorbis.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

    00631                                                              {
    00632    ast_log(LOG_WARNING, "Getting comments is not supported on OGG/Vorbis streams!\n");
    00633    return NULL;
    00634 }

static struct ast_filestream* ogg_vorbis_open | ( | FILE * | f | ) | `[static, read]`

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

Parameters:

  | f | File that points to on disk storage of the OGG/Vorbis data.

Returns:
  The new filestream.

Definition at line 100 of file format_ogg_vorbis.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), BLOCK_SIZE, ast_filestream::buffer, ast_filestream::bytes, ast_filestream::f, free, LOG_DEBUG, LOG_ERROR, LOG_WARNING, malloc, ast_filestream::og, ast_filestream::op, ast_filestream::os, ast_filestream::oy, result, ast_filestream::vb, ast_filestream::vc, ast_filestream::vd, ast_filestream::vi, and ast_filestream::writing.

Referenced by load_module().

    00101 {
    00102    int i;
    00103    int bytes;
    00104    int result;
    00105    char **ptr;
    00106    char *buffer;
    00107
    00108    struct ast_filestream *tmp;
    00109
    00110    if((tmp = malloc(sizeof(struct ast_filestream)))) {
    00111       memset(tmp, 0, sizeof(struct ast_filestream));
    00112
    00113       tmp->writing = 0;
    00114       tmp->f = f;
    00115
    00116       ogg_sync_init(&tmp->oy);
    00117
    00118       buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
    00119       bytes = fread(buffer, 1, BLOCK_SIZE, f);
    00120       ogg_sync_wrote(&tmp->oy, bytes);
    00121
    00122       result = ogg_sync_pageout(&tmp->oy, &tmp->og);
    00123       if(result != 1) {
    00124          if(bytes < BLOCK_SIZE) {
    00125             ast_log(LOG_ERROR, "Run out of data...\n");
    00126          } else {
    00127             ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
    00128          }
    00129          fclose(f);
    00130          ogg_sync_clear(&tmp->oy);
    00131          free(tmp);
    00132          return NULL;
    00133       }
    00134
    00135       ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
    00136       vorbis_info_init(&tmp->vi);
    00137       vorbis_comment_init(&tmp->vc);
    00138
    00139       if(ogg_stream_pagein(&tmp->os, &tmp->og) < 0) {
    00140          ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
    00141          fclose(f);
    00142          ogg_stream_clear(&tmp->os);
    00143          vorbis_comment_clear(&tmp->vc);
    00144          vorbis_info_clear(&tmp->vi);
    00145          ogg_sync_clear(&tmp->oy);
    00146          free(tmp);
    00147          return NULL;
    00148       }
    00149
    00150       if(ogg_stream_packetout(&tmp->os, &tmp->op) != 1) {
    00151          ast_log(LOG_ERROR, "Error reading initial header packet.\n");
    00152          fclose(f);
    00153          ogg_stream_clear(&tmp->os);
    00154          vorbis_comment_clear(&tmp->vc);
    00155          vorbis_info_clear(&tmp->vi);
    00156          ogg_sync_clear(&tmp->oy);
    00157          free(tmp);
    00158          return NULL;
    00159       }
    00160
    00161       if(vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0) {
    00162          ast_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
    00163          fclose(f);
    00164          ogg_stream_clear(&tmp->os);
    00165          vorbis_comment_clear(&tmp->vc);
    00166          vorbis_info_clear(&tmp->vi);
    00167          ogg_sync_clear(&tmp->oy);
    00168          free(tmp);
    00169          return NULL;
    00170       }
    00171
    00172       i = 0;
    00173       while(i < 2) {
    00174          while(i < 2){
    00175             result = ogg_sync_pageout(&tmp->oy, &tmp->og);
    00176             if(result == 0)
    00177                break;
    00178             if(result == 1) {
    00179                ogg_stream_pagein(&tmp->os, &tmp->og);
    00180                while(i < 2) {
    00181                   result = ogg_stream_packetout(&tmp->os,&tmp->op);
    00182                   if(result == 0)
    00183                      break;
    00184                   if(result < 0) {
    00185                      ast_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
    00186                      fclose(f);
    00187                      ogg_stream_clear(&tmp->os);
    00188                      vorbis_comment_clear(&tmp->vc);
    00189                      vorbis_info_clear(&tmp->vi);
    00190                      ogg_sync_clear(&tmp->oy);
    00191                      free(tmp);
    00192                      return NULL;
    00193                   }
    00194                   vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
    00195                   i++;
    00196                }
    00197             }
    00198          }
    00199
    00200          buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
    00201          bytes = fread(buffer, 1, BLOCK_SIZE, f);
    00202          if(bytes == 0 && i < 2) {
    00203             ast_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
    00204             fclose(f);
    00205             ogg_stream_clear(&tmp->os);
    00206             vorbis_comment_clear(&tmp->vc);
    00207             vorbis_info_clear(&tmp->vi);
    00208             ogg_sync_clear(&tmp->oy);
    00209             free(tmp);
    00210             return NULL;
    00211          }
    00212          ogg_sync_wrote(&tmp->oy, bytes);
    00213       }
    00214
    00215       ptr = tmp->vc.user_comments;
    00216       while(*ptr){
    00217          ast_log(LOG_DEBUG, "OGG/Vorbis comment: %s\n", *ptr);
    00218          ++ptr;
    00219       }
    00220       ast_log(LOG_DEBUG, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
    00221       ast_log(LOG_DEBUG, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);
    00222
    00223       if(tmp->vi.channels != 1) {
    00224          ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
    00225          ogg_stream_clear(&tmp->os);
    00226          vorbis_comment_clear(&tmp->vc);
    00227          vorbis_info_clear(&tmp->vi);
    00228          ogg_sync_clear(&tmp->oy);
    00229          free(tmp);
    00230          return NULL;
    00231       }
    00232
    00233
    00234       if(tmp->vi.rate != 8000) {
    00235          ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
    00236          fclose(f);
    00237          ogg_stream_clear(&tmp->os);
    00238          vorbis_block_clear(&tmp->vb);
    00239          vorbis_dsp_clear(&tmp->vd);
    00240          vorbis_comment_clear(&tmp->vc);
    00241          vorbis_info_clear(&tmp->vi);
    00242          ogg_sync_clear(&tmp->oy);
    00243          free(tmp);
    00244          return NULL;
    00245       }
    00246
    00247       vorbis_synthesis_init(&tmp->vd, &tmp->vi);
    00248       vorbis_block_init(&tmp->vd, &tmp->vb);
    00249
    00250       if(ast_mutex_lock(&ogg_vorbis_lock)) {
    00251          ast_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
    00252          fclose(f);
    00253          ogg_stream_clear(&tmp->os);
    00254          vorbis_block_clear(&tmp->vb);
    00255          vorbis_dsp_clear(&tmp->vd);
    00256          vorbis_comment_clear(&tmp->vc);
    00257          vorbis_info_clear(&tmp->vi);
    00258          ogg_sync_clear(&tmp->oy);
    00259          free(tmp);
    00260          return NULL;
    00261       }
    00262       glistcnt++;
    00263       ast_mutex_unlock(&ogg_vorbis_lock);
    00264       ast_update_use_count();
    00265    }
    00266    return tmp;
    00267 }

static struct ast_frame* ogg_vorbis_read | ( | struct ast_filestream * | s,
|  | int * | whennext |
| ) |  |  | `[static, read]`

Read a frame full of audio data from the filestream.

Parameters:

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

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_filestream::buffer, ast_frame::data, ast_frame::datalen, ast_filestream::fr, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, read_samples(), ast_frame::samples, SAMPLES_MAX, ast_frame::src, ast_frame::subclass, ast_filestream::vd, and ast_filestream::vi.

Referenced by load_module().

    00525 {
    00526    int clipflag = 0;
    00527    int i;
    00528    int j;
    00529    float **pcm;
    00530    float *mono;
    00531    double accumulator[SAMPLES_MAX];
    00532    int val;
    00533    int samples_in;
    00534    int samples_out = 0;
    00535
    00536    while (1) {
    00537       /* See ifwe have filled up an audio frame yet */
    00538       if(samples_out == SAMPLES_MAX)
    00539          break;
    00540
    00541       /* See ifVorbis decoder has some audio data for us ... */
    00542       samples_in = read_samples(s, &pcm);
    00543       if(samples_in <= 0)
    00544          break;
    00545
    00546       /* Got some audio data from Vorbis... */
    00547       /* Convert the float audio data to 16-bit signed linear */
    00548
    00549       clipflag = 0;
    00550
    00551       samples_in = samples_in < (SAMPLES_MAX - samples_out) ? samples_in : (SAMPLES_MAX - samples_out);
    00552
    00553       for(j = 0; j < samples_in; j++)
    00554          accumulator[j] = 0.0;
    00555
    00556       for(i = 0; i < s->vi.channels; i++) {
    00557          mono = pcm[i];
    00558          for (j = 0; j < samples_in; j++) {
    00559             accumulator[j] += mono[j];
    00560          }
    00561       }
    00562
    00563       for (j = 0; j < samples_in; j++) {
    00564          val =  accumulator[j] * 32767.0 / s->vi.channels;
    00565          if(val > 32767) {
    00566             val = 32767;
    00567             clipflag = 1;
    00568          }
    00569          if(val < -32768) {
    00570             val = -32768;
    00571             clipflag = 1;
    00572          }
    00573          s->buffer[samples_out + j] = val;
    00574       }
    00575
    00576       if(clipflag)
    00577          ast_log(LOG_WARNING, "Clipping in frame %ld\n", (long)(s->vd.sequence));
    00578
    00579       /* Tell the Vorbis decoder how many samples we actually used. */
    00580       vorbis_synthesis_read(&s->vd, samples_in);
    00581       samples_out += samples_in;
    00582    }
    00583
    00584    if(samples_out > 0) {
    00585       s->fr.frametype = AST_FRAME_VOICE;
    00586       s->fr.subclass = AST_FORMAT_SLINEAR;
    00587       s->fr.offset = AST_FRIENDLY_OFFSET;
    00588       s->fr.datalen = samples_out * 2;
    00589       s->fr.data = s->buffer;
    00590       s->fr.src = name;
    00591       s->fr.mallocd = 0;
    00592       s->fr.samples = samples_out;
    00593       *whennext = samples_out;
    00594
    00595       return &s->fr;
    00596    } else {
    00597       return NULL;
    00598    }
    00599 }

static struct ast_filestream* ogg_vorbis_rewrite | ( | FILE * | f,
|  | const char * | comment |
| ) |  |  | `[static, read]`

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

Parameters:

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

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), ast_filestream::eos, ast_filestream::f, free, LOG_ERROR, LOG_WARNING, malloc, ast_filestream::og, ast_filestream::os, ast_filestream::vb, ast_filestream::vc, ast_filestream::vd, ast_filestream::vi, and ast_filestream::writing.

Referenced by load_module().

    00276 {
    00277    ogg_packet header;
    00278    ogg_packet header_comm;
    00279    ogg_packet header_code;
    00280
    00281    struct ast_filestream *tmp;
    00282
    00283    if((tmp = malloc(sizeof(struct ast_filestream)))) {
    00284       memset(tmp, 0, sizeof(struct ast_filestream));
    00285
    00286       tmp->writing = 1;
    00287       tmp->f = f;
    00288
    00289       vorbis_info_init(&tmp->vi);
    00290
    00291       if(vorbis_encode_init_vbr(&tmp->vi, 1, 8000, 0.4)) {
    00292          ast_log(LOG_ERROR, "Unable to initialize Vorbis encoder!\n");
    00293          free(tmp);
    00294          return NULL;
    00295       }
    00296
    00297       vorbis_comment_init(&tmp->vc);
    00298       vorbis_comment_add_tag(&tmp->vc, "ENCODER", "Asterisk PBX");
    00299       if(comment)
    00300          vorbis_comment_add_tag(&tmp->vc, "COMMENT", (char *) comment);
    00301
    00302       vorbis_analysis_init(&tmp->vd, &tmp->vi);
    00303       vorbis_block_init(&tmp->vd, &tmp->vb);
    00304
    00305       ogg_stream_init(&tmp->os, rand());
    00306
    00307       vorbis_analysis_headerout(&tmp->vd, &tmp->vc, &header, &header_comm, &header_code);
    00308       ogg_stream_packetin(&tmp->os, &header);
    00309       ogg_stream_packetin(&tmp->os, &header_comm);
    00310       ogg_stream_packetin(&tmp->os, &header_code);
    00311
    00312       while(!tmp->eos) {
    00313          if(ogg_stream_flush(&tmp->os, &tmp->og) == 0)
    00314             break;
    00315          fwrite(tmp->og.header, 1, tmp->og.header_len, tmp->f);
    00316          fwrite(tmp->og.body, 1, tmp->og.body_len, tmp->f);
    00317          if(ogg_page_eos(&tmp->og))
    00318             tmp->eos = 1;
    00319       }
    00320
    00321       if(ast_mutex_lock(&ogg_vorbis_lock)) {
    00322          ast_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
    00323          fclose(f);
    00324          ogg_stream_clear(&tmp->os);
    00325          vorbis_block_clear(&tmp->vb);
    00326          vorbis_dsp_clear(&tmp->vd);
    00327          vorbis_comment_clear(&tmp->vc);
    00328          vorbis_info_clear(&tmp->vi);
    00329          free(tmp);
    00330          return NULL;
    00331       }
    00332       glistcnt++;
    00333       ast_mutex_unlock(&ogg_vorbis_lock);
    00334       ast_update_use_count();
    00335    }
    00336    return tmp;
    00337 }

static int ogg_vorbis_seek | ( | struct ast_filestream * | s,
|  | long | sample_offset,
|  | int | whence |
| ) |  |  | `[static]`

Seek to a specific position in an OGG/Vorbis filestream.

Parameters:

  | s | The filestream to truncate.
  | 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 621 of file format_ogg_vorbis.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

    00621                                                                                      {
    00622    ast_log(LOG_WARNING, "Seeking is not supported on OGG/Vorbis streams!\n");
    00623    return -1;
    00624 }

static long ogg_vorbis_tell | ( | struct ast_filestream * | s | ) | `[static]`

Definition at line 626 of file format_ogg_vorbis.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

    00626                                                       {
    00627    ast_log(LOG_WARNING, "Telling is not supported on OGG/Vorbis streams!\n");
    00628    return -1;
    00629 }

static int ogg_vorbis_trunc | ( | struct ast_filestream * | s | ) | `[static]`

Trucate an OGG/Vorbis filestream.

Parameters:

  | s | The filestream to truncate.

Returns:
  0 on success, -1 on failure.

Definition at line 607 of file format_ogg_vorbis.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

    00608 {
    00609    ast_log(LOG_WARNING, "Truncation is not supported on OGG/Vorbis streams!\n");
    00610    return -1;
    00611 }

static int ogg_vorbis_write | ( | struct ast_filestream * | s,
|  | struct ast_frame * | f |
| ) |  |  | `[static]`

Write audio data from a frame to an OGG/Vorbis filestream.

Parameters:

  | s | A OGG/Vorbis filestream.
  | f | An frame containing audio to be written to the filestream.

Returns:
  -1 ifthere was an error, 0 on success.

Definition at line 371 of file format_ogg_vorbis.c.

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_filestream::buffer, ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_ERROR, LOG_WARNING, ast_frame::samples, ast_frame::subclass, ast_filestream::vd, write_stream(), and ast_filestream::writing.

Referenced by load_module().

    00372 {
    00373    int i;
    00374    float **buffer;
    00375    short *data;
    00376
    00377    if(!s->writing) {
    00378       ast_log(LOG_ERROR, "This stream is not set up for writing!\n");
    00379       return -1;
    00380    }
    00381
    00382    if(f->frametype != AST_FRAME_VOICE) {
    00383       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
    00384       return -1;
    00385    }
    00386    if(f->subclass != AST_FORMAT_SLINEAR) {
    00387       ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass);
    00388       return -1;
    00389    }
    00390    if(!f->datalen)
    00391       return -1;
    00392
    00393    data = (short *) f->data;
    00394
    00395    buffer = vorbis_analysis_buffer(&s->vd, f->samples);
    00396
    00397    for (i = 0; i < f->samples; i++) {
    00398       buffer[0][i] = data[i]/32768.f;
    00399    }
    00400
    00401    vorbis_analysis_wrote(&s->vd, f->samples);
    00402
    00403    write_stream(s);
    00404
    00405    return 0;
    00406 }

static int read_samples | ( | struct ast_filestream * | s,
|  | float *** | pcm |
| ) |  |  | `[static]`

Get audio data.

Parameters:

  | s | An OGG/Vorbis filestream.
  | pcm | Pointer to a buffere to store audio data in.

Definition at line 449 of file format_ogg_vorbis.c.

References ast_log(), BLOCK_SIZE, ast_filestream::buffer, ast_filestream::bytes, ast_filestream::eos, ast_filestream::f, LOG_WARNING, ast_filestream::og, ast_filestream::op, ast_filestream::os, ast_filestream::oy, result, ast_filestream::vb, and ast_filestream::vd.

Referenced by ogg_vorbis_read().

    00450 {
    00451    int samples_in;
    00452    int result;
    00453    char *buffer;
    00454    int bytes;
    00455
    00456    while (1) {
    00457       samples_in = vorbis_synthesis_pcmout(&s->vd, pcm);
    00458       if(samples_in > 0) {
    00459          return samples_in;
    00460       }
    00461
    00462       /* The Vorbis decoder needs more data... */
    00463       /* See ifOGG has any packets in the current page for the Vorbis decoder. */
    00464       result = ogg_stream_packetout(&s->os, &s->op);
    00465       if(result > 0) {
    00466          /* Yes OGG had some more packets for the Vorbis decoder. */
    00467          if(vorbis_synthesis(&s->vb, &s->op) == 0) {
    00468             vorbis_synthesis_blockin(&s->vd, &s->vb);
    00469          }
    00470
    00471          continue;
    00472       }
    00473
    00474       if(result < 0)
    00475          ast_log(LOG_WARNING, "Corrupt or missing data at this page position; continuing...\n");
    00476
    00477       /* No more packets left in the current page... */
    00478
    00479       if(s->eos) {
    00480          /* No more pages left in the stream */
    00481          return -1;
    00482       }
    00483
    00484       while (!s->eos) {
    00485          /* See ifOGG has any pages in it's internal buffers */
    00486          result = ogg_sync_pageout(&s->oy, &s->og);
    00487          if(result > 0) {
    00488             /* Yes, OGG has more pages in it's internal buffers,
    00489                add the page to the stream state */
    00490             result = ogg_stream_pagein(&s->os, &s->og);
    00491             if(result == 0) {
    00492                /* Yes, got a new,valid page */
    00493                if(ogg_page_eos(&s->og)) {
    00494                   s->eos = 1;
    00495                }
    00496                break;
    00497             }
    00498             ast_log(LOG_WARNING, "Invalid page in the bitstream; continuing...\n");
    00499          }
    00500
    00501          if(result < 0)
    00502             ast_log(LOG_WARNING, "Corrupt or missing data in bitstream; continuing...\n");
    00503
    00504          /* No, we need to read more data from the file descrptor */
    00505          /* get a buffer from OGG to read the data into */
    00506          buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE);
    00507          /* read more data from the file descriptor */
    00508          bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
    00509          /* Tell OGG how many bytes we actually read into the buffer */
    00510          ogg_sync_wrote(&s->oy, bytes);
    00511          if(bytes == 0) {
    00512             s->eos = 1;
    00513          }
    00514       }
    00515    }
    00516 }

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Definition at line 650 of file format_ogg_vorbis.c.

References ast_format_unregister().

    00651 {
    00652    return ast_format_unregister(name);
    00653 }

int usecount | ( | void |  | ) |

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
  The module's usecount.

Definition at line 655 of file format_ogg_vorbis.c.

    00656 {
    00657    return glistcnt;
    00658 }

static void write_stream | ( | struct ast_filestream * | s | ) | `[static]`

Write out any pending encoded data.

Parameters:

  | s | A OGG/Vorbis filestream.

Definition at line 343 of file format_ogg_vorbis.c.

References ast_filestream::eos, ast_filestream::f, ast_filestream::og, ast_filestream::op, ast_filestream::os, ast_filestream::vb, and ast_filestream::vd.

Referenced by ogg_vorbis_close(), and ogg_vorbis_write().

    00344 {
    00345    while (vorbis_analysis_blockout(&s->vd, &s->vb) == 1) {
    00346       vorbis_analysis(&s->vb, NULL);
    00347       vorbis_bitrate_addblock(&s->vb);
    00348
    00349       while (vorbis_bitrate_flushpacket(&s->vd, &s->op)) {
    00350          ogg_stream_packetin(&s->os, &s->op);
    00351          while (!s->eos) {
    00352             if(ogg_stream_pageout(&s->os, &s->og) == 0) {
    00353                break;
    00354             }
    00355             fwrite(s->og.header, 1, s->og.header_len, s->f);
    00356             fwrite(s->og.body, 1, s->og.body_len, s->f);
    00357             if(ogg_page_eos(&s->og)) {
    00358                s->eos = 1;
    00359             }
    00360          }
    00361       }
    00362    }
    00363 }

## Variable Documentation

char* desc = "OGG/Vorbis audio"`[static]`

Definition at line 92 of file format_ogg_vorbis.c.

char* exts = "ogg"`[static]`

Definition at line 93 of file format_ogg_vorbis.c.

int glistcnt = 0`[static]`

Definition at line 89 of file format_ogg_vorbis.c.

char* name = "ogg_vorbis"`[static]`

Definition at line 91 of file format_ogg_vorbis.c.