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
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
00034
00035 #include "asterisk/frame.h"
00036 #include "asterisk/slinfactory.h"
00037 #include "asterisk/translate.h"
00038
00039 void ast_slinfactory_init(struct ast_slinfactory *sf)
00040 {
00041 memset(sf, 0, sizeof(*sf));
00042 sf->offset = sf->hold;
00043 sf->output_format = AST_FORMAT_SLINEAR;
00044 }
00045
00046 int ast_slinfactory_init_rate(struct ast_slinfactory *sf, unsigned int sample_rate)
00047 {
00048 memset(sf, 0, sizeof(*sf));
00049 sf->offset = sf->hold;
00050 switch (sample_rate) {
00051 case 8000:
00052 sf->output_format = AST_FORMAT_SLINEAR;
00053 break;
00054 case 16000:
00055 sf->output_format = AST_FORMAT_SLINEAR16;
00056 break;
00057 default:
00058 return -1;
00059 }
00060
00061 return 0;
00062 }
00063
00064 void ast_slinfactory_destroy(struct ast_slinfactory *sf)
00065 {
00066 struct ast_frame *f;
00067
00068 if (sf->trans) {
00069 ast_translator_free_path(sf->trans);
00070 sf->trans = NULL;
00071 }
00072
00073 while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
00074 ast_frfree(f);
00075 }
00076
00077 int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
00078 {
00079 struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
00080 unsigned int x = 0;
00081
00082
00083
00084
00085
00086
00087
00088 if (!f->data.ptr) {
00089 return 0;
00090 }
00091
00092 if (f->subclass.codec != sf->output_format) {
00093 if (sf->trans && f->subclass.codec != sf->format) {
00094 ast_translator_free_path(sf->trans);
00095 sf->trans = NULL;
00096 }
00097
00098 if (!sf->trans) {
00099 if (!(sf->trans = ast_translator_build_path(sf->output_format, f->subclass.codec))) {
00100 ast_log(LOG_WARNING, "Cannot build a path from %s to %s\n", ast_getformatname(f->subclass.codec),
00101 ast_getformatname(sf->output_format));
00102 return 0;
00103 }
00104 sf->format = f->subclass.codec;
00105 }
00106
00107 if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
00108 return 0;
00109 }
00110
00111 if (!(duped_frame = ast_frisolate(begin_frame))) {
00112 return 0;
00113 }
00114
00115 if (duped_frame != begin_frame) {
00116 ast_frfree(begin_frame);
00117 }
00118 } else {
00119 if (sf->trans) {
00120 ast_translator_free_path(sf->trans);
00121 sf->trans = NULL;
00122 }
00123 if (!(duped_frame = ast_frdup(f)))
00124 return 0;
00125 }
00126
00127 AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list) {
00128 x++;
00129 }
00130
00131
00132
00133
00134 for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
00135 AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
00136 sf->size += begin_frame->samples;
00137 }
00138
00139 return x;
00140 }
00141
00142 int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
00143 {
00144 struct ast_frame *frame_ptr;
00145 unsigned int sofar = 0, ineed, remain;
00146 short *frame_data, *offset = buf;
00147
00148 while (sofar < samples) {
00149 ineed = samples - sofar;
00150
00151 if (sf->holdlen) {
00152 if (sf->holdlen <= ineed) {
00153 memcpy(offset, sf->hold, sf->holdlen * sizeof(*offset));
00154 sofar += sf->holdlen;
00155 offset += sf->holdlen;
00156 sf->holdlen = 0;
00157 sf->offset = sf->hold;
00158 } else {
00159 remain = sf->holdlen - ineed;
00160 memcpy(offset, sf->offset, ineed * sizeof(*offset));
00161 sofar += ineed;
00162 sf->offset += ineed;
00163 sf->holdlen = remain;
00164 }
00165 continue;
00166 }
00167
00168 if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
00169 frame_data = frame_ptr->data.ptr;
00170
00171 if (frame_ptr->samples <= ineed) {
00172 memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
00173 sofar += frame_ptr->samples;
00174 offset += frame_ptr->samples;
00175 } else {
00176 remain = frame_ptr->samples - ineed;
00177 memcpy(offset, frame_data, ineed * sizeof(*offset));
00178 sofar += ineed;
00179 frame_data += ineed;
00180 if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
00181 remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
00182 }
00183 memcpy(sf->hold, frame_data, remain * sizeof(*offset));
00184 sf->holdlen = remain;
00185 }
00186 ast_frfree(frame_ptr);
00187 } else {
00188 break;
00189 }
00190 }
00191
00192 sf->size -= sofar;
00193 return sofar;
00194 }
00195
00196 unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
00197 {
00198 return sf->size;
00199 }
00200
00201 void ast_slinfactory_flush(struct ast_slinfactory *sf)
00202 {
00203 struct ast_frame *fr = NULL;
00204
00205 if (sf->trans) {
00206 ast_translator_free_path(sf->trans);
00207 sf->trans = NULL;
00208 }
00209
00210 while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
00211 ast_frfree(fr);
00212
00213 sf->size = sf->holdlen = 0;
00214 sf->offset = sf->hold;
00215
00216 return;
00217 }