]> git.sesse.net Git - ffmpeg/blob - libswscale/hscale.c
Merge commit 'd4066a702407352a0648af882c34ea81a404fa2b'
[ffmpeg] / libswscale / hscale.c
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
24 typedef 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
33 typedef struct ColorContext
34 {
35     uint32_t *pal;
36 } ColorContext;
37
38 static 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
86 static 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
127 int 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
144 int 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
166 static 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
202 static 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
235 int 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
250 int 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
272 static 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
281 int 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 }