Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. static int lum_planar_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
  34. {
  35.     VScalerContext *inst = desc->instance;
  36.     int dstW = desc->dst->width;
  37.  
  38.     int first = FFMAX(1-inst->filter_size, inst->filter_pos[sliceY]);
  39.     int sp = first - desc->src->plane[0].sliceY;
  40.     int dp = sliceY - desc->dst->plane[0].sliceY;
  41.     uint8_t **src = desc->src->plane[0].line + sp;
  42.     uint8_t **dst = desc->dst->plane[0].line + dp;
  43.     uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : sliceY * inst->filter_size);
  44.  
  45.     if (inst->filter_size == 1)
  46.         ((yuv2planar1_fn)inst->pfn)((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0);
  47.     else
  48.         ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0);
  49.  
  50.     if (desc->alpha) {
  51.         int sp = first - desc->src->plane[3].sliceY;
  52.         int dp = sliceY - desc->dst->plane[3].sliceY;
  53.         uint8_t **src = desc->src->plane[3].line + sp;
  54.         uint8_t **dst = desc->dst->plane[3].line + dp;
  55.         uint16_t *filter = inst->filter[1] + (inst->isMMX ? 0 : sliceY * inst->filter_size);
  56.  
  57.         if (inst->filter_size == 1)
  58.             ((yuv2planar1_fn)inst->pfn)((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0);
  59.         else
  60.             ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0);
  61.     }
  62.  
  63.     return 1;
  64. }
  65.  
  66. static int chr_planar_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
  67. {
  68.     const int chrSkipMask = (1 << desc->dst->v_chr_sub_sample) - 1;
  69.     if (sliceY & chrSkipMask)
  70.         return 0;
  71.     else {
  72.         VScalerContext *inst = desc->instance;
  73.         int dstW = FF_CEIL_RSHIFT(desc->dst->width, desc->dst->h_chr_sub_sample);
  74.         int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
  75.  
  76.         int first = FFMAX(1-inst->filter_size, inst->filter_pos[chrSliceY]);
  77.         int sp1 = first - desc->src->plane[1].sliceY;
  78.         int sp2 = first - desc->src->plane[2].sliceY;
  79.         int dp1 = chrSliceY - desc->dst->plane[1].sliceY;
  80.         int dp2 = chrSliceY - desc->dst->plane[2].sliceY;
  81.         uint8_t **src1 = desc->src->plane[1].line + sp1;
  82.         uint8_t **src2 = desc->src->plane[2].line + sp2;
  83.         uint8_t **dst1 = desc->dst->plane[1].line + dp1;
  84.         uint8_t **dst2 = desc->dst->plane[2].line + dp2;
  85.         uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : chrSliceY * inst->filter_size);
  86.  
  87.         if (c->yuv2nv12cX) {
  88.             ((yuv2interleavedX_fn)inst->pfn)(c, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW);
  89.         } else if (inst->filter_size == 1) {
  90.             ((yuv2planar1_fn)inst->pfn)((const int16_t*)src1[0], dst1[0], dstW, c->chrDither8, 0);
  91.             ((yuv2planar1_fn)inst->pfn)((const int16_t*)src2[0], dst2[0], dstW, c->chrDither8, 3);
  92.         } else {
  93.             ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src1, dst1[0], dstW, c->chrDither8, 0);
  94.             ((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.     return 1;
  99. }
  100.  
  101. static int packed_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
  102. {
  103.     VScalerContext *inst = desc->instance;
  104.     int dstW = desc->dst->width;
  105.     int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
  106.  
  107.     int lum_fsize = inst[0].filter_size;
  108.     int chr_fsize = inst[1].filter_size;
  109.     uint16_t *lum_filter = inst[0].filter[0];
  110.     uint16_t *chr_filter = inst[1].filter[0];
  111.  
  112.     int firstLum = FFMAX(1-lum_fsize, inst[0].filter_pos[chrSliceY]);
  113.     int firstChr = FFMAX(1-chr_fsize, inst[1].filter_pos[chrSliceY]);
  114.  
  115.     int sp0 = firstLum - desc->src->plane[0].sliceY;
  116.     int sp1 = firstChr - desc->src->plane[1].sliceY;
  117.     int sp2 = firstChr - desc->src->plane[2].sliceY;
  118.     int sp3 = firstLum - desc->src->plane[3].sliceY;
  119.     int dp = sliceY - desc->dst->plane[0].sliceY;
  120.     uint8_t **src0 = desc->src->plane[0].line + sp0;
  121.     uint8_t **src1 = desc->src->plane[1].line + sp1;
  122.     uint8_t **src2 = desc->src->plane[2].line + sp2;
  123.     uint8_t **src3 = desc->alpha ? desc->src->plane[3].line + sp3 : NULL;
  124.     uint8_t **dst = desc->dst->plane[0].line + dp;
  125.  
  126.  
  127.     if (c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 1) { // unscaled RGB
  128.         ((yuv2packed1_fn)inst->pfn)(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2,
  129.                                     (const int16_t*)(desc->alpha ? *src3 : NULL),  *dst, dstW, 0, sliceY);
  130.     } else if (c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 2 &&
  131.                chr_filter[2 * sliceY + 1] + chr_filter[2 * chrSliceY] == 4096 &&
  132.                chr_filter[2 * sliceY + 1] <= 4096U) { // unscaled RGB
  133.         int chrAlpha = chr_filter[2 * sliceY + 1];
  134.         ((yuv2packed1_fn)inst->pfn)(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2,
  135.                                     (const int16_t*)(desc->alpha ? *src3 : NULL),  *dst, dstW, chrAlpha, sliceY);
  136.     } else if (c->yuv2packed2 && lum_fsize == 2 && chr_fsize == 2 &&
  137.                lum_filter[2 * sliceY + 1] + lum_filter[2 * sliceY] == 4096 &&
  138.                lum_filter[2 * sliceY + 1] <= 4096U &&
  139.                chr_filter[2 * chrSliceY + 1] + chr_filter[2 * chrSliceY] == 4096 &&
  140.                chr_filter[2 * chrSliceY + 1] <= 4096U
  141.     ) { // bilinear upscale RGB
  142.         int lumAlpha = lum_filter[2 * sliceY + 1];
  143.         int chrAlpha = chr_filter[2 * sliceY + 1];
  144.         c->lumMmxFilter[2] =
  145.         c->lumMmxFilter[3] = lum_filter[2 * sliceY]    * 0x10001;
  146.         c->chrMmxFilter[2] =
  147.         c->chrMmxFilter[3] = chr_filter[2 * chrSliceY] * 0x10001;
  148.         ((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.         if ((c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 2) ||
  152.             (c->yuv2packed2 && lum_fsize == 2 && chr_fsize == 2)) {
  153.             if (!c->warned_unuseable_bilinear)
  154.                 av_log(c, AV_LOG_INFO, "Optimized 2 tap filter code cannot be used\n");
  155.             c->warned_unuseable_bilinear = 1;
  156.         }
  157.  
  158.         inst->yuv2packedX(c, lum_filter + sliceY * lum_fsize,
  159.                     (const int16_t**)src0, lum_fsize, chr_filter + sliceY * chr_fsize,
  160.                     (const int16_t**)src1, (const int16_t**)src2, chr_fsize, (const int16_t**)src3, *dst, dstW, sliceY);
  161.     }
  162.     return 1;
  163. }
  164.  
  165. static int any_vscale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
  166. {
  167.     VScalerContext *inst = desc->instance;
  168.     int dstW = desc->dst->width;
  169.     int chrSliceY = sliceY >> desc->dst->v_chr_sub_sample;
  170.  
  171.     int lum_fsize = inst[0].filter_size;
  172.     int chr_fsize = inst[1].filter_size;
  173.     uint16_t *lum_filter = inst[0].filter[0];
  174.     uint16_t *chr_filter = inst[1].filter[0];
  175.  
  176.     int firstLum = FFMAX(1-lum_fsize, inst[0].filter_pos[chrSliceY]);
  177.     int firstChr = FFMAX(1-chr_fsize, inst[1].filter_pos[chrSliceY]);
  178.  
  179.     int sp0 = firstLum - desc->src->plane[0].sliceY;
  180.     int sp1 = firstChr - desc->src->plane[1].sliceY;
  181.     int sp2 = firstChr - desc->src->plane[2].sliceY;
  182.     int sp3 = firstLum - desc->src->plane[3].sliceY;
  183.     int dp0 = sliceY - desc->dst->plane[0].sliceY;
  184.     int dp1 = chrSliceY - desc->dst->plane[1].sliceY;
  185.     int dp2 = chrSliceY - desc->dst->plane[2].sliceY;
  186.     int dp3 = sliceY - desc->dst->plane[3].sliceY;
  187.  
  188.     uint8_t **src0 = desc->src->plane[0].line + sp0;
  189.     uint8_t **src1 = desc->src->plane[1].line + sp1;
  190.     uint8_t **src2 = desc->src->plane[2].line + sp2;
  191.     uint8_t **src3 = desc->alpha ? desc->src->plane[3].line + sp3 : NULL;
  192.     uint8_t *dst[4] = { desc->dst->plane[0].line[dp0],
  193.                         desc->dst->plane[1].line[dp1],
  194.                         desc->dst->plane[2].line[dp2],
  195.                         desc->alpha ? desc->dst->plane[3].line[dp3] : NULL };
  196.  
  197.     av_assert1(!c->yuv2packed1 && !c->yuv2packed2);
  198.     ((yuv2anyX_fn)inst->pfn)(c, lum_filter + sliceY * lum_fsize,
  199.              (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.     return 1;
  203.  
  204. }
  205.  
  206. int ff_init_vscale(SwsContext *c, SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst)
  207. {
  208.     VScalerContext *lumCtx = NULL;
  209.     VScalerContext *chrCtx = NULL;
  210.  
  211.     if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
  212.         lumCtx = av_mallocz(sizeof(VScalerContext));
  213.         if (!lumCtx)
  214.             return AVERROR(ENOMEM);
  215.  
  216.  
  217.         desc[0].process = lum_planar_vscale;
  218.         desc[0].instance = lumCtx;
  219.         desc[0].src = src;
  220.         desc[0].dst = dst;
  221.         desc[0].alpha = c->alpPixBuf != 0;
  222.  
  223.         if (!isGray(c->dstFormat)) {
  224.             chrCtx = av_mallocz(sizeof(VScalerContext));
  225.             if (!chrCtx)
  226.                 return AVERROR(ENOMEM);
  227.             desc[1].process = chr_planar_vscale;
  228.             desc[1].instance = chrCtx;
  229.             desc[1].src = src;
  230.             desc[1].dst = dst;
  231.         }
  232.     } else {
  233.         lumCtx = av_mallocz_array(sizeof(VScalerContext), 2);
  234.         if (!lumCtx)
  235.             return AVERROR(ENOMEM);
  236.         chrCtx = &lumCtx[1];
  237.  
  238.         desc[0].process = c->yuv2packedX ? packed_vscale : any_vscale;
  239.         desc[0].instance = lumCtx;
  240.         desc[0].src = src;
  241.         desc[0].dst = dst;
  242.         desc[0].alpha = c->alpPixBuf != 0;
  243.     }
  244.  
  245.     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.     return 0;
  248. }
  249.  
  250. 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.     VScalerContext *lumCtx = NULL;
  260.     VScalerContext *chrCtx = NULL;
  261.     int idx = c->numDesc - (c->is_internal_gamma ? 2 : 1);
  262.  
  263.     if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {
  264.         if (!isGray(c->dstFormat)) {
  265.             chrCtx = c->desc[idx].instance;
  266.  
  267.             chrCtx->filter[0] = use_mmx ? (int16_t*)c->chrMmxFilter : c->vChrFilter;
  268.             chrCtx->filter_size = c->vChrFilterSize;
  269.             chrCtx->filter_pos = c->vChrFilterPos;
  270.             chrCtx->isMMX = use_mmx;
  271.  
  272.             --idx;
  273.             if (yuv2nv12cX)               chrCtx->pfn = yuv2nv12cX;
  274.             else if (c->vChrFilterSize == 1) chrCtx->pfn = yuv2plane1;
  275.             else                             chrCtx->pfn = yuv2planeX;
  276.         }
  277.  
  278.         lumCtx = c->desc[idx].instance;
  279.  
  280.         lumCtx->filter[0] = use_mmx ? (int16_t*)c->lumMmxFilter : c->vLumFilter;
  281.         lumCtx->filter[1] = use_mmx ? (int16_t*)c->alpMmxFilter : c->vLumFilter;
  282.         lumCtx->filter_size = c->vLumFilterSize;
  283.         lumCtx->filter_pos = c->vLumFilterPos;
  284.         lumCtx->isMMX = use_mmx;
  285.  
  286.         if (c->vLumFilterSize == 1) lumCtx->pfn = yuv2plane1;
  287.         else                        lumCtx->pfn = yuv2planeX;
  288.  
  289.     } else {
  290.         lumCtx = c->desc[idx].instance;
  291.         chrCtx = &lumCtx[1];
  292.  
  293.         lumCtx->filter[0] = c->vLumFilter;
  294.         lumCtx->filter_size = c->vLumFilterSize;
  295.         lumCtx->filter_pos = c->vLumFilterPos;
  296.  
  297.         chrCtx->filter[0] = c->vChrFilter;
  298.         chrCtx->filter_size = c->vChrFilterSize;
  299.         chrCtx->filter_pos = c->vChrFilterPos;
  300.  
  301.         lumCtx->isMMX = use_mmx;
  302.         chrCtx->isMMX = use_mmx;
  303.  
  304.         if (yuv2packedX) {
  305.             if (c->yuv2packed1 && c->vLumFilterSize == 1 && c->vChrFilterSize <= 2)
  306.                 lumCtx->pfn = yuv2packed1;
  307.             else if (c->yuv2packed2 && c->vLumFilterSize == 2 && c->vChrFilterSize == 2)
  308.                 lumCtx->pfn = yuv2packed2;
  309.             lumCtx->yuv2packedX = yuv2packedX;
  310.         } else
  311.             lumCtx->pfn = yuv2anyX;
  312.     }
  313. }
  314.  
  315.  
  316.