LCOV - code coverage report
Current view: top level - libswscale - vscale.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 174 198 87.9 %
Date: 2017-10-24 00:14:43 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     7708713 : static int lum_planar_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
      34             : {
      35     7708713 :     VScalerContext *inst = desc->instance;
      36     7708713 :     int dstW = desc->dst->width;
      37             : 
      38     7708713 :     int first = FFMAX(1-inst->filter_size, inst->filter_pos[sliceY]);
      39     7708713 :     int sp = first - desc->src->plane[0].sliceY;
      40     7708713 :     int dp = sliceY - desc->dst->plane[0].sliceY;
      41     7708713 :     uint8_t **src = desc->src->plane[0].line + sp;
      42     7708713 :     uint8_t **dst = desc->dst->plane[0].line + dp;
      43     7708713 :     uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : sliceY * inst->filter_size);
      44             : 
      45     7708713 :     if (inst->filter_size == 1)
      46     4339913 :         ((yuv2planar1_fn)inst->pfn)((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0);
      47             :     else
      48     3368800 :         ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0);
      49             : 
      50     7708713 :     if (desc->alpha) {
      51      163924 :         int sp = first - desc->src->plane[3].sliceY;
      52      163924 :         int dp = sliceY - desc->dst->plane[3].sliceY;
      53      163924 :         uint8_t **src = desc->src->plane[3].line + sp;
      54      163924 :         uint8_t **dst = desc->dst->plane[3].line + dp;
      55      163924 :         uint16_t *filter = inst->filter[1] + (inst->isMMX ? 0 : sliceY * inst->filter_size);
      56             : 
      57      163924 :         if (inst->filter_size == 1)
      58      161824 :             ((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     7708713 :     return 1;
      64             : }
      65             : 
      66     7481944 : static int chr_planar_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
      67             : {
      68     7481944 :     const int chrSkipMask = (1 << desc->dst->v_chr_sub_sample) - 1;
      69     7481944 :     if (sliceY & chrSkipMask)
      70     2798085 :         return 0;
      71             :     else {
      72     4683859 :         VScalerContext *inst = desc->instance;
      73     4683859 :         int dstW = AV_CEIL_RSHIFT(desc->dst->width, desc->dst->h_chr_sub_sample);
      74     4683859 :         int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
      75             : 
      76     4683859 :         int first = FFMAX(1-inst->filter_size, inst->filter_pos[chrSliceY]);
      77     4683859 :         int sp1 = first - desc->src->plane[1].sliceY;
      78     4683859 :         int sp2 = first - desc->src->plane[2].sliceY;
      79     4683859 :         int dp1 = chrSliceY - desc->dst->plane[1].sliceY;
      80     4683859 :         int dp2 = chrSliceY - desc->dst->plane[2].sliceY;
      81     4683859 :         uint8_t **src1 = desc->src->plane[1].line + sp1;
      82     4683859 :         uint8_t **src2 = desc->src->plane[2].line + sp2;
      83     4683859 :         uint8_t **dst1 = desc->dst->plane[1].line + dp1;
      84     4683859 :         uint8_t **dst2 = desc->dst->plane[2].line + dp2;
      85     4683859 :         uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : chrSliceY * inst->filter_size);
      86             : 
      87     4683859 :         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     4681787 :         } else if (inst->filter_size == 1) {
      90      792726 :             ((yuv2planar1_fn)inst->pfn)((const int16_t*)src1[0], dst1[0], dstW, c->chrDither8, 0);
      91      792726 :             ((yuv2planar1_fn)inst->pfn)((const int16_t*)src2[0], dst2[0], dstW, c->chrDither8, 3);
      92             :         } else {
      93     3889061 :             ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src1, dst1[0], dstW, c->chrDither8, 0);
      94     3889061 :             ((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     4683859 :     return 1;
      99             : }
     100             : 
     101     2070477 : static int packed_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
     102             : {
     103     2070477 :     VScalerContext *inst = desc->instance;
     104     2070477 :     int dstW = desc->dst->width;
     105     2070477 :     int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
     106             : 
     107     2070477 :     int lum_fsize = inst[0].filter_size;
     108     2070477 :     int chr_fsize = inst[1].filter_size;
     109     2070477 :     uint16_t *lum_filter = inst[0].filter[0];
     110     2070477 :     uint16_t *chr_filter = inst[1].filter[0];
     111             : 
     112     2070477 :     int firstLum = FFMAX(1-lum_fsize, inst[0].filter_pos[   sliceY]);
     113     2070477 :     int firstChr = FFMAX(1-chr_fsize, inst[1].filter_pos[chrSliceY]);
     114             : 
     115     2070477 :     int sp0 = firstLum - desc->src->plane[0].sliceY;
     116     2070477 :     int sp1 = firstChr - desc->src->plane[1].sliceY;
     117     2070477 :     int sp2 = firstChr - desc->src->plane[2].sliceY;
     118     2070477 :     int sp3 = firstLum - desc->src->plane[3].sliceY;
     119     2070477 :     int dp = sliceY - desc->dst->plane[0].sliceY;
     120     2070477 :     uint8_t **src0 = desc->src->plane[0].line + sp0;
     121     2070477 :     uint8_t **src1 = desc->src->plane[1].line + sp1;
     122     2070477 :     uint8_t **src2 = desc->src->plane[2].line + sp2;
     123     2070477 :     uint8_t **src3 = desc->alpha ? desc->src->plane[3].line + sp3 : NULL;
     124     2070477 :     uint8_t **dst = desc->dst->plane[0].line + dp;
     125             : 
     126             : 
     127     2070477 :     if (c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 1) { // unscaled RGB
     128     1326626 :         ((yuv2packed1_fn)inst->pfn)(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2,
     129      663313 :                                     (const int16_t*)(desc->alpha ? *src3 : NULL),  *dst, dstW, 0, sliceY);
     130     1407164 :     } 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     1407164 :     } 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     2814328 :         if ((c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 2) ||
     152     2810196 :             (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     2814328 :         inst->yuv2packedX(c, lum_filter + sliceY * lum_fsize,
     159     1407164 :                     (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     2070477 :     return 1;
     163             : }
     164             : 
     165      152356 : static int any_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
     166             : {
     167      152356 :     VScalerContext *inst = desc->instance;
     168      152356 :     int dstW = desc->dst->width;
     169      152356 :     int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
     170             : 
     171      152356 :     int lum_fsize = inst[0].filter_size;
     172      152356 :     int chr_fsize = inst[1].filter_size;
     173      152356 :     uint16_t *lum_filter = inst[0].filter[0];
     174      152356 :     uint16_t *chr_filter = inst[1].filter[0];
     175             : 
     176      152356 :     int firstLum = FFMAX(1-lum_fsize, inst[0].filter_pos[   sliceY]);
     177      152356 :     int firstChr = FFMAX(1-chr_fsize, inst[1].filter_pos[chrSliceY]);
     178             : 
     179      152356 :     int sp0 = firstLum - desc->src->plane[0].sliceY;
     180      152356 :     int sp1 = firstChr - desc->src->plane[1].sliceY;
     181      152356 :     int sp2 = firstChr - desc->src->plane[2].sliceY;
     182      152356 :     int sp3 = firstLum - desc->src->plane[3].sliceY;
     183      152356 :     int dp0 = sliceY - desc->dst->plane[0].sliceY;
     184      152356 :     int dp1 = chrSliceY - desc->dst->plane[1].sliceY;
     185      152356 :     int dp2 = chrSliceY - desc->dst->plane[2].sliceY;
     186      152356 :     int dp3 = sliceY - desc->dst->plane[3].sliceY;
     187             : 
     188      152356 :     uint8_t **src0 = desc->src->plane[0].line + sp0;
     189      152356 :     uint8_t **src1 = desc->src->plane[1].line + sp1;
     190      152356 :     uint8_t **src2 = desc->src->plane[2].line + sp2;
     191      152356 :     uint8_t **src3 = desc->alpha ? desc->src->plane[3].line + sp3 : NULL;
     192      609424 :     uint8_t *dst[4] = { desc->dst->plane[0].line[dp0],
     193      152356 :                         desc->dst->plane[1].line[dp1],
     194      152356 :                         desc->dst->plane[2].line[dp2],
     195      152356 :                         desc->alpha ? desc->dst->plane[3].line[dp3] : NULL };
     196             : 
     197             :     av_assert1(!c->yuv2packed1 && !c->yuv2packed2);
     198      304712 :     ((yuv2anyX_fn)inst->pfn)(c, lum_filter + sliceY * lum_fsize,
     199      152356 :              (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      152356 :     return 1;
     203             : 
     204             : }
     205             : 
     206        2406 : int ff_init_vscale(SwsContext *c, SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst)
     207             : {
     208        2406 :     VScalerContext *lumCtx = NULL;
     209        2406 :     VScalerContext *chrCtx = NULL;
     210             : 
     211        2406 :     if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
     212        1465 :         lumCtx = av_mallocz(sizeof(VScalerContext));
     213        1465 :         if (!lumCtx)
     214           0 :             return AVERROR(ENOMEM);
     215             : 
     216             : 
     217        1465 :         desc[0].process = lum_planar_vscale;
     218        1465 :         desc[0].instance = lumCtx;
     219        1465 :         desc[0].src = src;
     220        1465 :         desc[0].dst = dst;
     221        1465 :         desc[0].alpha = c->needAlpha;
     222             : 
     223        2930 :         if (!isGray(c->dstFormat)) {
     224        1336 :             chrCtx = av_mallocz(sizeof(VScalerContext));
     225        1336 :             if (!chrCtx)
     226           0 :                 return AVERROR(ENOMEM);
     227        1336 :             desc[1].process = chr_planar_vscale;
     228        1336 :             desc[1].instance = chrCtx;
     229        1336 :             desc[1].src = src;
     230        1336 :             desc[1].dst = dst;
     231             :         }
     232             :     } else {
     233         941 :         lumCtx = av_mallocz_array(sizeof(VScalerContext), 2);
     234         941 :         if (!lumCtx)
     235           0 :             return AVERROR(ENOMEM);
     236         941 :         chrCtx = &lumCtx[1];
     237             : 
     238         941 :         desc[0].process = c->yuv2packedX ? packed_vscale : any_vscale;
     239         941 :         desc[0].instance = lumCtx;
     240         941 :         desc[0].src = src;
     241         941 :         desc[0].dst = dst;
     242         941 :         desc[0].alpha = c->needAlpha;
     243             :     }
     244             : 
     245        2406 :     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        2406 :     return 0;
     248             : }
     249             : 
     250       93993 : 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       93993 :     VScalerContext *lumCtx = NULL;
     260       93993 :     VScalerContext *chrCtx = NULL;
     261       93993 :     int idx = c->numDesc - (c->is_internal_gamma ? 2 : 1); //FIXME avoid hardcoding indexes
     262             : 
     263       93993 :     if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
     264       65368 :         if (!isGray(c->dstFormat)) {
     265       62695 :             chrCtx = c->desc[idx].instance;
     266             : 
     267       62695 :             chrCtx->filter[0] = use_mmx ? (int16_t*)c->chrMmxFilter : c->vChrFilter;
     268       62695 :             chrCtx->filter_size = c->vChrFilterSize;
     269       62695 :             chrCtx->filter_pos = c->vChrFilterPos;
     270       62695 :             chrCtx->isMMX = use_mmx;
     271             : 
     272       62695 :             --idx;
     273       62695 :             if (yuv2nv12cX)               chrCtx->pfn = yuv2nv12cX;
     274       62631 :             else if (c->vChrFilterSize == 1) chrCtx->pfn = yuv2plane1;
     275       46150 :             else                             chrCtx->pfn = yuv2planeX;
     276             :         }
     277             : 
     278       65368 :         lumCtx = c->desc[idx].instance;
     279             : 
     280       65368 :         lumCtx->filter[0] = use_mmx ? (int16_t*)c->lumMmxFilter : c->vLumFilter;
     281       65368 :         lumCtx->filter[1] = use_mmx ? (int16_t*)c->alpMmxFilter : c->vLumFilter;
     282       65368 :         lumCtx->filter_size = c->vLumFilterSize;
     283       65368 :         lumCtx->filter_pos = c->vLumFilterPos;
     284       65368 :         lumCtx->isMMX = use_mmx;
     285             : 
     286      130736 :         if (c->vLumFilterSize == 1) lumCtx->pfn = yuv2plane1;
     287       10897 :         else                        lumCtx->pfn = yuv2planeX;
     288             : 
     289             :     } else {
     290       28625 :         lumCtx = c->desc[idx].instance;
     291       28625 :         chrCtx = &lumCtx[1];
     292             : 
     293       28625 :         lumCtx->filter[0] = c->vLumFilter;
     294       28625 :         lumCtx->filter_size = c->vLumFilterSize;
     295       28625 :         lumCtx->filter_pos = c->vLumFilterPos;
     296             : 
     297       28625 :         chrCtx->filter[0] = c->vChrFilter;
     298       28625 :         chrCtx->filter_size = c->vChrFilterSize;
     299       28625 :         chrCtx->filter_pos = c->vChrFilterPos;
     300             : 
     301       28625 :         lumCtx->isMMX = use_mmx;
     302       28625 :         chrCtx->isMMX = use_mmx;
     303             : 
     304       28625 :         if (yuv2packedX) {
     305       26728 :             if (c->yuv2packed1 && c->vLumFilterSize == 1 && c->vChrFilterSize <= 2)
     306        8999 :                 lumCtx->pfn = yuv2packed1;
     307       17729 :             else if (c->yuv2packed2 && c->vLumFilterSize == 2 && c->vChrFilterSize == 2)
     308           0 :                 lumCtx->pfn = yuv2packed2;
     309       26728 :             lumCtx->yuv2packedX = yuv2packedX;
     310             :         } else
     311        1897 :             lumCtx->pfn = yuv2anyX;
     312             :     }
     313       93993 : }
     314             : 
     315             : 

Generated by: LCOV version 1.13