Browse code

avfilter/vf_stereo3d: implement slice threading for anaglyph output

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2015/07/10 04:18:14
Showing 1 changed files
... ...
@@ -142,6 +142,7 @@ typedef struct Stereo3DContext {
142 142
     int pixstep[4];
143 143
     AVFrame *prev;
144 144
     double ts_unit;
145
+    int in_off_left[4], in_off_right[4];
145 146
 } Stereo3DContext;
146 147
 
147 148
 #define OFFSET(x) offsetof(Stereo3DContext, x)
... ...
@@ -485,6 +486,42 @@ static inline uint8_t ana_convert(const int *coeff, const uint8_t *left, const u
485 485
     return av_clip_uint8(sum >> 16);
486 486
 }
487 487
 
488
+typedef struct ThreadData {
489
+    AVFrame *ileft, *iright;
490
+    AVFrame *out;
491
+} ThreadData;
492
+
493
+static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
494
+{
495
+    Stereo3DContext *s = ctx->priv;
496
+    ThreadData *td = arg;
497
+    AVFrame *ileft = td->ileft;
498
+    AVFrame *iright = td->iright;
499
+    AVFrame *out = td->out;
500
+    int height = s->out.height;
501
+    int start = (height *  jobnr   ) / nb_jobs;
502
+    int end   = (height * (jobnr+1)) / nb_jobs;
503
+    uint8_t *dst = out->data[0];
504
+    const int **ana_matrix = s->ana_matrix;
505
+    int x, y, il, ir, o;
506
+    const uint8_t *lsrc = ileft->data[0];
507
+    const uint8_t *rsrc = iright->data[0];
508
+    int out_width = s->out.width;
509
+
510
+    for (y = start; y < end; y++) {
511
+        o   = out->linesize[0] * y;
512
+        il  = s->in_off_left[0]  + y * ileft->linesize[0];
513
+        ir  = s->in_off_right[0] + y * iright->linesize[0];
514
+        for (x = 0; x < out_width; x++, il += 3, ir += 3, o+= 3) {
515
+            dst[o    ] = ana_convert(ana_matrix[0], lsrc + il, rsrc + ir);
516
+            dst[o + 1] = ana_convert(ana_matrix[1], lsrc + il, rsrc + ir);
517
+            dst[o + 2] = ana_convert(ana_matrix[2], lsrc + il, rsrc + ir);
518
+        }
519
+    }
520
+
521
+    return 0;
522
+}
523
+
488 524
 static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
489 525
 {
490 526
     AVFilterContext *ctx  = inlink->dst;
... ...
@@ -492,7 +529,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
492 492
     AVFilterLink *outlink = ctx->outputs[0];
493 493
     AVFrame *out, *oleft, *oright, *ileft, *iright;
494 494
     int out_off_left[4], out_off_right[4];
495
-    int in_off_left[4], in_off_right[4];
496 495
     int i;
497 496
 
498 497
     switch (s->in.format) {
... ...
@@ -534,8 +570,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
534 534
     for (i = 0; i < 4; i++) {
535 535
         int hsub = i == 1 || i == 2 ? s->hsub : 0;
536 536
         int vsub = i == 1 || i == 2 ? s->vsub : 0;
537
-        in_off_left[i]   = (FF_CEIL_RSHIFT(s->in.row_left,   vsub) + s->in.off_lstep)  * ileft->linesize[i]  + FF_CEIL_RSHIFT(s->in.off_left   * s->pixstep[i], hsub);
538
-        in_off_right[i]  = (FF_CEIL_RSHIFT(s->in.row_right,  vsub) + s->in.off_rstep)  * iright->linesize[i] + FF_CEIL_RSHIFT(s->in.off_right  * s->pixstep[i], hsub);
537
+        s->in_off_left[i]   = (FF_CEIL_RSHIFT(s->in.row_left,   vsub) + s->in.off_lstep)  * ileft->linesize[i]  + FF_CEIL_RSHIFT(s->in.off_left   * s->pixstep[i], hsub);
538
+        s->in_off_right[i]  = (FF_CEIL_RSHIFT(s->in.row_right,  vsub) + s->in.off_rstep)  * iright->linesize[i] + FF_CEIL_RSHIFT(s->in.off_right  * s->pixstep[i], hsub);
539 539
         out_off_left[i]  = (FF_CEIL_RSHIFT(s->out.row_left,  vsub) + s->out.off_lstep) * oleft->linesize[i]  + FF_CEIL_RSHIFT(s->out.off_left  * s->pixstep[i], hsub);
540 540
         out_off_right[i] = (FF_CEIL_RSHIFT(s->out.row_right, vsub) + s->out.off_rstep) * oright->linesize[i] + FF_CEIL_RSHIFT(s->out.off_right * s->pixstep[i], hsub);
541 541
     }
... ...
@@ -556,12 +592,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
556 556
         for (i = 0; i < s->nb_planes; i++) {
557 557
             av_image_copy_plane(oleft->data[i] + out_off_left[i],
558 558
                                 oleft->linesize[i] * s->row_step,
559
-                                ileft->data[i] + in_off_left[i],
559
+                                ileft->data[i] + s->in_off_left[i],
560 560
                                 ileft->linesize[i] * s->row_step,
561 561
                                 s->linesize[i], s->pheight[i]);
562 562
             av_image_copy_plane(oright->data[i] + out_off_right[i],
563 563
                                 oright->linesize[i] * s->row_step,
564
-                                iright->data[i] + in_off_right[i],
564
+                                iright->data[i] + s->in_off_right[i],
565 565
                                 iright->linesize[i] * s->row_step,
566 566
                                 s->linesize[i], s->pheight[i]);
567 567
         }
... ...
@@ -571,7 +607,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
571 571
     case MONO_R:
572 572
         for (i = 0; i < s->nb_planes; i++) {
573 573
             av_image_copy_plane(out->data[i], out->linesize[i],
574
-                                iright->data[i] + in_off_left[i],
574
+                                iright->data[i] + s->in_off_left[i],
575 575
                                 iright->linesize[i],
576 576
                                 s->linesize[i], s->pheight[i]);
577 577
         }
... ...
@@ -590,23 +626,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
590 590
     case ANAGLYPH_YB_HALF:
591 591
     case ANAGLYPH_YB_COLOR:
592 592
     case ANAGLYPH_YB_DUBOIS: {
593
-        int x, y, il, ir, o;
594
-        const uint8_t *lsrc = ileft->data[0];
595
-        const uint8_t *rsrc = iright->data[0];
596
-        uint8_t *dst = out->data[0];
597
-        int out_width = s->out.width;
598
-        const int **ana_matrix = s->ana_matrix;
599
-
600
-        for (y = 0; y < s->out.height; y++) {
601
-            o   = out->linesize[0] * y;
602
-            il  = in_off_left[0]  + y * ileft->linesize[0];
603
-            ir  = in_off_right[0] + y * iright->linesize[0];
604
-            for (x = 0; x < out_width; x++, il += 3, ir += 3, o+= 3) {
605
-                dst[o    ] = ana_convert(ana_matrix[0], lsrc + il, rsrc + ir);
606
-                dst[o + 1] = ana_convert(ana_matrix[1], lsrc + il, rsrc + ir);
607
-                dst[o + 2] = ana_convert(ana_matrix[2], lsrc + il, rsrc + ir);
608
-            }
609
-        }
593
+        ThreadData td;
594
+
595
+        td.ileft = ileft; td.iright = iright; td.out = out;
596
+        ctx->internal->execute(ctx, filter_slice, &td, NULL,
597
+                               FFMIN(s->out.height, ctx->graph->nb_threads));
610 598
         break;
611 599
     }
612 600
     default:
... ...
@@ -663,4 +687,5 @@ AVFilter ff_vf_stereo3d = {
663 663
     .inputs        = stereo3d_inputs,
664 664
     .outputs       = stereo3d_outputs,
665 665
     .priv_class    = &stereo3d_class,
666
+    .flags         = AVFILTER_FLAG_SLICE_THREADS,
666 667
 };