slinfactory.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "asterisk.h"
00028
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 113296 $")
00030
00031 #include <string.h>
00032
00033 #include "asterisk/frame.h"
00034 #include "asterisk/slinfactory.h"
00035 #include "asterisk/logger.h"
00036 #include "asterisk/translate.h"
00037
00038 void ast_slinfactory_init(struct ast_slinfactory *sf)
00039 {
00040 memset(sf, 0, sizeof(*sf));
00041 sf->offset = sf->hold;
00042 }
00043
00044 void ast_slinfactory_destroy(struct ast_slinfactory *sf)
00045 {
00046 struct ast_frame *f;
00047
00048 if (sf->trans) {
00049 ast_translator_free_path(sf->trans);
00050 sf->trans = NULL;
00051 }
00052
00053 while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
00054 ast_frfree(f);
00055 }
00056
00057 int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
00058 {
00059 struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
00060 unsigned int x;
00061
00062 if (f->subclass != AST_FORMAT_SLINEAR) {
00063 if (sf->trans && f->subclass != sf->format) {
00064 ast_translator_free_path(sf->trans);
00065 sf->trans = NULL;
00066 }
00067
00068 if (!sf->trans) {
00069 if ((sf->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, f->subclass)) == NULL) {
00070 ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f->subclass));
00071 return 0;
00072 } else {
00073 sf->format = f->subclass;
00074 }
00075 }
00076
00077 if (!(begin_frame = ast_translate(sf->trans, f, 0)))
00078 return 0;
00079
00080 duped_frame = ast_frdup(begin_frame);
00081
00082 ast_frfree(begin_frame);
00083
00084 if (!duped_frame)
00085 return 0;
00086 } else {
00087 if (!(duped_frame = ast_frdup(f)))
00088 return 0;
00089 }
00090
00091 x = 0;
00092 AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list)
00093 x++;
00094
00095 AST_LIST_INSERT_TAIL(&sf->queue, duped_frame, frame_list);
00096
00097 sf->size += duped_frame->samples;
00098
00099 return x;
00100 }
00101
00102 int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
00103 {
00104 struct ast_frame *frame_ptr;
00105 unsigned int sofar = 0, ineed, remain;
00106 short *frame_data, *offset = buf;
00107
00108 while (sofar < samples) {
00109 ineed = samples - sofar;
00110
00111 if (sf->holdlen) {
00112 if (sf->holdlen <= ineed) {
00113 memcpy(offset, sf->hold, sf->holdlen * sizeof(*offset));
00114 sofar += sf->holdlen;
00115 offset += sf->holdlen;
00116 sf->holdlen = 0;
00117 sf->offset = sf->hold;
00118 } else {
00119 remain = sf->holdlen - ineed;
00120 memcpy(offset, sf->offset, ineed * sizeof(*offset));
00121 sofar += ineed;
00122 sf->offset += ineed;
00123 sf->holdlen = remain;
00124 }
00125 continue;
00126 }
00127
00128 if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
00129 frame_data = frame_ptr->data;
00130
00131 if (frame_ptr->samples <= ineed) {
00132 memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
00133 sofar += frame_ptr->samples;
00134 offset += frame_ptr->samples;
00135 } else {
00136 remain = frame_ptr->samples - ineed;
00137 memcpy(offset, frame_data, ineed * sizeof(*offset));
00138 sofar += ineed;
00139 frame_data += ineed;
00140 if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
00141 remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
00142 }
00143 memcpy(sf->hold, frame_data, remain * sizeof(*offset));
00144 sf->holdlen = remain;
00145 }
00146 ast_frfree(frame_ptr);
00147 } else {
00148 break;
00149 }
00150 }
00151
00152 sf->size -= sofar;
00153 return sofar;
00154 }
00155
00156 unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
00157 {
00158 return sf->size;
00159 }
00160
00161 void ast_slinfactory_flush(struct ast_slinfactory *sf)
00162 {
00163 struct ast_frame *fr = NULL;
00164
00165 if (sf->trans) {
00166 ast_translator_free_path(sf->trans);
00167 sf->trans = NULL;
00168 }
00169
00170 while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
00171 ast_frfree(fr);
00172
00173 sf->size = sf->holdlen = 0;
00174 sf->offset = sf->hold;
00175
00176 return;
00177 }