[FFmpeg-devel] [PATCH] lavfi: use ceil right shift for chroma width/height.

Clément Bœsch ubitux at gmail.com
Thu May 9 18:14:34 CEST 2013


This should fix several issues with odd dimensions inputs.

---
Note: this is mostly untested
---
 libavfilter/vf_blend.c         |  4 ++--
 libavfilter/vf_boxblur.c       |  2 +-
 libavfilter/vf_decimate.c      |  4 ++--
 libavfilter/vf_delogo.c        |  6 ++++--
 libavfilter/vf_extractplanes.c |  4 ++--
 libavfilter/vf_fade.c          |  3 ++-
 libavfilter/vf_fieldmatch.c    |  8 ++++----
 libavfilter/vf_geq.c           |  8 ++++----
 libavfilter/vf_hflip.c         | 20 ++++++++++----------
 libavfilter/vf_hqdn3d.c        |  4 ++--
 libavfilter/vf_hue.c           |  3 ++-
 libavfilter/vf_il.c            |  2 +-
 libavfilter/vf_interlace.c     |  2 +-
 libavfilter/vf_kerndeint.c     |  2 +-
 libavfilter/vf_mpdecimate.c    |  3 ++-
 libavfilter/vf_noise.c         |  2 +-
 libavfilter/vf_showinfo.c      |  2 +-
 libavfilter/vf_smartblur.c     |  7 ++++---
 libavfilter/vf_telecine.c      |  2 +-
 libavfilter/vf_tinterlace.c    |  2 +-
 libavfilter/vf_transpose.c     |  4 ++--
 21 files changed, 50 insertions(+), 44 deletions(-)

diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
index b4c62ba..a0022cd 100644
--- a/libavfilter/vf_blend.c
+++ b/libavfilter/vf_blend.c
@@ -372,8 +372,8 @@ static void blend_frame(AVFilterContext *ctx,
     for (plane = 0; plane < b->nb_planes; plane++) {
         int hsub = plane == 1 || plane == 2 ? b->hsub : 0;
         int vsub = plane == 1 || plane == 2 ? b->vsub : 0;
-        int outw = dst_buf->width  >> hsub;
-        int outh = dst_buf->height >> vsub;
+        int outw = FF_CEIL_RSHIFT(dst_buf->width,  hsub);
+        int outh = FF_CEIL_RSHIFT(dst_buf->height, vsub);
         uint8_t *dst    = dst_buf->data[plane];
         uint8_t *top    = top_buf->data[plane];
         uint8_t *bottom = bottom_buf->data[plane];
diff --git a/libavfilter/vf_boxblur.c b/libavfilter/vf_boxblur.c
index b010670..a8a2014 100644
--- a/libavfilter/vf_boxblur.c
+++ b/libavfilter/vf_boxblur.c
@@ -302,7 +302,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     AVFilterLink *outlink = inlink->dst->outputs[0];
     AVFrame *out;
     int plane;
-    int cw = inlink->w >> boxblur->hsub, ch = in->height >> boxblur->vsub;
+    int cw = FF_CEIL_RSHIFT(inlink->w, boxblur->hsub), ch = FF_CEIL_RSHIFT(in->height, boxblur->vsub);
     int w[4] = { inlink->w, cw, cw, inlink->w };
     int h[4] = { in->height, ch, ch, in->height };
 
diff --git a/libavfilter/vf_decimate.c b/libavfilter/vf_decimate.c
index 9548531..8767d5f 100644
--- a/libavfilter/vf_decimate.c
+++ b/libavfilter/vf_decimate.c
@@ -92,8 +92,8 @@ static void calc_diffs(const DecimateContext *dm, struct qitem *q,
         const int linesize2 = f2->linesize[plane];
         const uint8_t *f1p = f1->data[plane];
         const uint8_t *f2p = f2->data[plane];
-        int width    = plane ? f1->width  >> dm->hsub : f1->width;
-        int height   = plane ? f1->height >> dm->vsub : f1->height;
+        int width    = plane ? FF_CEIL_RSHIFT(f1->width,  dm->hsub) : f1->width;
+        int height   = plane ? FF_CEIL_RSHIFT(f1->height, dm->vsub) : f1->height;
         int hblockx  = dm->blockx / 2;
         int hblocky  = dm->blocky / 2;
 
diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c
index c747b02..b644190 100644
--- a/libavfilter/vf_delogo.c
+++ b/libavfilter/vf_delogo.c
@@ -228,9 +228,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
         apply_delogo(out->data[plane], out->linesize[plane],
                      in ->data[plane], in ->linesize[plane],
-                     inlink->w>>hsub, inlink->h>>vsub,
+                     FF_CEIL_RSHIFT(inlink->w, hsub),
+                     FF_CEIL_RSHIFT(inlink->h, vsub),
                      delogo->x>>hsub, delogo->y>>vsub,
-                     delogo->w>>hsub, delogo->h>>vsub,
+                     FF_CEIL_RSHIFT(delogo->w, hsub),
+                     FF_CEIL_RSHIFT(delogo->h, vsub),
                      delogo->band>>FFMIN(hsub, vsub),
                      delogo->show, direct);
     }
diff --git a/libavfilter/vf_extractplanes.c b/libavfilter/vf_extractplanes.c
index 229e3d5..9844ed5 100644
--- a/libavfilter/vf_extractplanes.c
+++ b/libavfilter/vf_extractplanes.c
@@ -171,8 +171,8 @@ static int config_output(AVFilterLink *outlink)
     const int output = outlink->srcpad - ctx->output_pads;
 
     if (e->map[output] == 1 || e->map[output] == 2) {
-        outlink->h = inlink->h >> desc->log2_chroma_h;
-        outlink->w = inlink->w >> desc->log2_chroma_w;
+        outlink->h = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
+        outlink->w = FF_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
     }
 
     return 0;
diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
index 4dbd4c7..4f7039e 100644
--- a/libavfilter/vf_fade.c
+++ b/libavfilter/vf_fade.c
@@ -233,8 +233,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
                 /* chroma planes */
                 for (plane = 1; plane < 3; plane++) {
                     for (i = 0; i < frame->height; i++) {
+                        const int width = FF_CEIL_RSHIFT(inlink->w, fade->hsub);
                         p = frame->data[plane] + (i >> fade->vsub) * frame->linesize[plane];
-                        for (j = 0; j < inlink->w >> fade->hsub; j++) {
+                        for (j = 0; j < width; j++) {
                             /* 8421367 = ((128 << 1) + 1) << 15. It is an integer
                              * representation of 128.5. The .5 is for rounding
                              * purposes. */
diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c
index 3495895..3a6f806 100644
--- a/libavfilter/vf_fieldmatch.c
+++ b/libavfilter/vf_fieldmatch.c
@@ -153,12 +153,12 @@ AVFILTER_DEFINE_CLASS(fieldmatch);
 
 static int get_width(const FieldMatchContext *fm, const AVFrame *f, int plane)
 {
-    return plane ? f->width >> fm->hsub : f->width;
+    return plane ? FF_CEIL_RSHIFT(f->width, fm->hsub) : f->width;
 }
 
 static int get_height(const FieldMatchContext *fm, const AVFrame *f, int plane)
 {
-    return plane ? f->height >> fm->vsub : f->height;
+    return plane ? FF_CEIL_RSHIFT(f->height, fm->vsub) : f->height;
 }
 
 static int64_t luma_abs_diff(const AVFrame *f1, const AVFrame *f2)
@@ -270,8 +270,8 @@ static int calc_combed_score(const FieldMatchContext *fm, const AVFrame *src)
         uint8_t *cmkp  = fm->cmask_data[0];
         uint8_t *cmkpU = fm->cmask_data[1];
         uint8_t *cmkpV = fm->cmask_data[2];
-        const int width  = src->width  >> fm->hsub;
-        const int height = src->height >> fm->vsub;
+        const int width  = FF_CEIL_RSHIFT(src->width,  fm->hsub);
+        const int height = FF_CEIL_RSHIFT(src->height, fm->vsub);
         const int cmk_linesize   = fm->cmask_linesize[0] << 1;
         const int cmk_linesizeUV = fm->cmask_linesize[2];
         uint8_t *cmkpp  = cmkp - (cmk_linesize>>1);
diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c
index a5396f8..5ee75d1 100644
--- a/libavfilter/vf_geq.c
+++ b/libavfilter/vf_geq.c
@@ -66,8 +66,8 @@ static inline double getpix(void *priv, double x, double y, int plane)
     AVFrame *picref = geq->picref;
     const uint8_t *src = picref->data[plane];
     const int linesize = picref->linesize[plane];
-    const int w = picref->width  >> ((plane == 1 || plane == 2) ? geq->hsub : 0);
-    const int h = picref->height >> ((plane == 1 || plane == 2) ? geq->vsub : 0);
+    const int w = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(picref->width,  geq->hsub) : picref->width;
+    const int h = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(picref->height, geq->vsub) : picref->height;
 
     if (!src)
         return 0;
@@ -209,8 +209,8 @@ static int geq_filter_frame(AVFilterLink *inlink, AVFrame *in)
         int x, y;
         uint8_t *dst = out->data[plane];
         const int linesize = out->linesize[plane];
-        const int w = inlink->w >> ((plane == 1 || plane == 2) ? geq->hsub : 0);
-        const int h = inlink->h >> ((plane == 1 || plane == 2) ? geq->vsub : 0);
+        const int w = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->w, geq->hsub) : inlink->w;
+        const int h = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->h, geq->vsub) : inlink->h;
 
         values[VAR_W]  = w;
         values[VAR_H]  = h;
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index cb51981..0250b43 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -77,7 +77,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     AVFilterLink *outlink = ctx->outputs[0];
     AVFrame *out;
     uint8_t *inrow, *outrow;
-    int i, j, plane, step, hsub, vsub;
+    int i, j, plane, step;
 
     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     if (!out) {
@@ -91,16 +91,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         memcpy(out->data[1], in->data[1], AVPALETTE_SIZE);
 
     for (plane = 0; plane < 4 && in->data[plane]; plane++) {
+        const int width  = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->w, flip->hsub) : inlink->w;
+        const int height = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->h, flip->vsub) : inlink->h;
         step = flip->max_step[plane];
-        hsub = (plane == 1 || plane == 2) ? flip->hsub : 0;
-        vsub = (plane == 1 || plane == 2) ? flip->vsub : 0;
 
         outrow = out->data[plane];
-        inrow  = in ->data[plane] + ((inlink->w >> hsub) - 1) * step;
-        for (i = 0; i < in->height >> vsub; i++) {
+        inrow  = in ->data[plane] + (width - 1) * step;
+        for (i = 0; i < height; i++) {
             switch (step) {
             case 1:
-                for (j = 0; j < (inlink->w >> hsub); j++)
+                for (j = 0; j < width; j++)
                     outrow[j] = inrow[-j];
             break;
 
@@ -108,7 +108,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             {
                 uint16_t *outrow16 = (uint16_t *)outrow;
                 uint16_t * inrow16 = (uint16_t *) inrow;
-                for (j = 0; j < (inlink->w >> hsub); j++)
+                for (j = 0; j < width; j++)
                     outrow16[j] = inrow16[-j];
             }
             break;
@@ -117,7 +117,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             {
                 uint8_t *in  =  inrow;
                 uint8_t *out = outrow;
-                for (j = 0; j < (inlink->w >> hsub); j++, out += 3, in -= 3) {
+                for (j = 0; j < width; j++, out += 3, in -= 3) {
                     int32_t v = AV_RB24(in);
                     AV_WB24(out, v);
                 }
@@ -128,13 +128,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             {
                 uint32_t *outrow32 = (uint32_t *)outrow;
                 uint32_t * inrow32 = (uint32_t *) inrow;
-                for (j = 0; j < (inlink->w >> hsub); j++)
+                for (j = 0; j < width; j++)
                     outrow32[j] = inrow32[-j];
             }
             break;
 
             default:
-                for (j = 0; j < (inlink->w >> hsub); j++)
+                for (j = 0; j < width; j++)
                     memcpy(outrow + j*step, inrow - j*step, step);
             }
 
diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c
index 51adeb8..8e8f553 100644
--- a/libavfilter/vf_hqdn3d.c
+++ b/libavfilter/vf_hqdn3d.c
@@ -297,8 +297,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     for (c = 0; c < 3; c++) {
         denoise(hqdn3d, in->data[c], out->data[c],
                 hqdn3d->line, &hqdn3d->frame_prev[c],
-                in->width  >> (!!c * hqdn3d->hsub),
-                in->height >> (!!c * hqdn3d->vsub),
+                FF_CEIL_RSHIFT(in->width,  (!!c * hqdn3d->hsub)),
+                FF_CEIL_RSHIFT(in->height, (!!c * hqdn3d->vsub)),
                 in->linesize[c], out->linesize[c],
                 hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]);
     }
diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c
index c62cba8..cba39d0 100644
--- a/libavfilter/vf_hue.c
+++ b/libavfilter/vf_hue.c
@@ -305,7 +305,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
 
     process_chrominance(outpic->data[1], outpic->data[2], outpic->linesize[1],
                         inpic->data[1],  inpic->data[2],  inpic->linesize[1],
-                        inlink->w >> hue->hsub, inlink->h >> hue->vsub,
+                        FF_CEIL_RSHIFT(inlink->w, hue->hsub),
+                        FF_CEIL_RSHIFT(inlink->h, hue->vsub),
                         hue->hue_cos, hue->hue_sin);
 
     if (!direct)
diff --git a/libavfilter/vf_il.c b/libavfilter/vf_il.c
index 7edd042..783b91a 100644
--- a/libavfilter/vf_il.c
+++ b/libavfilter/vf_il.c
@@ -110,7 +110,7 @@ static int config_input(AVFilterLink *inlink)
     if ((ret = av_image_fill_linesizes(il->linesize, inlink->format, inlink->w)) < 0)
         return ret;
 
-    il->chroma_height = inlink->h >> desc->log2_chroma_h;
+    il->chroma_height = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
 
     return 0;
 }
diff --git a/libavfilter/vf_interlace.c b/libavfilter/vf_interlace.c
index 3e787ab..3315fb0 100644
--- a/libavfilter/vf_interlace.c
+++ b/libavfilter/vf_interlace.c
@@ -131,7 +131,7 @@ static void copy_picture_field(AVFrame *src_frame, AVFrame *dst_frame,
     int plane, i, j;
 
     for (plane = 0; plane < desc->nb_components; plane++) {
-        int lines = (plane == 1 || plane == 2) ? inlink->h >> vsub : inlink->h;
+        int lines = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->h, vsub) : inlink->h;
         int linesize = av_image_get_linesize(inlink->format, inlink->w, plane);
         uint8_t *dstp = dst_frame->data[plane];
         const uint8_t *srcp = src_frame->data[plane];
diff --git a/libavfilter/vf_kerndeint.c b/libavfilter/vf_kerndeint.c
index 8a44868..431a0a9 100644
--- a/libavfilter/vf_kerndeint.c
+++ b/libavfilter/vf_kerndeint.c
@@ -151,7 +151,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
     outpic->interlaced_frame = 0;
 
     for (plane = 0; inpic->data[plane] && plane < 4; plane++) {
-        h = plane == 0 ? inlink->h : inlink->h >> kerndeint->vsub;
+        h = plane == 0 ? inlink->h : FF_CEIL_RSHIFT(inlink->h, kerndeint->vsub);
         bwidth = kerndeint->tmp_bwidth[plane];
 
         srcp = srcp_saved = inpic->data[plane];
diff --git a/libavfilter/vf_mpdecimate.c b/libavfilter/vf_mpdecimate.c
index 2e386f7..45d510b 100644
--- a/libavfilter/vf_mpdecimate.c
+++ b/libavfilter/vf_mpdecimate.c
@@ -122,7 +122,8 @@ static int decimate_frame(AVFilterContext *ctx,
         int hsub = plane == 1 || plane == 2 ? decimate->hsub : 0;
         if (diff_planes(ctx,
                         cur->data[plane], ref->data[plane], ref->linesize[plane],
-                        ref->width>>hsub, ref->height>>vsub))
+                        FF_CEIL_RSHIFT(ref->width,  hsub),
+                        FF_CEIL_RSHIFT(ref->height, vsub)))
             return 0;
     }
 
diff --git a/libavfilter/vf_noise.c b/libavfilter/vf_noise.c
index c965cbf..da418fe 100644
--- a/libavfilter/vf_noise.c
+++ b/libavfilter/vf_noise.c
@@ -193,7 +193,7 @@ static int config_input(AVFilterLink *inlink)
     if ((ret = av_image_fill_linesizes(n->linesize, inlink->format, inlink->w)) < 0)
         return ret;
 
-    n->height[1] = n->height[2] = inlink->h >> desc->log2_chroma_h;
+    n->height[1] = n->height[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
     n->height[0] = n->height[3] = inlink->h;
 
     return 0;
diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c
index dd97843..9acadcf 100644
--- a/libavfilter/vf_showinfo.c
+++ b/libavfilter/vf_showinfo.c
@@ -46,7 +46,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
     for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
         int64_t linesize = av_image_get_linesize(frame->format, frame->width, plane);
         uint8_t *data = frame->data[plane];
-        int h = plane == 1 || plane == 2 ? inlink->h >> vsub : inlink->h;
+        int h = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT(inlink->h, vsub) : inlink->h;
 
         if (linesize < 0)
             return linesize;
diff --git a/libavfilter/vf_smartblur.c b/libavfilter/vf_smartblur.c
index 4dd1664..daf7451 100644
--- a/libavfilter/vf_smartblur.c
+++ b/libavfilter/vf_smartblur.c
@@ -166,7 +166,8 @@ static int config_props(AVFilterLink *inlink)
 
     alloc_sws_context(&sblur->luma, inlink->w, inlink->h, sblur->sws_flags);
     alloc_sws_context(&sblur->chroma,
-                      inlink->w >> sblur->hsub, inlink->h >> sblur->vsub,
+                      FF_CEIL_RSHIFT(inlink->w, sblur->hsub),
+                      FF_CEIL_RSHIFT(inlink->h, sblur->vsub),
                       sblur->sws_flags);
 
     return 0;
@@ -241,8 +242,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
     SmartblurContext  *sblur  = inlink->dst->priv;
     AVFilterLink *outlink     = inlink->dst->outputs[0];
     AVFrame *outpic;
-    int cw = inlink->w >> sblur->hsub;
-    int ch = inlink->h >> sblur->vsub;
+    int cw = FF_CEIL_RSHIFT(inlink->w, sblur->hsub);
+    int ch = FF_CEIL_RSHIFT(inlink->h, sblur->vsub);
 
     outpic = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     if (!outpic) {
diff --git a/libavfilter/vf_telecine.c b/libavfilter/vf_telecine.c
index e30f357..ba47da1 100644
--- a/libavfilter/vf_telecine.c
+++ b/libavfilter/vf_telecine.c
@@ -129,7 +129,7 @@ static int config_input(AVFilterLink *inlink)
     if ((ret = av_image_fill_linesizes(tc->stride, inlink->format, inlink->w)) < 0)
         return ret;
 
-    tc->planeheight[1] = tc->planeheight[2] = inlink->h >> desc->log2_chroma_h;
+    tc->planeheight[1] = tc->planeheight[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
     tc->planeheight[0] = tc->planeheight[3] = inlink->h;
 
     tc->nb_planes = av_pix_fmt_count_planes(inlink->format);
diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c
index f6bf054..5e89162 100644
--- a/libavfilter/vf_tinterlace.c
+++ b/libavfilter/vf_tinterlace.c
@@ -130,7 +130,7 @@ static int config_out_props(AVFilterLink *outlink)
 
         /* fill black picture with black */
         for (i = 0; i < 4 && tinterlace->black_data[i]; i++) {
-            int h = i == 1 || i == 2 ? outlink->h >> desc->log2_chroma_h : outlink->h;
+            int h = i == 1 || i == 2 ? FF_CEIL_RSHIFT(outlink->h, desc->log2_chroma_h) : outlink->h;
             memset(tinterlace->black_data[i], black[i],
                    tinterlace->black_linesize[i] * h);
         }
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index bd66a61..c949e07 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -163,8 +163,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         int vsub = plane == 1 || plane == 2 ? trans->vsub : 0;
         int pixstep = trans->pixsteps[plane];
         int inh  = in->height  >> vsub;
-        int outw = out->width  >> hsub;
-        int outh = out->height >> vsub;
+        int outw = FF_CEIL_RSHIFT(out->width,  hsub);
+        int outh = FF_CEIL_RSHIFT(out->height, vsub);
         uint8_t *dst, *src;
         int dstlinesize, srclinesize;
         int x, y;
-- 
1.8.2.2



More information about the ffmpeg-devel mailing list