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: 200991 $")
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 = 0;
00061
00062
00063
00064
00065
00066
00067
00068 if (!f->data) {
00069 return 0;
00070 }
00071
00072 if (f->subclass != AST_FORMAT_SLINEAR) {
00073 if (sf->trans && f->subclass != sf->format) {
00074 ast_translator_free_path(sf->trans);
00075 sf->trans = NULL;
00076 }
00077
00078 if (!sf->trans) {
00079 if ((sf->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, f->subclass)) == NULL) {
00080 ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f->subclass));
00081 return 0;
00082 } else {
00083 sf->format = f->subclass;
00084 }
00085 }
00086
00087 if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
00088 return 0;
00089 }
00090
00091 if (!(duped_frame = ast_frisolate(begin_frame))) {
00092 return 0;
00093 }
00094
00095 if (duped_frame != begin_frame) {
00096 ast_frfree(begin_frame);
00097 }
00098 } else {
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
00107
00108
00109
00110 for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
00111 AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
00112 sf->size += begin_frame->samples;
00113 }
00114
00115 return x;
00116 }
00117
00118 int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
00119 {
00120 struct ast_frame *frame_ptr;
00121 unsigned int sofar = 0, ineed, remain;
00122 short *frame_data, *offset = buf;
00123
00124 while (sofar < samples) {
00125 ineed = samples - sofar;
00126
00127 if (sf->holdlen) {
00128 if (sf->holdlen <= ineed) {
00129 memcpy(offset, sf->hold, sf->holdlen * sizeof(*offset));
00130 sofar += sf->holdlen;
00131 offset += sf->holdlen;
00132 sf->holdlen = 0;
00133 sf->offset = sf->hold;
00134 } else {
00135 remain = sf->holdlen - ineed;
00136 memcpy(offset, sf->offset, ineed * sizeof(*offset));
00137 sofar += ineed;
00138 sf->offset += ineed;
00139 sf->holdlen = remain;
00140 }
00141 continue;
00142 }
00143
00144 if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
00145 frame_data = frame_ptr->data;
00146
00147 if (frame_ptr->samples <= ineed) {
00148 memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
00149 sofar += frame_ptr->samples;
00150 offset += frame_ptr->samples;
00151 } else {
00152 remain = frame_ptr->samples - ineed;
00153 memcpy(offset, frame_data, ineed * sizeof(*offset));
00154 sofar += ineed;
00155 frame_data += ineed;
00156 if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
00157 remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
00158 }
00159 memcpy(sf->hold, frame_data, remain * sizeof(*offset));
00160 sf->holdlen = remain;
00161 }
00162 ast_frfree(frame_ptr);
00163 } else {
00164 break;
00165 }
00166 }
00167
00168 sf->size -= sofar;
00169 return sofar;
00170 }
00171
00172 unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
00173 {
00174 return sf->size;
00175 }
00176
00177 void ast_slinfactory_flush(struct ast_slinfactory *sf)
00178 {
00179 struct ast_frame *fr = NULL;
00180
00181 if (sf->trans) {
00182 ast_translator_free_path(sf->trans);
00183 sf->trans = NULL;
00184 }
00185
00186 while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
00187 ast_frfree(fr);
00188
00189 sf->size = sf->holdlen = 0;
00190 sf->offset = sf->hold;
00191
00192 return;
00193 }