]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_stereo3d.c
Merge commit '732a37d1466d45b3812509d68c82e783530e291a'
[ffmpeg] / libavfilter / vf_stereo3d.c
index 8e9cc83af11eda17aa2ce0c12d6abe665d4cf9af..f207d920f59dcd346709c478d53f4ea1ce7b0692 100644 (file)
@@ -148,7 +148,6 @@ typedef struct Stereo3DContext {
     int hsub, vsub;
     int pixstep[4];
     AVFrame *prev;
-    double ts_unit;
     int blanks;
     int in_off_left[4], in_off_right[4];
     Stereo3DDSPContext dsp;
@@ -544,7 +543,6 @@ static int config_output(AVFilterLink *outlink)
         return ret;
     s->nb_planes = av_pix_fmt_count_planes(outlink->format);
     av_image_fill_max_pixsteps(s->pixstep, NULL, desc);
-    s->ts_unit = av_q2d(av_inv_q(av_mul_q(outlink->frame_rate, outlink->time_base)));
     s->pheight[1] = s->pheight[2] = FF_CEIL_RSHIFT(s->height, desc->log2_chroma_h);
     s->pheight[0] = s->pheight[3] = s->height;
     s->hsub = desc->log2_chroma_w;
@@ -593,11 +591,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
     AVFilterLink *outlink = ctx->outputs[0];
     AVFrame *out, *oleft, *oright, *ileft, *iright;
     int out_off_left[4], out_off_right[4];
-    int i;
+    int i, ret;
 
     if (s->in.format == s->out.format)
         return ff_filter_frame(outlink, inpicref);
 
+    switch (s->out.format) {
+    case ALTERNATING_LR:
+    case ALTERNATING_RL:
+        if (!s->prev) {
+            s->prev = inpicref;
+            return 0;
+        }
+        break;
+    };
+
     switch (s->in.format) {
     case ALTERNATING_LR:
     case ALTERNATING_RL:
@@ -614,24 +622,80 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
         ileft = iright = inpicref;
     };
 
-    out = oleft = oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        av_frame_free(&s->prev);
-        av_frame_free(&inpicref);
-        return AVERROR(ENOMEM);
-    }
-    av_frame_copy_props(out, inpicref);
-
-    if (s->out.format == ALTERNATING_LR ||
-        s->out.format == ALTERNATING_RL) {
-        oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-        if (!oright) {
+    if ((s->out.format == ALTERNATING_LR ||
+         s->out.format == ALTERNATING_RL) &&
+        (s->in.format == SIDE_BY_SIDE_LR ||
+         s->in.format == SIDE_BY_SIDE_RL ||
+         s->in.format == SIDE_BY_SIDE_2_LR ||
+         s->in.format == SIDE_BY_SIDE_2_RL ||
+         s->in.format == ABOVE_BELOW_LR ||
+         s->in.format == ABOVE_BELOW_RL ||
+         s->in.format == ABOVE_BELOW_2_LR ||
+         s->in.format == ABOVE_BELOW_2_RL)) {
+        oright = av_frame_clone(s->prev);
+        oleft  = av_frame_clone(s->prev);
+        if (!oright || !oleft) {
+            av_frame_free(&oright);
             av_frame_free(&oleft);
             av_frame_free(&s->prev);
             av_frame_free(&inpicref);
             return AVERROR(ENOMEM);
         }
-        av_frame_copy_props(oright, inpicref);
+    } else if ((s->out.format == MONO_L ||
+                s->out.format == MONO_R) &&
+        (s->in.format == SIDE_BY_SIDE_LR ||
+         s->in.format == SIDE_BY_SIDE_RL ||
+         s->in.format == SIDE_BY_SIDE_2_LR ||
+         s->in.format == SIDE_BY_SIDE_2_RL ||
+         s->in.format == ABOVE_BELOW_LR ||
+         s->in.format == ABOVE_BELOW_RL ||
+         s->in.format == ABOVE_BELOW_2_LR ||
+         s->in.format == ABOVE_BELOW_2_RL)) {
+        out = oleft = oright = av_frame_clone(inpicref);
+        if (!out) {
+            av_frame_free(&s->prev);
+            av_frame_free(&inpicref);
+            return AVERROR(ENOMEM);
+        }
+    } else if ((s->out.format == MONO_L && s->in.format == ALTERNATING_LR) ||
+               (s->out.format == MONO_R && s->in.format == ALTERNATING_RL)) {
+        s->prev->pts /= 2;
+        ret = ff_filter_frame(outlink, s->prev);
+        av_frame_free(&inpicref);
+        s->prev = NULL;
+        return ret;
+    } else if ((s->out.format == MONO_L && s->in.format == ALTERNATING_RL) ||
+               (s->out.format == MONO_R && s->in.format == ALTERNATING_LR)) {
+        av_frame_free(&s->prev);
+        inpicref->pts /= 2;
+        return ff_filter_frame(outlink, inpicref);
+    } else if ((s->out.format == ALTERNATING_LR && s->in.format == ALTERNATING_RL) ||
+               (s->out.format == ALTERNATING_RL && s->in.format == ALTERNATING_LR)) {
+        FFSWAP(int64_t, s->prev->pts, inpicref->pts);
+        ff_filter_frame(outlink, inpicref);
+        ret = ff_filter_frame(outlink, s->prev);
+        s->prev = NULL;
+        return ret;
+    } else {
+        out = oleft = oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+        if (!out) {
+            av_frame_free(&s->prev);
+            av_frame_free(&inpicref);
+            return AVERROR(ENOMEM);
+        }
+        av_frame_copy_props(out, inpicref);
+
+        if (s->out.format == ALTERNATING_LR ||
+            s->out.format == ALTERNATING_RL) {
+            oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+            if (!oright) {
+                av_frame_free(&oleft);
+                av_frame_free(&s->prev);
+                av_frame_free(&inpicref);
+                return AVERROR(ENOMEM);
+            }
+            av_frame_copy_props(oright, s->prev);
+        }
     }
 
     for (i = 0; i < 4; i++) {
@@ -644,6 +708,32 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
     }
 
     switch (s->out.format) {
+    case ALTERNATING_LR:
+    case ALTERNATING_RL:
+        switch (s->in.format) {
+        case ABOVE_BELOW_LR:
+        case ABOVE_BELOW_RL:
+        case ABOVE_BELOW_2_LR:
+        case ABOVE_BELOW_2_RL:
+        case SIDE_BY_SIDE_LR:
+        case SIDE_BY_SIDE_RL:
+        case SIDE_BY_SIDE_2_LR:
+        case SIDE_BY_SIDE_2_RL:
+            oleft->width   = outlink->w;
+            oright->width  = outlink->w;
+            oleft->height  = outlink->h;
+            oright->height = outlink->h;
+
+            for (i = 0; i < s->nb_planes; i++) {
+                oleft->data[i]  += s->in_off_left[i];
+                oright->data[i] += s->in_off_right[i];
+            }
+            break;
+        default:
+            goto copy;
+            break;
+        }
+        break;
     case HDMI:
         for (i = 0; i < s->nb_planes; i++) {
             int j, h = s->height >> ((i == 1 || i == 2) ? s->vsub : 0);
@@ -652,8 +742,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
             for (j = h; j < h + b; j++)
                 memset(oleft->data[i] + j * s->linesize[i], 0, s->linesize[i]);
         }
-    case ALTERNATING_LR:
-    case ALTERNATING_RL:
     case SIDE_BY_SIDE_LR:
     case SIDE_BY_SIDE_RL:
     case SIDE_BY_SIDE_2_LR:
@@ -664,6 +752,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
     case ABOVE_BELOW_2_RL:
     case INTERLEAVE_ROWS_LR:
     case INTERLEAVE_ROWS_RL:
+copy:
         for (i = 0; i < s->nb_planes; i++) {
             av_image_copy_plane(oleft->data[i] + out_off_left[i],
                                 oleft->linesize[i] * s->out.row_step,
@@ -680,11 +769,30 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
     case MONO_L:
         iright = ileft;
     case MONO_R:
-        for (i = 0; i < s->nb_planes; i++) {
-            av_image_copy_plane(out->data[i], out->linesize[i],
-                                iright->data[i] + s->in_off_left[i],
-                                iright->linesize[i] * s->in.row_step,
-                                s->linesize[i], s->pheight[i]);
+        switch (s->in.format) {
+        case ABOVE_BELOW_LR:
+        case ABOVE_BELOW_RL:
+        case ABOVE_BELOW_2_LR:
+        case ABOVE_BELOW_2_RL:
+        case SIDE_BY_SIDE_LR:
+        case SIDE_BY_SIDE_RL:
+        case SIDE_BY_SIDE_2_LR:
+        case SIDE_BY_SIDE_2_RL:
+            out->width  = outlink->w;
+            out->height = outlink->h;
+
+            for (i = 0; i < s->nb_planes; i++) {
+                out->data[i] += s->in_off_left[i];
+            }
+            break;
+        default:
+            for (i = 0; i < s->nb_planes; i++) {
+                av_image_copy_plane(out->data[i], out->linesize[i],
+                                    iright->data[i] + s->in_off_left[i],
+                                    iright->linesize[i] * s->in.row_step,
+                                    s->linesize[i], s->pheight[i]);
+            }
+            break;
         }
         break;
     case ANAGLYPH_RB_GRAY:
@@ -821,18 +929,23 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
         av_assert0(0);
     }
 
-    av_frame_free(&inpicref);
-    av_frame_free(&s->prev);
     if (oright != oleft) {
         if (s->out.format == ALTERNATING_LR)
             FFSWAP(AVFrame *, oleft, oright);
-        oright->pts = outlink->frame_count * s->ts_unit;
+        oright->pts = s->prev->pts * 2;
         ff_filter_frame(outlink, oright);
         out = oleft;
-        oleft->pts = outlink->frame_count * s->ts_unit;
+        oleft->pts = s->prev->pts + inpicref->pts;
+        av_frame_free(&s->prev);
+        s->prev = inpicref;
     } else if (s->in.format == ALTERNATING_LR ||
                s->in.format == ALTERNATING_RL) {
-        out->pts = outlink->frame_count * s->ts_unit;
+        out->pts = s->prev->pts / 2;
+        av_frame_free(&s->prev);
+        av_frame_free(&inpicref);
+    } else {
+        av_frame_free(&s->prev);
+        av_frame_free(&inpicref);
     }
     return ff_filter_frame(outlink, out);
 }