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/audioconvert.h"
00027 #include "libavutil/avassert.h"
00028 #include "libavutil/pixdesc.h"
00029 #include "avfilter.h"
00030 #include "avfiltergraph.h"
00031 #include "formats.h"
00032 #include "internal.h"
00033
00034 #include "libavutil/audioconvert.h"
00035 #include "libavutil/log.h"
00036
00037 static const AVClass filtergraph_class = {
00038 .class_name = "AVFilterGraph",
00039 .item_name = av_default_item_name,
00040 .version = LIBAVUTIL_VERSION_INT,
00041 };
00042
00043 AVFilterGraph *avfilter_graph_alloc(void)
00044 {
00045 AVFilterGraph *ret = av_mallocz(sizeof(AVFilterGraph));
00046 if (!ret)
00047 return NULL;
00048 #if FF_API_GRAPH_AVCLASS
00049 ret->av_class = &filtergraph_class;
00050 #endif
00051 return ret;
00052 }
00053
00054 void avfilter_graph_free(AVFilterGraph **graph)
00055 {
00056 if (!*graph)
00057 return;
00058 for (; (*graph)->filter_count > 0; (*graph)->filter_count--)
00059 avfilter_free((*graph)->filters[(*graph)->filter_count - 1]);
00060 av_freep(&(*graph)->sink_links);
00061 av_freep(&(*graph)->scale_sws_opts);
00062 av_freep(&(*graph)->filters);
00063 av_freep(graph);
00064 }
00065
00066 int avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter)
00067 {
00068 AVFilterContext **filters = av_realloc(graph->filters,
00069 sizeof(AVFilterContext*) * (graph->filter_count+1));
00070 if (!filters)
00071 return AVERROR(ENOMEM);
00072
00073 graph->filters = filters;
00074 graph->filters[graph->filter_count++] = filter;
00075
00076 return 0;
00077 }
00078
00079 int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt,
00080 const char *name, const char *args, void *opaque,
00081 AVFilterGraph *graph_ctx)
00082 {
00083 int ret;
00084
00085 if ((ret = avfilter_open(filt_ctx, filt, name)) < 0)
00086 goto fail;
00087 if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0)
00088 goto fail;
00089 if ((ret = avfilter_graph_add_filter(graph_ctx, *filt_ctx)) < 0)
00090 goto fail;
00091 return 0;
00092
00093 fail:
00094 if (*filt_ctx)
00095 avfilter_free(*filt_ctx);
00096 *filt_ctx = NULL;
00097 return ret;
00098 }
00099
00100 void avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags)
00101 {
00102 graph->disable_auto_convert = flags;
00103 }
00104
00105 int ff_avfilter_graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx)
00106 {
00107 AVFilterContext *filt;
00108 int i, j;
00109
00110 for (i = 0; i < graph->filter_count; i++) {
00111 filt = graph->filters[i];
00112
00113 for (j = 0; j < filt->input_count; j++) {
00114 if (!filt->inputs[j] || !filt->inputs[j]->src) {
00115 av_log(log_ctx, AV_LOG_ERROR,
00116 "Input pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any source\n",
00117 filt->input_pads[j].name, filt->name, filt->filter->name);
00118 return AVERROR(EINVAL);
00119 }
00120 }
00121
00122 for (j = 0; j < filt->output_count; j++) {
00123 if (!filt->outputs[j] || !filt->outputs[j]->dst) {
00124 av_log(log_ctx, AV_LOG_ERROR,
00125 "Output pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any destination\n",
00126 filt->output_pads[j].name, filt->name, filt->filter->name);
00127 return AVERROR(EINVAL);
00128 }
00129 }
00130 }
00131
00132 return 0;
00133 }
00134
00135 int ff_avfilter_graph_config_links(AVFilterGraph *graph, AVClass *log_ctx)
00136 {
00137 AVFilterContext *filt;
00138 int i, ret;
00139
00140 for (i=0; i < graph->filter_count; i++) {
00141 filt = graph->filters[i];
00142
00143 if (!filt->output_count) {
00144 if ((ret = avfilter_config_links(filt)))
00145 return ret;
00146 }
00147 }
00148
00149 return 0;
00150 }
00151
00152 AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
00153 {
00154 int i;
00155
00156 for (i = 0; i < graph->filter_count; i++)
00157 if (graph->filters[i]->name && !strcmp(name, graph->filters[i]->name))
00158 return graph->filters[i];
00159
00160 return NULL;
00161 }
00162
00163 static int insert_conv_filter(AVFilterGraph *graph, AVFilterLink *link,
00164 const char *filt_name, const char *filt_args)
00165 {
00166 static int auto_count = 0, ret;
00167 char inst_name[32];
00168 AVFilterContext *filt_ctx;
00169
00170 if (graph->disable_auto_convert) {
00171 av_log(NULL, AV_LOG_ERROR,
00172 "The filters '%s' and '%s' do not have a common format "
00173 "and automatic conversion is disabled.\n",
00174 link->src->name, link->dst->name);
00175 return AVERROR(EINVAL);
00176 }
00177
00178 snprintf(inst_name, sizeof(inst_name), "auto-inserted %s %d",
00179 filt_name, auto_count++);
00180
00181 if ((ret = avfilter_graph_create_filter(&filt_ctx,
00182 avfilter_get_by_name(filt_name),
00183 inst_name, filt_args, NULL, graph)) < 0)
00184 return ret;
00185 if ((ret = avfilter_insert_filter(link, filt_ctx, 0, 0)) < 0)
00186 return ret;
00187
00188 filt_ctx->filter->query_formats(filt_ctx);
00189
00190 if ( ((link = filt_ctx-> inputs[0]) &&
00191 !avfilter_merge_formats(link->in_formats, link->out_formats)) ||
00192 ((link = filt_ctx->outputs[0]) &&
00193 !avfilter_merge_formats(link->in_formats, link->out_formats))
00194 ) {
00195 av_log(NULL, AV_LOG_ERROR,
00196 "Impossible to convert between the formats supported by the filter "
00197 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
00198 return AVERROR(EINVAL);
00199 }
00200
00201 if (link->type == AVMEDIA_TYPE_AUDIO &&
00202 (((link = filt_ctx-> inputs[0]) &&
00203 !ff_merge_channel_layouts(link->in_channel_layouts, link->out_channel_layouts)) ||
00204 ((link = filt_ctx->outputs[0]) &&
00205 !ff_merge_channel_layouts(link->in_channel_layouts, link->out_channel_layouts)))
00206 ) {
00207 av_log(NULL, AV_LOG_ERROR,
00208 "Impossible to convert between the channel layouts formats supported by the filter "
00209 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
00210 return AVERROR(EINVAL);
00211 }
00212
00213 return 0;
00214 }
00215
00216 static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
00217 {
00218 int i, j, ret;
00219 char filt_args[128];
00220 AVFilterFormats *formats;
00221 AVFilterChannelLayouts *chlayouts;
00222 AVFilterFormats *samplerates;
00223 int scaler_count = 0, resampler_count = 0;
00224
00225
00226 for (i = 0; i < graph->filter_count; i++) {
00227 if (graph->filters[i]->filter->query_formats)
00228 graph->filters[i]->filter->query_formats(graph->filters[i]);
00229 else
00230 ff_default_query_formats(graph->filters[i]);
00231 }
00232
00233
00234 for (i = 0; i < graph->filter_count; i++) {
00235 AVFilterContext *filter = graph->filters[i];
00236
00237 for (j = 0; j < filter->input_count; j++) {
00238 AVFilterLink *link = filter->inputs[j];
00239 #if 0
00240 if (!link) continue;
00241
00242 if (!link->in_formats || !link->out_formats)
00243 return AVERROR(EINVAL);
00244
00245 if (link->type == AVMEDIA_TYPE_VIDEO &&
00246 !avfilter_merge_formats(link->in_formats, link->out_formats)) {
00247
00248
00249 snprintf(filt_args, sizeof(filt_args), "0:0:%s",
00250 graph->scale_sws_opts);
00251 if (ret = insert_conv_filter(graph, link, "scale", filt_args))
00252 return ret;
00253 }
00254 else if (link->type == AVMEDIA_TYPE_AUDIO) {
00255 if (!link->in_channel_layouts || !link->out_channel_layouts)
00256 return AVERROR(EINVAL);
00257
00258
00259
00260
00261 formats = avfilter_merge_formats(link->in_formats, link->out_formats);
00262 chlayouts = ff_merge_channel_layouts(link->in_channel_layouts , link->out_channel_layouts);
00263 samplerates = ff_merge_samplerates (link->in_samplerates, link->out_samplerates);
00264
00265 if (!formats || !chlayouts || !samplerates)
00266 if (ret = insert_conv_filter(graph, link, "aresample", NULL))
00267 return ret;
00268 #else
00269 int convert_needed = 0;
00270
00271 if (!link)
00272 continue;
00273
00274 if (link->in_formats != link->out_formats &&
00275 !avfilter_merge_formats(link->in_formats,
00276 link->out_formats))
00277 convert_needed = 1;
00278 if (link->type == AVMEDIA_TYPE_AUDIO) {
00279 if (link->in_channel_layouts != link->out_channel_layouts &&
00280 !ff_merge_channel_layouts(link->in_channel_layouts,
00281 link->out_channel_layouts))
00282 convert_needed = 1;
00283 if (link->in_samplerates != link->out_samplerates &&
00284 !ff_merge_samplerates(link->in_samplerates,
00285 link->out_samplerates))
00286 convert_needed = 1;
00287 }
00288
00289 if (convert_needed) {
00290 AVFilterContext *convert;
00291 AVFilter *filter;
00292 AVFilterLink *inlink, *outlink;
00293 char scale_args[256];
00294 char inst_name[30];
00295
00296
00297 switch (link->type) {
00298 case AVMEDIA_TYPE_VIDEO:
00299 snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d",
00300 scaler_count++);
00301 snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts);
00302 if ((ret = avfilter_graph_create_filter(&convert,
00303 avfilter_get_by_name("scale"),
00304 inst_name, scale_args, NULL,
00305 graph)) < 0)
00306 return ret;
00307 break;
00308 case AVMEDIA_TYPE_AUDIO:
00309 if (!(filter = avfilter_get_by_name("aresample"))) {
00310 av_log(log_ctx, AV_LOG_ERROR, "'resample' filter "
00311 "not present, cannot convert audio formats.\n");
00312 return AVERROR(EINVAL);
00313 }
00314
00315 snprintf(inst_name, sizeof(inst_name), "auto-inserted resampler %d",
00316 resampler_count++);
00317 if ((ret = avfilter_graph_create_filter(&convert,
00318 avfilter_get_by_name("aresample"),
00319 inst_name, NULL, NULL, graph)) < 0)
00320 return ret;
00321 break;
00322 default:
00323 return AVERROR(EINVAL);
00324 }
00325
00326 if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0)
00327 return ret;
00328
00329 convert->filter->query_formats(convert);
00330 inlink = convert->inputs[0];
00331 outlink = convert->outputs[0];
00332 if (!avfilter_merge_formats( inlink->in_formats, inlink->out_formats) ||
00333 !avfilter_merge_formats(outlink->in_formats, outlink->out_formats))
00334 ret |= AVERROR(ENOSYS);
00335 if (inlink->type == AVMEDIA_TYPE_AUDIO &&
00336 (!ff_merge_samplerates(inlink->in_samplerates,
00337 inlink->out_samplerates) ||
00338 !ff_merge_channel_layouts(inlink->in_channel_layouts,
00339 inlink->out_channel_layouts)))
00340 ret |= AVERROR(ENOSYS);
00341 if (outlink->type == AVMEDIA_TYPE_AUDIO &&
00342 (!ff_merge_samplerates(outlink->in_samplerates,
00343 outlink->out_samplerates) ||
00344 !ff_merge_channel_layouts(outlink->in_channel_layouts,
00345 outlink->out_channel_layouts)))
00346 ret |= AVERROR(ENOSYS);
00347
00348 if (ret < 0) {
00349 av_log(log_ctx, AV_LOG_ERROR,
00350 "Impossible to convert between the formats supported by the filter "
00351 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
00352 return ret;
00353 }
00354 #endif
00355 }
00356 }
00357 }
00358
00359 return 0;
00360 }
00361
00362 static int pick_format(AVFilterLink *link, AVFilterLink *ref)
00363 {
00364 if (!link || !link->in_formats)
00365 return 0;
00366
00367 if (link->type == AVMEDIA_TYPE_VIDEO) {
00368 if(ref && ref->type == AVMEDIA_TYPE_VIDEO){
00369 int has_alpha= av_pix_fmt_descriptors[ref->format].nb_components % 2 == 0;
00370 enum PixelFormat best= PIX_FMT_NONE;
00371 int i;
00372 for (i=0; i<link->in_formats->format_count; i++) {
00373 enum PixelFormat p = link->in_formats->formats[i];
00374 best= avcodec_find_best_pix_fmt2(best, p, ref->format, has_alpha, NULL);
00375 }
00376 link->in_formats->formats[0] = best;
00377 }
00378 }
00379
00380 link->in_formats->format_count = 1;
00381 link->format = link->in_formats->formats[0];
00382
00383 if (link->type == AVMEDIA_TYPE_AUDIO) {
00384 if (!link->in_samplerates->format_count) {
00385 av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for"
00386 " the link between filters %s and %s.\n", link->src->name,
00387 link->dst->name);
00388 return AVERROR(EINVAL);
00389 }
00390 link->in_samplerates->format_count = 1;
00391 link->sample_rate = link->in_samplerates->formats[0];
00392
00393 if (!link->in_channel_layouts->nb_channel_layouts) {
00394 av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
00395 "the link between filters %s and %s.\n", link->src->name,
00396 link->dst->name);
00397 return AVERROR(EINVAL);
00398 }
00399 link->in_channel_layouts->nb_channel_layouts = 1;
00400 link->channel_layout = link->in_channel_layouts->channel_layouts[0];
00401 }
00402
00403 avfilter_formats_unref(&link->in_formats);
00404 avfilter_formats_unref(&link->out_formats);
00405 avfilter_formats_unref(&link->in_samplerates);
00406 avfilter_formats_unref(&link->out_samplerates);
00407 ff_channel_layouts_unref(&link->in_channel_layouts);
00408 ff_channel_layouts_unref(&link->out_channel_layouts);
00409
00410 return 0;
00411 }
00412
00413 #define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \
00414 do { \
00415 for (i = 0; i < filter->input_count; i++) { \
00416 AVFilterLink *link = filter->inputs[i]; \
00417 fmt_type fmt; \
00418 \
00419 if (!link->out_ ## list || link->out_ ## list->nb != 1) \
00420 continue; \
00421 fmt = link->out_ ## list->var[0]; \
00422 \
00423 for (j = 0; j < filter->output_count; j++) { \
00424 AVFilterLink *out_link = filter->outputs[j]; \
00425 list_type *fmts; \
00426 \
00427 if (link->type != out_link->type || \
00428 out_link->in_ ## list->nb == 1) \
00429 continue; \
00430 fmts = out_link->in_ ## list; \
00431 \
00432 if (!out_link->in_ ## list->nb) { \
00433 add_format(&out_link->in_ ##list, fmt); \
00434 break; \
00435 } \
00436 \
00437 for (k = 0; k < out_link->in_ ## list->nb; k++) \
00438 if (fmts->var[k] == fmt) { \
00439 fmts->var[0] = fmt; \
00440 fmts->nb = 1; \
00441 ret = 1; \
00442 break; \
00443 } \
00444 } \
00445 } \
00446 } while (0)
00447
00448 static int reduce_formats_on_filter(AVFilterContext *filter)
00449 {
00450 int i, j, k, ret = 0;
00451
00452 REDUCE_FORMATS(int, AVFilterFormats, formats, formats,
00453 format_count, avfilter_add_format);
00454 REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
00455 format_count, avfilter_add_format);
00456 REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
00457 channel_layouts, nb_channel_layouts, ff_add_channel_layout);
00458
00459 return ret;
00460 }
00461
00462 static void reduce_formats(AVFilterGraph *graph)
00463 {
00464 int i, reduced;
00465
00466 do {
00467 reduced = 0;
00468
00469 for (i = 0; i < graph->filter_count; i++)
00470 reduced |= reduce_formats_on_filter(graph->filters[i]);
00471 } while (reduced);
00472 }
00473
00474 static void swap_samplerates_on_filter(AVFilterContext *filter)
00475 {
00476 AVFilterLink *link = NULL;
00477 int sample_rate;
00478 int i, j;
00479
00480 for (i = 0; i < filter->input_count; i++) {
00481 link = filter->inputs[i];
00482
00483 if (link->type == AVMEDIA_TYPE_AUDIO &&
00484 link->out_samplerates->format_count == 1)
00485 break;
00486 }
00487 if (i == filter->input_count)
00488 return;
00489
00490 sample_rate = link->out_samplerates->formats[0];
00491
00492 for (i = 0; i < filter->output_count; i++) {
00493 AVFilterLink *outlink = filter->outputs[i];
00494 int best_idx, best_diff = INT_MAX;
00495
00496 if (outlink->type != AVMEDIA_TYPE_AUDIO ||
00497 outlink->in_samplerates->format_count < 2)
00498 continue;
00499
00500 for (j = 0; j < outlink->in_samplerates->format_count; j++) {
00501 int diff = abs(sample_rate - outlink->in_samplerates->formats[j]);
00502
00503 if (diff < best_diff) {
00504 best_diff = diff;
00505 best_idx = j;
00506 }
00507 }
00508 FFSWAP(int, outlink->in_samplerates->formats[0],
00509 outlink->in_samplerates->formats[best_idx]);
00510 }
00511 }
00512
00513 static void swap_samplerates(AVFilterGraph *graph)
00514 {
00515 int i;
00516
00517 for (i = 0; i < graph->filter_count; i++)
00518 swap_samplerates_on_filter(graph->filters[i]);
00519 }
00520
00521 static void swap_channel_layouts_on_filter(AVFilterContext *filter)
00522 {
00523 AVFilterLink *link = NULL;
00524 uint64_t chlayout;
00525 int i, j;
00526
00527 for (i = 0; i < filter->input_count; i++) {
00528 link = filter->inputs[i];
00529
00530 if (link->type == AVMEDIA_TYPE_AUDIO &&
00531 link->out_channel_layouts->nb_channel_layouts == 1)
00532 break;
00533 }
00534 if (i == filter->input_count)
00535 return;
00536
00537 chlayout = link->out_channel_layouts->channel_layouts[0];
00538
00539 for (i = 0; i < filter->output_count; i++) {
00540 AVFilterLink *outlink = filter->outputs[i];
00541 int best_idx, best_score = INT_MIN;
00542
00543 if (outlink->type != AVMEDIA_TYPE_AUDIO ||
00544 outlink->in_channel_layouts->nb_channel_layouts < 2)
00545 continue;
00546
00547 for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
00548 uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
00549 int matched_channels = av_get_channel_layout_nb_channels(chlayout &
00550 out_chlayout);
00551 int extra_channels = av_get_channel_layout_nb_channels(out_chlayout &
00552 (~chlayout));
00553 int score = matched_channels - extra_channels;
00554
00555 if (score > best_score) {
00556 best_score = score;
00557 best_idx = j;
00558 }
00559 }
00560 FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],
00561 outlink->in_channel_layouts->channel_layouts[best_idx]);
00562 }
00563
00564 }
00565
00566 static void swap_channel_layouts(AVFilterGraph *graph)
00567 {
00568 int i;
00569
00570 for (i = 0; i < graph->filter_count; i++)
00571 swap_channel_layouts_on_filter(graph->filters[i]);
00572 }
00573
00574 static void swap_sample_fmts_on_filter(AVFilterContext *filter)
00575 {
00576 AVFilterLink *link = NULL;
00577 int format, bps;
00578 int i, j;
00579
00580 for (i = 0; i < filter->input_count; i++) {
00581 link = filter->inputs[i];
00582
00583 if (link->type == AVMEDIA_TYPE_AUDIO &&
00584 link->out_formats->format_count == 1)
00585 break;
00586 }
00587 if (i == filter->input_count)
00588 return;
00589
00590 format = link->out_formats->formats[0];
00591 bps = av_get_bytes_per_sample(format);
00592
00593 for (i = 0; i < filter->output_count; i++) {
00594 AVFilterLink *outlink = filter->outputs[i];
00595 int best_idx, best_score = INT_MIN;
00596
00597 if (outlink->type != AVMEDIA_TYPE_AUDIO ||
00598 outlink->in_formats->format_count < 2)
00599 continue;
00600
00601 for (j = 0; j < outlink->in_formats->format_count; j++) {
00602 int out_format = outlink->in_formats->formats[j];
00603 int out_bps = av_get_bytes_per_sample(out_format);
00604 int score;
00605
00606 if (av_get_packed_sample_fmt(out_format) == format ||
00607 av_get_planar_sample_fmt(out_format) == format) {
00608 best_idx = j;
00609 break;
00610 }
00611
00612
00613 if (bps == 4 && out_bps == 8) {
00614 best_idx = j;
00615 break;
00616 }
00617
00618
00619 score = -abs(out_bps - bps);
00620 if (out_bps >= bps)
00621 score += INT_MAX/2;
00622
00623 if (score > best_score) {
00624 best_score = score;
00625 best_idx = j;
00626 }
00627 }
00628 FFSWAP(int, outlink->in_formats->formats[0],
00629 outlink->in_formats->formats[best_idx]);
00630 }
00631 }
00632
00633 static void swap_sample_fmts(AVFilterGraph *graph)
00634 {
00635 int i;
00636
00637 for (i = 0; i < graph->filter_count; i++)
00638 swap_sample_fmts_on_filter(graph->filters[i]);
00639
00640 }
00641
00642 static int pick_formats(AVFilterGraph *graph)
00643 {
00644 int i, j, ret;
00645 int change;
00646
00647 do{
00648 change = 0;
00649 for (i = 0; i < graph->filter_count; i++) {
00650 AVFilterContext *filter = graph->filters[i];
00651 if (filter->input_count){
00652 for (j = 0; j < filter->input_count; j++){
00653 if(filter->inputs[j]->in_formats && filter->inputs[j]->in_formats->format_count == 1) {
00654 pick_format(filter->inputs[j], NULL);
00655 change = 1;
00656 }
00657 }
00658 }
00659 if (filter->output_count){
00660 for (j = 0; j < filter->output_count; j++){
00661 if(filter->outputs[j]->in_formats && filter->outputs[j]->in_formats->format_count == 1) {
00662 pick_format(filter->outputs[j], NULL);
00663 change = 1;
00664 }
00665 }
00666 }
00667 if (filter->input_count && filter->output_count && filter->inputs[0]->format>=0) {
00668 for (j = 0; j < filter->output_count; j++) {
00669 if(filter->outputs[j]->format<0) {
00670 pick_format(filter->outputs[j], filter->inputs[0]);
00671 change = 1;
00672 }
00673 }
00674 }
00675 }
00676 }while(change);
00677
00678 for (i = 0; i < graph->filter_count; i++) {
00679 AVFilterContext *filter = graph->filters[i];
00680
00681 for (j = 0; j < filter->input_count; j++)
00682 if ((ret = pick_format(filter->inputs[j], NULL)) < 0)
00683 return ret;
00684 for (j = 0; j < filter->output_count; j++)
00685 if ((ret = pick_format(filter->outputs[j], NULL)) < 0)
00686 return ret;
00687 }
00688 return 0;
00689 }
00690
00691 int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
00692 {
00693 int ret;
00694
00695
00696 if ((ret = query_formats(graph, log_ctx)) < 0)
00697 return ret;
00698
00699
00700
00701
00702 reduce_formats(graph);
00703
00704
00705
00706 swap_sample_fmts(graph);
00707 swap_samplerates(graph);
00708 swap_channel_layouts(graph);
00709
00710 if ((ret = pick_formats(graph)) < 0)
00711 return ret;
00712
00713 return 0;
00714 }
00715
00716 static int ff_avfilter_graph_config_pointers(AVFilterGraph *graph,
00717 AVClass *log_ctx)
00718 {
00719 unsigned i, j;
00720 int sink_links_count = 0, n = 0;
00721 AVFilterContext *f;
00722 AVFilterLink **sinks;
00723
00724 for (i = 0; i < graph->filter_count; i++) {
00725 f = graph->filters[i];
00726 for (j = 0; j < f->input_count; j++) {
00727 f->inputs[j]->graph = graph;
00728 f->inputs[j]->age_index = -1;
00729 }
00730 for (j = 0; j < f->output_count; j++) {
00731 f->outputs[j]->graph = graph;
00732 f->outputs[j]->age_index= -1;
00733 }
00734 if (!f->output_count) {
00735 if (f->input_count > INT_MAX - sink_links_count)
00736 return AVERROR(EINVAL);
00737 sink_links_count += f->input_count;
00738 }
00739 }
00740 sinks = av_calloc(sink_links_count, sizeof(*sinks));
00741 if (!sinks)
00742 return AVERROR(ENOMEM);
00743 for (i = 0; i < graph->filter_count; i++) {
00744 f = graph->filters[i];
00745 if (!f->output_count) {
00746 for (j = 0; j < f->input_count; j++) {
00747 sinks[n] = f->inputs[j];
00748 f->inputs[j]->age_index = n++;
00749 }
00750 }
00751 }
00752 av_assert0(n == sink_links_count);
00753 graph->sink_links = sinks;
00754 graph->sink_links_count = sink_links_count;
00755 return 0;
00756 }
00757
00758 int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
00759 {
00760 int ret;
00761
00762 if ((ret = ff_avfilter_graph_check_validity(graphctx, log_ctx)))
00763 return ret;
00764 if ((ret = ff_avfilter_graph_config_formats(graphctx, log_ctx)))
00765 return ret;
00766 if ((ret = ff_avfilter_graph_config_links(graphctx, log_ctx)))
00767 return ret;
00768 if ((ret = ff_avfilter_graph_config_pointers(graphctx, log_ctx)))
00769 return ret;
00770
00771 return 0;
00772 }
00773
00774 int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags)
00775 {
00776 int i, r = AVERROR(ENOSYS);
00777
00778 if(!graph)
00779 return r;
00780
00781 if((flags & AVFILTER_CMD_FLAG_ONE) && !(flags & AVFILTER_CMD_FLAG_FAST)) {
00782 r=avfilter_graph_send_command(graph, target, cmd, arg, res, res_len, flags | AVFILTER_CMD_FLAG_FAST);
00783 if(r != AVERROR(ENOSYS))
00784 return r;
00785 }
00786
00787 if(res_len && res)
00788 res[0]= 0;
00789
00790 for (i = 0; i < graph->filter_count; i++) {
00791 AVFilterContext *filter = graph->filters[i];
00792 if(!strcmp(target, "all") || (filter->name && !strcmp(target, filter->name)) || !strcmp(target, filter->filter->name)){
00793 r = avfilter_process_command(filter, cmd, arg, res, res_len, flags);
00794 if(r != AVERROR(ENOSYS)) {
00795 if((flags & AVFILTER_CMD_FLAG_ONE) || r<0)
00796 return r;
00797 }
00798 }
00799 }
00800
00801 return r;
00802 }
00803
00804 int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *command, const char *arg, int flags, double ts)
00805 {
00806 int i;
00807
00808 if(!graph)
00809 return 0;
00810
00811 for (i = 0; i < graph->filter_count; i++) {
00812 AVFilterContext *filter = graph->filters[i];
00813 if(filter && (!strcmp(target, "all") || !strcmp(target, filter->name) || !strcmp(target, filter->filter->name))){
00814 AVFilterCommand **que = &filter->command_queue, *next;
00815 while(*que && (*que)->time <= ts)
00816 que = &(*que)->next;
00817 next= *que;
00818 *que= av_mallocz(sizeof(AVFilterCommand));
00819 (*que)->command = av_strdup(command);
00820 (*que)->arg = av_strdup(arg);
00821 (*que)->time = ts;
00822 (*que)->flags = flags;
00823 (*que)->next = next;
00824 if(flags & AVFILTER_CMD_FLAG_ONE)
00825 return 0;
00826 }
00827 }
00828
00829 return 0;
00830 }
00831
00832 static void heap_bubble_up(AVFilterGraph *graph,
00833 AVFilterLink *link, int index)
00834 {
00835 AVFilterLink **links = graph->sink_links;
00836
00837 while (index) {
00838 int parent = (index - 1) >> 1;
00839 if (links[parent]->current_pts >= link->current_pts)
00840 break;
00841 links[index] = links[parent];
00842 links[index]->age_index = index;
00843 index = parent;
00844 }
00845 links[index] = link;
00846 link->age_index = index;
00847 }
00848
00849 static void heap_bubble_down(AVFilterGraph *graph,
00850 AVFilterLink *link, int index)
00851 {
00852 AVFilterLink **links = graph->sink_links;
00853
00854 while (1) {
00855 int child = 2 * index + 1;
00856 if (child >= graph->sink_links_count)
00857 break;
00858 if (child + 1 < graph->sink_links_count &&
00859 links[child + 1]->current_pts < links[child]->current_pts)
00860 child++;
00861 if (link->current_pts < links[child]->current_pts)
00862 break;
00863 links[index] = links[child];
00864 links[index]->age_index = index;
00865 index = child;
00866 }
00867 links[index] = link;
00868 link->age_index = index;
00869 }
00870
00871 void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link)
00872 {
00873 heap_bubble_up (graph, link, link->age_index);
00874 heap_bubble_down(graph, link, link->age_index);
00875 }
00876
00877
00878 int avfilter_graph_request_oldest(AVFilterGraph *graph)
00879 {
00880 while (graph->sink_links_count) {
00881 AVFilterLink *oldest = graph->sink_links[0];
00882 int r = avfilter_request_frame(oldest);
00883 if (r != AVERROR_EOF)
00884 return r;
00885
00886 if (oldest->age_index < --graph->sink_links_count)
00887 heap_bubble_down(graph, graph->sink_links[graph->sink_links_count],
00888 oldest->age_index);
00889 oldest->age_index = -1;
00890 }
00891 return AVERROR_EOF;
00892 }