FFmpeg
hscale.c
Go to the documentation of this file.
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;
30  int xInc;
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 {
41  FilterContext *instance = desc->instance;
42  int srcW = desc->src->width;
43  int dstW = desc->dst->width;
44  int xInc = instance->xInc;
45 
46  int i;
47  for (i = 0; i < sliceH; ++i) {
48  uint8_t ** src = desc->src->plane[0].line;
49  uint8_t ** dst = desc->dst->plane[0].line;
50  int src_pos = sliceY+i - desc->src->plane[0].sliceY;
51  int dst_pos = sliceY+i - desc->dst->plane[0].sliceY;
52 
53 
54  if (c->hyscale_fast) {
55  c->hyscale_fast(c, (int16_t*)dst[dst_pos], dstW, src[src_pos], srcW, xInc);
56  } else {
57  c->hyScale(c, (int16_t*)dst[dst_pos], dstW, (const uint8_t *)src[src_pos], instance->filter,
58  instance->filter_pos, instance->filter_size);
59  }
60 
61  if (c->lumConvertRange)
62  c->lumConvertRange((int16_t*)dst[dst_pos], dstW,
63  c->lumConvertRange_coeff, c->lumConvertRange_offset);
64 
65  desc->dst->plane[0].sliceH += 1;
66 
67  if (desc->alpha) {
68  src = desc->src->plane[3].line;
69  dst = desc->dst->plane[3].line;
70 
71  src_pos = sliceY+i - desc->src->plane[3].sliceY;
72  dst_pos = sliceY+i - desc->dst->plane[3].sliceY;
73 
74  desc->dst->plane[3].sliceH += 1;
75 
76  if (c->hyscale_fast) {
77  c->hyscale_fast(c, (int16_t*)dst[dst_pos], dstW, src[src_pos], srcW, xInc);
78  } else {
79  c->hyScale(c, (int16_t*)dst[dst_pos], dstW, (const uint8_t *)src[src_pos], instance->filter,
80  instance->filter_pos, instance->filter_size);
81  }
82  }
83  }
84 
85  return sliceH;
86 }
87 
88 static int lum_convert(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
89 {
90  int srcW = desc->src->width;
91  ColorContext * instance = desc->instance;
92  uint32_t * pal = instance->pal;
93  int i;
94 
95  desc->dst->plane[0].sliceY = sliceY;
96  desc->dst->plane[0].sliceH = sliceH;
97  desc->dst->plane[3].sliceY = sliceY;
98  desc->dst->plane[3].sliceH = sliceH;
99 
100  for (i = 0; i < sliceH; ++i) {
101  int sp0 = sliceY+i - desc->src->plane[0].sliceY;
102  int sp1 = ((sliceY+i) >> desc->src->v_chr_sub_sample) - desc->src->plane[1].sliceY;
103  const uint8_t * src[4] = { desc->src->plane[0].line[sp0],
104  desc->src->plane[1].line[sp1],
105  desc->src->plane[2].line[sp1],
106  desc->src->plane[3].line[sp0]};
107  uint8_t * dst = desc->dst->plane[0].line[i];
108 
109  if (c->lumToYV12) {
110  c->lumToYV12(dst, src[0], src[1], src[2], srcW, pal, c->input_opaque);
111  } else if (c->readLumPlanar) {
112  c->readLumPlanar(dst, src, srcW, c->input_rgb2yuv_table, c->input_opaque);
113  }
114 
115 
116  if (desc->alpha) {
117  dst = desc->dst->plane[3].line[i];
118  if (c->alpToYV12) {
119  c->alpToYV12(dst, src[3], src[1], src[2], srcW, pal, c->input_opaque);
120  } else if (c->readAlpPlanar) {
121  c->readAlpPlanar(dst, src, srcW, NULL, c->input_opaque);
122  }
123  }
124  }
125 
126  return sliceH;
127 }
128 
130 {
131  ColorContext * li = av_malloc(sizeof(ColorContext));
132  if (!li)
133  return AVERROR(ENOMEM);
134  li->pal = pal;
135  desc->instance = li;
136 
137  desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
138  desc->src =src;
139  desc->dst = dst;
140  desc->process = &lum_convert;
141 
142  return 0;
143 }
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 {
148  FilterContext *li = av_malloc(sizeof(FilterContext));
149  if (!li)
150  return AVERROR(ENOMEM);
151 
152  li->filter = filter;
153  li->filter_pos = filter_pos;
154  li->filter_size = filter_size;
155  li->xInc = xInc;
156 
157  desc->instance = li;
158 
159  desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
160  desc->src = src;
161  desc->dst = dst;
162 
163  desc->process = &lum_h_scale;
164 
165  return 0;
166 }
167 
168 static int chr_h_scale(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
169 {
170  FilterContext *instance = desc->instance;
171  int srcW = AV_CEIL_RSHIFT(desc->src->width, desc->src->h_chr_sub_sample);
172  int dstW = AV_CEIL_RSHIFT(desc->dst->width, desc->dst->h_chr_sub_sample);
173  int xInc = instance->xInc;
174 
175  uint8_t ** src1 = desc->src->plane[1].line;
176  uint8_t ** dst1 = desc->dst->plane[1].line;
177  uint8_t ** src2 = desc->src->plane[2].line;
178  uint8_t ** dst2 = desc->dst->plane[2].line;
179 
180  int src_pos1 = sliceY - desc->src->plane[1].sliceY;
181  int dst_pos1 = sliceY - desc->dst->plane[1].sliceY;
182 
183  int src_pos2 = sliceY - desc->src->plane[2].sliceY;
184  int dst_pos2 = sliceY - desc->dst->plane[2].sliceY;
185 
186  int i;
187  for (i = 0; i < sliceH; ++i) {
188  if (c->hcscale_fast) {
189  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  } else {
191  c->hcScale(c, (uint16_t*)dst1[dst_pos1+i], dstW, src1[src_pos1+i], instance->filter, instance->filter_pos, instance->filter_size);
192  c->hcScale(c, (uint16_t*)dst2[dst_pos2+i], dstW, src2[src_pos2+i], instance->filter, instance->filter_pos, instance->filter_size);
193  }
194 
195  if (c->chrConvertRange)
196  c->chrConvertRange((uint16_t*)dst1[dst_pos1+i], (uint16_t*)dst2[dst_pos2+i], dstW,
197  c->chrConvertRange_coeff, c->chrConvertRange_offset);
198 
199  desc->dst->plane[1].sliceH += 1;
200  desc->dst->plane[2].sliceH += 1;
201  }
202  return sliceH;
203 }
204 
205 static int chr_convert(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
206 {
207  int srcW = AV_CEIL_RSHIFT(desc->src->width, desc->src->h_chr_sub_sample);
208  ColorContext * instance = desc->instance;
209  uint32_t * pal = instance->pal;
210 
211  int sp0 = (sliceY - (desc->src->plane[0].sliceY >> desc->src->v_chr_sub_sample)) << desc->src->v_chr_sub_sample;
212  int sp1 = sliceY - desc->src->plane[1].sliceY;
213 
214  int i;
215 
216  desc->dst->plane[1].sliceY = sliceY;
217  desc->dst->plane[1].sliceH = sliceH;
218  desc->dst->plane[2].sliceY = sliceY;
219  desc->dst->plane[2].sliceH = sliceH;
220 
221  for (i = 0; i < sliceH; ++i) {
222  const uint8_t * src[4] = { desc->src->plane[0].line[sp0+i],
223  desc->src->plane[1].line[sp1+i],
224  desc->src->plane[2].line[sp1+i],
225  desc->src->plane[3].line[sp0+i]};
226 
227  uint8_t * dst1 = desc->dst->plane[1].line[i];
228  uint8_t * dst2 = desc->dst->plane[2].line[i];
229  if (c->chrToYV12) {
230  c->chrToYV12(dst1, dst2, src[0], src[1], src[2], srcW, pal, c->input_opaque);
231  } else if (c->readChrPlanar) {
232  c->readChrPlanar(dst1, dst2, src, srcW, c->input_rgb2yuv_table, c->input_opaque);
233  }
234  }
235  return sliceH;
236 }
237 
239 {
240  ColorContext * li = av_malloc(sizeof(ColorContext));
241  if (!li)
242  return AVERROR(ENOMEM);
243  li->pal = pal;
244  desc->instance = li;
245 
246  desc->src =src;
247  desc->dst = dst;
248  desc->process = &chr_convert;
249 
250  return 0;
251 }
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 {
255  FilterContext *li = av_malloc(sizeof(FilterContext));
256  if (!li)
257  return AVERROR(ENOMEM);
258 
259  li->filter = filter;
260  li->filter_pos = filter_pos;
261  li->filter_size = filter_size;
262  li->xInc = xInc;
263 
264  desc->instance = li;
265 
266  desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
267  desc->src = src;
268  desc->dst = dst;
269 
270  desc->process = &chr_h_scale;
271 
272  return 0;
273 }
274 
275 static int no_chr_scale(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
276 {
277  desc->dst->plane[1].sliceY = sliceY + sliceH - desc->dst->plane[1].available_lines;
278  desc->dst->plane[1].sliceH = desc->dst->plane[1].available_lines;
279  desc->dst->plane[2].sliceY = sliceY + sliceH - desc->dst->plane[2].available_lines;
280  desc->dst->plane[2].sliceH = desc->dst->plane[2].available_lines;
281  return 0;
282 }
283 
285 {
286  desc->src = src;
287  desc->dst = dst;
288  desc->alpha = 0;
289  desc->instance = NULL;
290  desc->process = &no_chr_scale;
291  return 0;
292 }
ff_init_desc_cfmt_convert
int ff_init_desc_cfmt_convert(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint32_t *pal)
initializes chr pixel format conversion descriptor
Definition: hscale.c:238
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
ColorContext::pal
uint32_t * pal
Definition: hscale.c:36
lum_convert
static int lum_convert(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:88
src1
const pixel * src1
Definition: h264pred_template.c:421
ColorContext
Color conversion instance data.
Definition: hscale.c:34
ff_init_desc_hscale
int ff_init_desc_hscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint16_t *filter, int *filter_pos, int filter_size, int xInc)
initializes lum horizontal scaling descriptor
Definition: hscale.c:146
SwsFilterDescriptor
Struct which holds all necessary data for processing a slice.
Definition: swscale_internal.h:1119
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
ff_init_desc_no_chr
int ff_init_desc_no_chr(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst)
Definition: hscale.c:284
no_chr_scale
static int no_chr_scale(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:275
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
lum_h_scale
static int lum_h_scale(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:39
NULL
#define NULL
Definition: coverity.c:32
FilterContext::filter_size
int filter_size
Definition: hscale.c:29
FilterContext
Scaler instance data.
Definition: hscale.c:25
ff_init_desc_chscale
int ff_init_desc_chscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint16_t *filter, int *filter_pos, int filter_size, int xInc)
initializes chr horizontal scaling descriptor
Definition: hscale.c:253
chr_convert
static int chr_convert(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:205
FilterContext::xInc
int xInc
Definition: hscale.c:30
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
chr_h_scale
static int chr_h_scale(SwsInternal *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:168
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
src2
const pixel * src2
Definition: h264pred_template.c:422
swscale_internal.h
SwsSlice
Struct which defines a slice of an image to be scaled or an output for a scaled slice.
Definition: swscale_internal.h:1104
SwsInternal
Definition: swscale_internal.h:317
FilterContext::filter
uint16_t * filter
Definition: hscale.c:27
desc
const char * desc
Definition: libsvtav1.c:79
mem.h
ff_init_desc_fmt_convert
int ff_init_desc_fmt_convert(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint32_t *pal)
initializes lum pixel format conversion descriptor
Definition: hscale.c:129
FilterContext::filter_pos
int * filter_pos
Definition: hscale.c:28
src
#define src
Definition: vp8dsp.c:248
isALPHA
static av_always_inline int isALPHA(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:878