2 * Copyright (C) 2015 Pedro Arthur <bygrandao@gmail.com>
4 * This file is part of FFmpeg.
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.
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.
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
21 #include "swscale_internal.h"
23 static int lum_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
25 FilterContext *instance = desc->instance;
26 int srcW = desc->src->width;
27 int dstW = desc->dst->width;
28 int xInc = instance->xInc;
31 for (i = 0; i < sliceH; ++i) {
32 uint8_t ** src = desc->src->plane[0].line;
33 uint8_t ** dst = desc->dst->plane[0].line;
34 int src_pos = sliceY+i - desc->src->plane[0].sliceY;
35 int dst_pos = sliceY+i - desc->dst->plane[0].sliceY;
38 if (c->hyscale_fast) {
39 c->hyscale_fast(c, (int16_t*)dst[dst_pos], dstW, src[src_pos], srcW, xInc);
41 c->hyScale(c, (int16_t*)dst[dst_pos], dstW, (const uint8_t *)src[src_pos], instance->filter,
42 instance->filter_pos, instance->filter_size);
45 if (c->lumConvertRange)
46 c->lumConvertRange((int16_t*)dst[dst_pos], dstW);
48 desc->dst->plane[0].sliceH += 1;
51 src = desc->src->plane[3].line;
52 dst = desc->dst->plane[3].line;
54 src_pos = sliceY+i - desc->src->plane[3].sliceY;
55 dst_pos = sliceY+i - desc->dst->plane[3].sliceY;
57 desc->dst->plane[3].sliceH += 1;
59 if (c->hyscale_fast) {
60 c->hyscale_fast(c, (int16_t*)dst[dst_pos], dstW, src[src_pos], srcW, xInc);
62 c->hyScale(c, (int16_t*)dst[dst_pos], dstW, (const uint8_t *)src[src_pos], instance->filter,
63 instance->filter_pos, instance->filter_size);
71 static int lum_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
73 int srcW = desc->src->width;
74 ColorContext * instance = desc->instance;
75 uint32_t * pal = instance->pal;
78 desc->dst->plane[0].sliceY = sliceY;
79 desc->dst->plane[0].sliceH = sliceH;
80 desc->dst->plane[3].sliceY = sliceY;
81 desc->dst->plane[3].sliceH = sliceH;
83 for (i = 0; i < sliceH; ++i) {
84 int sp0 = sliceY+i - desc->src->plane[0].sliceY;
85 int sp1 = ((sliceY+i) >> desc->src->v_chr_sub_sample) - desc->src->plane[1].sliceY;
86 const uint8_t * src[4] = { desc->src->plane[0].line[sp0],
87 desc->src->plane[1].line[sp1],
88 desc->src->plane[2].line[sp1],
89 desc->src->plane[3].line[sp0]};
90 uint8_t * dst = desc->dst->plane[0].line[i];
93 c->lumToYV12(dst, src[0], src[1], src[2], srcW, pal);
94 } else if (c->readLumPlanar) {
95 c->readLumPlanar(dst, src, srcW, c->input_rgb2yuv_table);
100 dst = desc->dst->plane[3].line[i];
102 c->alpToYV12(dst, src[3], src[1], src[2], srcW, pal);
103 } else if (c->readAlpPlanar) {
104 c->readAlpPlanar(dst, src, srcW, NULL);
112 int ff_init_desc_fmt_convert(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst, uint32_t *pal)
114 ColorContext * li = av_malloc(sizeof(ColorContext));
116 return AVERROR(ENOMEM);
120 desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
123 desc->process = &lum_convert;
129 int ff_init_desc_hscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint16_t *filter, int * filter_pos, int filter_size, int xInc)
131 FilterContext *li = av_malloc(sizeof(FilterContext));
133 return AVERROR(ENOMEM);
136 li->filter_pos = filter_pos;
137 li->filter_size = filter_size;
142 desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
146 desc->process = &lum_h_scale;
151 static int chr_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
153 FilterContext *instance = desc->instance;
154 int srcW = FF_CEIL_RSHIFT(desc->src->width, desc->src->h_chr_sub_sample);
155 int dstW = FF_CEIL_RSHIFT(desc->dst->width, desc->dst->h_chr_sub_sample);
156 int xInc = instance->xInc;
158 uint8_t ** src1 = desc->src->plane[1].line;
159 uint8_t ** dst1 = desc->dst->plane[1].line;
160 uint8_t ** src2 = desc->src->plane[2].line;
161 uint8_t ** dst2 = desc->dst->plane[2].line;
163 int src_pos1 = sliceY - desc->src->plane[1].sliceY;
164 int dst_pos1 = sliceY - desc->dst->plane[1].sliceY;
166 int src_pos2 = sliceY - desc->src->plane[2].sliceY;
167 int dst_pos2 = sliceY - desc->dst->plane[2].sliceY;
170 for (i = 0; i < sliceH; ++i) {
171 if (c->hcscale_fast) {
172 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);
174 c->hcScale(c, (uint16_t*)dst1[dst_pos1+i], dstW, src1[src_pos1+i], instance->filter, instance->filter_pos, instance->filter_size);
175 c->hcScale(c, (uint16_t*)dst2[dst_pos2+i], dstW, src2[src_pos2+i], instance->filter, instance->filter_pos, instance->filter_size);
178 if (c->chrConvertRange)
179 c->chrConvertRange((uint16_t*)dst1[dst_pos1+i], (uint16_t*)dst2[dst_pos2+i], dstW);
181 desc->dst->plane[1].sliceH += 1;
182 desc->dst->plane[2].sliceH += 1;
187 static int chr_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
189 int srcW = FF_CEIL_RSHIFT(desc->src->width, desc->src->h_chr_sub_sample);
190 ColorContext * instance = desc->instance;
191 uint32_t * pal = instance->pal;
193 int sp0 = (sliceY - (desc->src->plane[0].sliceY >> desc->src->v_chr_sub_sample)) << desc->src->v_chr_sub_sample;
194 int sp1 = sliceY - desc->src->plane[1].sliceY;
198 desc->dst->plane[1].sliceY = sliceY;
199 desc->dst->plane[1].sliceH = sliceH;
200 desc->dst->plane[2].sliceY = sliceY;
201 desc->dst->plane[2].sliceH = sliceH;
203 for (i = 0; i < sliceH; ++i) {
204 const uint8_t * src[4] = { desc->src->plane[0].line[sp0+i],
205 desc->src->plane[1].line[sp1+i],
206 desc->src->plane[2].line[sp1+i],
207 desc->src->plane[3].line[sp0+i]};
209 uint8_t * dst1 = desc->dst->plane[1].line[i];
210 uint8_t * dst2 = desc->dst->plane[2].line[i];
212 c->chrToYV12(dst1, dst2, src[0], src[1], src[2], srcW, pal);
213 } else if (c->readChrPlanar) {
214 c->readChrPlanar(dst1, dst2, src, srcW, c->input_rgb2yuv_table);
220 int ff_init_desc_cfmt_convert(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst, uint32_t *pal)
222 ColorContext * li = av_malloc(sizeof(ColorContext));
224 return AVERROR(ENOMEM);
230 desc->process = &chr_convert;
235 int ff_init_desc_chscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint16_t *filter, int * filter_pos, int filter_size, int xInc)
237 FilterContext *li = av_malloc(sizeof(FilterContext));
239 return AVERROR(ENOMEM);
242 li->filter_pos = filter_pos;
243 li->filter_size = filter_size;
248 desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
252 desc->process = &chr_h_scale;
257 static int no_chr_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
259 desc->dst->plane[1].sliceY = sliceY + sliceH - desc->dst->plane[1].available_lines;
260 desc->dst->plane[1].sliceH = desc->dst->plane[1].available_lines;
261 desc->dst->plane[2].sliceY = sliceY + sliceH - desc->dst->plane[2].available_lines;
262 desc->dst->plane[2].sliceH = desc->dst->plane[2].available_lines;
266 int ff_init_desc_no_chr(SwsFilterDescriptor *desc, SwsSlice * src, SwsSlice *dst)
271 desc->instance = NULL;
272 desc->process = &no_chr_scale;