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(SwsContext *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 
64  desc->dst->plane[0].sliceH += 1;
65 
66  if (desc->alpha) {
67  src = desc->src->plane[3].line;
68  dst = desc->dst->plane[3].line;
69 
70  src_pos = sliceY+i - desc->src->plane[3].sliceY;
71  dst_pos = sliceY+i - desc->dst->plane[3].sliceY;
72 
73  desc->dst->plane[3].sliceH += 1;
74 
75  if (c->hyscale_fast) {
76  c->hyscale_fast(c, (int16_t*)dst[dst_pos], dstW, src[src_pos], srcW, xInc);
77  } else {
78  c->hyScale(c, (int16_t*)dst[dst_pos], dstW, (const uint8_t *)src[src_pos], instance->filter,
79  instance->filter_pos, instance->filter_size);
80  }
81  }
82  }
83 
84  return sliceH;
85 }
86 
87 static int lum_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
88 {
89  int srcW = desc->src->width;
90  ColorContext * instance = desc->instance;
91  uint32_t * pal = instance->pal;
92  int i;
93 
94  desc->dst->plane[0].sliceY = sliceY;
95  desc->dst->plane[0].sliceH = sliceH;
96  desc->dst->plane[3].sliceY = sliceY;
97  desc->dst->plane[3].sliceH = sliceH;
98 
99  for (i = 0; i < sliceH; ++i) {
100  int sp0 = sliceY+i - desc->src->plane[0].sliceY;
101  int sp1 = ((sliceY+i) >> desc->src->v_chr_sub_sample) - desc->src->plane[1].sliceY;
102  const uint8_t * src[4] = { desc->src->plane[0].line[sp0],
103  desc->src->plane[1].line[sp1],
104  desc->src->plane[2].line[sp1],
105  desc->src->plane[3].line[sp0]};
106  uint8_t * dst = desc->dst->plane[0].line[i];
107 
108  if (c->lumToYV12) {
109  c->lumToYV12(dst, src[0], src[1], src[2], srcW, pal, c->input_opaque);
110  } else if (c->readLumPlanar) {
111  c->readLumPlanar(dst, src, srcW, c->input_rgb2yuv_table, c->input_opaque);
112  }
113 
114 
115  if (desc->alpha) {
116  dst = desc->dst->plane[3].line[i];
117  if (c->alpToYV12) {
118  c->alpToYV12(dst, src[3], src[1], src[2], srcW, pal, c->input_opaque);
119  } else if (c->readAlpPlanar) {
120  c->readAlpPlanar(dst, src, srcW, NULL, c->input_opaque);
121  }
122  }
123  }
124 
125  return sliceH;
126 }
127 
129 {
130  ColorContext * li = av_malloc(sizeof(ColorContext));
131  if (!li)
132  return AVERROR(ENOMEM);
133  li->pal = pal;
134  desc->instance = li;
135 
136  desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
137  desc->src =src;
138  desc->dst = dst;
139  desc->process = &lum_convert;
140 
141  return 0;
142 }
143 
144 
145 int ff_init_desc_hscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint16_t *filter, int * filter_pos, int filter_size, int xInc)
146 {
147  FilterContext *li = av_malloc(sizeof(FilterContext));
148  if (!li)
149  return AVERROR(ENOMEM);
150 
151  li->filter = filter;
152  li->filter_pos = filter_pos;
153  li->filter_size = filter_size;
154  li->xInc = xInc;
155 
156  desc->instance = li;
157 
158  desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
159  desc->src = src;
160  desc->dst = dst;
161 
162  desc->process = &lum_h_scale;
163 
164  return 0;
165 }
166 
167 static int chr_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
168 {
169  FilterContext *instance = desc->instance;
170  int srcW = AV_CEIL_RSHIFT(desc->src->width, desc->src->h_chr_sub_sample);
171  int dstW = AV_CEIL_RSHIFT(desc->dst->width, desc->dst->h_chr_sub_sample);
172  int xInc = instance->xInc;
173 
174  uint8_t ** src1 = desc->src->plane[1].line;
175  uint8_t ** dst1 = desc->dst->plane[1].line;
176  uint8_t ** src2 = desc->src->plane[2].line;
177  uint8_t ** dst2 = desc->dst->plane[2].line;
178 
179  int src_pos1 = sliceY - desc->src->plane[1].sliceY;
180  int dst_pos1 = sliceY - desc->dst->plane[1].sliceY;
181 
182  int src_pos2 = sliceY - desc->src->plane[2].sliceY;
183  int dst_pos2 = sliceY - desc->dst->plane[2].sliceY;
184 
185  int i;
186  for (i = 0; i < sliceH; ++i) {
187  if (c->hcscale_fast) {
188  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);
189  } else {
190  c->hcScale(c, (uint16_t*)dst1[dst_pos1+i], dstW, src1[src_pos1+i], instance->filter, instance->filter_pos, instance->filter_size);
191  c->hcScale(c, (uint16_t*)dst2[dst_pos2+i], dstW, src2[src_pos2+i], instance->filter, instance->filter_pos, instance->filter_size);
192  }
193 
194  if (c->chrConvertRange)
195  c->chrConvertRange((uint16_t*)dst1[dst_pos1+i], (uint16_t*)dst2[dst_pos2+i], dstW);
196 
197  desc->dst->plane[1].sliceH += 1;
198  desc->dst->plane[2].sliceH += 1;
199  }
200  return sliceH;
201 }
202 
203 static int chr_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
204 {
205  int srcW = AV_CEIL_RSHIFT(desc->src->width, desc->src->h_chr_sub_sample);
206  ColorContext * instance = desc->instance;
207  uint32_t * pal = instance->pal;
208 
209  int sp0 = (sliceY - (desc->src->plane[0].sliceY >> desc->src->v_chr_sub_sample)) << desc->src->v_chr_sub_sample;
210  int sp1 = sliceY - desc->src->plane[1].sliceY;
211 
212  int i;
213 
214  desc->dst->plane[1].sliceY = sliceY;
215  desc->dst->plane[1].sliceH = sliceH;
216  desc->dst->plane[2].sliceY = sliceY;
217  desc->dst->plane[2].sliceH = sliceH;
218 
219  for (i = 0; i < sliceH; ++i) {
220  const uint8_t * src[4] = { desc->src->plane[0].line[sp0+i],
221  desc->src->plane[1].line[sp1+i],
222  desc->src->plane[2].line[sp1+i],
223  desc->src->plane[3].line[sp0+i]};
224 
225  uint8_t * dst1 = desc->dst->plane[1].line[i];
226  uint8_t * dst2 = desc->dst->plane[2].line[i];
227  if (c->chrToYV12) {
228  c->chrToYV12(dst1, dst2, src[0], src[1], src[2], srcW, pal, c->input_opaque);
229  } else if (c->readChrPlanar) {
230  c->readChrPlanar(dst1, dst2, src, srcW, c->input_rgb2yuv_table, c->input_opaque);
231  }
232  }
233  return sliceH;
234 }
235 
237 {
238  ColorContext * li = av_malloc(sizeof(ColorContext));
239  if (!li)
240  return AVERROR(ENOMEM);
241  li->pal = pal;
242  desc->instance = li;
243 
244  desc->src =src;
245  desc->dst = dst;
246  desc->process = &chr_convert;
247 
248  return 0;
249 }
250 
251 int ff_init_desc_chscale(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst, uint16_t *filter, int * filter_pos, int filter_size, int xInc)
252 {
253  FilterContext *li = av_malloc(sizeof(FilterContext));
254  if (!li)
255  return AVERROR(ENOMEM);
256 
257  li->filter = filter;
258  li->filter_pos = filter_pos;
259  li->filter_size = filter_size;
260  li->xInc = xInc;
261 
262  desc->instance = li;
263 
264  desc->alpha = isALPHA(src->fmt) && isALPHA(dst->fmt);
265  desc->src = src;
266  desc->dst = dst;
267 
268  desc->process = &chr_h_scale;
269 
270  return 0;
271 }
272 
273 static int no_chr_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
274 {
275  desc->dst->plane[1].sliceY = sliceY + sliceH - desc->dst->plane[1].available_lines;
276  desc->dst->plane[1].sliceH = desc->dst->plane[1].available_lines;
277  desc->dst->plane[2].sliceY = sliceY + sliceH - desc->dst->plane[2].available_lines;
278  desc->dst->plane[2].sliceH = desc->dst->plane[2].available_lines;
279  return 0;
280 }
281 
283 {
284  desc->src = src;
285  desc->dst = dst;
286  desc->alpha = 0;
287  desc->instance = NULL;
288  desc->process = &no_chr_scale;
289  return 0;
290 }
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:236
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:39
ColorContext::pal
uint32_t * pal
Definition: hscale.c:36
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:145
SwsFilterDescriptor
Struct which holds all necessary data for processing a slice.
Definition: swscale_internal.h:1078
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
lum_convert
static int lum_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:87
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
SwsSlice::fmt
enum AVPixelFormat fmt
planes pixel format
Definition: swscale_internal.h:1070
ff_init_desc_no_chr
int ff_init_desc_no_chr(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst)
Definition: hscale.c:282
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:59
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:251
FilterContext::xInc
int xInc
Definition: hscale.c:30
chr_h_scale
static int chr_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:167
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
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:1063
FilterContext::filter
uint16_t * filter
Definition: hscale.c:27
desc
const char * desc
Definition: libsvtav1.c:79
mem.h
no_chr_scale
static int no_chr_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:273
chr_convert
static int chr_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:203
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
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:128
FilterContext::filter_pos
int * filter_pos
Definition: hscale.c:28
SwsContext
Definition: swscale_internal.h:301
isALPHA
static av_always_inline int isALPHA(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:857