LCOV - code coverage report
Current view: top level - src/tests/checkasm - vf_colorspace.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 165 169 97.6 %
Date: 2017-01-19 23:52:33 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com>
       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             : #include <string.h>
      22             : #include "checkasm.h"
      23             : #include "libavfilter/colorspacedsp.h"
      24             : #include "libavutil/common.h"
      25             : #include "libavutil/internal.h"
      26             : #include "libavutil/intreadwrite.h"
      27             : 
      28             : #define W 64
      29             : #define H 64
      30             : 
      31             : #define randomize_buffers()                     \
      32             :     do {                                        \
      33             :         unsigned mask = bpp_mask[idepth];       \
      34             :         int n, m;                               \
      35             :         int bpp = 1 + (!!idepth);               \
      36             :         int buf_size = W * H * bpp;             \
      37             :         for (m = 0; m < 3; m++) {               \
      38             :             int ss = m ? ss_w + ss_h : 0;       \
      39             :             int plane_sz = buf_size >> ss;      \
      40             :             for (n = 0; n < plane_sz; n += 4) { \
      41             :                 unsigned r = rnd() & mask;      \
      42             :                 AV_WN32A(&src[m][n], r);        \
      43             :             }                                   \
      44             :         }                                       \
      45             :     } while (0)
      46             : 
      47             : static const char *format_string[] = {
      48             :     "444", "422", "420"
      49             : };
      50             : 
      51             : static const unsigned bpp_mask[] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff };
      52             : 
      53          11 : static void check_yuv2yuv(void)
      54             : {
      55          11 :     declare_func(void, uint8_t *dst[3], ptrdiff_t dst_stride[3],
      56             :                  uint8_t *src[3], ptrdiff_t src_stride[3],
      57             :                  int w, int h, const int16_t coeff[3][3][8],
      58             :                  const int16_t off[2][8]);
      59             :     ColorSpaceDSPContext dsp;
      60             :     int idepth, odepth, fmt, n;
      61          11 :     LOCAL_ALIGNED_32(uint8_t, src_y, [W * H * 2]);
      62          11 :     LOCAL_ALIGNED_32(uint8_t, src_u, [W * H * 2]);
      63          11 :     LOCAL_ALIGNED_32(uint8_t, src_v, [W * H * 2]);
      64          11 :     uint8_t *src[3] = { src_y, src_u, src_v };
      65          11 :     LOCAL_ALIGNED_32(uint8_t, dst0_y, [W * H * 2]);
      66          11 :     LOCAL_ALIGNED_32(uint8_t, dst0_u, [W * H * 2]);
      67          11 :     LOCAL_ALIGNED_32(uint8_t, dst0_v, [W * H * 2]);
      68          11 :     LOCAL_ALIGNED_32(uint8_t, dst1_y, [W * H * 2]);
      69          11 :     LOCAL_ALIGNED_32(uint8_t, dst1_u, [W * H * 2]);
      70          11 :     LOCAL_ALIGNED_32(uint8_t, dst1_v, [W * H * 2]);
      71          11 :     uint8_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
      72          11 :     LOCAL_ALIGNED_32(int16_t, offset_buf, [16]);
      73          11 :     LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
      74          11 :     int16_t (*offset)[8] = (int16_t(*)[8]) offset_buf;
      75          11 :     int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
      76             : 
      77          11 :     ff_colorspacedsp_init(&dsp);
      78          99 :     for (n = 0; n < 8; n++) {
      79          88 :         offset[0][n] = offset[1][n] = 16;
      80             : 
      81          88 :         coeff[0][0][n] = (1 << 14) + (1 << 7) + 1;
      82          88 :         coeff[0][1][n] = (1 << 7) - 1;
      83          88 :         coeff[0][2][n] = -(1 << 8);
      84          88 :         coeff[1][0][n] = coeff[2][0][n] = 0;
      85          88 :         coeff[1][1][n] = (1 << 14) + (1 << 7);
      86          88 :         coeff[1][2][n] = -(1 << 7);
      87          88 :         coeff[2][2][n] = (1 << 14) - (1 << 6);
      88          88 :         coeff[2][1][n] = 1 << 6;
      89             :     }
      90          44 :     for (idepth = 0; idepth < 3; idepth++) {
      91         132 :         for (odepth = 0; odepth < 3; odepth++) {
      92         396 :             for (fmt = 0; fmt < 3; fmt++) {
      93         297 :                 if (check_func(dsp.yuv2yuv[idepth][odepth][fmt],
      94             :                                "ff_colorspacedsp_yuv2yuv_%sp%dto%d",
      95             :                                format_string[fmt],
      96             :                                idepth * 2 + 8, odepth * 2 + 8)) {
      97          54 :                     int ss_w = !!fmt, ss_h = fmt == 2;
      98          54 :                     int y_src_stride = W << !!idepth, y_dst_stride = W << !!odepth;
      99          54 :                     int uv_src_stride = y_src_stride >> ss_w, uv_dst_stride = y_dst_stride >> ss_w;
     100             : 
     101          54 :                     randomize_buffers();
     102          54 :                     call_ref(dst0, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
     103             :                              src, (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
     104             :                              W, H, coeff, offset);
     105          54 :                     call_new(dst1, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
     106             :                              src, (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
     107             :                              W, H, coeff, offset);
     108         108 :                     if (memcmp(dst0[0], dst1[0], y_dst_stride * H) ||
     109         108 :                         memcmp(dst0[1], dst1[1], uv_dst_stride * H >> ss_h) ||
     110          54 :                         memcmp(dst0[2], dst1[2], uv_dst_stride * H >> ss_h)) {
     111           0 :                         fail();
     112             :                     }
     113             :                 }
     114             :             }
     115             :         }
     116             :     }
     117             : 
     118          11 :     report("yuv2yuv");
     119          11 : }
     120             : 
     121          11 : static void check_yuv2rgb(void)
     122             : {
     123          11 :     declare_func(void, int16_t *dst[3], ptrdiff_t dst_stride,
     124             :                  uint8_t *src[3], ptrdiff_t src_stride[3],
     125             :                  int w, int h, const int16_t coeff[3][3][8],
     126             :                  const int16_t off[8]);
     127             :     ColorSpaceDSPContext dsp;
     128             :     int idepth, fmt, n;
     129          11 :     LOCAL_ALIGNED_32(uint8_t, src_y, [W * H * 2]);
     130          11 :     LOCAL_ALIGNED_32(uint8_t, src_u, [W * H * 2]);
     131          11 :     LOCAL_ALIGNED_32(uint8_t, src_v, [W * H * 2]);
     132          11 :     uint8_t *src[3] = { src_y, src_u, src_v };
     133          11 :     LOCAL_ALIGNED_32(int16_t, dst0_y, [W * H]);
     134          11 :     LOCAL_ALIGNED_32(int16_t, dst0_u, [W * H]);
     135          11 :     LOCAL_ALIGNED_32(int16_t, dst0_v, [W * H]);
     136          11 :     LOCAL_ALIGNED_32(int16_t, dst1_y, [W * H]);
     137          11 :     LOCAL_ALIGNED_32(int16_t, dst1_u, [W * H]);
     138          11 :     LOCAL_ALIGNED_32(int16_t, dst1_v, [W * H]);
     139          11 :     int16_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
     140          11 :     LOCAL_ALIGNED_32(int16_t, offset, [8]);
     141          11 :     LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
     142          11 :     int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
     143             : 
     144          11 :     ff_colorspacedsp_init(&dsp);
     145          99 :     for (n = 0; n < 8; n++) {
     146          88 :         offset[n] = 16;
     147             : 
     148          88 :         coeff[0][0][n] = coeff[1][0][n] = coeff[2][0][n] = (1 << 14) | 1;
     149          88 :         coeff[0][1][n] = coeff[2][2][n] = 0;
     150          88 :         coeff[0][2][n] = 1 << 13;
     151          88 :         coeff[1][1][n] = -(1 << 12);
     152          88 :         coeff[1][2][n] = 1 << 12;
     153          88 :         coeff[2][1][n] = 1 << 11;
     154             :     }
     155          44 :     for (idepth = 0; idepth < 3; idepth++) {
     156         132 :         for (fmt = 0; fmt < 3; fmt++) {
     157          99 :             if (check_func(dsp.yuv2rgb[idepth][fmt],
     158             :                            "ff_colorspacedsp_yuv2rgb_%sp%d",
     159             :                            format_string[fmt], idepth * 2 + 8)) {
     160          18 :                 int ss_w = !!fmt, ss_h = fmt == 2;
     161          18 :                 int y_src_stride = W << !!idepth;
     162          18 :                 int uv_src_stride = y_src_stride >> ss_w;
     163             : 
     164          18 :                 randomize_buffers();
     165          18 :                 call_ref(dst0, W, src,
     166             :                          (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
     167             :                          W, H, coeff, offset);
     168          18 :                 call_new(dst1, W, src,
     169             :                          (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
     170             :                          W, H, coeff, offset);
     171          36 :                 if (memcmp(dst0[0], dst1[0], W * H * sizeof(int16_t)) ||
     172          36 :                     memcmp(dst0[1], dst1[1], W * H * sizeof(int16_t)) ||
     173          18 :                     memcmp(dst0[2], dst1[2], W * H * sizeof(int16_t))) {
     174           0 :                     fail();
     175             :                 }
     176             :             }
     177             :         }
     178             :     }
     179             : 
     180          11 :     report("yuv2rgb");
     181          11 : }
     182             : 
     183             : #undef randomize_buffers
     184             : #define randomize_buffers()                     \
     185             :     do {                                        \
     186             :         int y, x, p;                            \
     187             :         for (p = 0; p < 3; p++) {               \
     188             :             for (y = 0; y < H; y++) {           \
     189             :                 for (x = 0; x < W; x++) {       \
     190             :                     int r = rnd() & 0x7fff;     \
     191             :                     r -= (32768 - 28672) >> 1;  \
     192             :                     src[p][y * W + x] = r;      \
     193             :                 }                               \
     194             :             }                                   \
     195             :         }                                       \
     196             :     } while (0)
     197             : 
     198          11 : static void check_rgb2yuv(void)
     199             : {
     200          11 :     declare_func(void, uint8_t *dst[3], ptrdiff_t dst_stride[3],
     201             :                  int16_t *src[3], ptrdiff_t src_stride,
     202             :                  int w, int h, const int16_t coeff[3][3][8],
     203             :                  const int16_t off[8]);
     204             :     ColorSpaceDSPContext dsp;
     205             :     int odepth, fmt, n;
     206          11 :     LOCAL_ALIGNED_32(int16_t, src_y, [W * H * 2]);
     207          11 :     LOCAL_ALIGNED_32(int16_t, src_u, [W * H * 2]);
     208          11 :     LOCAL_ALIGNED_32(int16_t, src_v, [W * H * 2]);
     209          11 :     int16_t *src[3] = { src_y, src_u, src_v };
     210          11 :     LOCAL_ALIGNED_32(uint8_t, dst0_y, [W * H * 2]);
     211          11 :     LOCAL_ALIGNED_32(uint8_t, dst0_u, [W * H * 2]);
     212          11 :     LOCAL_ALIGNED_32(uint8_t, dst0_v, [W * H * 2]);
     213          11 :     LOCAL_ALIGNED_32(uint8_t, dst1_y, [W * H * 2]);
     214          11 :     LOCAL_ALIGNED_32(uint8_t, dst1_u, [W * H * 2]);
     215          11 :     LOCAL_ALIGNED_32(uint8_t, dst1_v, [W * H * 2]);
     216          11 :     uint8_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
     217          11 :     LOCAL_ALIGNED_32(int16_t, offset, [8]);
     218          11 :     LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
     219          11 :     int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
     220             : 
     221          11 :     ff_colorspacedsp_init(&dsp);
     222          99 :     for (n = 0; n < 8; n++) {
     223          88 :         offset[n] = 16;
     224             : 
     225             :         // these somewhat resemble bt601/smpte170m coefficients
     226          88 :         coeff[0][0][n] = lrint(0.3 * (1 << 14));
     227          88 :         coeff[0][1][n] = lrint(0.6 * (1 << 14));
     228          88 :         coeff[0][2][n] = lrint(0.1 * (1 << 14));
     229          88 :         coeff[1][0][n] = lrint(-0.15 * (1 << 14));
     230          88 :         coeff[1][1][n] = lrint(-0.35 * (1 << 14));
     231          88 :         coeff[1][2][n] = lrint(0.5 * (1 << 14));
     232          88 :         coeff[2][0][n] = lrint(0.5 * (1 << 14));
     233          88 :         coeff[2][1][n] = lrint(-0.42 * (1 << 14));
     234          88 :         coeff[2][2][n] = lrint(-0.08 * (1 << 14));
     235             :     }
     236          44 :     for (odepth = 0; odepth < 3; odepth++) {
     237         132 :         for (fmt = 0; fmt < 3; fmt++) {
     238          99 :             if (check_func(dsp.rgb2yuv[odepth][fmt],
     239             :                            "ff_colorspacedsp_rgb2yuv_%sp%d",
     240             :                            format_string[fmt], odepth * 2 + 8)) {
     241          18 :                 int ss_w = !!fmt, ss_h = fmt == 2;
     242          18 :                 int y_dst_stride = W << !!odepth;
     243          18 :                 int uv_dst_stride = y_dst_stride >> ss_w;
     244             : 
     245          18 :                 randomize_buffers();
     246          18 :                 call_ref(dst0, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
     247             :                          src, W, W, H, coeff, offset);
     248          18 :                 call_new(dst1, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
     249             :                          src, W, W, H, coeff, offset);
     250          36 :                 if (memcmp(dst0[0], dst1[0], H * y_dst_stride) ||
     251          36 :                     memcmp(dst0[1], dst1[1], H * uv_dst_stride >> ss_h) ||
     252          18 :                     memcmp(dst0[2], dst1[2], H * uv_dst_stride >> ss_h)) {
     253           0 :                     fail();
     254             :                 }
     255             :             }
     256             :         }
     257             :     }
     258             : 
     259          11 :     report("rgb2yuv");
     260          11 : }
     261             : 
     262          11 : static void check_multiply3x3(void)
     263             : {
     264          11 :     declare_func(void, int16_t *data[3], ptrdiff_t stride,
     265             :                  int w, int h, const int16_t coeff[3][3][8]);
     266             :     ColorSpaceDSPContext dsp;
     267          11 :     LOCAL_ALIGNED_32(int16_t, dst0_y, [W * H]);
     268          11 :     LOCAL_ALIGNED_32(int16_t, dst0_u, [W * H]);
     269          11 :     LOCAL_ALIGNED_32(int16_t, dst0_v, [W * H]);
     270          11 :     LOCAL_ALIGNED_32(int16_t, dst1_y, [W * H]);
     271          11 :     LOCAL_ALIGNED_32(int16_t, dst1_u, [W * H]);
     272          11 :     LOCAL_ALIGNED_32(int16_t, dst1_v, [W * H]);
     273          11 :     int16_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
     274          11 :     int16_t **src = dst0;
     275          11 :     LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
     276          11 :     int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
     277             :     int n;
     278             : 
     279          11 :     ff_colorspacedsp_init(&dsp);
     280          99 :     for (n = 0; n < 8; n++) {
     281          88 :         coeff[0][0][n] = lrint(0.85 * (1 << 14));
     282          88 :         coeff[0][1][n] = lrint(0.10 * (1 << 14));
     283          88 :         coeff[0][2][n] = lrint(0.05 * (1 << 14));
     284          88 :         coeff[1][0][n] = lrint(-0.1 * (1 << 14));
     285          88 :         coeff[1][1][n] = lrint(0.95 * (1 << 14));
     286          88 :         coeff[1][2][n] = lrint(0.15 * (1 << 14));
     287          88 :         coeff[2][0][n] = lrint(-0.2 * (1 << 14));
     288          88 :         coeff[2][1][n] = lrint(0.30 * (1 << 14));
     289          88 :         coeff[2][2][n] = lrint(0.90 * (1 << 14));
     290             :     }
     291          11 :     if (check_func(dsp.multiply3x3, "ff_colorspacedsp_multiply3x3")) {
     292           2 :         randomize_buffers();
     293           2 :         memcpy(dst1_y, dst0_y, W * H * sizeof(*dst1_y));
     294           2 :         memcpy(dst1_u, dst0_u, W * H * sizeof(*dst1_u));
     295           2 :         memcpy(dst1_v, dst0_v, W * H * sizeof(*dst1_v));
     296           2 :         call_ref(dst0, W, W, H, coeff);
     297           2 :         call_new(dst1, W, W, H, coeff);
     298           4 :         if (memcmp(dst0[0], dst1[0], H * W * sizeof(*dst0_y)) ||
     299           4 :             memcmp(dst0[1], dst1[1], H * W * sizeof(*dst0_u)) ||
     300           2 :             memcmp(dst0[2], dst1[2], H * W * sizeof(*dst0_v))) {
     301           0 :             fail();
     302             :         }
     303             :     }
     304             : 
     305          11 :     report("multiply3x3");
     306          11 : }
     307             : 
     308          11 : void checkasm_check_colorspace(void)
     309             : {
     310          11 :     check_yuv2yuv();
     311          11 :     check_yuv2rgb();
     312          11 :     check_rgb2yuv();
     313          11 :     check_multiply3x3();
     314          11 : }

Generated by: LCOV version 1.12