Hi,

updated version attached.
From 4a4d760c78f16e8ddeab65a0fc6532059bf13750 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <one...@gmail.com>
Date: Sun, 17 Jan 2016 20:14:55 +0100
Subject: [PATCH] avfilter/vf_crop: make it possible to use frame metadata when
 cropping

Signed-off-by: Paul B Mahol <one...@gmail.com>
---
 doc/filters.texi      |  6 +++++
 libavfilter/vf_crop.c | 64 +++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 7f2c419..87bf4dd 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -4760,6 +4760,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.
+
+@item metadata
+If set to 1, the frame metadata as inserted by the cropdetect filter
+will be used to determine all parameters. This requires that the
+@ref{cropdetect} filter is inserted before this filter in the chain.
 @end table
 
 The @var{out_w}, @var{out_h}, @var{x}, @var{y} parameters are
@@ -4920,6 +4925,7 @@ If the specified expression is not valid, it is kept at its current
 value.
 @end table
 
+@anchor{cropdetect}
 @section cropdetect
 
 Auto-detect the crop size.
diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c
index 01773fa..8cea499 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
@@ -243,23 +244,55 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
 {
     AVFilterContext *ctx = link->dst;
     CropContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
-    int i;
-
-    frame->width  = s->w;
-    frame->height = s->h;
+    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;
+            }
+        }
+    }
 
-    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);
+    if (s->w != frame->width || s->h != frame->height) {
+        frame->width  = outlink->w = s->w;
+        frame->height = outlink->h = s->h;
+        avfilter_config_links(ctx);
+    }
 
-    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;
@@ -294,7 +327,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
         frame->data[3] += s->x * s->max_step[3];
     }
 
-    return ff_filter_frame(link->dst->outputs[0], frame);
+    return ff_filter_frame(outlink, frame);
 }
 
 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
@@ -344,6 +377,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

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to