Thu Jul 9 13:40:41 2009

Asterisk developer's documentation


slinfactory.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2005, Anthony Minessale II.
00005  *
00006  * Anthony Minessale <anthmct@yahoo.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief A machine to gather up arbitrary frames and convert them
00022  * to raw slinear on demand.
00023  *
00024  * \author Anthony Minessale <anthmct@yahoo.com>
00025  */
00026 
00027 #include "asterisk.h"
00028 
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 201093 $")
00030 
00031 #include "asterisk/frame.h"
00032 #include "asterisk/slinfactory.h"
00033 #include "asterisk/translate.h"
00034 
00035 void ast_slinfactory_init(struct ast_slinfactory *sf) 
00036 {
00037    memset(sf, 0, sizeof(*sf));
00038    sf->offset = sf->hold;
00039 }
00040 
00041 void ast_slinfactory_destroy(struct ast_slinfactory *sf) 
00042 {
00043    struct ast_frame *f;
00044 
00045    if (sf->trans) {
00046       ast_translator_free_path(sf->trans);
00047       sf->trans = NULL;
00048    }
00049 
00050    while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
00051       ast_frfree(f);
00052 }
00053 
00054 int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
00055 {
00056    struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
00057    unsigned int x = 0;
00058 
00059    /* In some cases, we can be passed a frame which has no data in it, but
00060     * which has a positive number of samples defined. Once such situation is
00061     * when a jitter buffer is in use and the jitter buffer interpolates a frame.
00062     * The frame it produces has data set to NULL, datalen set to 0, and samples
00063     * set to either 160 or 240.
00064     */
00065    if (!f->data) {
00066       return 0;
00067    }
00068 
00069    if (f->subclass != AST_FORMAT_SLINEAR && f->subclass != AST_FORMAT_SLINEAR16) {
00070       if (sf->trans && f->subclass != sf->format) {
00071          ast_translator_free_path(sf->trans);
00072          sf->trans = NULL;
00073       }
00074 
00075       if (!sf->trans) {
00076          if (!(sf->trans = ast_translator_build_path((f->subclass == AST_FORMAT_G722 ? AST_FORMAT_SLINEAR16 : AST_FORMAT_SLINEAR), f->subclass))) {
00077             ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f->subclass));
00078             return 0;
00079          }
00080          sf->format = f->subclass;
00081       }
00082 
00083       if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
00084          return 0;
00085       }
00086       
00087       if (!(duped_frame = ast_frisolate(begin_frame))) {
00088          return 0;
00089       }
00090 
00091       if (duped_frame != begin_frame) {
00092          ast_frfree(begin_frame);
00093       }
00094    } else {
00095       if (sf->trans) {
00096          ast_translator_free_path(sf->trans);
00097          sf->trans = NULL;
00098       }
00099       if (!(duped_frame = ast_frdup(f)))
00100          return 0;
00101    }
00102 
00103    AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list)
00104       x++;
00105 
00106    /* if the frame was translated, the translator may have returned multiple
00107       frames, so process each of them
00108    */
00109    for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
00110       AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
00111       sf->size += begin_frame->samples;
00112    }
00113 
00114    return x;
00115 }
00116 
00117 int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples) 
00118 {
00119    struct ast_frame *frame_ptr;
00120    unsigned int sofar = 0, ineed, remain;
00121    short *frame_data, *offset = buf;
00122 
00123    while (sofar < samples) {
00124       ineed = samples - sofar;
00125 
00126       if (sf->holdlen) {
00127          if (sf->holdlen <= ineed) {
00128             memcpy(offset, sf->hold, sf->holdlen * sizeof(*offset));
00129             sofar += sf->holdlen;
00130             offset += sf->holdlen;
00131             sf->holdlen = 0;
00132             sf->offset = sf->hold;
00133          } else {
00134             remain = sf->holdlen - ineed;
00135             memcpy(offset, sf->offset, ineed * sizeof(*offset));
00136             sofar += ineed;
00137             sf->offset += ineed;
00138             sf->holdlen = remain;
00139          }
00140          continue;
00141       }
00142       
00143       if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
00144          frame_data = frame_ptr->data;
00145          
00146          if (frame_ptr->samples <= ineed) {
00147             memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
00148             sofar += frame_ptr->samples;
00149             offset += frame_ptr->samples;
00150          } else {
00151             remain = frame_ptr->samples - ineed;
00152             memcpy(offset, frame_data, ineed * sizeof(*offset));
00153             sofar += ineed;
00154             frame_data += ineed;
00155             if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
00156                remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
00157             }
00158             memcpy(sf->hold, frame_data, remain * sizeof(*offset));
00159             sf->holdlen = remain;
00160          }
00161          ast_frfree(frame_ptr);
00162       } else {
00163          break;
00164       }
00165    }
00166 
00167    sf->size -= sofar;
00168    return sofar;
00169 }
00170 
00171 unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
00172 {
00173    return sf->size;
00174 }
00175 
00176 void ast_slinfactory_flush(struct ast_slinfactory *sf)
00177 {
00178    struct ast_frame *fr = NULL;
00179 
00180    if (sf->trans) {
00181       ast_translator_free_path(sf->trans);
00182       sf->trans = NULL;
00183    }
00184 
00185    while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
00186       ast_frfree(fr);
00187 
00188    sf->size = sf->holdlen = 0;
00189    sf->offset = sf->hold;
00190 
00191    return;
00192 }

Generated on Thu Jul 9 13:40:41 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7