LCOV - code coverage report
Current view: top level - src/libswscale - vscale.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 174 198 87.9 %
Date: 2017-01-19 23:52:33 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2015 Pedro Arthur <bygrandao@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             : #include "swscale_internal.h"
      21             : 
      22             : typedef struct VScalerContext
      23             : {
      24             :     uint16_t *filter[2];
      25             :     int32_t  *filter_pos;
      26             :     int filter_size;
      27             :     int isMMX;
      28             :     void *pfn;
      29             :     yuv2packedX_fn yuv2packedX;
      30             : } VScalerContext;
      31             : 
      32             : 
      33     7423637 : static int lum_planar_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
      34             : {
      35     7423637 :     VScalerContext *inst = desc->instance;
      36     7423637 :     int dstW = desc->dst->width;
      37             : 
      38     7423637 :     int first = FFMAX(1-inst->filter_size, inst->filter_pos[sliceY]);
      39     7423637 :     int sp = first - desc->src->plane[0].sliceY;
      40     7423637 :     int dp = sliceY - desc->dst->plane[0].sliceY;
      41     7423637 :     uint8_t **src = desc->src->plane[0].line + sp;
      42     7423637 :     uint8_t **dst = desc->dst->plane[0].line + dp;
      43     7423637 :     uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : sliceY * inst->filter_size);
      44             : 
      45     7423637 :     if (inst->filter_size == 1)
      46     4058533 :         ((yuv2planar1_fn)inst->pfn)((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0);
      47             :     else
      48     3365104 :         ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0);
      49             : 
      50     7423637 :     if (desc->alpha) {
      51      151636 :         int sp = first - desc->src->plane[3].sliceY;
      52      151636 :         int dp = sliceY - desc->dst->plane[3].sliceY;
      53      151636 :         uint8_t **src = desc->src->plane[3].line + sp;
      54      151636 :         uint8_t **dst = desc->dst->plane[3].line + dp;
      55      151636 :         uint16_t *filter = inst->filter[1] + (inst->isMMX ? 0 : sliceY * inst->filter_size);
      56             : 
      57      151636 :         if (inst->filter_size == 1)
      58      149536 :             ((yuv2planar1_fn)inst->pfn)((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0);
      59             :         else
      60        2100 :             ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0);
      61             :     }
      62             : 
      63     7423637 :     return 1;
      64             : }
      65             : 
      66     7252436 : static int chr_planar_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
      67             : {
      68     7252436 :     const int chrSkipMask = (1 << desc->dst->v_chr_sub_sample) - 1;
      69     7252436 :     if (sliceY & chrSkipMask)
      70     2701731 :         return 0;
      71             :     else {
      72     4550705 :         VScalerContext *inst = desc->instance;
      73     4550705 :         int dstW = AV_CEIL_RSHIFT(desc->dst->width, desc->dst->h_chr_sub_sample);
      74     4550705 :         int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
      75             : 
      76     4550705 :         int first = FFMAX(1-inst->filter_size, inst->filter_pos[chrSliceY]);
      77     4550705 :         int sp1 = first - desc->src->plane[1].sliceY;
      78     4550705 :         int sp2 = first - desc->src->plane[2].sliceY;
      79     4550705 :         int dp1 = chrSliceY - desc->dst->plane[1].sliceY;
      80     4550705 :         int dp2 = chrSliceY - desc->dst->plane[2].sliceY;
      81     4550705 :         uint8_t **src1 = desc->src->plane[1].line + sp1;
      82     4550705 :         uint8_t **src2 = desc->src->plane[2].line + sp2;
      83     4550705 :         uint8_t **dst1 = desc->dst->plane[1].line + dp1;
      84     4550705 :         uint8_t **dst2 = desc->dst->plane[2].line + dp2;
      85     4550705 :         uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : chrSliceY * inst->filter_size);
      86             : 
      87     4550705 :         if (c->yuv2nv12cX) {
      88        2072 :             ((yuv2interleavedX_fn)inst->pfn)(c, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW);
      89     4548633 :         } else if (inst->filter_size == 1) {
      90      697782 :             ((yuv2planar1_fn)inst->pfn)((const int16_t*)src1[0], dst1[0], dstW, c->chrDither8, 0);
      91      697782 :             ((yuv2planar1_fn)inst->pfn)((const int16_t*)src2[0], dst2[0], dstW, c->chrDither8, 3);
      92             :         } else {
      93     3850851 :             ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src1, dst1[0], dstW, c->chrDither8, 0);
      94     3850851 :             ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src2, dst2[0], dstW, c->chrDither8, inst->isMMX ? (c->uv_offx2 >> 1) : 3);
      95             :         }
      96             :     }
      97             : 
      98     4550705 :     return 1;
      99             : }
     100             : 
     101     2069886 : static int packed_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
     102             : {
     103     2069886 :     VScalerContext *inst = desc->instance;
     104     2069886 :     int dstW = desc->dst->width;
     105     2069886 :     int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
     106             : 
     107     2069886 :     int lum_fsize = inst[0].filter_size;
     108     2069886 :     int chr_fsize = inst[1].filter_size;
     109     2069886 :     uint16_t *lum_filter = inst[0].filter[0];
     110     2069886 :     uint16_t *chr_filter = inst[1].filter[0];
     111             : 
     112     2069886 :     int firstLum = FFMAX(1-lum_fsize, inst[0].filter_pos[   sliceY]);
     113     2069886 :     int firstChr = FFMAX(1-chr_fsize, inst[1].filter_pos[chrSliceY]);
     114             : 
     115     2069886 :     int sp0 = firstLum - desc->src->plane[0].sliceY;
     116     2069886 :     int sp1 = firstChr - desc->src->plane[1].sliceY;
     117     2069886 :     int sp2 = firstChr - desc->src->plane[2].sliceY;
     118     2069886 :     int sp3 = firstLum - desc->src->plane[3].sliceY;
     119     2069886 :     int dp = sliceY - desc->dst->plane[0].sliceY;
     120     2069886 :     uint8_t **src0 = desc->src->plane[0].line + sp0;
     121     2069886 :     uint8_t **src1 = desc->src->plane[1].line + sp1;
     122     2069886 :     uint8_t **src2 = desc->src->plane[2].line + sp2;
     123     2069886 :     uint8_t **src3 = desc->alpha ? desc->src->plane[3].line + sp3 : NULL;
     124     2069886 :     uint8_t **dst = desc->dst->plane[0].line + dp;
     125             : 
     126             : 
     127     2069886 :     if (c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 1) { // unscaled RGB
     128     1326644 :         ((yuv2packed1_fn)inst->pfn)(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2,
     129      663322 :                                     (const int16_t*)(desc->alpha ? *src3 : NULL),  *dst, dstW, 0, sliceY);
     130     1406564 :     } else if (c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 2 &&
     131           0 :                chr_filter[2 * chrSliceY + 1] + chr_filter[2 * chrSliceY] == 4096 &&
     132           0 :                chr_filter[2 * chrSliceY + 1] <= 4096U) { // unscaled RGB
     133           0 :         int chrAlpha = chr_filter[2 * chrSliceY + 1];
     134           0 :         ((yuv2packed1_fn)inst->pfn)(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2,
     135           0 :                                     (const int16_t*)(desc->alpha ? *src3 : NULL),  *dst, dstW, chrAlpha, sliceY);
     136     1406564 :     } else if (c->yuv2packed2 && lum_fsize == 2 && chr_fsize == 2 &&
     137           0 :                lum_filter[2 * sliceY + 1] + lum_filter[2 * sliceY] == 4096 &&
     138           0 :                lum_filter[2 * sliceY + 1] <= 4096U &&
     139           0 :                chr_filter[2 * chrSliceY + 1] + chr_filter[2 * chrSliceY] == 4096 &&
     140           0 :                chr_filter[2 * chrSliceY + 1] <= 4096U
     141           0 :     ) { // bilinear upscale RGB
     142           0 :         int lumAlpha = lum_filter[2 * sliceY + 1];
     143           0 :         int chrAlpha = chr_filter[2 * chrSliceY + 1];
     144           0 :         c->lumMmxFilter[2] =
     145           0 :         c->lumMmxFilter[3] = lum_filter[2 * sliceY]    * 0x10001;
     146           0 :         c->chrMmxFilter[2] =
     147           0 :         c->chrMmxFilter[3] = chr_filter[2 * chrSliceY] * 0x10001;
     148           0 :         ((yuv2packed2_fn)inst->pfn)(c, (const int16_t**)src0, (const int16_t**)src1, (const int16_t**)src2, (const int16_t**)src3,
     149             :                     *dst, dstW, lumAlpha, chrAlpha, sliceY);
     150             :     } else { // general RGB
     151     2813128 :         if ((c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 2) ||
     152     2808996 :             (c->yuv2packed2 && lum_fsize == 2 && chr_fsize == 2)) {
     153           0 :             if (!c->warned_unuseable_bilinear)
     154           0 :                 av_log(c, AV_LOG_INFO, "Optimized 2 tap filter code cannot be used\n");
     155           0 :             c->warned_unuseable_bilinear = 1;
     156             :         }
     157             : 
     158     2813128 :         inst->yuv2packedX(c, lum_filter + sliceY * lum_fsize,
     159     1406564 :                     (const int16_t**)src0, lum_fsize, chr_filter + chrSliceY * chr_fsize,
     160             :                     (const int16_t**)src1, (const int16_t**)src2, chr_fsize, (const int16_t**)src3, *dst, dstW, sliceY);
     161             :     }
     162     2069886 :     return 1;
     163             : }
     164             : 
     165       93672 : static int any_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
     166             : {
     167       93672 :     VScalerContext *inst = desc->instance;
     168       93672 :     int dstW = desc->dst->width;
     169       93672 :     int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
     170             : 
     171       93672 :     int lum_fsize = inst[0].filter_size;
     172       93672 :     int chr_fsize = inst[1].filter_size;
     173       93672 :     uint16_t *lum_filter = inst[0].filter[0];
     174       93672 :     uint16_t *chr_filter = inst[1].filter[0];
     175             : 
     176       93672 :     int firstLum = FFMAX(1-lum_fsize, inst[0].filter_pos[   sliceY]);
     177       93672 :     int firstChr = FFMAX(1-chr_fsize, inst[1].filter_pos[chrSliceY]);
     178             : 
     179       93672 :     int sp0 = firstLum - desc->src->plane[0].sliceY;
     180       93672 :     int sp1 = firstChr - desc->src->plane[1].sliceY;
     181       93672 :     int sp2 = firstChr - desc->src->plane[2].sliceY;
     182       93672 :     int sp3 = firstLum - desc->src->plane[3].sliceY;
     183       93672 :     int dp0 = sliceY - desc->dst->plane[0].sliceY;
     184       93672 :     int dp1 = chrSliceY - desc->dst->plane[1].sliceY;
     185       93672 :     int dp2 = chrSliceY - desc->dst->plane[2].sliceY;
     186       93672 :     int dp3 = sliceY - desc->dst->plane[3].sliceY;
     187             : 
     188       93672 :     uint8_t **src0 = desc->src->plane[0].line + sp0;
     189       93672 :     uint8_t **src1 = desc->src->plane[1].line + sp1;
     190       93672 :     uint8_t **src2 = desc->src->plane[2].line + sp2;
     191       93672 :     uint8_t **src3 = desc->alpha ? desc->src->plane[3].line + sp3 : NULL;
     192      374688 :     uint8_t *dst[4] = { desc->dst->plane[0].line[dp0],
     193       93672 :                         desc->dst->plane[1].line[dp1],
     194       93672 :                         desc->dst->plane[2].line[dp2],
     195       93672 :                         desc->alpha ? desc->dst->plane[3].line[dp3] : NULL };
     196             : 
     197             :     av_assert1(!c->yuv2packed1 && !c->yuv2packed2);
     198      187344 :     ((yuv2anyX_fn)inst->pfn)(c, lum_filter + sliceY * lum_fsize,
     199       93672 :              (const int16_t**)src0, lum_fsize, chr_filter + sliceY * chr_fsize,
     200             :              (const int16_t**)src1, (const int16_t**)src2, chr_fsize, (const int16_t**)src3, dst, dstW, sliceY);
     201             : 
     202       93672 :     return 1;
     203             : 
     204             : }
     205             : 
     206        2247 : int ff_init_vscale(SwsContext *c, SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst)
     207             : {
     208        2247 :     VScalerContext *lumCtx = NULL;
     209        2247 :     VScalerContext *chrCtx = NULL;
     210             : 
     211        2247 :     if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
     212        1315 :         lumCtx = av_mallocz(sizeof(VScalerContext));
     213        1315 :         if (!lumCtx)
     214           0 :             return AVERROR(ENOMEM);
     215             : 
     216             : 
     217        1315 :         desc[0].process = lum_planar_vscale;
     218        1315 :         desc[0].instance = lumCtx;
     219        1315 :         desc[0].src = src;
     220        1315 :         desc[0].dst = dst;
     221        1315 :         desc[0].alpha = c->needAlpha;
     222             : 
     223        2630 :         if (!isGray(c->dstFormat)) {
     224        1257 :             chrCtx = av_mallocz(sizeof(VScalerContext));
     225        1257 :             if (!chrCtx)
     226           0 :                 return AVERROR(ENOMEM);
     227        1257 :             desc[1].process = chr_planar_vscale;
     228        1257 :             desc[1].instance = chrCtx;
     229        1257 :             desc[1].src = src;
     230        1257 :             desc[1].dst = dst;
     231             :         }
     232             :     } else {
     233         932 :         lumCtx = av_mallocz_array(sizeof(VScalerContext), 2);
     234         932 :         if (!lumCtx)
     235           0 :             return AVERROR(ENOMEM);
     236         932 :         chrCtx = &lumCtx[1];
     237             : 
     238         932 :         desc[0].process = c->yuv2packedX ? packed_vscale : any_vscale;
     239         932 :         desc[0].instance = lumCtx;
     240         932 :         desc[0].src = src;
     241         932 :         desc[0].dst = dst;
     242         932 :         desc[0].alpha = c->needAlpha;
     243             :     }
     244             : 
     245        2247 :     ff_init_vscale_pfn(c, c->yuv2plane1, c->yuv2planeX, c->yuv2nv12cX,
     246             :         c->yuv2packed1, c->yuv2packed2, c->yuv2packedX, c->yuv2anyX, c->use_mmx_vfilter);
     247        2247 :     return 0;
     248             : }
     249             : 
     250       89544 : void ff_init_vscale_pfn(SwsContext *c,
     251             :     yuv2planar1_fn yuv2plane1,
     252             :     yuv2planarX_fn yuv2planeX,
     253             :     yuv2interleavedX_fn yuv2nv12cX,
     254             :     yuv2packed1_fn yuv2packed1,
     255             :     yuv2packed2_fn yuv2packed2,
     256             :     yuv2packedX_fn yuv2packedX,
     257             :     yuv2anyX_fn yuv2anyX, int use_mmx)
     258             : {
     259       89544 :     VScalerContext *lumCtx = NULL;
     260       89544 :     VScalerContext *chrCtx = NULL;
     261       89544 :     int idx = c->numDesc - (c->is_internal_gamma ? 2 : 1); //FIXME avoid hardcoding indexes
     262             : 
     263       89544 :     if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
     264       61594 :         if (!isGray(c->dstFormat)) {
     265       59601 :             chrCtx = c->desc[idx].instance;
     266             : 
     267       59601 :             chrCtx->filter[0] = use_mmx ? (int16_t*)c->chrMmxFilter : c->vChrFilter;
     268       59601 :             chrCtx->filter_size = c->vChrFilterSize;
     269       59601 :             chrCtx->filter_pos = c->vChrFilterPos;
     270       59601 :             chrCtx->isMMX = use_mmx;
     271             : 
     272       59601 :             --idx;
     273       59601 :             if (yuv2nv12cX)               chrCtx->pfn = yuv2nv12cX;
     274       59537 :             else if (c->vChrFilterSize == 1) chrCtx->pfn = yuv2plane1;
     275       45602 :             else                             chrCtx->pfn = yuv2planeX;
     276             :         }
     277             : 
     278       61594 :         lumCtx = c->desc[idx].instance;
     279             : 
     280       61594 :         lumCtx->filter[0] = use_mmx ? (int16_t*)c->lumMmxFilter : c->vLumFilter;
     281       61594 :         lumCtx->filter[1] = use_mmx ? (int16_t*)c->alpMmxFilter : c->vLumFilter;
     282       61594 :         lumCtx->filter_size = c->vLumFilterSize;
     283       61594 :         lumCtx->filter_pos = c->vLumFilterPos;
     284       61594 :         lumCtx->isMMX = use_mmx;
     285             : 
     286      123188 :         if (c->vLumFilterSize == 1) lumCtx->pfn = yuv2plane1;
     287       10731 :         else                        lumCtx->pfn = yuv2planeX;
     288             : 
     289             :     } else {
     290       27950 :         lumCtx = c->desc[idx].instance;
     291       27950 :         chrCtx = &lumCtx[1];
     292             : 
     293       27950 :         lumCtx->filter[0] = c->vLumFilter;
     294       27950 :         lumCtx->filter_size = c->vLumFilterSize;
     295       27950 :         lumCtx->filter_pos = c->vLumFilterPos;
     296             : 
     297       27950 :         chrCtx->filter[0] = c->vChrFilter;
     298       27950 :         chrCtx->filter_size = c->vChrFilterSize;
     299       27950 :         chrCtx->filter_pos = c->vChrFilterPos;
     300             : 
     301       27950 :         lumCtx->isMMX = use_mmx;
     302       27950 :         chrCtx->isMMX = use_mmx;
     303             : 
     304       27950 :         if (yuv2packedX) {
     305       26717 :             if (c->yuv2packed1 && c->vLumFilterSize == 1 && c->vChrFilterSize <= 2)
     306        9004 :                 lumCtx->pfn = yuv2packed1;
     307       17713 :             else if (c->yuv2packed2 && c->vLumFilterSize == 2 && c->vChrFilterSize == 2)
     308           0 :                 lumCtx->pfn = yuv2packed2;
     309       26717 :             lumCtx->yuv2packedX = yuv2packedX;
     310             :         } else
     311        1233 :             lumCtx->pfn = yuv2anyX;
     312             :     }
     313       89544 : }
     314             : 
     315             : 

Generated by: LCOV version 1.12