00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "libavutil/audioconvert.h"
00028 #include "libavutil/avstring.h"
00029 #include "libavutil/fifo.h"
00030 #include "asrc_abuffer.h"
00031 #include "internal.h"
00032
00033 typedef struct {
00034
00035 int sample_rate;
00036 unsigned int sample_format;
00037 int64_t channel_layout;
00038 int packing_format;
00039
00040
00041 AVFifoBuffer *fifo;
00042
00043
00044 AVFilterContext *aconvert;
00045 AVFilterContext *aresample;
00046 } ABufferSourceContext;
00047
00048 #define FIFO_SIZE 8
00049
00050 static void buf_free(AVFilterBuffer *ptr)
00051 {
00052 av_free(ptr);
00053 return;
00054 }
00055
00056 static void set_link_source(AVFilterContext *src, AVFilterLink *link)
00057 {
00058 link->src = src;
00059 link->srcpad = &(src->output_pads[0]);
00060 src->outputs[0] = link;
00061 }
00062
00063 static int reconfigure_filter(ABufferSourceContext *abuffer, AVFilterContext *filt_ctx)
00064 {
00065 int ret;
00066 AVFilterLink * const inlink = filt_ctx->inputs[0];
00067 AVFilterLink * const outlink = filt_ctx->outputs[0];
00068
00069 inlink->format = abuffer->sample_format;
00070 inlink->channel_layout = abuffer->channel_layout;
00071 inlink->planar = abuffer->packing_format;
00072 inlink->sample_rate = abuffer->sample_rate;
00073
00074 filt_ctx->filter->uninit(filt_ctx);
00075 memset(filt_ctx->priv, 0, filt_ctx->filter->priv_size);
00076 if ((ret = filt_ctx->filter->init(filt_ctx, NULL , NULL)) < 0)
00077 return ret;
00078 if ((ret = inlink->srcpad->config_props(inlink)) < 0)
00079 return ret;
00080 return outlink->srcpad->config_props(outlink);
00081 }
00082
00083 static int insert_filter(ABufferSourceContext *abuffer,
00084 AVFilterLink *link, AVFilterContext **filt_ctx,
00085 const char *filt_name)
00086 {
00087 int ret;
00088
00089 if ((ret = avfilter_open(filt_ctx, avfilter_get_by_name(filt_name), NULL)) < 0)
00090 return ret;
00091
00092 link->src->outputs[0] = NULL;
00093 if ((ret = avfilter_link(link->src, 0, *filt_ctx, 0)) < 0) {
00094 link->src->outputs[0] = link;
00095 return ret;
00096 }
00097
00098 set_link_source(*filt_ctx, link);
00099
00100 if ((ret = reconfigure_filter(abuffer, *filt_ctx)) < 0) {
00101 avfilter_free(*filt_ctx);
00102 return ret;
00103 }
00104
00105 return 0;
00106 }
00107
00108 static void remove_filter(AVFilterContext **filt_ctx)
00109 {
00110 AVFilterLink *outlink = (*filt_ctx)->outputs[0];
00111 AVFilterContext *src = (*filt_ctx)->inputs[0]->src;
00112
00113 (*filt_ctx)->outputs[0] = NULL;
00114 avfilter_free(*filt_ctx);
00115 *filt_ctx = NULL;
00116
00117 set_link_source(src, outlink);
00118 }
00119
00120 static inline void log_input_change(void *ctx, AVFilterLink *link, AVFilterBufferRef *ref)
00121 {
00122 char old_layout_str[16], new_layout_str[16];
00123 av_get_channel_layout_string(old_layout_str, sizeof(old_layout_str),
00124 -1, link->channel_layout);
00125 av_get_channel_layout_string(new_layout_str, sizeof(new_layout_str),
00126 -1, ref->audio->channel_layout);
00127 av_log(ctx, AV_LOG_INFO,
00128 "Audio input format changed: "
00129 "%s:%s:%d -> %s:%s:%d, normalizing\n",
00130 av_get_sample_fmt_name(link->format),
00131 old_layout_str, (int)link->sample_rate,
00132 av_get_sample_fmt_name(ref->format),
00133 new_layout_str, ref->audio->sample_rate);
00134 }
00135
00136 int av_asrc_buffer_add_audio_buffer_ref(AVFilterContext *ctx,
00137 AVFilterBufferRef *samplesref,
00138 int av_unused flags)
00139 {
00140 ABufferSourceContext *abuffer = ctx->priv;
00141 AVFilterLink *link;
00142 int ret, logged = 0;
00143
00144 if (av_fifo_space(abuffer->fifo) < sizeof(samplesref)) {
00145 av_log(ctx, AV_LOG_ERROR,
00146 "Buffering limit reached. Please consume some available frames "
00147 "before adding new ones.\n");
00148 return AVERROR(EINVAL);
00149 }
00150
00151
00152
00153 link = ctx->outputs[0];
00154 if (samplesref->audio->sample_rate != link->sample_rate) {
00155
00156 log_input_change(ctx, link, samplesref);
00157 logged = 1;
00158
00159 abuffer->sample_rate = samplesref->audio->sample_rate;
00160
00161 if (!abuffer->aresample) {
00162 ret = insert_filter(abuffer, link, &abuffer->aresample, "aresample");
00163 if (ret < 0) return ret;
00164 } else {
00165 link = abuffer->aresample->outputs[0];
00166 if (samplesref->audio->sample_rate == link->sample_rate)
00167 remove_filter(&abuffer->aresample);
00168 else
00169 if ((ret = reconfigure_filter(abuffer, abuffer->aresample)) < 0)
00170 return ret;
00171 }
00172 }
00173
00174 link = ctx->outputs[0];
00175 if (samplesref->format != link->format ||
00176 samplesref->audio->channel_layout != link->channel_layout ||
00177 samplesref->audio->planar != link->planar) {
00178
00179 if (!logged) log_input_change(ctx, link, samplesref);
00180
00181 abuffer->sample_format = samplesref->format;
00182 abuffer->channel_layout = samplesref->audio->channel_layout;
00183 abuffer->packing_format = samplesref->audio->planar;
00184
00185 if (!abuffer->aconvert) {
00186 ret = insert_filter(abuffer, link, &abuffer->aconvert, "aconvert");
00187 if (ret < 0) return ret;
00188 } else {
00189 link = abuffer->aconvert->outputs[0];
00190 if (samplesref->format == link->format &&
00191 samplesref->audio->channel_layout == link->channel_layout &&
00192 samplesref->audio->planar == link->planar
00193 )
00194 remove_filter(&abuffer->aconvert);
00195 else
00196 if ((ret = reconfigure_filter(abuffer, abuffer->aconvert)) < 0)
00197 return ret;
00198 }
00199 }
00200
00201 if (sizeof(samplesref) != av_fifo_generic_write(abuffer->fifo, &samplesref,
00202 sizeof(samplesref), NULL)) {
00203 av_log(ctx, AV_LOG_ERROR, "Error while writing to FIFO\n");
00204 return AVERROR(EINVAL);
00205 }
00206
00207 return 0;
00208 }
00209
00210 int av_asrc_buffer_add_samples(AVFilterContext *ctx,
00211 uint8_t *data[8], int linesize[8],
00212 int nb_samples, int sample_rate,
00213 int sample_fmt, int64_t channel_layout, int planar,
00214 int64_t pts, int av_unused flags)
00215 {
00216 AVFilterBufferRef *samplesref;
00217
00218 samplesref = avfilter_get_audio_buffer_ref_from_arrays(
00219 data, linesize, AV_PERM_WRITE,
00220 nb_samples,
00221 sample_fmt, channel_layout, planar);
00222 if (!samplesref)
00223 return AVERROR(ENOMEM);
00224
00225 samplesref->buf->free = buf_free;
00226 samplesref->pts = pts;
00227 samplesref->audio->sample_rate = sample_rate;
00228
00229 return av_asrc_buffer_add_audio_buffer_ref(ctx, samplesref, 0);
00230 }
00231
00232 int av_asrc_buffer_add_buffer(AVFilterContext *ctx,
00233 uint8_t *buf, int buf_size, int sample_rate,
00234 int sample_fmt, int64_t channel_layout, int planar,
00235 int64_t pts, int av_unused flags)
00236 {
00237 uint8_t *data[8];
00238 int linesize[8];
00239 int nb_channels = av_get_channel_layout_nb_channels(channel_layout),
00240 nb_samples = buf_size / nb_channels / av_get_bytes_per_sample(sample_fmt);
00241
00242 av_samples_fill_arrays(data, linesize,
00243 buf, nb_channels, nb_samples,
00244 sample_fmt, 16);
00245
00246 return av_asrc_buffer_add_samples(ctx,
00247 data, linesize, nb_samples,
00248 sample_rate,
00249 sample_fmt, channel_layout, planar,
00250 pts, flags);
00251 }
00252
00253 static av_cold int init(AVFilterContext *ctx, const char *args0, void *opaque)
00254 {
00255 ABufferSourceContext *abuffer = ctx->priv;
00256 char *arg = NULL, *ptr, chlayout_str[16];
00257 char *args = av_strdup(args0);
00258 int ret;
00259
00260 arg = av_strtok(args, ":", &ptr);
00261
00262 #define ADD_FORMAT(fmt_name) \
00263 if (!arg) \
00264 goto arg_fail; \
00265 if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0) { \
00266 av_freep(&args); \
00267 return ret; \
00268 } \
00269 if (*args) \
00270 arg = av_strtok(NULL, ":", &ptr)
00271
00272 ADD_FORMAT(sample_rate);
00273 ADD_FORMAT(sample_format);
00274 ADD_FORMAT(channel_layout);
00275 ADD_FORMAT(packing_format);
00276
00277 abuffer->fifo = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*));
00278 if (!abuffer->fifo) {
00279 av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo, filter init failed.\n");
00280 return AVERROR(ENOMEM);
00281 }
00282
00283 av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str),
00284 -1, abuffer->channel_layout);
00285 av_log(ctx, AV_LOG_INFO, "format:%s layout:%s rate:%d\n",
00286 av_get_sample_fmt_name(abuffer->sample_format), chlayout_str,
00287 abuffer->sample_rate);
00288 av_freep(&args);
00289
00290 return 0;
00291
00292 arg_fail:
00293 av_log(ctx, AV_LOG_ERROR, "Invalid arguments, must be of the form "
00294 "sample_rate:sample_fmt:channel_layout:packing\n");
00295 av_freep(&args);
00296 return AVERROR(EINVAL);
00297 }
00298
00299 static av_cold void uninit(AVFilterContext *ctx)
00300 {
00301 ABufferSourceContext *abuffer = ctx->priv;
00302 av_fifo_free(abuffer->fifo);
00303 }
00304
00305 static int query_formats(AVFilterContext *ctx)
00306 {
00307 ABufferSourceContext *abuffer = ctx->priv;
00308 AVFilterFormats *formats;
00309
00310 formats = NULL;
00311 avfilter_add_format(&formats, abuffer->sample_format);
00312 avfilter_set_common_sample_formats(ctx, formats);
00313
00314 formats = NULL;
00315 avfilter_add_format(&formats, abuffer->channel_layout);
00316 avfilter_set_common_channel_layouts(ctx, formats);
00317
00318 formats = NULL;
00319 avfilter_add_format(&formats, abuffer->packing_format);
00320 avfilter_set_common_packing_formats(ctx, formats);
00321
00322 return 0;
00323 }
00324
00325 static int config_output(AVFilterLink *outlink)
00326 {
00327 ABufferSourceContext *abuffer = outlink->src->priv;
00328 outlink->sample_rate = abuffer->sample_rate;
00329 return 0;
00330 }
00331
00332 static int request_frame(AVFilterLink *outlink)
00333 {
00334 ABufferSourceContext *abuffer = outlink->src->priv;
00335 AVFilterBufferRef *samplesref;
00336
00337 if (!av_fifo_size(abuffer->fifo)) {
00338 av_log(outlink->src, AV_LOG_ERROR,
00339 "request_frame() called with no available frames!\n");
00340 return AVERROR(EINVAL);
00341 }
00342
00343 av_fifo_generic_read(abuffer->fifo, &samplesref, sizeof(samplesref), NULL);
00344 avfilter_filter_samples(outlink, avfilter_ref_buffer(samplesref, ~0));
00345 avfilter_unref_buffer(samplesref);
00346
00347 return 0;
00348 }
00349
00350 static int poll_frame(AVFilterLink *outlink)
00351 {
00352 ABufferSourceContext *abuffer = outlink->src->priv;
00353 return av_fifo_size(abuffer->fifo)/sizeof(AVFilterBufferRef*);
00354 }
00355
00356 AVFilter avfilter_asrc_abuffer = {
00357 .name = "abuffer",
00358 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
00359 .priv_size = sizeof(ABufferSourceContext),
00360 .query_formats = query_formats,
00361
00362 .init = init,
00363 .uninit = uninit,
00364
00365 .inputs = (const AVFilterPad[]) {{ .name = NULL }},
00366 .outputs = (const AVFilterPad[]) {{ .name = "default",
00367 .type = AVMEDIA_TYPE_AUDIO,
00368 .request_frame = request_frame,
00369 .poll_frame = poll_frame,
00370 .config_props = config_output, },
00371 { .name = NULL}},
00372 };