[FFmpeg-devel] [PATCH] avfilter/vf_crop: make it possible to use frame metadata when cropping

Paul B Mahol onemda at gmail.com
Sun Jan 17 20:15:45 CET 2016


Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
 doc/filters.texi      |  6 ++++++
 libavfilter/vf_crop.c | 54 +++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index f4bda6a..aee4e66 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -4621,6 +4621,11 @@ This expression is evaluated per-frame.
 If set to 1 will force the output display aspect ratio
 to be the same of the input, by changing the output sample aspect
 ratio. It defaults to 0.
+
+ at item metadata
+If set to 1 it will use frame metadata instead to obtain all parameters.
+To make use of this feature you need to start @ref{cropdetect} filter before
+this filter.
 @end table
 
 The @var{out_w}, @var{out_h}, @var{x}, @var{y} parameters are
@@ -4781,6 +4786,7 @@ If the specified expression is not valid, it is kept at its current
 value.
 @end table
 
+ at anchor{cropdetect}
 @section cropdetect
 
 Auto-detect the crop size.
diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c
index 01773fa..7890d6c 100644
--- a/libavfilter/vf_crop.c
+++ b/libavfilter/vf_crop.c
@@ -82,6 +82,7 @@ typedef struct CropContext {
 
     AVRational out_sar; ///< output sample aspect ratio
     int keep_aspect;    ///< keep display aspect ratio when cropping
+    int metadata;       ///< use frame metadata instead of expressions
 
     int max_step[4];    ///< max pixel step for each plane, expressed as a number of bytes
     int hsub, vsub;     ///< chroma subsampling
@@ -244,22 +245,50 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
     AVFilterContext *ctx = link->dst;
     CropContext *s = ctx->priv;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
-    int i;
+    int i, metadata = 0;
+
+    if (s->metadata) {
+        AVDictionaryEntry *ex, *ey, *ew, *eh;
+
+        ew = av_dict_get(frame->metadata, "lavfi.cropdetect.w", NULL, AV_DICT_MATCH_CASE);
+        eh = av_dict_get(frame->metadata, "lavfi.cropdetect.h", NULL, AV_DICT_MATCH_CASE);
+        ex = av_dict_get(frame->metadata, "lavfi.cropdetect.x", NULL, AV_DICT_MATCH_CASE);
+        ey = av_dict_get(frame->metadata, "lavfi.cropdetect.y", NULL, AV_DICT_MATCH_CASE);
+
+        if (ex && ey && ew && eh) {
+            char *xendptr = NULL, *yendptr = NULL, *wendptr = NULL, *hendptr = NULL;
+            int x, y, w, h;
+
+            x = strtol(ex->value, &xendptr, 10);
+            y = strtol(ey->value, &yendptr, 10);
+            w = strtol(ew->value, &wendptr, 10);
+            h = strtol(eh->value, &hendptr, 10);
+            if (x >= 0 && y >= 0 && w > 0 && h >0) {
+                metadata = 1;
+                s->x = x;
+                s->y = y;
+                s->w = w;
+                s->h = h;
+            }
+        }
+    }
 
     frame->width  = s->w;
     frame->height = s->h;
 
-    s->var_values[VAR_N] = link->frame_count;
-    s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
-        NAN : frame->pts * av_q2d(link->time_base);
-    s->var_values[VAR_POS] = av_frame_get_pkt_pos(frame) == -1 ?
-        NAN : av_frame_get_pkt_pos(frame);
-    s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
-    s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, NULL);
-    s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
-
-    normalize_double(&s->x, s->var_values[VAR_X]);
-    normalize_double(&s->y, s->var_values[VAR_Y]);
+    if (!metadata) {
+        s->var_values[VAR_N] = link->frame_count;
+        s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
+            NAN : frame->pts * av_q2d(link->time_base);
+        s->var_values[VAR_POS] = av_frame_get_pkt_pos(frame) == -1 ?
+            NAN : av_frame_get_pkt_pos(frame);
+        s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
+        s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, NULL);
+        s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
+
+        normalize_double(&s->x, s->var_values[VAR_X]);
+        normalize_double(&s->y, s->var_values[VAR_Y]);
+    }
 
     if (s->x < 0)
         s->x = 0;
@@ -344,6 +373,7 @@ static const AVOption crop_options[] = {
     { "x",           "set the x crop area expression",       OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "(in_w-out_w)/2"}, CHAR_MIN, CHAR_MAX, FLAGS },
     { "y",           "set the y crop area expression",       OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "(in_h-out_h)/2"}, CHAR_MIN, CHAR_MAX, FLAGS },
     { "keep_aspect", "keep aspect ratio",                    OFFSET(keep_aspect), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
+    { "metadata",    "use frame metadata",                   OFFSET(metadata),    AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
     { NULL }
 };
 
-- 
1.9.1



More information about the ffmpeg-devel mailing list