Browse code

lavfi/overlay: switch to filter_frame API

Stefano Sabatini authored on 2012/12/08 23:15:20
Showing 1 changed files
... ...
@@ -294,26 +294,24 @@ static int config_output(AVFilterLink *outlink)
294 294
 // ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)) is a faster version of: 255 * (x + y)
295 295
 #define UNPREMULTIPLY_ALPHA(x, y) ((((x) << 16) - ((x) << 9) + (x)) / ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)))
296 296
 
297
-static void blend_slice(AVFilterContext *ctx,
297
+/**
298
+ * Blend image in src to destination buffer dst at position (x, y).
299
+ *
300
+ * It is assumed that the src image at position (x, y) is contained in
301
+ * dst.
302
+ */
303
+static void blend_image(AVFilterContext *ctx,
298 304
                         AVFilterBufferRef *dst, AVFilterBufferRef *src,
299
-                        int x, int y, int w, int h,
300
-                        int slice_y, int slice_w, int slice_h)
305
+                        int x, int y)
301 306
 {
302 307
     OverlayContext *over = ctx->priv;
303 308
     int i, j, k;
304
-    int width, height;
305
-    int overlay_end_y = y+h;
306
-    int slice_end_y = slice_y+slice_h;
307
-    int end_y, start_y;
308
-
309
-    width = FFMIN(slice_w - x, w);
310
-    end_y = FFMIN(slice_end_y, overlay_end_y);
311
-    start_y = FFMAX(y, slice_y);
312
-    height = end_y - start_y;
309
+    int width   = src->video->w;
310
+    int height  = src->video->h;
313 311
 
314 312
     if (over->main_is_packed_rgb) {
315 313
         uint8_t *dp = dst->data[0] + x * over->main_pix_step[0] +
316
-                      start_y * dst->linesize[0];
314
+                      y * dst->linesize[0];
317 315
         uint8_t *sp = src->data[0];
318 316
         uint8_t alpha;          ///< the amount of overlay to blend on to main
319 317
         const int dr = over->main_rgba_map[R];
... ...
@@ -327,8 +325,6 @@ static void blend_slice(AVFilterContext *ctx,
327 327
         const int sa = over->overlay_rgba_map[A];
328 328
         const int sstep = over->overlay_pix_step[0];
329 329
         const int main_has_alpha = over->main_has_alpha;
330
-        if (slice_y > y)
331
-            sp += (slice_y - y) * src->linesize[0];
332 330
         for (i = 0; i < height; i++) {
333 331
             uint8_t *d = dp, *s = sp;
334 332
             for (j = 0; j < width; j++) {
... ...
@@ -378,11 +374,9 @@ static void blend_slice(AVFilterContext *ctx,
378 378
         const int main_has_alpha = over->main_has_alpha;
379 379
         if (main_has_alpha) {
380 380
             uint8_t *da = dst->data[3] + x * over->main_pix_step[3] +
381
-                          start_y * dst->linesize[3];
381
+                          y * dst->linesize[3];
382 382
             uint8_t *sa = src->data[3];
383 383
             uint8_t alpha;          ///< the amount of overlay to blend on to main
384
-            if (slice_y > y)
385
-                sa += (slice_y - y) * src->linesize[3];
386 384
             for (i = 0; i < height; i++) {
387 385
                 uint8_t *d = da, *s = sa;
388 386
                 for (j = 0; j < width; j++) {
... ...
@@ -412,15 +406,11 @@ static void blend_slice(AVFilterContext *ctx,
412 412
             int hsub = i ? over->hsub : 0;
413 413
             int vsub = i ? over->vsub : 0;
414 414
             uint8_t *dp = dst->data[i] + (x >> hsub) +
415
-                (start_y >> vsub) * dst->linesize[i];
415
+                (y >> vsub) * dst->linesize[i];
416 416
             uint8_t *sp = src->data[i];
417 417
             uint8_t *ap = src->data[3];
418 418
             int wp = FFALIGN(width, 1<<hsub) >> hsub;
419 419
             int hp = FFALIGN(height, 1<<vsub) >> vsub;
420
-            if (slice_y > y) {
421
-                sp += ((slice_y - y) >> vsub) * src->linesize[i];
422
-                ap += (slice_y - y) * src->linesize[3];
423
-            }
424 420
             for (j = 0; j < hp; j++) {
425 421
                 uint8_t *d = dp, *s = sp, *a = ap;
426 422
                 for (k = 0; k < wp; k++) {
... ...
@@ -468,11 +458,11 @@ static void blend_slice(AVFilterContext *ctx,
468 468
     }
469 469
 }
470 470
 
471
-static int try_start_frame(AVFilterContext *ctx, AVFilterBufferRef *mainpic)
471
+static int try_filter_frame(AVFilterContext *ctx, AVFilterBufferRef *mainpic)
472 472
 {
473 473
     OverlayContext *over = ctx->priv;
474 474
     AVFilterLink *outlink = ctx->outputs[0];
475
-    AVFilterBufferRef *next_overpic, *outpicref;
475
+    AVFilterBufferRef *next_overpic;
476 476
     int ret;
477 477
 
478 478
     /* Discard obsolete overlay frames: if there is a next overlay frame with pts
... ...
@@ -496,21 +486,21 @@ static int try_start_frame(AVFilterContext *ctx, AVFilterBufferRef *mainpic)
496 496
 
497 497
     /* At this point, we know that the current overlay frame extends to the
498 498
      * time of the main frame. */
499
-    outlink->out_buf = outpicref = avfilter_ref_buffer(mainpic, ~0);
500
-
501 499
     av_dlog(ctx, "main_pts:%s main_pts_time:%s",
502
-            av_ts2str(outpicref->pts), av_ts2timestr(outpicref->pts, &outlink->time_base));
500
+            av_ts2str(mainpic->pts), av_ts2timestr(mainpic->pts, &outlink->time_base));
503 501
     if (over->overpicref)
504 502
         av_dlog(ctx, " over_pts:%s over_pts_time:%s",
505 503
                 av_ts2str(over->overpicref->pts), av_ts2timestr(over->overpicref->pts, &outlink->time_base));
506 504
     av_dlog(ctx, "\n");
507 505
 
508
-    ret = ff_start_frame(ctx->outputs[0], avfilter_ref_buffer(outpicref, ~0));
506
+    if (over->overpicref)
507
+        blend_image(ctx, mainpic, over->overpicref, over->x, over->y);
508
+    ret = ff_filter_frame(ctx->outputs[0], mainpic);
509 509
     over->frame_requested = 0;
510 510
     return ret;
511 511
 }
512 512
 
513
-static int try_start_next_frame(AVFilterContext *ctx)
513
+static int try_filter_next_frame(AVFilterContext *ctx)
514 514
 {
515 515
     OverlayContext *over = ctx->priv;
516 516
     AVFilterBufferRef *next_mainpic = ff_bufqueue_peek(&over->queue_main, 0);
... ...
@@ -518,41 +508,21 @@ static int try_start_next_frame(AVFilterContext *ctx)
518 518
 
519 519
     if (!next_mainpic)
520 520
         return AVERROR(EAGAIN);
521
-    if ((ret = try_start_frame(ctx, next_mainpic)) == AVERROR(EAGAIN))
521
+    if ((ret = try_filter_frame(ctx, next_mainpic)) == AVERROR(EAGAIN))
522 522
         return ret;
523
-    avfilter_unref_buffer(ff_bufqueue_get(&over->queue_main));
523
+    ff_bufqueue_get(&over->queue_main);
524 524
     return ret;
525 525
 }
526 526
 
527
-static int try_push_frame(AVFilterContext *ctx)
528
-{
529
-    OverlayContext *over = ctx->priv;
530
-    AVFilterLink *outlink = ctx->outputs[0];
531
-    AVFilterBufferRef *outpicref;
532
-    int ret;
533
-
534
-    if ((ret = try_start_next_frame(ctx)) < 0)
535
-        return ret;
536
-    outpicref = outlink->out_buf;
537
-    if (over->overpicref)
538
-        blend_slice(ctx, outpicref, over->overpicref, over->x, over->y,
539
-                    over->overpicref->video->w, over->overpicref->video->h,
540
-                    0, outpicref->video->w, outpicref->video->h);
541
-    if ((ret = ff_draw_slice(outlink, 0, outpicref->video->h, +1)) < 0 ||
542
-        (ret = ff_end_frame(outlink)) < 0)
543
-        return ret;
544
-    return 0;
545
-}
546
-
547 527
 static int flush_frames(AVFilterContext *ctx)
548 528
 {
549 529
     int ret;
550 530
 
551
-    while (!(ret = try_push_frame(ctx)));
531
+    while (!(ret = try_filter_next_frame(ctx)));
552 532
     return ret == AVERROR(EAGAIN) ? 0 : ret;
553 533
 }
554 534
 
555
-static int start_frame_main(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
535
+static int filter_frame_main(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
556 536
 {
557 537
     AVFilterContext *ctx = inlink->dst;
558 538
     OverlayContext *over = ctx->priv;
... ...
@@ -560,64 +530,29 @@ static int start_frame_main(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
560 560
 
561 561
     if ((ret = flush_frames(ctx)) < 0)
562 562
         return ret;
563
-    if ((ret = try_start_frame(ctx, inpicref)) < 0) {
563
+    if ((ret = try_filter_frame(ctx, inpicref)) < 0) {
564 564
         if (ret != AVERROR(EAGAIN))
565 565
             return ret;
566 566
         ff_bufqueue_add(ctx, &over->queue_main, inpicref);
567
-        av_assert1(inpicref == inlink->cur_buf);
568
-        inlink->cur_buf = NULL;
569 567
     }
570
-    return 0;
571
-}
572 568
 
573
-static int draw_slice_main(AVFilterLink *inlink, int y, int h, int slice_dir)
574
-{
575
-    AVFilterContext *ctx = inlink->dst;
576
-    OverlayContext *over = ctx->priv;
577
-    AVFilterLink *outlink = ctx->outputs[0];
578
-    AVFilterBufferRef *outpicref = outlink->out_buf;
579
-
580
-    if (!outpicref)
569
+    if (!over->overpicref)
581 570
         return 0;
582
-    if (over->overpicref &&
583
-        y + h > over->y && y < over->y + over->overpicref->video->h) {
584
-        blend_slice(ctx, outpicref, over->overpicref, over->x, over->y,
585
-                    over->overpicref->video->w, over->overpicref->video->h,
586
-                    y, outpicref->video->w, h);
587
-    }
588
-    return ff_draw_slice(outlink, y, h, slice_dir);
589
-}
590
-
591
-static int end_frame_main(AVFilterLink *inlink)
592
-{
593
-    AVFilterContext *ctx = inlink->dst;
594
-    AVFilterLink *outlink = ctx->outputs[0];
595
-    AVFilterBufferRef *outpicref = outlink->out_buf;
596 571
     flush_frames(ctx);
597 572
 
598
-    if (!outpicref)
599
-        return 0;
600
-    return ff_end_frame(ctx->outputs[0]);
601
-}
602
-
603
-static int start_frame_over(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
604
-{
605 573
     return 0;
606 574
 }
607 575
 
608
-static int end_frame_over(AVFilterLink *inlink)
576
+static int filter_frame_over(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
609 577
 {
610 578
     AVFilterContext *ctx = inlink->dst;
611 579
     OverlayContext *over = ctx->priv;
612
-    AVFilterBufferRef *inpicref = inlink->cur_buf;
613 580
     int ret;
614 581
 
615
-    inlink->cur_buf = NULL;
616
-
617 582
     if ((ret = flush_frames(ctx)) < 0)
618 583
         return ret;
619 584
     ff_bufqueue_add(ctx, &over->queue_over, inpicref);
620
-    ret = try_push_frame(ctx);
585
+    ret = try_filter_next_frame(ctx);
621 586
     return ret == AVERROR(EAGAIN) ? 0 : ret;
622 587
 }
623 588
 
... ...
@@ -627,7 +562,7 @@ static int request_frame(AVFilterLink *outlink)
627 627
     OverlayContext *over = ctx->priv;
628 628
     int input, ret;
629 629
 
630
-    if (!try_push_frame(ctx))
630
+    if (!try_filter_next_frame(ctx))
631 631
         return 0;
632 632
     over->frame_requested = 1;
633 633
     while (over->frame_requested) {
... ...
@@ -639,7 +574,7 @@ static int request_frame(AVFilterLink *outlink)
639 639
         /* EOF on main is reported immediately */
640 640
         if (ret == AVERROR_EOF && input == OVERLAY) {
641 641
             over->overlay_eof = 1;
642
-            if ((ret = try_start_next_frame(ctx)) != AVERROR(EAGAIN))
642
+            if ((ret = try_filter_next_frame(ctx)) != AVERROR(EAGAIN))
643 643
                 return ret;
644 644
             ret = 0; /* continue requesting frames on main */
645 645
         }
... ...
@@ -649,29 +584,20 @@ static int request_frame(AVFilterLink *outlink)
649 649
     return 0;
650 650
 }
651 651
 
652
-static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
653
-{
654
-    return 0;
655
-}
656
-
657 652
 static const AVFilterPad avfilter_vf_overlay_inputs[] = {
658 653
     {
659 654
         .name         = "main",
660 655
         .type         = AVMEDIA_TYPE_VIDEO,
661 656
         .get_video_buffer = ff_null_get_video_buffer,
662 657
         .config_props = config_input_main,
663
-        .start_frame  = start_frame_main,
664
-        .draw_slice   = draw_slice_main,
665
-        .end_frame    = end_frame_main,
658
+        .filter_frame = filter_frame_main,
666 659
         .min_perms    = AV_PERM_READ | AV_PERM_WRITE | AV_PERM_PRESERVE,
667 660
     },
668 661
     {
669 662
         .name         = "overlay",
670 663
         .type         = AVMEDIA_TYPE_VIDEO,
671 664
         .config_props = config_input_overlay,
672
-        .start_frame  = start_frame_over,
673
-        .draw_slice   = null_draw_slice,
674
-        .end_frame    = end_frame_over,
665
+        .filter_frame = filter_frame_over,
675 666
         .min_perms    = AV_PERM_READ | AV_PERM_PRESERVE,
676 667
     },
677 668
     { NULL }