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