]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_transpose.c
lavu: Drop the {minus,plus}1 suffix from AVComponentDescriptor fields
[ffmpeg] / libavfilter / vf_transpose.c
index d7a173989f0ae5a44d463fc9de999e8f29ae12db..07602b9086dd3ab46f7778d7f2de50065d830619 100644 (file)
 
 #include <stdio.h>
 
-#include "libavutil/intreadwrite.h"
-#include "libavutil/pixdesc.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
 #include "avfilter.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
 
-typedef struct {
+enum TransposeDir {
+    TRANSPOSE_CCLOCK_FLIP,
+    TRANSPOSE_CLOCK,
+    TRANSPOSE_CCLOCK,
+    TRANSPOSE_CLOCK_FLIP,
+};
+
+typedef struct TransContext {
+    const AVClass *class;
     int hsub, vsub;
     int pixsteps[4];
 
-    /* 0    Rotate by 90 degrees counterclockwise and vflip. */
-    /* 1    Rotate by 90 degrees clockwise.                  */
-    /* 2    Rotate by 90 degrees counterclockwise.           */
-    /* 3    Rotate by 90 degrees clockwise and vflip.        */
-    int dir;
+    enum TransposeDir dir;
 } TransContext;
 
-static av_cold int init(AVFilterContext *ctx, const char *args)
-{
-    TransContext *trans = ctx->priv;
-    trans->dir = 0;
-
-    if (args)
-        sscanf(args, "%d", &trans->dir);
-
-    if (trans->dir < 0 || trans->dir > 3) {
-        av_log(ctx, AV_LOG_ERROR, "Invalid value %d not between 0 and 3.\n",
-               trans->dir);
-        return AVERROR(EINVAL);
-    }
-    return 0;
-}
-
 static int query_formats(AVFilterContext *ctx)
 {
     enum AVPixelFormat pix_fmts[] = {
@@ -109,63 +99,65 @@ static int config_props_output(AVFilterLink *outlink)
     outlink->w = inlink->h;
     outlink->h = inlink->w;
 
-    if (inlink->sample_aspect_ratio.num){
-        outlink->sample_aspect_ratio = av_div_q((AVRational){1,1}, inlink->sample_aspect_ratio);
-    } else
+    if (inlink->sample_aspect_ratio.num)
+        outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 },
+                                                inlink->sample_aspect_ratio);
+    else
         outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
 
-    av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n",
+    av_log(ctx, AV_LOG_VERBOSE,
+           "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n",
            inlink->w, inlink->h, trans->dir, outlink->w, outlink->h,
            trans->dir == 1 || trans->dir == 3 ? "clockwise" : "counterclockwise",
            trans->dir == 0 || trans->dir == 3);
     return 0;
 }
 
-static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
     AVFilterLink *outlink = inlink->dst->outputs[0];
     TransContext *trans = inlink->dst->priv;
-    AVFilterBufferRef *out;
+    AVFrame *out;
     int plane;
 
-    out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     if (!out) {
-        avfilter_unref_bufferp(&in);
+        av_frame_free(&in);
         return AVERROR(ENOMEM);
     }
 
     out->pts = in->pts;
 
-    if (in->video->pixel_aspect.num == 0) {
-        out->video->pixel_aspect = in->video->pixel_aspect;
+    if (in->sample_aspect_ratio.num == 0) {
+        out->sample_aspect_ratio = in->sample_aspect_ratio;
     } else {
-        out->video->pixel_aspect.num = in->video->pixel_aspect.den;
-        out->video->pixel_aspect.den = in->video->pixel_aspect.num;
+        out->sample_aspect_ratio.num = in->sample_aspect_ratio.den;
+        out->sample_aspect_ratio.den = in->sample_aspect_ratio.num;
     }
 
     for (plane = 0; out->data[plane]; plane++) {
-        int hsub = plane == 1 || plane == 2 ? trans->hsub : 0;
-        int vsub = plane == 1 || plane == 2 ? trans->vsub : 0;
+        int hsub    = plane == 1 || plane == 2 ? trans->hsub : 0;
+        int vsub    = plane == 1 || plane == 2 ? trans->vsub : 0;
         int pixstep = trans->pixsteps[plane];
-        int inh  = in->video->h>>vsub;
-        int outw = out->video->w>>hsub;
-        int outh = out->video->h>>vsub;
+        int inh     = in->height >> vsub;
+        int outw    = out->width >> hsub;
+        int outh    = out->height >> vsub;
         uint8_t *dst, *src;
         int dstlinesize, srclinesize;
         int x, y;
 
-        dst = out->data[plane];
+        dst         = out->data[plane];
         dstlinesize = out->linesize[plane];
-        src = in->data[plane];
+        src         = in->data[plane];
         srclinesize = in->linesize[plane];
 
-        if (trans->dir&1) {
-            src +=  in->linesize[plane] * (inh-1);
+        if (trans->dir & 1) {
+            src         += in->linesize[plane] * (inh - 1);
             srclinesize *= -1;
         }
 
-        if (trans->dir&2) {
-            dst += out->linesize[plane] * (outh-1);
+        if (trans->dir & 2) {
+            dst         += out->linesize[plane] * (outh - 1);
             dstlinesize *= -1;
         }
 
@@ -173,37 +165,57 @@ static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
             switch (pixstep) {
             case 1:
                 for (x = 0; x < outw; x++)
-                    dst[x] = src[x*srclinesize + y];
+                    dst[x] = src[x * srclinesize + y];
                 break;
             case 2:
                 for (x = 0; x < outw; x++)
-                    *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*srclinesize + y*2));
+                    *((uint16_t *)(dst + 2 * x)) =
+                        *((uint16_t *)(src + x * srclinesize + y * 2));
                 break;
             case 3:
                 for (x = 0; x < outw; x++) {
-                    int32_t v = AV_RB24(src + x*srclinesize + y*3);
-                    AV_WB24(dst + 3*x, v);
+                    int32_t v = AV_RB24(src + x * srclinesize + y * 3);
+                    AV_WB24(dst + 3 * x, v);
                 }
                 break;
             case 4:
                 for (x = 0; x < outw; x++)
-                    *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*srclinesize + y*4));
+                    *((uint32_t *)(dst + 4 * x)) =
+                        *((uint32_t *)(src + x * srclinesize + y * 4));
                 break;
             }
             dst += dstlinesize;
         }
     }
 
-    avfilter_unref_bufferp(&in);
+    av_frame_free(&in);
     return ff_filter_frame(outlink, out);
 }
 
+#define OFFSET(x) offsetof(TransContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
+static const AVOption options[] = {
+    { "dir", "Transpose direction", OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP },
+        TRANSPOSE_CCLOCK_FLIP, TRANSPOSE_CLOCK_FLIP, FLAGS, "dir" },
+        { "cclock_flip", "counter-clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .unit = "dir" },
+        { "clock",       "clockwise",                            0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK       }, .unit = "dir" },
+        { "cclock",      "counter-clockwise",                    0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK      }, .unit = "dir" },
+        { "clock_flip",  "clockwise with vertical flip",         0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP  }, .unit = "dir" },
+    { NULL },
+};
+
+static const AVClass transpose_class = {
+    .class_name = "transpose",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 static const AVFilterPad avfilter_vf_transpose_inputs[] = {
     {
-        .name        = "default",
-        .type        = AVMEDIA_TYPE_VIDEO,
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
-        .min_perms   = AV_PERM_READ,
     },
     { NULL }
 };
@@ -217,15 +229,12 @@ static const AVFilterPad avfilter_vf_transpose_outputs[] = {
     { NULL }
 };
 
-AVFilter avfilter_vf_transpose = {
-    .name      = "transpose",
-    .description = NULL_IF_CONFIG_SMALL("Transpose input video."),
-
-    .init = init,
-    .priv_size = sizeof(TransContext),
-
+AVFilter ff_vf_transpose = {
+    .name          = "transpose",
+    .description   = NULL_IF_CONFIG_SMALL("Transpose input video."),
+    .priv_size     = sizeof(TransContext),
+    .priv_class    = &transpose_class,
     .query_formats = query_formats,
-
-    .inputs    = avfilter_vf_transpose_inputs,
-    .outputs   = avfilter_vf_transpose_outputs,
+    .inputs        = avfilter_vf_transpose_inputs,
+    .outputs       = avfilter_vf_transpose_outputs,
 };