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 21#include "swscale_internal.h" 22 23/// Scaler instance data 24typedef struct FilterContext 25{ 26 uint16_t *filter; 27 int *filter_pos; 28 int filter_size; 29 int xInc; 30} FilterContext; 31 32/// Color conversion instance data 33typedef struct ColorContext 34{ 35 uint32_t *pal; 36} ColorContext; 37 38static int lum_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH) 39{ 40 FilterContext *instance = desc->instance; 41 int srcW = desc->src->width; 42 int dstW = desc->dst->width; 43 int xInc = instance->xInc; 44 45 int i; 46 for (i = 0; i < sliceH; ++i) { 47 uint8_t ** src = desc->src->plane[0].line; 48 uint8_t ** dst = desc->dst->plane[0].line; 49 int src_pos = sliceY+i - desc->src->plane[0].sliceY; 50 int dst_pos = sliceY+i - desc->dst->plane[0].sliceY; 51 52 53 if (c->hyscale_fast) { 54 c->hyscale_fast(c, (int16_t*)dst[dst_pos], dstW, src[src_pos], srcW, xInc); 55 } else { 56 c->hyScale(c, (int16_t*)dst[dst_pos], dstW, (const uint8_t *)src[src_pos], instance->filter, 57 instance->filter_pos, instance->filter_size); 58 } 59 60 if (c->lumConvertRange) 61 c->lumConvertRange((int16_t*)dst[dst_pos], dstW); 62 63 desc->dst->plane[0].sliceH += 1; 64 65 if (desc->alpha) { 66 src = desc->src->plane[3].line; 67 dst = desc->dst->plane[3].line; 68 69 src_pos = sliceY+i - desc->src->plane[3].sliceY; 70 dst_pos = sliceY+i - desc->dst->plane[3].sliceY; 71 72 desc->dst->plane[3].sliceH += 1; 73 74 if (c->hyscale_fast) { 75 c->hyscale_fast(c, (int16_t*)dst[dst_pos], dstW, src[src_pos], srcW, xInc); 76 } else { 77 c->hyScale(c, (int16_t*)dst[dst_pos], dstW, (const uint8_t *)src[src_pos], instance->filter, 78 instance->filter_pos, instance->filter_size); 79 } 80 } 81 } 82 83 return sliceH; 84} 85 86static int lum_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH) 87{ 88 int srcW = desc->src->width; 89 ColorContext * instance = desc->instance; 90 uint32_t * pal = instance->pal; 91 int i; 92 93 desc->dst->plane[0].sliceY = sliceY; 94 desc->dst->plane[0].sliceH = sliceH; 95 desc->dst->plane[3].sliceY = sliceY; 96 desc->dst->plane[3].sliceH = sliceH; 97 98 for (i = 0; i < sliceH; ++i) { 99 int sp0 = sliceY+i - desc->src->plane[0].sliceY; 100 int sp1 = ((sliceY+i) >> desc->src->v_chr_sub_sample) - desc->src->plane[1].sliceY; 101 const uint8_t * src[4] = { desc->src->plane[0].line[sp0], 102 desc->src->plane[1].line[sp1], 103 desc->src->plane[2].line[sp1], 104 desc->src->plane[3].line[sp0]}; 105 uint8_t * dst = desc->dst->plane[0].line[i]; 106 107 if (c->lumToYV12) { 108 c->lumToYV12(dst, src[0], src[1], src[2], srcW, pal); 109 } else if (c->readLumPlanar) { 110 c->readLumPlanar(dst, src, srcW, c->input_rgb2yuv_table); 111 } 112 113 114 if (desc->alpha) { 115 dst = desc->dst->plane[3].line[i]; 116 if (c->alpToYV12) { 117 c->alpToYV12(dst, src[3], src[1], src[2], srcW, pal); 118 } else if (c->readAlpPlanar) { 119 c->readAlpPlanar(dst, src, srcW, NULL); 120 } 121 } 122 } 123 124 return sliceH; 125} 126 127int ff_init_desc_fmt_convert(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst, uint32_t *pal) 128{ 129 ColorContext * li = av_malloc(sizeof(ColorContext)); 130 if (!li) 131 return AVERROR(ENOMEM); 132 li->pal = pal; 133 desc->instance = li; 134 135 desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt); 136 desc->src =src; 137 desc->dst = dst; 138 desc->process = &lum_convert; 139 140 return 0; 141} 142 143 144int ff_init_desc_hscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint16_t *filter, int * filter_pos, int filter_size, int xInc) 145{ 146 FilterContext *li = av_malloc(sizeof(FilterContext)); 147 if (!li) 148 return AVERROR(ENOMEM); 149 150 li->filter = filter; 151 li->filter_pos = filter_pos; 152 li->filter_size = filter_size; 153 li->xInc = xInc; 154 155 desc->instance = li; 156 157 desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt); 158 desc->src = src; 159 desc->dst = dst; 160 161 desc->process = &lum_h_scale; 162 163 return 0; 164} 165 166static int chr_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH) 167{ 168 FilterContext *instance = desc->instance; 169 int srcW = AV_CEIL_RSHIFT(desc->src->width, desc->src->h_chr_sub_sample); 170 int dstW = AV_CEIL_RSHIFT(desc->dst->width, desc->dst->h_chr_sub_sample); 171 int xInc = instance->xInc; 172 173 uint8_t ** src1 = desc->src->plane[1].line; 174 uint8_t ** dst1 = desc->dst->plane[1].line; 175 uint8_t ** src2 = desc->src->plane[2].line; 176 uint8_t ** dst2 = desc->dst->plane[2].line; 177 178 int src_pos1 = sliceY - desc->src->plane[1].sliceY; 179 int dst_pos1 = sliceY - desc->dst->plane[1].sliceY; 180 181 int src_pos2 = sliceY - desc->src->plane[2].sliceY; 182 int dst_pos2 = sliceY - desc->dst->plane[2].sliceY; 183 184 int i; 185 for (i = 0; i < sliceH; ++i) { 186 if (c->hcscale_fast) { 187 c->hcscale_fast(c, (uint16_t*)dst1[dst_pos1+i], (uint16_t*)dst2[dst_pos2+i], dstW, src1[src_pos1+i], src2[src_pos2+i], srcW, xInc); 188 } else { 189 c->hcScale(c, (uint16_t*)dst1[dst_pos1+i], dstW, src1[src_pos1+i], instance->filter, instance->filter_pos, instance->filter_size); 190 c->hcScale(c, (uint16_t*)dst2[dst_pos2+i], dstW, src2[src_pos2+i], instance->filter, instance->filter_pos, instance->filter_size); 191 } 192 193 if (c->chrConvertRange) 194 c->chrConvertRange((uint16_t*)dst1[dst_pos1+i], (uint16_t*)dst2[dst_pos2+i], dstW); 195 196 desc->dst->plane[1].sliceH += 1; 197 desc->dst->plane[2].sliceH += 1; 198 } 199 return sliceH; 200} 201 202static int chr_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH) 203{ 204 int srcW = AV_CEIL_RSHIFT(desc->src->width, desc->src->h_chr_sub_sample); 205 ColorContext * instance = desc->instance; 206 uint32_t * pal = instance->pal; 207 208 int sp0 = (sliceY - (desc->src->plane[0].sliceY >> desc->src->v_chr_sub_sample)) << desc->src->v_chr_sub_sample; 209 int sp1 = sliceY - desc->src->plane[1].sliceY; 210 211 int i; 212 213 desc->dst->plane[1].sliceY = sliceY; 214 desc->dst->plane[1].sliceH = sliceH; 215 desc->dst->plane[2].sliceY = sliceY; 216 desc->dst->plane[2].sliceH = sliceH; 217 218 for (i = 0; i < sliceH; ++i) { 219 const uint8_t * src[4] = { desc->src->plane[0].line[sp0+i], 220 desc->src->plane[1].line[sp1+i], 221 desc->src->plane[2].line[sp1+i], 222 desc->src->plane[3].line[sp0+i]}; 223 224 uint8_t * dst1 = desc->dst->plane[1].line[i]; 225 uint8_t * dst2 = desc->dst->plane[2].line[i]; 226 if (c->chrToYV12) { 227 c->chrToYV12(dst1, dst2, src[0], src[1], src[2], srcW, pal); 228 } else if (c->readChrPlanar) { 229 c->readChrPlanar(dst1, dst2, src, srcW, c->input_rgb2yuv_table); 230 } 231 } 232 return sliceH; 233} 234 235int ff_init_desc_cfmt_convert(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst, uint32_t *pal) 236{ 237 ColorContext * li = av_malloc(sizeof(ColorContext)); 238 if (!li) 239 return AVERROR(ENOMEM); 240 li->pal = pal; 241 desc->instance = li; 242 243 desc->src =src; 244 desc->dst = dst; 245 desc->process = &chr_convert; 246 247 return 0; 248} 249 250int ff_init_desc_chscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint16_t *filter, int * filter_pos, int filter_size, int xInc) 251{ 252 FilterContext *li = av_malloc(sizeof(FilterContext)); 253 if (!li) 254 return AVERROR(ENOMEM); 255 256 li->filter = filter; 257 li->filter_pos = filter_pos; 258 li->filter_size = filter_size; 259 li->xInc = xInc; 260 261 desc->instance = li; 262 263 desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt); 264 desc->src = src; 265 desc->dst = dst; 266 267 desc->process = &chr_h_scale; 268 269 return 0; 270} 271 272static int no_chr_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH) 273{ 274 desc->dst->plane[1].sliceY = sliceY + sliceH - desc->dst->plane[1].available_lines; 275 desc->dst->plane[1].sliceH = desc->dst->plane[1].available_lines; 276 desc->dst->plane[2].sliceY = sliceY + sliceH - desc->dst->plane[2].available_lines; 277 desc->dst->plane[2].sliceH = desc->dst->plane[2].available_lines; 278 return 0; 279} 280 281int ff_init_desc_no_chr(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst) 282{ 283 desc->src = src; 284 desc->dst = dst; 285 desc->alpha = 0; 286 desc->instance = NULL; 287 desc->process = &no_chr_scale; 288 return 0; 289} 290