Sat Apr 26 2014 22:03:19

Asterisk developer's documentation


slinfactory.c File Reference

A machine to gather up arbitrary frames and convert them to raw slinear on demand. More...

#include "asterisk.h"
#include "asterisk/frame.h"
#include "asterisk/slinfactory.h"
#include "asterisk/translate.h"
Include dependency graph for slinfactory.c:

Go to the source code of this file.

Functions

unsigned int ast_slinfactory_available (const struct ast_slinfactory *sf)
 Retrieve number of samples currently in a slinfactory.
void ast_slinfactory_destroy (struct ast_slinfactory *sf)
 Destroy the contents of a slinfactory.
int ast_slinfactory_feed (struct ast_slinfactory *sf, struct ast_frame *f)
 Feed audio into a slinfactory.
void ast_slinfactory_flush (struct ast_slinfactory *sf)
 Flush the contents of a slinfactory.
void ast_slinfactory_init (struct ast_slinfactory *sf)
 Initialize a slinfactory.
int ast_slinfactory_init_with_format (struct ast_slinfactory *sf, const struct ast_format *slin_out)
 Initialize a slinfactory.
int ast_slinfactory_read (struct ast_slinfactory *sf, short *buf, size_t samples)
 Read samples from a slinfactory.

Detailed Description

A machine to gather up arbitrary frames and convert them to raw slinear on demand.

Author:
Anthony Minessale <anthmct@yahoo.com>

Definition in file slinfactory.c.


Function Documentation

unsigned int ast_slinfactory_available ( const struct ast_slinfactory sf)

Retrieve number of samples currently in a slinfactory.

Parameters:
sfThe slinfactory to peek into
Returns:
Number of samples in slinfactory

Definition at line 193 of file slinfactory.c.

References ast_slinfactory::size.

Referenced by ast_audiohook_write_frame(), audio_audiohook_write_list(), audiohook_read_frame_both(), audiohook_read_frame_single(), softmix_bridge_write(), and softmix_process_read_audio().

{
   return sf->size;
}

Destroy the contents of a slinfactory.

Parameters:
sfThe slinfactory that is no longer needed

This function will free any memory allocated for the contents of the slinfactory. It does not free the slinfactory itself. If the sf is malloc'd, then it must be explicitly free'd after calling this function.

Returns:
Nothing

Definition at line 58 of file slinfactory.c.

References ast_frfree, AST_LIST_REMOVE_HEAD, ast_translator_free_path(), f, and ast_slinfactory::trans.

Referenced by ast_audiohook_destroy(), audiohook_set_internal_rate(), set_softmix_bridge_data(), and softmix_bridge_leave().

{
   struct ast_frame *f;

   if (sf->trans) {
      ast_translator_free_path(sf->trans);
      sf->trans = NULL;
   }

   while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
      ast_frfree(f);
}
int ast_slinfactory_feed ( struct ast_slinfactory sf,
struct ast_frame f 
)

Feed audio into a slinfactory.

Parameters:
sfThe slinfactory to feed into
fFrame containing audio to feed in
Returns:
Number of frames currently in factory

Definition at line 71 of file slinfactory.c.

References ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_copy(), ast_frdup(), ast_frfree, ast_frisolate(), ast_getformatname(), AST_LIST_INSERT_TAIL, AST_LIST_NEXT, AST_LIST_TRAVERSE, ast_log(), ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_frame::data, f, ast_slinfactory::format, ast_frame_subclass::format, ast_format::id, LOG_WARNING, ast_slinfactory::output_format, ast_frame::ptr, ast_frame::samples, ast_slinfactory::size, ast_frame::subclass, and ast_slinfactory::trans.

Referenced by ast_audiohook_write_frame(), and softmix_bridge_write().

{
   struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
   unsigned int x = 0;

   /* In some cases, we can be passed a frame which has no data in it, but
    * which has a positive number of samples defined. Once such situation is
    * when a jitter buffer is in use and the jitter buffer interpolates a frame.
    * The frame it produces has data set to NULL, datalen set to 0, and samples
    * set to either 160 or 240.
    */
   if (!f->data.ptr) {
      return 0;
   }

   if (ast_format_cmp(&f->subclass.format, &sf->output_format) == AST_FORMAT_CMP_NOT_EQUAL) {
      if (sf->trans && (ast_format_cmp(&f->subclass.format, &sf->format) == AST_FORMAT_CMP_NOT_EQUAL)) {
         ast_translator_free_path(sf->trans);
         sf->trans = NULL;
      }

      if (!sf->trans) {
         if (!(sf->trans = ast_translator_build_path(&sf->output_format, &f->subclass.format))) {
            ast_log(LOG_WARNING, "Cannot build a path from %s (%d)to %s (%d)\n",
               ast_getformatname(&f->subclass.format),
               f->subclass.format.id,
               ast_getformatname(&sf->output_format),
               sf->output_format.id);
            return 0;
         }
         ast_format_copy(&sf->format, &f->subclass.format);
      }

      if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
         return 0;
      }

      if (!(duped_frame = ast_frisolate(begin_frame))) {
         return 0;
      }

      if (duped_frame != begin_frame) {
         ast_frfree(begin_frame);
      }
   } else {
      if (sf->trans) {
         ast_translator_free_path(sf->trans);
         sf->trans = NULL;
      }
      if (!(duped_frame = ast_frdup(f)))
         return 0;
   }

   AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list) {
      x++;
   }

   /* if the frame was translated, the translator may have returned multiple
      frames, so process each of them
   */
   for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
      AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
      sf->size += begin_frame->samples;
   }

   return x;
}
void ast_slinfactory_flush ( struct ast_slinfactory sf)

Flush the contents of a slinfactory.

Parameters:
sfThe slinfactory to flush
Returns:
Nothing

Definition at line 198 of file slinfactory.c.

References ast_frfree, AST_LIST_REMOVE_HEAD, ast_translator_free_path(), ast_slinfactory::hold, ast_slinfactory::holdlen, ast_slinfactory::offset, ast_slinfactory::size, and ast_slinfactory::trans.

Referenced by ast_audiohook_write_frame(), and softmix_bridge_write().

{
   struct ast_frame *fr = NULL;

   if (sf->trans) {
      ast_translator_free_path(sf->trans);
      sf->trans = NULL;
   }

   while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
      ast_frfree(fr);

   sf->size = sf->holdlen = 0;
   sf->offset = sf->hold;

   return;
}
void ast_slinfactory_init ( struct ast_slinfactory sf)

Initialize a slinfactory.

Parameters:
sfThe slinfactory to initialize
Returns:
Nothing

Definition at line 39 of file slinfactory.c.

References ast_format_set(), AST_FORMAT_SLINEAR, ast_slinfactory::hold, ast_slinfactory::offset, and ast_slinfactory::output_format.

{
   memset(sf, 0, sizeof(*sf));
   sf->offset = sf->hold;
   ast_format_set(&sf->output_format, AST_FORMAT_SLINEAR, 0);
}
int ast_slinfactory_init_with_format ( struct ast_slinfactory sf,
const struct ast_format slin_out 
)

Initialize a slinfactory.

Parameters:
sfThe slinfactory to initialize
slin_outthe slinear output format desired.
Returns:
0 on success, non-zero on failure

Definition at line 46 of file slinfactory.c.

References ast_format_copy(), ast_format_is_slinear(), ast_slinfactory::hold, ast_slinfactory::offset, and ast_slinfactory::output_format.

Referenced by audiohook_set_internal_rate(), and set_softmix_bridge_data().

{
   memset(sf, 0, sizeof(*sf));
   sf->offset = sf->hold;
   if (!ast_format_is_slinear(slin_out)) {
      return -1;
   }
   ast_format_copy(&sf->output_format, slin_out);

   return 0;
}
int ast_slinfactory_read ( struct ast_slinfactory sf,
short *  buf,
size_t  samples 
)

Read samples from a slinfactory.

Parameters:
sfThe slinfactory to read from
bufBuffer to put samples into
samplesNumber of samples wanted
Returns:
Number of samples read

Definition at line 139 of file slinfactory.c.

References ast_frfree, AST_LIST_REMOVE_HEAD, AST_SLINFACTORY_MAX_HOLD, ast_frame::data, ast_slinfactory::hold, ast_slinfactory::holdlen, ast_slinfactory::offset, ast_frame::offset, ast_frame::ptr, ast_frame::samples, and ast_slinfactory::size.

Referenced by audio_audiohook_write_list(), audiohook_read_frame_both(), audiohook_read_frame_single(), and softmix_process_read_audio().

{
   struct ast_frame *frame_ptr;
   unsigned int sofar = 0, ineed, remain;
   short *frame_data, *offset = buf;

   while (sofar < samples) {
      ineed = samples - sofar;

      if (sf->holdlen) {
         if (sf->holdlen <= ineed) {
            memcpy(offset, sf->offset, sf->holdlen * sizeof(*offset));
            sofar += sf->holdlen;
            offset += sf->holdlen;
            sf->holdlen = 0;
            sf->offset = sf->hold;
         } else {
            remain = sf->holdlen - ineed;
            memcpy(offset, sf->offset, ineed * sizeof(*offset));
            sofar += ineed;
            sf->offset += ineed;
            sf->holdlen = remain;
         }
         continue;
      }

      if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
         frame_data = frame_ptr->data.ptr;

         if (frame_ptr->samples <= ineed) {
            memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
            sofar += frame_ptr->samples;
            offset += frame_ptr->samples;
         } else {
            remain = frame_ptr->samples - ineed;
            memcpy(offset, frame_data, ineed * sizeof(*offset));
            sofar += ineed;
            frame_data += ineed;
            if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
               remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
            }
            memcpy(sf->hold, frame_data, remain * sizeof(*offset));
            sf->holdlen = remain;
         }
         ast_frfree(frame_ptr);
      } else {
         break;
      }
   }

   sf->size -= sofar;
   return sofar;
}