00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <ctype.h>
00024 #include <string.h>
00025
00026 #include "libavutil/avassert.h"
00027 #include "libavutil/channel_layout.h"
00028 #include "libavutil/opt.h"
00029 #include "libavutil/pixdesc.h"
00030 #include "libavcodec/avcodec.h"
00031 #include "avfilter.h"
00032 #include "avfiltergraph.h"
00033 #include "formats.h"
00034 #include "internal.h"
00035
00036 #define OFFSET(x) offsetof(AVFilterGraph,x)
00037
00038 static const AVOption options[]={
00039 {"scale_sws_opts" , "default scale filter options" , OFFSET(scale_sws_opts) , AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 0 },
00040 {"aresample_swr_opts" , "default aresample filter options" , OFFSET(aresample_swr_opts) , AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 0 },
00041 {0}
00042 };
00043
00044
00045 static const AVClass filtergraph_class = {
00046 .class_name = "AVFilterGraph",
00047 .item_name = av_default_item_name,
00048 .option = options,
00049 .version = LIBAVUTIL_VERSION_INT,
00050 .category = AV_CLASS_CATEGORY_FILTER,
00051 };
00052
00053 AVFilterGraph *avfilter_graph_alloc(void)
00054 {
00055 AVFilterGraph *ret = av_mallocz(sizeof(AVFilterGraph));
00056 if (!ret)
00057 return NULL;
00058 ret->av_class = &filtergraph_class;
00059 return ret;
00060 }
00061
00062 void avfilter_graph_free(AVFilterGraph **graph)
00063 {
00064 if (!*graph)
00065 return;
00066 for (; (*graph)->filter_count > 0; (*graph)->filter_count--)
00067 avfilter_free((*graph)->filters[(*graph)->filter_count - 1]);
00068 av_freep(&(*graph)->sink_links);
00069 av_freep(&(*graph)->scale_sws_opts);
00070 av_freep(&(*graph)->aresample_swr_opts);
00071 av_freep(&(*graph)->filters);
00072 av_freep(graph);
00073 }
00074
00075 int avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter)
00076 {
00077 AVFilterContext **filters = av_realloc(graph->filters,
00078 sizeof(AVFilterContext*) * (graph->filter_count+1));
00079 if (!filters)
00080 return AVERROR(ENOMEM);
00081
00082 graph->filters = filters;
00083 graph->filters[graph->filter_count++] = filter;
00084
00085 return 0;
00086 }
00087
00088 int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt,
00089 const char *name, const char *args, void *opaque,
00090 AVFilterGraph *graph_ctx)
00091 {
00092 int ret;
00093
00094 if ((ret = avfilter_open(filt_ctx, filt, name)) < 0)
00095 goto fail;
00096 if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0)
00097 goto fail;
00098 if ((ret = avfilter_graph_add_filter(graph_ctx, *filt_ctx)) < 0)
00099 goto fail;
00100 return 0;
00101
00102 fail:
00103 if (*filt_ctx)
00104 avfilter_free(*filt_ctx);
00105 *filt_ctx = NULL;
00106 return ret;
00107 }
00108
00109 void avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags)
00110 {
00111 graph->disable_auto_convert = flags;
00112 }
00113
00122 static int graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx)
00123 {
00124 AVFilterContext *filt;
00125 int i, j;
00126
00127 for (i = 0; i < graph->filter_count; i++) {
00128 const AVFilterPad *pad;
00129 filt = graph->filters[i];
00130
00131 for (j = 0; j < filt->nb_inputs; j++) {
00132 if (!filt->inputs[j] || !filt->inputs[j]->src) {
00133 pad = &filt->input_pads[j];
00134 av_log(log_ctx, AV_LOG_ERROR,
00135 "Input pad \"%s\" with type %s of the filter instance \"%s\" of %s not connected to any source\n",
00136 pad->name, av_get_media_type_string(pad->type), filt->name, filt->filter->name);
00137 return AVERROR(EINVAL);
00138 }
00139 }
00140
00141 for (j = 0; j < filt->nb_outputs; j++) {
00142 if (!filt->outputs[j] || !filt->outputs[j]->dst) {
00143 pad = &filt->output_pads[j];
00144 av_log(log_ctx, AV_LOG_ERROR,
00145 "Output pad \"%s\" with type %s of the filter instance \"%s\" of %s not connected to any destination\n",
00146 pad->name, av_get_media_type_string(pad->type), filt->name, filt->filter->name);
00147 return AVERROR(EINVAL);
00148 }
00149 }
00150 }
00151
00152 return 0;
00153 }
00154
00160 static int graph_config_links(AVFilterGraph *graph, AVClass *log_ctx)
00161 {
00162 AVFilterContext *filt;
00163 int i, ret;
00164
00165 for (i=0; i < graph->filter_count; i++) {
00166 filt = graph->filters[i];
00167
00168 if (!filt->nb_outputs) {
00169 if ((ret = avfilter_config_links(filt)))
00170 return ret;
00171 }
00172 }
00173
00174 return 0;
00175 }
00176
00177 AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
00178 {
00179 int i;
00180
00181 for (i = 0; i < graph->filter_count; i++)
00182 if (graph->filters[i]->name && !strcmp(name, graph->filters[i]->name))
00183 return graph->filters[i];
00184
00185 return NULL;
00186 }
00187
00188 static int filter_query_formats(AVFilterContext *ctx)
00189 {
00190 int ret;
00191 AVFilterFormats *formats;
00192 AVFilterChannelLayouts *chlayouts;
00193 AVFilterFormats *samplerates;
00194 enum AVMediaType type = ctx->inputs && ctx->inputs [0] ? ctx->inputs [0]->type :
00195 ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type :
00196 AVMEDIA_TYPE_VIDEO;
00197
00198 if ((ret = ctx->filter->query_formats(ctx)) < 0)
00199 return ret;
00200
00201 formats = ff_all_formats(type);
00202 if (!formats)
00203 return AVERROR(ENOMEM);
00204 ff_set_common_formats(ctx, formats);
00205 if (type == AVMEDIA_TYPE_AUDIO) {
00206 samplerates = ff_all_samplerates();
00207 if (!samplerates)
00208 return AVERROR(ENOMEM);
00209 ff_set_common_samplerates(ctx, samplerates);
00210 chlayouts = ff_all_channel_layouts();
00211 if (!chlayouts)
00212 return AVERROR(ENOMEM);
00213 ff_set_common_channel_layouts(ctx, chlayouts);
00214 }
00215 return 0;
00216 }
00217
00218 static int insert_conv_filter(AVFilterGraph *graph, AVFilterLink *link,
00219 const char *filt_name, const char *filt_args)
00220 {
00221 static int auto_count = 0, ret;
00222 char inst_name[32];
00223 AVFilterContext *filt_ctx;
00224
00225 if (graph->disable_auto_convert) {
00226 av_log(NULL, AV_LOG_ERROR,
00227 "The filters '%s' and '%s' do not have a common format "
00228 "and automatic conversion is disabled.\n",
00229 link->src->name, link->dst->name);
00230 return AVERROR(EINVAL);
00231 }
00232
00233 snprintf(inst_name, sizeof(inst_name), "auto-inserted %s %d",
00234 filt_name, auto_count++);
00235
00236 if ((ret = avfilter_graph_create_filter(&filt_ctx,
00237 avfilter_get_by_name(filt_name),
00238 inst_name, filt_args, NULL, graph)) < 0)
00239 return ret;
00240 if ((ret = avfilter_insert_filter(link, filt_ctx, 0, 0)) < 0)
00241 return ret;
00242
00243 filter_query_formats(filt_ctx);
00244
00245 if ( ((link = filt_ctx-> inputs[0]) &&
00246 !ff_merge_formats(link->in_formats, link->out_formats)) ||
00247 ((link = filt_ctx->outputs[0]) &&
00248 !ff_merge_formats(link->in_formats, link->out_formats))
00249 ) {
00250 av_log(NULL, AV_LOG_ERROR,
00251 "Impossible to convert between the formats supported by the filter "
00252 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
00253 return AVERROR(EINVAL);
00254 }
00255
00256 if (link->type == AVMEDIA_TYPE_AUDIO &&
00257 (((link = filt_ctx-> inputs[0]) &&
00258 !ff_merge_channel_layouts(link->in_channel_layouts, link->out_channel_layouts)) ||
00259 ((link = filt_ctx->outputs[0]) &&
00260 !ff_merge_channel_layouts(link->in_channel_layouts, link->out_channel_layouts)))
00261 ) {
00262 av_log(NULL, AV_LOG_ERROR,
00263 "Impossible to convert between the channel layouts formats supported by the filter "
00264 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
00265 return AVERROR(EINVAL);
00266 }
00267
00268 return 0;
00269 }
00270
00271 static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
00272 {
00273 int i, j, ret;
00274 char filt_args[128];
00275 AVFilterFormats *formats;
00276 AVFilterChannelLayouts *chlayouts;
00277 AVFilterFormats *samplerates;
00278 int scaler_count = 0, resampler_count = 0;
00279
00280 for (j = 0; j < 2; j++) {
00281
00282 for (i = 0; i < graph->filter_count; i++) {
00283
00284
00285
00286 if (!graph->filters[i]->nb_inputs == j)
00287 continue;
00288 if (graph->filters[i]->filter->query_formats)
00289 ret = filter_query_formats(graph->filters[i]);
00290 else
00291 ret = ff_default_query_formats(graph->filters[i]);
00292 if (ret < 0)
00293 return ret;
00294 }
00295 }
00296
00297
00298 for (i = 0; i < graph->filter_count; i++) {
00299 AVFilterContext *filter = graph->filters[i];
00300
00301 for (j = 0; j < filter->nb_inputs; j++) {
00302 AVFilterLink *link = filter->inputs[j];
00303 #if 0
00304 if (!link) continue;
00305
00306 if (!link->in_formats || !link->out_formats)
00307 return AVERROR(EINVAL);
00308
00309 if (link->type == AVMEDIA_TYPE_VIDEO &&
00310 !ff_merge_formats(link->in_formats, link->out_formats)) {
00311
00312
00313 snprintf(filt_args, sizeof(filt_args), "0:0:%s",
00314 graph->scale_sws_opts);
00315 if (ret = insert_conv_filter(graph, link, "scale", filt_args))
00316 return ret;
00317 }
00318 else if (link->type == AVMEDIA_TYPE_AUDIO) {
00319 if (!link->in_channel_layouts || !link->out_channel_layouts)
00320 return AVERROR(EINVAL);
00321
00322
00323
00324
00325 formats = ff_merge_formats(link->in_formats, link->out_formats);
00326 chlayouts = ff_merge_channel_layouts(link->in_channel_layouts , link->out_channel_layouts);
00327 samplerates = ff_merge_samplerates (link->in_samplerates, link->out_samplerates);
00328
00329 if (!formats || !chlayouts || !samplerates)
00330 if (ret = insert_conv_filter(graph, link, "aresample", NULL))
00331 return ret;
00332 #else
00333 int convert_needed = 0;
00334
00335 if (!link)
00336 continue;
00337
00338 if (link->in_formats != link->out_formats &&
00339 !ff_merge_formats(link->in_formats,
00340 link->out_formats))
00341 convert_needed = 1;
00342 if (link->type == AVMEDIA_TYPE_AUDIO) {
00343 if (link->in_channel_layouts != link->out_channel_layouts &&
00344 !ff_merge_channel_layouts(link->in_channel_layouts,
00345 link->out_channel_layouts))
00346 convert_needed = 1;
00347 if (link->in_samplerates != link->out_samplerates &&
00348 !ff_merge_samplerates(link->in_samplerates,
00349 link->out_samplerates))
00350 convert_needed = 1;
00351 }
00352
00353 if (convert_needed) {
00354 AVFilterContext *convert;
00355 AVFilter *filter;
00356 AVFilterLink *inlink, *outlink;
00357 char scale_args[256];
00358 char inst_name[30];
00359
00360
00361 switch (link->type) {
00362 case AVMEDIA_TYPE_VIDEO:
00363 if (!(filter = avfilter_get_by_name("scale"))) {
00364 av_log(log_ctx, AV_LOG_ERROR, "'scale' filter "
00365 "not present, cannot convert pixel formats.\n");
00366 return AVERROR(EINVAL);
00367 }
00368
00369 snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d",
00370 scaler_count++);
00371 if (graph->scale_sws_opts)
00372 snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts);
00373 else
00374 snprintf(scale_args, sizeof(scale_args), "0:0");
00375
00376 if ((ret = avfilter_graph_create_filter(&convert, filter,
00377 inst_name, scale_args, NULL,
00378 graph)) < 0)
00379 return ret;
00380 break;
00381 case AVMEDIA_TYPE_AUDIO:
00382 if (!(filter = avfilter_get_by_name("aresample"))) {
00383 av_log(log_ctx, AV_LOG_ERROR, "'aresample' filter "
00384 "not present, cannot convert audio formats.\n");
00385 return AVERROR(EINVAL);
00386 }
00387
00388 snprintf(inst_name, sizeof(inst_name), "auto-inserted resampler %d",
00389 resampler_count++);
00390 if ((ret = avfilter_graph_create_filter(&convert, filter,
00391 inst_name, graph->aresample_swr_opts, NULL, graph)) < 0)
00392 return ret;
00393 break;
00394 default:
00395 return AVERROR(EINVAL);
00396 }
00397
00398 if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0)
00399 return ret;
00400
00401 filter_query_formats(convert);
00402 inlink = convert->inputs[0];
00403 outlink = convert->outputs[0];
00404 if (!ff_merge_formats( inlink->in_formats, inlink->out_formats) ||
00405 !ff_merge_formats(outlink->in_formats, outlink->out_formats))
00406 ret |= AVERROR(ENOSYS);
00407 if (inlink->type == AVMEDIA_TYPE_AUDIO &&
00408 (!ff_merge_samplerates(inlink->in_samplerates,
00409 inlink->out_samplerates) ||
00410 !ff_merge_channel_layouts(inlink->in_channel_layouts,
00411 inlink->out_channel_layouts)))
00412 ret |= AVERROR(ENOSYS);
00413 if (outlink->type == AVMEDIA_TYPE_AUDIO &&
00414 (!ff_merge_samplerates(outlink->in_samplerates,
00415 outlink->out_samplerates) ||
00416 !ff_merge_channel_layouts(outlink->in_channel_layouts,
00417 outlink->out_channel_layouts)))
00418 ret |= AVERROR(ENOSYS);
00419
00420 if (ret < 0) {
00421 av_log(log_ctx, AV_LOG_ERROR,
00422 "Impossible to convert between the formats supported by the filter "
00423 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
00424 return ret;
00425 }
00426 #endif
00427 }
00428 }
00429 }
00430
00431 return 0;
00432 }
00433
00434 static int pick_format(AVFilterLink *link, AVFilterLink *ref)
00435 {
00436 if (!link || !link->in_formats)
00437 return 0;
00438
00439 if (link->type == AVMEDIA_TYPE_VIDEO) {
00440 if(ref && ref->type == AVMEDIA_TYPE_VIDEO){
00441 int has_alpha= av_pix_fmt_desc_get(ref->format)->nb_components % 2 == 0;
00442 enum AVPixelFormat best= AV_PIX_FMT_NONE;
00443 int i;
00444 for (i=0; i<link->in_formats->format_count; i++) {
00445 enum AVPixelFormat p = link->in_formats->formats[i];
00446 best= avcodec_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL);
00447 }
00448 av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n",
00449 av_get_pix_fmt_name(best), link->in_formats->format_count,
00450 av_get_pix_fmt_name(ref->format), has_alpha);
00451 link->in_formats->formats[0] = best;
00452 }
00453 }
00454
00455 link->in_formats->format_count = 1;
00456 link->format = link->in_formats->formats[0];
00457
00458 if (link->type == AVMEDIA_TYPE_AUDIO) {
00459 if (!link->in_samplerates->format_count) {
00460 av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for"
00461 " the link between filters %s and %s.\n", link->src->name,
00462 link->dst->name);
00463 return AVERROR(EINVAL);
00464 }
00465 link->in_samplerates->format_count = 1;
00466 link->sample_rate = link->in_samplerates->formats[0];
00467
00468 if (!link->in_channel_layouts->nb_channel_layouts) {
00469 av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
00470 "the link between filters %s and %s.\n", link->src->name,
00471 link->dst->name);
00472 return AVERROR(EINVAL);
00473 }
00474 link->in_channel_layouts->nb_channel_layouts = 1;
00475 link->channel_layout = link->in_channel_layouts->channel_layouts[0];
00476 }
00477
00478 ff_formats_unref(&link->in_formats);
00479 ff_formats_unref(&link->out_formats);
00480 ff_formats_unref(&link->in_samplerates);
00481 ff_formats_unref(&link->out_samplerates);
00482 ff_channel_layouts_unref(&link->in_channel_layouts);
00483 ff_channel_layouts_unref(&link->out_channel_layouts);
00484
00485 return 0;
00486 }
00487
00488 #define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \
00489 do { \
00490 for (i = 0; i < filter->nb_inputs; i++) { \
00491 AVFilterLink *link = filter->inputs[i]; \
00492 fmt_type fmt; \
00493 \
00494 if (!link->out_ ## list || link->out_ ## list->nb != 1) \
00495 continue; \
00496 fmt = link->out_ ## list->var[0]; \
00497 \
00498 for (j = 0; j < filter->nb_outputs; j++) { \
00499 AVFilterLink *out_link = filter->outputs[j]; \
00500 list_type *fmts; \
00501 \
00502 if (link->type != out_link->type || \
00503 out_link->in_ ## list->nb == 1) \
00504 continue; \
00505 fmts = out_link->in_ ## list; \
00506 \
00507 if (!out_link->in_ ## list->nb) { \
00508 add_format(&out_link->in_ ##list, fmt); \
00509 break; \
00510 } \
00511 \
00512 for (k = 0; k < out_link->in_ ## list->nb; k++) \
00513 if (fmts->var[k] == fmt) { \
00514 fmts->var[0] = fmt; \
00515 fmts->nb = 1; \
00516 ret = 1; \
00517 break; \
00518 } \
00519 } \
00520 } \
00521 } while (0)
00522
00523 static int reduce_formats_on_filter(AVFilterContext *filter)
00524 {
00525 int i, j, k, ret = 0;
00526
00527 REDUCE_FORMATS(int, AVFilterFormats, formats, formats,
00528 format_count, ff_add_format);
00529 REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
00530 format_count, ff_add_format);
00531 REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
00532 channel_layouts, nb_channel_layouts, ff_add_channel_layout);
00533
00534 return ret;
00535 }
00536
00537 static void reduce_formats(AVFilterGraph *graph)
00538 {
00539 int i, reduced;
00540
00541 do {
00542 reduced = 0;
00543
00544 for (i = 0; i < graph->filter_count; i++)
00545 reduced |= reduce_formats_on_filter(graph->filters[i]);
00546 } while (reduced);
00547 }
00548
00549 static void swap_samplerates_on_filter(AVFilterContext *filter)
00550 {
00551 AVFilterLink *link = NULL;
00552 int sample_rate;
00553 int i, j;
00554
00555 for (i = 0; i < filter->nb_inputs; i++) {
00556 link = filter->inputs[i];
00557
00558 if (link->type == AVMEDIA_TYPE_AUDIO &&
00559 link->out_samplerates->format_count == 1)
00560 break;
00561 }
00562 if (i == filter->nb_inputs)
00563 return;
00564
00565 sample_rate = link->out_samplerates->formats[0];
00566
00567 for (i = 0; i < filter->nb_outputs; i++) {
00568 AVFilterLink *outlink = filter->outputs[i];
00569 int best_idx, best_diff = INT_MAX;
00570
00571 if (outlink->type != AVMEDIA_TYPE_AUDIO ||
00572 outlink->in_samplerates->format_count < 2)
00573 continue;
00574
00575 for (j = 0; j < outlink->in_samplerates->format_count; j++) {
00576 int diff = abs(sample_rate - outlink->in_samplerates->formats[j]);
00577
00578 if (diff < best_diff) {
00579 best_diff = diff;
00580 best_idx = j;
00581 }
00582 }
00583 FFSWAP(int, outlink->in_samplerates->formats[0],
00584 outlink->in_samplerates->formats[best_idx]);
00585 }
00586 }
00587
00588 static void swap_samplerates(AVFilterGraph *graph)
00589 {
00590 int i;
00591
00592 for (i = 0; i < graph->filter_count; i++)
00593 swap_samplerates_on_filter(graph->filters[i]);
00594 }
00595
00596 #define CH_CENTER_PAIR (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)
00597 #define CH_FRONT_PAIR (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)
00598 #define CH_STEREO_PAIR (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)
00599 #define CH_WIDE_PAIR (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT)
00600 #define CH_SIDE_PAIR (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)
00601 #define CH_DIRECT_PAIR (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)
00602 #define CH_BACK_PAIR (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)
00603
00604
00605
00606 static const uint64_t ch_subst[][2] = {
00607 { CH_FRONT_PAIR, CH_CENTER_PAIR },
00608 { CH_FRONT_PAIR, CH_WIDE_PAIR },
00609 { CH_FRONT_PAIR, AV_CH_FRONT_CENTER },
00610 { CH_CENTER_PAIR, CH_FRONT_PAIR },
00611 { CH_CENTER_PAIR, CH_WIDE_PAIR },
00612 { CH_CENTER_PAIR, AV_CH_FRONT_CENTER },
00613 { CH_WIDE_PAIR, CH_FRONT_PAIR },
00614 { CH_WIDE_PAIR, CH_CENTER_PAIR },
00615 { CH_WIDE_PAIR, AV_CH_FRONT_CENTER },
00616 { AV_CH_FRONT_CENTER, CH_FRONT_PAIR },
00617 { AV_CH_FRONT_CENTER, CH_CENTER_PAIR },
00618 { AV_CH_FRONT_CENTER, CH_WIDE_PAIR },
00619 { CH_SIDE_PAIR, CH_DIRECT_PAIR },
00620 { CH_SIDE_PAIR, CH_BACK_PAIR },
00621 { CH_SIDE_PAIR, AV_CH_BACK_CENTER },
00622 { CH_BACK_PAIR, CH_DIRECT_PAIR },
00623 { CH_BACK_PAIR, CH_SIDE_PAIR },
00624 { CH_BACK_PAIR, AV_CH_BACK_CENTER },
00625 { AV_CH_BACK_CENTER, CH_BACK_PAIR },
00626 { AV_CH_BACK_CENTER, CH_DIRECT_PAIR },
00627 { AV_CH_BACK_CENTER, CH_SIDE_PAIR },
00628 };
00629
00630 static void swap_channel_layouts_on_filter(AVFilterContext *filter)
00631 {
00632 AVFilterLink *link = NULL;
00633 int i, j, k;
00634
00635 for (i = 0; i < filter->nb_inputs; i++) {
00636 link = filter->inputs[i];
00637
00638 if (link->type == AVMEDIA_TYPE_AUDIO &&
00639 link->out_channel_layouts->nb_channel_layouts == 1)
00640 break;
00641 }
00642 if (i == filter->nb_inputs)
00643 return;
00644
00645 for (i = 0; i < filter->nb_outputs; i++) {
00646 AVFilterLink *outlink = filter->outputs[i];
00647 int best_idx = -1, best_score = INT_MIN, best_count_diff = INT_MAX;
00648
00649 if (outlink->type != AVMEDIA_TYPE_AUDIO ||
00650 outlink->in_channel_layouts->nb_channel_layouts < 2)
00651 continue;
00652
00653 for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
00654 uint64_t in_chlayout = link->out_channel_layouts->channel_layouts[0];
00655 uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
00656 int in_channels = av_get_channel_layout_nb_channels(in_chlayout);
00657 int out_channels = av_get_channel_layout_nb_channels(out_chlayout);
00658 int count_diff = out_channels - in_channels;
00659 int matched_channels, extra_channels;
00660 int score = 0;
00661
00662
00663 for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {
00664 uint64_t cmp0 = ch_subst[k][0];
00665 uint64_t cmp1 = ch_subst[k][1];
00666 if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) &&
00667 (out_chlayout & cmp1) && (!( in_chlayout & cmp1))) {
00668 in_chlayout &= ~cmp0;
00669 out_chlayout &= ~cmp1;
00670
00671
00672 score += 10 * av_get_channel_layout_nb_channels(cmp1) - 2;
00673 }
00674 }
00675
00676
00677 if ( (in_chlayout & AV_CH_LOW_FREQUENCY) &&
00678 (out_chlayout & AV_CH_LOW_FREQUENCY))
00679 score += 10;
00680 in_chlayout &= ~AV_CH_LOW_FREQUENCY;
00681 out_chlayout &= ~AV_CH_LOW_FREQUENCY;
00682
00683 matched_channels = av_get_channel_layout_nb_channels(in_chlayout &
00684 out_chlayout);
00685 extra_channels = av_get_channel_layout_nb_channels(out_chlayout &
00686 (~in_chlayout));
00687 score += 10 * matched_channels - 5 * extra_channels;
00688
00689 if (score > best_score ||
00690 (count_diff < best_count_diff && score == best_score)) {
00691 best_score = score;
00692 best_idx = j;
00693 best_count_diff = count_diff;
00694 }
00695 }
00696 av_assert0(best_idx >= 0);
00697 FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],
00698 outlink->in_channel_layouts->channel_layouts[best_idx]);
00699 }
00700
00701 }
00702
00703 static void swap_channel_layouts(AVFilterGraph *graph)
00704 {
00705 int i;
00706
00707 for (i = 0; i < graph->filter_count; i++)
00708 swap_channel_layouts_on_filter(graph->filters[i]);
00709 }
00710
00711 static void swap_sample_fmts_on_filter(AVFilterContext *filter)
00712 {
00713 AVFilterLink *link = NULL;
00714 int format, bps;
00715 int i, j;
00716
00717 for (i = 0; i < filter->nb_inputs; i++) {
00718 link = filter->inputs[i];
00719
00720 if (link->type == AVMEDIA_TYPE_AUDIO &&
00721 link->out_formats->format_count == 1)
00722 break;
00723 }
00724 if (i == filter->nb_inputs)
00725 return;
00726
00727 format = link->out_formats->formats[0];
00728 bps = av_get_bytes_per_sample(format);
00729
00730 for (i = 0; i < filter->nb_outputs; i++) {
00731 AVFilterLink *outlink = filter->outputs[i];
00732 int best_idx = -1, best_score = INT_MIN;
00733
00734 if (outlink->type != AVMEDIA_TYPE_AUDIO ||
00735 outlink->in_formats->format_count < 2)
00736 continue;
00737
00738 for (j = 0; j < outlink->in_formats->format_count; j++) {
00739 int out_format = outlink->in_formats->formats[j];
00740 int out_bps = av_get_bytes_per_sample(out_format);
00741 int score;
00742
00743 if (av_get_packed_sample_fmt(out_format) == format ||
00744 av_get_planar_sample_fmt(out_format) == format) {
00745 best_idx = j;
00746 break;
00747 }
00748
00749
00750 if (bps == 4 && out_bps == 8) {
00751 best_idx = j;
00752 break;
00753 }
00754
00755
00756 score = -abs(out_bps - bps);
00757 if (out_bps >= bps)
00758 score += INT_MAX/2;
00759
00760 if (score > best_score) {
00761 best_score = score;
00762 best_idx = j;
00763 }
00764 }
00765 av_assert0(best_idx >= 0);
00766 FFSWAP(int, outlink->in_formats->formats[0],
00767 outlink->in_formats->formats[best_idx]);
00768 }
00769 }
00770
00771 static void swap_sample_fmts(AVFilterGraph *graph)
00772 {
00773 int i;
00774
00775 for (i = 0; i < graph->filter_count; i++)
00776 swap_sample_fmts_on_filter(graph->filters[i]);
00777
00778 }
00779
00780 static int pick_formats(AVFilterGraph *graph)
00781 {
00782 int i, j, ret;
00783 int change;
00784
00785 do{
00786 change = 0;
00787 for (i = 0; i < graph->filter_count; i++) {
00788 AVFilterContext *filter = graph->filters[i];
00789 if (filter->nb_inputs){
00790 for (j = 0; j < filter->nb_inputs; j++){
00791 if(filter->inputs[j]->in_formats && filter->inputs[j]->in_formats->format_count == 1) {
00792 pick_format(filter->inputs[j], NULL);
00793 change = 1;
00794 }
00795 }
00796 }
00797 if (filter->nb_outputs){
00798 for (j = 0; j < filter->nb_outputs; j++){
00799 if(filter->outputs[j]->in_formats && filter->outputs[j]->in_formats->format_count == 1) {
00800 pick_format(filter->outputs[j], NULL);
00801 change = 1;
00802 }
00803 }
00804 }
00805 if (filter->nb_inputs && filter->nb_outputs && filter->inputs[0]->format>=0) {
00806 for (j = 0; j < filter->nb_outputs; j++) {
00807 if(filter->outputs[j]->format<0) {
00808 pick_format(filter->outputs[j], filter->inputs[0]);
00809 change = 1;
00810 }
00811 }
00812 }
00813 }
00814 }while(change);
00815
00816 for (i = 0; i < graph->filter_count; i++) {
00817 AVFilterContext *filter = graph->filters[i];
00818
00819 for (j = 0; j < filter->nb_inputs; j++)
00820 if ((ret = pick_format(filter->inputs[j], NULL)) < 0)
00821 return ret;
00822 for (j = 0; j < filter->nb_outputs; j++)
00823 if ((ret = pick_format(filter->outputs[j], NULL)) < 0)
00824 return ret;
00825 }
00826 return 0;
00827 }
00828
00832 static int graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
00833 {
00834 int ret;
00835
00836
00837 if ((ret = query_formats(graph, log_ctx)) < 0)
00838 return ret;
00839
00840
00841
00842
00843 reduce_formats(graph);
00844
00845
00846
00847 swap_sample_fmts(graph);
00848 swap_samplerates(graph);
00849 swap_channel_layouts(graph);
00850
00851 if ((ret = pick_formats(graph)) < 0)
00852 return ret;
00853
00854 return 0;
00855 }
00856
00857 static int ff_avfilter_graph_config_pointers(AVFilterGraph *graph,
00858 AVClass *log_ctx)
00859 {
00860 unsigned i, j;
00861 int sink_links_count = 0, n = 0;
00862 AVFilterContext *f;
00863 AVFilterLink **sinks;
00864
00865 for (i = 0; i < graph->filter_count; i++) {
00866 f = graph->filters[i];
00867 for (j = 0; j < f->nb_inputs; j++) {
00868 f->inputs[j]->graph = graph;
00869 f->inputs[j]->age_index = -1;
00870 }
00871 for (j = 0; j < f->nb_outputs; j++) {
00872 f->outputs[j]->graph = graph;
00873 f->outputs[j]->age_index= -1;
00874 }
00875 if (!f->nb_outputs) {
00876 if (f->nb_inputs > INT_MAX - sink_links_count)
00877 return AVERROR(EINVAL);
00878 sink_links_count += f->nb_inputs;
00879 }
00880 }
00881 sinks = av_calloc(sink_links_count, sizeof(*sinks));
00882 if (!sinks)
00883 return AVERROR(ENOMEM);
00884 for (i = 0; i < graph->filter_count; i++) {
00885 f = graph->filters[i];
00886 if (!f->nb_outputs) {
00887 for (j = 0; j < f->nb_inputs; j++) {
00888 sinks[n] = f->inputs[j];
00889 f->inputs[j]->age_index = n++;
00890 }
00891 }
00892 }
00893 av_assert0(n == sink_links_count);
00894 graph->sink_links = sinks;
00895 graph->sink_links_count = sink_links_count;
00896 return 0;
00897 }
00898
00899 static int graph_insert_fifos(AVFilterGraph *graph, AVClass *log_ctx)
00900 {
00901 AVFilterContext *f;
00902 int i, j, ret;
00903 int fifo_count = 0;
00904
00905 for (i = 0; i < graph->filter_count; i++) {
00906 f = graph->filters[i];
00907
00908 for (j = 0; j < f->nb_inputs; j++) {
00909 AVFilterLink *link = f->inputs[j];
00910 AVFilterContext *fifo_ctx;
00911 AVFilter *fifo;
00912 char name[32];
00913
00914 if (!link->dstpad->needs_fifo)
00915 continue;
00916
00917 fifo = f->inputs[j]->type == AVMEDIA_TYPE_VIDEO ?
00918 avfilter_get_by_name("fifo") :
00919 avfilter_get_by_name("afifo");
00920
00921 snprintf(name, sizeof(name), "auto-inserted fifo %d", fifo_count++);
00922
00923 ret = avfilter_graph_create_filter(&fifo_ctx, fifo, name, NULL,
00924 NULL, graph);
00925 if (ret < 0)
00926 return ret;
00927
00928 ret = avfilter_insert_filter(link, fifo_ctx, 0, 0);
00929 if (ret < 0)
00930 return ret;
00931 }
00932 }
00933
00934 return 0;
00935 }
00936
00937 int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
00938 {
00939 int ret;
00940
00941 if ((ret = graph_check_validity(graphctx, log_ctx)))
00942 return ret;
00943 if ((ret = graph_insert_fifos(graphctx, log_ctx)) < 0)
00944 return ret;
00945 if ((ret = graph_config_formats(graphctx, log_ctx)))
00946 return ret;
00947 if ((ret = graph_config_links(graphctx, log_ctx)))
00948 return ret;
00949 if ((ret = ff_avfilter_graph_config_pointers(graphctx, log_ctx)))
00950 return ret;
00951
00952 return 0;
00953 }
00954
00955 int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags)
00956 {
00957 int i, r = AVERROR(ENOSYS);
00958
00959 if(!graph)
00960 return r;
00961
00962 if((flags & AVFILTER_CMD_FLAG_ONE) && !(flags & AVFILTER_CMD_FLAG_FAST)) {
00963 r=avfilter_graph_send_command(graph, target, cmd, arg, res, res_len, flags | AVFILTER_CMD_FLAG_FAST);
00964 if(r != AVERROR(ENOSYS))
00965 return r;
00966 }
00967
00968 if(res_len && res)
00969 res[0]= 0;
00970
00971 for (i = 0; i < graph->filter_count; i++) {
00972 AVFilterContext *filter = graph->filters[i];
00973 if(!strcmp(target, "all") || (filter->name && !strcmp(target, filter->name)) || !strcmp(target, filter->filter->name)){
00974 r = avfilter_process_command(filter, cmd, arg, res, res_len, flags);
00975 if(r != AVERROR(ENOSYS)) {
00976 if((flags & AVFILTER_CMD_FLAG_ONE) || r<0)
00977 return r;
00978 }
00979 }
00980 }
00981
00982 return r;
00983 }
00984
00985 int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *command, const char *arg, int flags, double ts)
00986 {
00987 int i;
00988
00989 if(!graph)
00990 return 0;
00991
00992 for (i = 0; i < graph->filter_count; i++) {
00993 AVFilterContext *filter = graph->filters[i];
00994 if(filter && (!strcmp(target, "all") || !strcmp(target, filter->name) || !strcmp(target, filter->filter->name))){
00995 AVFilterCommand **que = &filter->command_queue, *next;
00996 while(*que && (*que)->time <= ts)
00997 que = &(*que)->next;
00998 next= *que;
00999 *que= av_mallocz(sizeof(AVFilterCommand));
01000 (*que)->command = av_strdup(command);
01001 (*que)->arg = av_strdup(arg);
01002 (*que)->time = ts;
01003 (*que)->flags = flags;
01004 (*que)->next = next;
01005 if(flags & AVFILTER_CMD_FLAG_ONE)
01006 return 0;
01007 }
01008 }
01009
01010 return 0;
01011 }
01012
01013 static void heap_bubble_up(AVFilterGraph *graph,
01014 AVFilterLink *link, int index)
01015 {
01016 AVFilterLink **links = graph->sink_links;
01017
01018 while (index) {
01019 int parent = (index - 1) >> 1;
01020 if (links[parent]->current_pts >= link->current_pts)
01021 break;
01022 links[index] = links[parent];
01023 links[index]->age_index = index;
01024 index = parent;
01025 }
01026 links[index] = link;
01027 link->age_index = index;
01028 }
01029
01030 static void heap_bubble_down(AVFilterGraph *graph,
01031 AVFilterLink *link, int index)
01032 {
01033 AVFilterLink **links = graph->sink_links;
01034
01035 while (1) {
01036 int child = 2 * index + 1;
01037 if (child >= graph->sink_links_count)
01038 break;
01039 if (child + 1 < graph->sink_links_count &&
01040 links[child + 1]->current_pts < links[child]->current_pts)
01041 child++;
01042 if (link->current_pts < links[child]->current_pts)
01043 break;
01044 links[index] = links[child];
01045 links[index]->age_index = index;
01046 index = child;
01047 }
01048 links[index] = link;
01049 link->age_index = index;
01050 }
01051
01052 void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link)
01053 {
01054 heap_bubble_up (graph, link, link->age_index);
01055 heap_bubble_down(graph, link, link->age_index);
01056 }
01057
01058
01059 int avfilter_graph_request_oldest(AVFilterGraph *graph)
01060 {
01061 while (graph->sink_links_count) {
01062 AVFilterLink *oldest = graph->sink_links[0];
01063 int r = ff_request_frame(oldest);
01064 if (r != AVERROR_EOF)
01065 return r;
01066 av_log(oldest->dst, AV_LOG_DEBUG, "EOF on sink link %s:%s.\n",
01067 oldest->dst ? oldest->dst->name : "unknown",
01068 oldest->dstpad ? oldest->dstpad->name : "unknown");
01069
01070 if (oldest->age_index < --graph->sink_links_count)
01071 heap_bubble_down(graph, graph->sink_links[graph->sink_links_count],
01072 oldest->age_index);
01073 oldest->age_index = -1;
01074 }
01075 return AVERROR_EOF;
01076 }