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