lavfi/atempo: fix tempo range limit inconsistency
[ffmpeg.git] / libavfilter / vf_crop.c
index 93a58da..84be4c7 100644 (file)
@@ -82,6 +82,7 @@ typedef struct CropContext {
 
     AVRational out_sar; ///< output sample aspect ratio
     int keep_aspect;    ///< keep display aspect ratio when cropping
+    int exact;          ///< exact cropping, for subsampled formats
 
     int max_step[4];    ///< max pixel step for each plane, expressed as a number of bytes
     int hsub, vsub;     ///< chroma subsampling
@@ -126,7 +127,7 @@ static inline int normalize_double(int *n, double d)
         *n = d > INT_MAX ? INT_MAX : INT_MIN;
         ret = AVERROR(EINVAL);
     } else
-        *n = round(d);
+        *n = lrint(d);
 
     return ret;
 }
@@ -184,8 +185,11 @@ static int config_input(AVFilterLink *link)
                s->w_expr, s->h_expr);
         return AVERROR(EINVAL);
     }
-    s->w &= ~((1 << s->hsub) - 1);
-    s->h &= ~((1 << s->vsub) - 1);
+
+    if (!s->exact) {
+        s->w &= ~((1 << s->hsub) - 1);
+        s->h &= ~((1 << s->vsub) - 1);
+    }
 
     av_expr_free(s->x_pexpr);
     av_expr_free(s->y_pexpr);
@@ -219,8 +223,10 @@ static int config_input(AVFilterLink *link)
     /* set default, required in the case the first computed value for x/y is NAN */
     s->x = (link->w - s->w) / 2;
     s->y = (link->h - s->h) / 2;
-    s->x &= ~((1 << s->hsub) - 1);
-    s->y &= ~((1 << s->vsub) - 1);
+    if (!s->exact) {
+        s->x &= ~((1 << s->hsub) - 1);
+        s->y &= ~((1 << s->vsub) - 1);
+    }
     return 0;
 
 fail_expr:
@@ -249,13 +255,14 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
     frame->width  = s->w;
     frame->height = s->h;
 
-    s->var_values[VAR_N] = link->frame_count;
+    s->var_values[VAR_N] = link->frame_count_out;
     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_POS] = frame->pkt_pos == -1 ?
+        NAN : frame->pkt_pos;
     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);
+    /* It is necessary if x is expressed from y  */
     s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
 
     normalize_double(&s->x, s->var_values[VAR_X]);
@@ -269,8 +276,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
         s->x = link->w - s->w;
     if ((unsigned)s->y + (unsigned)s->h > link->h)
         s->y = link->h - s->h;
-    s->x &= ~((1 << s->hsub) - 1);
-    s->y &= ~((1 << s->vsub) - 1);
+    if (!s->exact) {
+        s->x &= ~((1 << s->hsub) - 1);
+        s->y &= ~((1 << s->vsub) - 1);
+    }
 
     av_log(ctx, AV_LOG_TRACE, "n:%d t:%f pos:%f x:%d y:%d x+w:%d y+h:%d\n",
             (int)s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_POS],
@@ -279,7 +288,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
     frame->data[0] += s->y * frame->linesize[0];
     frame->data[0] += s->x * s->max_step[0];
 
-    if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)) {
+    if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & FF_PSEUDOPAL)) {
         for (i = 1; i < 3; i ++) {
             if (frame->data[i]) {
                 frame->data[i] += (s->y >> s->vsub) * frame->linesize[i];
@@ -344,6 +353,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 },
+    { "exact",       "do exact cropping",                    OFFSET(exact),  AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
     { NULL }
 };