* qatar/master: vsrc_buffer: fix check from 7ae7c41. libxvid: Reorder functions to avoid forward declarations; make functions static. libxvid: drop some pointless dead code wmal: vertical alignment cosmetics wmal: Warn about missing bitstream splicing feature and ask for sample. wmal: Skip seekable_frame_in_packet. wmal: Drop unused variable num_possible_block_size. avfiltergraph: make the AVFilterInOut alloc/free API public graphparser: allow specifying sws flags in the graph description. graphparser: fix the order of connecting unlabeled links. graphparser: add avfilter_graph_parse2(). vsrc_buffer: allow using a NULL buffer to signal EOF. swscale: handle last pixel if lines have an odd width. qdm2: fix a dubious pointer cast WMAL: Do not try to read rawpcm coefficients if bits is invalid mov: Fix detecting there is no sync sample. tiffdec: K&R cosmetics avf: has_duration does not check the global one dsputil: fix optimized emu_edge function on Win64. Conflicts: doc/APIchanges libavcodec/libxvid_rc.c libavcodec/libxvidff.c libavcodec/tiff.c libavcodec/wmalosslessdec.c libavfilter/avfiltergraph.h libavfilter/graphparser.c libavfilter/version.h libavfilter/vsrc_buffer.c libswscale/output.c
Showing the changes to libavfilter/graphparser.c (1 of 18 files). Show all
Unified · Split
| @@ -189,13 +189,15 @@ static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links) · 188 unmodified lines | ||
| 189 | 189 | { |
| 190 | 190 | AVFilterInOut *ret; |
| 191 | 191 | |
| 192 | − while (*links && strcmp((*links)->name, label)) | |
| 192 | + while (*links && (!(*links)->name || strcmp((*links)->name, label))) | |
| 193 | 193 | links = &((*links)->next); |
| 194 | 194 | |
| 195 | 195 | ret = *links; |
| 196 | 196 | |
| 197 | − if (ret) | |
| 197 | + if (ret) { | |
| 198 | 198 | *links = ret->next; |
| 199 | + ret->next = NULL; | |
| 200 | + } | |
| 199 | 201 | |
| 200 | 202 | return ret; |
| 201 | 203 | } |
| @@ -206,22 +208,31 @@ static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element) · 4 unmodified lines | ||
| 206 | 208 | *inouts = element; |
| 207 | 209 | } |
| 208 | 210 | |
| 211 | +static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element) | |
| 212 | +{ | |
| 213 | + while (*inouts && (*inouts)->next) | |
| 214 | + inouts = &((*inouts)->next); | |
| 215 | + | |
| 216 | + if (!*inouts) | |
| 217 | + *inouts = *element; | |
| 218 | + else | |
| 219 | + (*inouts)->next = *element; | |
| 220 | + *element = NULL; | |
| 221 | +} | |
| 222 | + | |
| 209 | 223 | static int link_filter_inouts(AVFilterContext *filt_ctx, |
| 210 | 224 | AVFilterInOut **curr_inputs, |
| 211 | 225 | AVFilterInOut **open_inputs, void *log_ctx) |
| 212 | 226 | { |
| 213 | − int pad = filt_ctx->input_count, ret; | |
| 227 | + int pad, ret; | |
| 214 | 228 | |
| 215 | − while (pad--) { | |
| 229 | + for (pad = 0; pad < filt_ctx->input_count; pad++) { | |
| 216 | 230 | AVFilterInOut *p = *curr_inputs; |
| 217 | − if (!p) { | |
| 218 | − av_log(log_ctx, AV_LOG_ERROR, | |
| 219 | − "Not enough inputs specified for the \"%s\" filter.\n", | |
| 220 | − filt_ctx->filter->name); | |
| 221 | − return AVERROR(EINVAL); | |
| 222 | − } | |
| 223 | 231 | |
| 224 | − *curr_inputs = (*curr_inputs)->next; | |
| 232 | + if (p) | |
| 233 | + *curr_inputs = (*curr_inputs)->next; | |
| 234 | + else if (!(p = av_mallocz(sizeof(*p)))) | |
| 235 | + return AVERROR(ENOMEM); | |
| 225 | 236 | |
| 226 | 237 | if (p->filter_ctx) { |
| 227 | 238 | if ((ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx)) < 0) |
| @@ -258,6 +269,7 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, · 30 unmodified lines | ||
| 258 | 269 | static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, |
| 259 | 270 | AVFilterInOut **open_outputs, void *log_ctx) |
| 260 | 271 | { |
| 272 | + AVFilterInOut *parsed_inputs = NULL; | |
| 261 | 273 | int pad = 0; |
| 262 | 274 | |
| 263 | 275 | while (**buf == '[') { |
| @@ -280,12 +292,15 @@ static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, · 16 unmodified lines | ||
| 280 | 292 | match->pad_idx = pad; |
| 281 | 293 | } |
| 282 | 294 | |
| 283 | − insert_inout(curr_inputs, match); | |
| 295 | + append_inout(&parsed_inputs, &match); | |
| 284 | 296 | |
| 285 | 297 | *buf += strspn(*buf, WHITESPACES); |
| 286 | 298 | pad++; |
| 287 | 299 | } |
| 288 | 300 | |
| 301 | + append_inout(&parsed_inputs, curr_inputs); | |
| 302 | + *curr_inputs = parsed_inputs; | |
| 303 | + | |
| 289 | 304 | return pad; |
| 290 | 305 | } |
| 291 | 306 | |
| @@ -334,10 +349,173 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, · 42 unmodified lines | ||
| 334 | 349 | return pad; |
| 335 | 350 | } |
| 336 | 351 | |
| 352 | +#if FF_API_GRAPH_AVCLASS | |
| 353 | +#define log_ctx graph | |
| 354 | +#else | |
| 355 | +#define log_ctx NULL | |
| 356 | +#endif | |
| 357 | + | |
| 358 | +static int parse_sws_flags(const char **buf, AVFilterGraph *graph) | |
| 359 | +{ | |
| 360 | + char *p = strchr(*buf, ';'); | |
| 361 | + | |
| 362 | + if (strncmp(*buf, "sws_flags=", 10)) | |
| 363 | + return 0; | |
| 364 | + | |
| 365 | + if (!p) { | |
| 366 | + av_log(log_ctx, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n"); | |
| 367 | + return AVERROR(EINVAL); | |
| 368 | + } | |
| 369 | + | |
| 370 | + *buf += 4; // keep the 'flags=' part | |
| 371 | + | |
| 372 | + av_freep(&graph->scale_sws_opts); | |
| 373 | + if (!(graph->scale_sws_opts = av_mallocz(p - *buf + 1))) | |
| 374 | + return AVERROR(ENOMEM); | |
| 375 | + av_strlcpy(graph->scale_sws_opts, *buf, p - *buf + 1); | |
| 376 | + | |
| 377 | + *buf = p + 1; | |
| 378 | + return 0; | |
| 379 | +} | |
| 380 | + | |
| 381 | +int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, | |
| 382 | + AVFilterInOut **inputs, | |
| 383 | + AVFilterInOut **outputs) | |
| 384 | +{ | |
| 385 | + int index = 0, ret = 0; | |
| 386 | + char chr = 0; | |
| 387 | + | |
| 388 | + AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL; | |
| 389 | + | |
| 390 | + filters += strspn(filters, WHITESPACES); | |
| 391 | + | |
| 392 | + if ((ret = parse_sws_flags(&filters, graph)) < 0) | |
| 393 | + goto fail; | |
| 394 | + | |
| 395 | + do { | |
| 396 | + AVFilterContext *filter; | |
| 397 | + filters += strspn(filters, WHITESPACES); | |
| 398 | + | |
| 399 | + if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) | |
| 400 | + goto end; | |
| 401 | + | |
| 402 | + if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) | |
| 403 | + goto end; | |
| 404 | + | |
| 405 | + if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) | |
| 406 | + goto end; | |
| 407 | + | |
| 408 | + if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, | |
| 409 | + log_ctx)) < 0) | |
| 410 | + goto end; | |
| 411 | + | |
| 412 | + filters += strspn(filters, WHITESPACES); | |
| 413 | + chr = *filters++; | |
| 414 | + | |
| 415 | + if (chr == ';' && curr_inputs) | |
| 416 | + append_inout(&open_outputs, &curr_inputs); | |
| 417 | + index++; | |
| 418 | + } while (chr == ',' || chr == ';'); | |
| 419 | + | |
| 420 | + if (chr) { | |
| 421 | + av_log(log_ctx, AV_LOG_ERROR, | |
| 422 | + "Unable to parse graph description substring: \"%s\"\n", | |
| 423 | + filters - 1); | |
| 424 | + ret = AVERROR(EINVAL); | |
| 425 | + goto end; | |
| 426 | + } | |
| 427 | + | |
| 428 | + append_inout(&open_outputs, &curr_inputs); | |
| 429 | + | |
| 430 | + | |
| 431 | + *inputs = open_inputs; | |
| 432 | + *outputs = open_outputs; | |
| 433 | + return 0; | |
| 434 | + | |
| 435 | + fail:end: | |
| 436 | + for (; graph->filter_count > 0; graph->filter_count--) | |
| 437 | + avfilter_free(graph->filters[graph->filter_count - 1]); | |
| 438 | + av_freep(&graph->filters); | |
| 439 | + avfilter_inout_free(&open_inputs); | |
| 440 | + avfilter_inout_free(&open_outputs); | |
| 441 | + avfilter_inout_free(&curr_inputs); | |
| 442 | + | |
| 443 | + *inputs = NULL; | |
| 444 | + *outputs = NULL; | |
| 445 | + | |
| 446 | + return ret; | |
| 447 | +} | |
| 448 | +#undef log_ctx | |
| 449 | + | |
| 337 | 450 | int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, |
| 338 | 451 | AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, |
| 339 | 452 | void *log_ctx) |
| 340 | 453 | { |
| 454 | +#if 0 | |
| 455 | + int ret; | |
| 456 | + AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; | |
| 457 | + AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; | |
| 458 | + AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL; | |
| 459 | + | |
| 460 | + if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0) | |
| 461 | + goto fail; | |
| 462 | + | |
| 463 | + /* First input can be omitted if it is "[in]" */ | |
| 464 | + if (inputs && !inputs->name) | |
| 465 | + inputs->name = av_strdup("in"); | |
| 466 | + for (cur = inputs; cur; cur = cur->next) { | |
| 467 | + if (!cur->name) { | |
| 468 | + av_log(log_ctx, AV_LOG_ERROR, | |
| 469 | + "Not enough inputs specified for the \"%s\" filter.\n", | |
| 470 | + cur->filter_ctx->filter->name); | |
| 471 | + ret = AVERROR(EINVAL); | |
| 472 | + goto fail; | |
| 473 | + } | |
| 474 | + if (!(match = extract_inout(cur->name, &open_outputs))) | |
| 475 | + continue; | |
| 476 | + ret = avfilter_link(match->filter_ctx, match->pad_idx, | |
| 477 | + cur->filter_ctx, cur->pad_idx); | |
| 478 | + avfilter_inout_free(&match); | |
| 479 | + if (ret < 0) | |
| 480 | + goto fail; | |
| 481 | + } | |
| 482 | + | |
| 483 | + /* Last output can be omitted if it is "[out]" */ | |
| 484 | + if (outputs && !outputs->name) | |
| 485 | + outputs->name = av_strdup("out"); | |
| 486 | + for (cur = outputs; cur; cur = cur->next) { | |
| 487 | + if (!cur->name) { | |
| 488 | + av_log(log_ctx, AV_LOG_ERROR, | |
| 489 | + "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", | |
| 490 | + filters); | |
| 491 | + ret = AVERROR(EINVAL); | |
| 492 | + goto fail; | |
| 493 | + } | |
| 494 | + if (!(match = extract_inout(cur->name, &open_inputs))) | |
| 495 | + continue; | |
| 496 | + ret = avfilter_link(cur->filter_ctx, cur->pad_idx, | |
| 497 | + match->filter_ctx, match->pad_idx); | |
| 498 | + avfilter_inout_free(&match); | |
| 499 | + if (ret < 0) | |
| 500 | + goto fail; | |
| 501 | + } | |
| 502 | + | |
| 503 | + fail: | |
| 504 | + if (ret < 0) { | |
| 505 | + for (; graph->filter_count > 0; graph->filter_count--) | |
| 506 | + avfilter_free(graph->filters[graph->filter_count - 1]); | |
| 507 | + av_freep(&graph->filters); | |
| 508 | + } | |
| 509 | + avfilter_inout_free(&inputs); | |
| 510 | + avfilter_inout_free(&outputs); | |
| 511 | + /* clear open_in/outputs only if not passed as parameters */ | |
| 512 | + if (open_inputs_ptr) *open_inputs_ptr = open_inputs; | |
| 513 | + else avfilter_inout_free(&open_inputs); | |
| 514 | + if (open_outputs_ptr) *open_outputs_ptr = open_outputs; | |
| 515 | + else avfilter_inout_free(&open_outputs); | |
| 516 | + return ret; | |
| 517 | +} | |
| 518 | +#else | |
| 341 | 519 | int index = 0, ret = 0; |
| 342 | 520 | char chr = 0; |
| 343 | 521 | |
| @@ -414,3 +592,5 @@ end: · 70 unmodified lines | ||
| 414 | 592 | } |
| 415 | 593 | return ret; |
| 416 | 594 | } |
| 595 | + | |
| 596 | +#endif | |