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 "swscale_internal.h"
22 
23 /// Scaler instance data
24 typedef struct FilterContext
25 {
26  uint16_t *filter;
27  int *filter_pos;
29  int xInc;
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 
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 
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 
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 }
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:235
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
lum_h_scale
static int lum_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:38
ColorContext::pal
uint32_t * pal
Definition: hscale.c:35
ColorContext
Color conversion instance data.
Definition: hscale.c:33
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:144
SwsFilterDescriptor
Struct which holds all necessary data for processing a slice.
Definition: swscale_internal.h:1047
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
Definition: filter_design.txt:228
lum_convert
static int lum_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:86
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
SwsSlice::fmt
enum AVPixelFormat fmt
planes pixel format
Definition: swscale_internal.h:1039
ff_init_desc_no_chr
int ff_init_desc_no_chr(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst)
Definition: hscale.c:281
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:51
NULL
#define NULL
Definition: coverity.c:32
FilterContext::filter_size
int filter_size
Definition: hscale.c:28
src
#define src
Definition: vp8dsp.c:255
FilterContext
Scaler instance data.
Definition: hscale.c:24
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:250
FilterContext::xInc
int xInc
Definition: hscale.c:29
chr_h_scale
static int chr_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:166
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
isALPHA
#define isALPHA(x)
Definition: swscale.c:51
src1
#define src1
Definition: h264pred.c:140
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
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:1032
FilterContext::filter
uint16_t * filter
Definition: hscale.c:26
desc
const char * desc
Definition: libsvtav1.c:79
no_chr_scale
static int no_chr_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:272
chr_convert
static int chr_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:202
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:127
FilterContext::filter_pos
int * filter_pos
Definition: hscale.c:27
SwsContext
Definition: swscale_internal.h:300