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