LCOV - code coverage report
Current view: top level - libavfilter - vf_deblock.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 81 0.0 %
Date: 2018-05-20 11:54:08 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018 Paul B Mahol
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Lesser General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2.1 of the License, or (at your option) any later version.
      10             :  *
      11             :  * FFmpeg is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with FFmpeg; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : /*
      22             :  * Based on paper: A Simple and Efficient Deblocking Algorithm for Low Bit-Rate Video Coding.
      23             :  */
      24             : 
      25             : #include "libavutil/imgutils.h"
      26             : #include "libavutil/opt.h"
      27             : #include "libavutil/pixdesc.h"
      28             : 
      29             : #include "avfilter.h"
      30             : #include "formats.h"
      31             : #include "internal.h"
      32             : #include "video.h"
      33             : 
      34             : enum FilterType { WEAK, STRONG, NB_FILTER };
      35             : 
      36             : typedef struct DeblockContext {
      37             :     const AVClass *class;
      38             :     const AVPixFmtDescriptor *desc;
      39             :     int filter;
      40             :     int block;
      41             :     int planes;
      42             :     float alpha;
      43             :     float beta;
      44             :     float gamma;
      45             :     float delta;
      46             : 
      47             :     int ath;
      48             :     int bth;
      49             :     int gth;
      50             :     int dth;
      51             :     int max;
      52             :     int depth;
      53             :     int bpc;
      54             :     int nb_planes;
      55             :     int planewidth[4];
      56             :     int planeheight[4];
      57             : 
      58             :     void (*deblockh)(uint8_t *dst, ptrdiff_t dst_linesize, int block,
      59             :                      int ath, int bth, int gth, int dth, int max);
      60             :     void (*deblockv)(uint8_t *dst, ptrdiff_t dst_linesize, int block,
      61             :                      int ath, int bth, int gth, int dth, int max);
      62             : } DeblockContext;
      63             : 
      64           0 : static int query_formats(AVFilterContext *ctx)
      65             : {
      66             :     static const enum AVPixelFormat pixel_fmts[] = {
      67             :         AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P,
      68             :         AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P,
      69             :         AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P,
      70             :         AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
      71             :         AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P,
      72             :         AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9,
      73             :         AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
      74             :         AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12,
      75             :         AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14,
      76             :         AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16,
      77             :         AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
      78             :         AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
      79             :         AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16,
      80             :         AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
      81             :         AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16,
      82             :         AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16,
      83             :         AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY16,
      84             :         AV_PIX_FMT_NONE
      85             :     };
      86           0 :     AVFilterFormats *formats = ff_make_format_list(pixel_fmts);
      87           0 :     if (!formats)
      88           0 :         return AVERROR(ENOMEM);
      89           0 :     return ff_set_common_formats(ctx, formats);
      90             : }
      91             : 
      92             : #define WEAK_HFILTER(name, type, ldiv)                                              \
      93             : static void deblockh##name##_weak(uint8_t *dstp, ptrdiff_t dst_linesize, int block, \
      94             :                                   int ath, int bth, int gth, int dth, int max)      \
      95             : {                                                                                   \
      96             :     type *dst;                                                                      \
      97             :     int x;                                                                          \
      98             :                                                                                     \
      99             :     dst = (type *)dstp;                                                             \
     100             :     dst_linesize /= ldiv;                                                           \
     101             :                                                                                     \
     102             :     for (x = 0; x < block; x++) {                                                   \
     103             :         int delta = dst[x] - dst[x - dst_linesize];                                 \
     104             :         int A, B, C, D, a, b, c, d;                                                 \
     105             :                                                                                     \
     106             :         if (FFABS(delta) >= ath ||                                                  \
     107             :             FFABS(dst[x - 1 * dst_linesize] - dst[x - 2 * dst_linesize]) >= bth ||  \
     108             :             FFABS(dst[x + 0 * dst_linesize] - dst[x + 1 * dst_linesize]) >= gth)    \
     109             :             continue;                                                               \
     110             :                                                                                     \
     111             :         A = dst[x - 2 * dst_linesize];                                              \
     112             :         B = dst[x - 1 * dst_linesize];                                              \
     113             :         C = dst[x + 0 * dst_linesize];                                              \
     114             :         D = dst[x + 1 * dst_linesize];                                              \
     115             :                                                                                     \
     116             :         a = A + delta / 8;                                                          \
     117             :         b = B + delta / 2;                                                          \
     118             :         c = C - delta / 2;                                                          \
     119             :         d = D - delta / 8;                                                          \
     120             :                                                                                     \
     121             :         dst[x - 2 * dst_linesize] = av_clip(a, 0, max);                             \
     122             :         dst[x - 1 * dst_linesize] = av_clip(b, 0, max);                             \
     123             :         dst[x + 0 * dst_linesize] = av_clip(c, 0, max);                             \
     124             :         dst[x + 1 * dst_linesize] = av_clip(d, 0, max);                             \
     125             :     }                                                                               \
     126             : }
     127             : 
     128           0 : WEAK_HFILTER(8, uint8_t, 1)
     129           0 : WEAK_HFILTER(16, uint16_t, 2)
     130             : 
     131             : #define WEAK_VFILTER(name, type, ldiv)                                              \
     132             : static void deblockv##name##_weak(uint8_t *dstp, ptrdiff_t dst_linesize, int block, \
     133             :                                   int ath, int bth, int gth, int dth, int max)      \
     134             : {                                                                                   \
     135             :     type *dst;                                                                      \
     136             :     int y;                                                                          \
     137             :                                                                                     \
     138             :     dst = (type *)dstp;                                                             \
     139             :     dst_linesize /= ldiv;                                                           \
     140             :                                                                                     \
     141             :     for (y = 0; y < block; y++) {                                                   \
     142             :         int delta = dst[0] - dst[-1];                                               \
     143             :         int A, B, C, D, a, b, c, d;                                                 \
     144             :                                                                                     \
     145             :         if (FFABS(delta) >= ath ||                                                  \
     146             :             FFABS(dst[-1] - dst[-2]) >= bth ||                                      \
     147             :             FFABS(dst[0] - dst[1]) >= gth)                                          \
     148             :             continue;                                                               \
     149             :                                                                                     \
     150             :         A = dst[-2];                                                                \
     151             :         B = dst[-1];                                                                \
     152             :         C = dst[+0];                                                                \
     153             :         D = dst[+1];                                                                \
     154             :                                                                                     \
     155             :         a = A + delta / 8;                                                          \
     156             :         b = B + delta / 2;                                                          \
     157             :         c = C - delta / 2;                                                          \
     158             :         d = D - delta / 8;                                                          \
     159             :                                                                                     \
     160             :         dst[-2] = av_clip(a, 0, max);                                               \
     161             :         dst[-1] = av_clip(b, 0, max);                                               \
     162             :         dst[+0] = av_clip(c, 0, max);                                               \
     163             :         dst[+1] = av_clip(d, 0, max);                                               \
     164             :                                                                                     \
     165             :         dst += dst_linesize;                                                        \
     166             :     }                                                                               \
     167             : }
     168             : 
     169           0 : WEAK_VFILTER(8, uint8_t, 1)
     170           0 : WEAK_VFILTER(16, uint16_t, 2)
     171             : 
     172             : #define STRONG_HFILTER(name, type, ldiv)                                           \
     173             : static void deblockh##name##_strong(uint8_t *dstp, ptrdiff_t dst_linesize, int block,\
     174             :                                     int ath, int bth, int gth, int dth, int max)   \
     175             : {                                                                                  \
     176             :     type *dst;                                                                     \
     177             :     int x;                                                                         \
     178             :                                                                                    \
     179             :     dst = (type *)dstp;                                                            \
     180             :     dst_linesize /= ldiv;                                                          \
     181             :                                                                                    \
     182             :     for (x = 0; x < block; x++) {                                                  \
     183             :         int A, B, C, D, E, F, a, b, c, d, e, f;                                    \
     184             :         int delta = dst[x] - dst[x - dst_linesize];                                \
     185             :                                                                                    \
     186             :         if (FFABS(delta) >= ath ||                                                 \
     187             :             FFABS(dst[x - 1 * dst_linesize] - dst[x - 2 * dst_linesize]) >= bth || \
     188             :             FFABS(dst[x + 1 * dst_linesize] - dst[x + 2 * dst_linesize]) >= gth || \
     189             :             FFABS(dst[x + 0 * dst_linesize] - dst[x + 1 * dst_linesize]) >= dth)   \
     190             :             continue;                                                              \
     191             :                                                                                    \
     192             :         A = dst[x - 3 * dst_linesize];                                             \
     193             :         B = dst[x - 2 * dst_linesize];                                             \
     194             :         C = dst[x - 1 * dst_linesize];                                             \
     195             :         D = dst[x + 0 * dst_linesize];                                             \
     196             :         E = dst[x + 1 * dst_linesize];                                             \
     197             :         F = dst[x + 2 * dst_linesize];                                             \
     198             :                                                                                    \
     199             :         a = A + delta / 8;                                                         \
     200             :         b = B + delta / 4;                                                         \
     201             :         c = C + delta / 2;                                                         \
     202             :         d = D - delta / 2;                                                         \
     203             :         e = E - delta / 4;                                                         \
     204             :         f = F - delta / 8;                                                         \
     205             :                                                                                    \
     206             :         dst[x - 3 * dst_linesize] = av_clip(a, 0, max);                            \
     207             :         dst[x - 2 * dst_linesize] = av_clip(b, 0, max);                            \
     208             :         dst[x - 1 * dst_linesize] = av_clip(c, 0, max);                            \
     209             :         dst[x + 0 * dst_linesize] = av_clip(d, 0, max);                            \
     210             :         dst[x + 1 * dst_linesize] = av_clip(e, 0, max);                            \
     211             :         dst[x + 2 * dst_linesize] = av_clip(f, 0, max);                            \
     212             :     }                                                                              \
     213             : }
     214             : 
     215           0 : STRONG_HFILTER(8, uint8_t, 1)
     216           0 : STRONG_HFILTER(16, uint16_t, 2)
     217             : 
     218             : #define STRONG_VFILTER(name, type, ldiv)                                           \
     219             : static void deblockv##name##_strong(uint8_t *dstp, ptrdiff_t dst_linesize, int block,\
     220             :                                     int ath, int bth, int gth, int dth, int max)   \
     221             : {                                                                                  \
     222             :     type *dst;                                                                     \
     223             :     int y;                                                                         \
     224             :                                                                                    \
     225             :     dst = (type *)dstp;                                                            \
     226             :     dst_linesize /= ldiv;                                                          \
     227             :                                                                                    \
     228             :     for (y = 0; y < block; y++) {                                                  \
     229             :         int A, B, C, D, E, F, a, b, c, d, e, f;                                    \
     230             :         int delta = dst[0] - dst[-1];                                              \
     231             :                                                                                    \
     232             :         if (FFABS(delta) >= ath ||                                                 \
     233             :             FFABS(dst[-1] - dst[-2]) >= bth ||                                     \
     234             :             FFABS(dst[+1] - dst[+2]) >= gth ||                                     \
     235             :             FFABS(dst[+0] - dst[+1]) >= dth)                                       \
     236             :             continue;                                                              \
     237             :                                                                                    \
     238             :         A = dst[-3];                                                               \
     239             :         B = dst[-2];                                                               \
     240             :         C = dst[-1];                                                               \
     241             :         D = dst[+0];                                                               \
     242             :         E = dst[+1];                                                               \
     243             :         F = dst[+2];                                                               \
     244             :                                                                                    \
     245             :         a = A + delta / 8;                                                         \
     246             :         b = B + delta / 4;                                                         \
     247             :         c = C + delta / 2;                                                         \
     248             :         d = D - delta / 2;                                                         \
     249             :         e = E - delta / 4;                                                         \
     250             :         f = F - delta / 8;                                                         \
     251             :                                                                                    \
     252             :         dst[-3] = av_clip(a, 0, max);                                              \
     253             :         dst[-2] = av_clip(b, 0, max);                                              \
     254             :         dst[-1] = av_clip(c, 0, max);                                              \
     255             :         dst[+0] = av_clip(d, 0, max);                                              \
     256             :         dst[+1] = av_clip(e, 0, max);                                              \
     257             :         dst[+2] = av_clip(f, 0, max);                                              \
     258             :                                                                                    \
     259             :         dst += dst_linesize;                                                       \
     260             :     }                                                                              \
     261             : }
     262             : 
     263           0 : STRONG_VFILTER(8, uint8_t, 1)
     264           0 : STRONG_VFILTER(16, uint16_t, 2)
     265             : 
     266           0 : static int config_output(AVFilterLink *outlink)
     267             : {
     268           0 :     AVFilterContext *ctx = outlink->src;
     269           0 :     DeblockContext *s = ctx->priv;
     270           0 :     AVFilterLink *inlink = ctx->inputs[0];
     271             : 
     272           0 :     s->desc = av_pix_fmt_desc_get(outlink->format);
     273           0 :     if (!s->desc)
     274           0 :         return AVERROR_BUG;
     275           0 :     s->nb_planes = av_pix_fmt_count_planes(outlink->format);
     276           0 :     s->depth = s->desc->comp[0].depth;
     277           0 :     s->bpc = (s->depth + 7) / 8;
     278           0 :     s->max = (1 << s->depth) - 1;
     279           0 :     s->ath = s->alpha * s->max;
     280           0 :     s->bth = s->beta  * s->max;
     281           0 :     s->gth = s->gamma * s->max;
     282           0 :     s->dth = s->delta * s->max;
     283             : 
     284           0 :     if (s->depth <= 8 && s->filter == WEAK) {
     285           0 :         s->deblockh = deblockh8_weak;
     286           0 :         s->deblockv = deblockv8_weak;
     287           0 :     } else if (s->depth >= 8 && s->filter == WEAK) {
     288           0 :         s->deblockh = deblockh16_weak;
     289           0 :         s->deblockv = deblockv16_weak;
     290             :     }
     291           0 :     if (s->depth <= 8 && s->filter == STRONG) {
     292           0 :         s->deblockh = deblockh8_strong;
     293           0 :         s->deblockv = deblockv8_strong;
     294           0 :     } else if (s->depth >= 8 && s->filter == STRONG) {
     295           0 :         s->deblockh = deblockh16_strong;
     296           0 :         s->deblockv = deblockv16_strong;
     297             :     }
     298             : 
     299           0 :     s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, s->desc->log2_chroma_w);
     300           0 :     s->planewidth[0] = s->planewidth[3] = inlink->w;
     301             : 
     302           0 :     s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h);
     303           0 :     s->planeheight[0] = s->planeheight[3] = inlink->h;
     304             : 
     305           0 :     return 0;
     306             : }
     307             : 
     308           0 : static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     309             : {
     310           0 :     AVFilterContext *ctx = inlink->dst;
     311           0 :     AVFilterLink *outlink = ctx->outputs[0];
     312           0 :     DeblockContext *s = ctx->priv;
     313           0 :     const int block = s->block;
     314             :     AVFrame *out;
     315             :     int plane, x, y;
     316             : 
     317           0 :     if (av_frame_is_writable(in)) {
     318           0 :         out = in;
     319             :     } else {
     320           0 :         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     321           0 :         if (!out) {
     322           0 :             av_frame_free(&in);
     323           0 :             return AVERROR(ENOMEM);
     324             :         }
     325           0 :         av_frame_copy_props(out, in);
     326             :     }
     327             : 
     328           0 :     for (plane = 0; plane < s->nb_planes; plane++) {
     329           0 :         const int width = s->planewidth[plane];
     330           0 :         const int height = s->planeheight[plane];
     331           0 :         const uint8_t *src = (const uint8_t *)in->data[plane];
     332           0 :         uint8_t *dst = (uint8_t *)out->data[plane];
     333             : 
     334           0 :         if (in != out)
     335           0 :             av_image_copy_plane(dst, out->linesize[plane],
     336           0 :                                 src, in->linesize[plane],
     337           0 :                                 width * s->bpc, height);
     338             : 
     339           0 :         if (!((1 << plane) & s->planes))
     340           0 :             continue;
     341             : 
     342           0 :         for (x = block; x < width; x += block)
     343           0 :             s->deblockv(dst + x * s->bpc, out->linesize[plane],
     344             :                         FFMIN(block, height), s->ath, s->bth, s->gth, s->dth, s->max);
     345             : 
     346           0 :         for (y = block; y < height; y += block) {
     347           0 :             dst += out->linesize[plane] * block;
     348             : 
     349           0 :             s->deblockh(dst, out->linesize[plane],
     350             :                         FFMIN(block, width),
     351             :                         s->ath, s->bth, s->gth, s->dth, s->max);
     352             : 
     353           0 :             for (x = block; x < width; x += block) {
     354           0 :                 s->deblockh(dst + x * s->bpc, out->linesize[plane],
     355           0 :                             FFMIN(block, width - x),
     356             :                             s->ath, s->bth, s->gth, s->dth, s->max);
     357           0 :                 s->deblockv(dst + x * s->bpc, out->linesize[plane],
     358           0 :                             FFMIN(block, height - y),
     359             :                             s->ath, s->bth, s->gth, s->dth, s->max);
     360             :             }
     361             :         }
     362             :     }
     363             : 
     364           0 :     if (in != out)
     365           0 :         av_frame_free(&in);
     366           0 :     return ff_filter_frame(outlink, out);
     367             : }
     368             : 
     369             : #define OFFSET(x) offsetof(DeblockContext, x)
     370             : #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
     371             : 
     372             : static const AVOption deblock_options[] = {
     373             :     { "filter",    "set type of filter",          OFFSET(filter),    AV_OPT_TYPE_INT,   {.i64=STRONG},0, 1,  FLAGS, "filter" },
     374             :     { "weak",      0,                             0,                 AV_OPT_TYPE_CONST, {.i64=WEAK},  0, 0,  FLAGS, "filter" },
     375             :     { "strong",    0,                             0,                 AV_OPT_TYPE_CONST, {.i64=STRONG},0, 0,  FLAGS, "filter" },
     376             :     { "block",     "set size of block",           OFFSET(block),     AV_OPT_TYPE_INT,   {.i64=8},    4, 512, FLAGS },
     377             :     { "alpha",     "set 1st detection threshold", OFFSET(alpha),     AV_OPT_TYPE_FLOAT, {.dbl=.098}, 0,  1,  FLAGS },
     378             :     { "beta",      "set 2nd detection threshold", OFFSET(beta),      AV_OPT_TYPE_FLOAT, {.dbl=.05},  0,  1,  FLAGS },
     379             :     { "gamma",     "set 3rd detection threshold", OFFSET(gamma),     AV_OPT_TYPE_FLOAT, {.dbl=.05},  0,  1,  FLAGS },
     380             :     { "delta",     "set 4th detection threshold", OFFSET(delta),     AV_OPT_TYPE_FLOAT, {.dbl=.05},  0,  1,  FLAGS },
     381             :     { "planes",    "set planes to filter",        OFFSET(planes),    AV_OPT_TYPE_INT,   {.i64=15},   0, 15,  FLAGS },
     382             :     { NULL },
     383             : };
     384             : 
     385             : static const AVFilterPad inputs[] = {
     386             :     {
     387             :         .name           = "default",
     388             :         .type           = AVMEDIA_TYPE_VIDEO,
     389             :         .filter_frame   = filter_frame,
     390             :     },
     391             :     { NULL }
     392             : };
     393             : 
     394             : static const AVFilterPad outputs[] = {
     395             :     {
     396             :         .name          = "default",
     397             :         .type          = AVMEDIA_TYPE_VIDEO,
     398             :         .config_props  = config_output,
     399             :     },
     400             :     { NULL }
     401             : };
     402             : 
     403             : AVFILTER_DEFINE_CLASS(deblock);
     404             : 
     405             : AVFilter ff_vf_deblock = {
     406             :     .name          = "deblock",
     407             :     .description   = NULL_IF_CONFIG_SMALL("Deblock video."),
     408             :     .priv_size     = sizeof(DeblockContext),
     409             :     .priv_class    = &deblock_class,
     410             :     .query_formats = query_formats,
     411             :     .inputs        = inputs,
     412             :     .outputs       = outputs,
     413             :     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     414             : };

Generated by: LCOV version 1.13