00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "libswresample/swresample.h"
00027 #include "avfilter.h"
00028 #include "internal.h"
00029
00030 #define QUEUE_SIZE 16
00031
00032 typedef struct {
00033 int nb_in_ch[2];
00034 int route[SWR_CH_MAX];
00035 int bps;
00036 struct amerge_queue {
00037 AVFilterBufferRef *buf[QUEUE_SIZE];
00038 int nb_buf, nb_samples, pos;
00039 } queue[2];
00040 } AMergeContext;
00041
00042 static av_cold void uninit(AVFilterContext *ctx)
00043 {
00044 AMergeContext *am = ctx->priv;
00045 int i, j;
00046
00047 for (i = 0; i < 2; i++)
00048 for (j = 0; j < am->queue[i].nb_buf; j++)
00049 avfilter_unref_buffer(am->queue[i].buf[j]);
00050 }
00051
00052 static int query_formats(AVFilterContext *ctx)
00053 {
00054 AMergeContext *am = ctx->priv;
00055 int64_t inlayout[2], outlayout;
00056 const int packing_fmts[] = { AVFILTER_PACKED, -1 };
00057 AVFilterFormats *formats;
00058 int i;
00059
00060 for (i = 0; i < 2; i++) {
00061 if (!ctx->inputs[i]->in_chlayouts ||
00062 !ctx->inputs[i]->in_chlayouts->format_count) {
00063 av_log(ctx, AV_LOG_ERROR,
00064 "No channel layout for input %d\n", i + 1);
00065 return AVERROR(EINVAL);
00066 }
00067 inlayout[i] = ctx->inputs[i]->in_chlayouts->formats[0];
00068 if (ctx->inputs[i]->in_chlayouts->format_count > 1) {
00069 char buf[256];
00070 av_get_channel_layout_string(buf, sizeof(buf), 0, inlayout[i]);
00071 av_log(ctx, AV_LOG_INFO, "Using \"%s\" for input %d\n", buf, i + 1);
00072 }
00073 am->nb_in_ch[i] = av_get_channel_layout_nb_channels(inlayout[i]);
00074 }
00075 if (am->nb_in_ch[0] + am->nb_in_ch[1] > SWR_CH_MAX) {
00076 av_log(ctx, AV_LOG_ERROR, "Too many channels (max %d)\n", SWR_CH_MAX);
00077 return AVERROR(EINVAL);
00078 }
00079 if (inlayout[0] & inlayout[1]) {
00080 av_log(ctx, AV_LOG_WARNING,
00081 "Inputs overlap: output layout will be meaningless\n");
00082 for (i = 0; i < am->nb_in_ch[0] + am->nb_in_ch[1]; i++)
00083 am->route[i] = i;
00084 outlayout = av_get_default_channel_layout(am->nb_in_ch[0] +
00085 am->nb_in_ch[1]);
00086 if (!outlayout)
00087 outlayout = ((int64_t)1 << (am->nb_in_ch[0] + am->nb_in_ch[1])) - 1;
00088 } else {
00089 int *route[2] = { am->route, am->route + am->nb_in_ch[0] };
00090 int c, out_ch_number = 0;
00091
00092 outlayout = inlayout[0] | inlayout[1];
00093 for (c = 0; c < 64; c++)
00094 for (i = 0; i < 2; i++)
00095 if ((inlayout[i] >> c) & 1)
00096 *(route[i]++) = out_ch_number++;
00097 }
00098 formats = avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO);
00099 avfilter_set_common_sample_formats(ctx, formats);
00100 formats = avfilter_make_format_list(packing_fmts);
00101 avfilter_set_common_packing_formats(ctx, formats);
00102 for (i = 0; i < 2; i++) {
00103 formats = NULL;
00104 avfilter_add_format(&formats, inlayout[i]);
00105 avfilter_formats_ref(formats, &ctx->inputs[i]->out_chlayouts);
00106 }
00107 formats = NULL;
00108 avfilter_add_format(&formats, outlayout);
00109 avfilter_formats_ref(formats, &ctx->outputs[0]->in_chlayouts);
00110 return 0;
00111 }
00112
00113 static int config_output(AVFilterLink *outlink)
00114 {
00115 AVFilterContext *ctx = outlink->src;
00116 AMergeContext *am = ctx->priv;
00117 int64_t layout;
00118 char name[3][256];
00119 int i;
00120
00121 if (ctx->inputs[0]->sample_rate != ctx->inputs[1]->sample_rate) {
00122 av_log(ctx, AV_LOG_ERROR,
00123 "Inputs must have the same sample rate "
00124 "(%"PRIi64" vs %"PRIi64")\n",
00125 ctx->inputs[0]->sample_rate, ctx->inputs[1]->sample_rate);
00126 return AVERROR(EINVAL);
00127 }
00128 am->bps = av_get_bytes_per_sample(ctx->outputs[0]->format);
00129 outlink->sample_rate = ctx->inputs[0]->sample_rate;
00130 outlink->time_base = ctx->inputs[0]->time_base;
00131 for (i = 0; i < 3; i++) {
00132 layout = (i < 2 ? ctx->inputs[i] : ctx->outputs[0])->channel_layout;
00133 av_get_channel_layout_string(name[i], sizeof(name[i]), -1, layout);
00134 }
00135 av_log(ctx, AV_LOG_INFO,
00136 "in1:%s + in2:%s -> out:%s\n", name[0], name[1], name[2]);
00137 return 0;
00138 }
00139
00140 static int request_frame(AVFilterLink *outlink)
00141 {
00142 AVFilterContext *ctx = outlink->src;
00143 AMergeContext *am = ctx->priv;
00144 int i;
00145
00146 for (i = 0; i < 2; i++)
00147 if (!am->queue[i].nb_samples)
00148 avfilter_request_frame(ctx->inputs[i]);
00149 return 0;
00150 }
00151
00167 static inline void copy_samples(int nb_in_ch[2], int *route, uint8_t *ins[2],
00168 uint8_t **outs, int ns, int bps)
00169 {
00170 int *route_cur;
00171 int i, c;
00172
00173 while (ns--) {
00174 route_cur = route;
00175 for (i = 0; i < 2; i++) {
00176 for (c = 0; c < nb_in_ch[i]; c++) {
00177 memcpy((*outs) + bps * *(route_cur++), ins[i], bps);
00178 ins[i] += bps;
00179 }
00180 }
00181 *outs += (nb_in_ch[0] + nb_in_ch[1]) * bps;
00182 }
00183 }
00184
00185 static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
00186 {
00187 AVFilterContext *ctx = inlink->dst;
00188 AMergeContext *am = ctx->priv;
00189 int input_number = inlink == ctx->inputs[1];
00190 struct amerge_queue *inq = &am->queue[input_number];
00191 int nb_samples, ns, i;
00192 AVFilterBufferRef *outbuf, **inbuf[2];
00193 uint8_t *ins[2], *outs;
00194
00195 if (inq->nb_buf == QUEUE_SIZE) {
00196 av_log(ctx, AV_LOG_ERROR, "Packet queue overflow; dropped\n");
00197 avfilter_unref_buffer(insamples);
00198 return;
00199 }
00200 inq->buf[inq->nb_buf++] = avfilter_ref_buffer(insamples, AV_PERM_READ |
00201 AV_PERM_PRESERVE);
00202 inq->nb_samples += insamples->audio->nb_samples;
00203 avfilter_unref_buffer(insamples);
00204 if (!am->queue[!input_number].nb_samples)
00205 return;
00206
00207 nb_samples = FFMIN(am->queue[0].nb_samples,
00208 am->queue[1].nb_samples);
00209 outbuf = avfilter_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE,
00210 nb_samples);
00211 outs = outbuf->data[0];
00212 for (i = 0; i < 2; i++) {
00213 inbuf[i] = am->queue[i].buf;
00214 ins[i] = (*inbuf[i])->data[0] +
00215 am->queue[i].pos * am->nb_in_ch[i] * am->bps;
00216 }
00217 while (nb_samples) {
00218 ns = nb_samples;
00219 for (i = 0; i < 2; i++)
00220 ns = FFMIN(ns, (*inbuf[i])->audio->nb_samples - am->queue[i].pos);
00221
00222
00223 switch (am->bps) {
00224 case 1:
00225 copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 1);
00226 break;
00227 case 2:
00228 copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 2);
00229 break;
00230 case 4:
00231 copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 4);
00232 break;
00233 default:
00234 copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, am->bps);
00235 break;
00236 }
00237
00238 nb_samples -= ns;
00239 for (i = 0; i < 2; i++) {
00240 am->queue[i].nb_samples -= ns;
00241 am->queue[i].pos += ns;
00242 if (am->queue[i].pos == (*inbuf[i])->audio->nb_samples) {
00243 am->queue[i].pos = 0;
00244 avfilter_unref_buffer(*inbuf[i]);
00245 *inbuf[i] = NULL;
00246 inbuf[i]++;
00247 ins[i] = *inbuf[i] ? (*inbuf[i])->data[0] : NULL;
00248 }
00249 }
00250 }
00251 for (i = 0; i < 2; i++) {
00252 int nbufused = inbuf[i] - am->queue[i].buf;
00253 if (nbufused) {
00254 am->queue[i].nb_buf -= nbufused;
00255 memmove(am->queue[i].buf, inbuf[i],
00256 am->queue[i].nb_buf * sizeof(**inbuf));
00257 }
00258 }
00259 avfilter_filter_samples(ctx->outputs[0], outbuf);
00260 }
00261
00262 AVFilter avfilter_af_amerge = {
00263 .name = "amerge",
00264 .description = NULL_IF_CONFIG_SMALL("Merge two audio streams into "
00265 "a single multi-channel stream."),
00266 .priv_size = sizeof(AMergeContext),
00267 .uninit = uninit,
00268 .query_formats = query_formats,
00269
00270 .inputs = (const AVFilterPad[]) {
00271 { .name = "in1",
00272 .type = AVMEDIA_TYPE_AUDIO,
00273 .filter_samples = filter_samples,
00274 .min_perms = AV_PERM_READ, },
00275 { .name = "in2",
00276 .type = AVMEDIA_TYPE_AUDIO,
00277 .filter_samples = filter_samples,
00278 .min_perms = AV_PERM_READ, },
00279 { .name = NULL }
00280 },
00281 .outputs = (const AVFilterPad[]) {
00282 { .name = "default",
00283 .type = AVMEDIA_TYPE_AUDIO,
00284 .config_props = config_output,
00285 .request_frame = request_frame, },
00286 { .name = NULL }
00287 },
00288 };