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 
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 
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 }
#define NULL
Definition: coverity.c:32
void(* hcScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize)
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
void(* chrConvertRange)(int16_t *dst1, int16_t *dst2, int width)
Color range conversion function for chroma planes if needed.
const char * desc
Definition: nvenc.c:68
int h_chr_sub_sample
horizontal chroma subsampling factor
Struct which holds all necessary data for processing a slice.
void(* chrToYV12)(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, int width, uint32_t *pal)
Unscaled conversion of chroma planes to YV12 for horizontal scaler.
void(* alpToYV12)(uint8_t *dst, const uint8_t *src, const uint8_t *src2, const uint8_t *src3, int width, uint32_t *pal)
Unscaled conversion of alpha plane to YV12 for horizontal scaler.
static int chr_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:202
void(* hyScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Scale one horizontal line of input data using a filter over the input lines, to produce one (differen...
void(* hyscale_fast)(struct SwsContext *c, int16_t *dst, int dstWidth, const uint8_t *src, int srcW, int xInc)
Scale one horizontal line of input data using a bilinear filter to produce one line of output data...
#define src
Definition: vp8dsp.c:254
static int lum_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:38
uint8_t
#define av_malloc(s)
uint8_t ** line
line buffer
int alpha
Flag for processing alpha channel.
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
int v_chr_sub_sample
vertical chroma subsampling factor
SwsSlice * dst
Output slice.
#define isALPHA(x)
Definition: swscale.c:51
uint16_t * filter
Definition: hscale.c:26
int filter_size
Definition: hscale.c:28
int ff_init_desc_no_chr(SwsFilterDescriptor *desc, SwsSlice *src, SwsSlice *dst)
Definition: hscale.c:281
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
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
void(* hcscale_fast)(struct SwsContext *c, int16_t *dst1, int16_t *dst2, int dstWidth, const uint8_t *src1, const uint8_t *src2, int srcW, int xInc)
static int lum_convert(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:86
SwsPlane plane[MAX_SLICE_PLANES]
color planes
int sliceH
number of lines
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
static int no_chr_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:272
void(* readChrPlanar)(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width, int32_t *rgb2yuv)
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
int available_lines
max number of lines that can be hold by this plane
static int chr_h_scale(SwsContext *c, SwsFilterDescriptor *desc, int sliceY, int sliceH)
Definition: hscale.c:166
void(* lumConvertRange)(int16_t *dst, int width)
Color range conversion function for luma plane if needed.
#define src1
Definition: h264pred.c:139
Color conversion instance data.
Definition: hscale.c:33
void(* readAlpPlanar)(uint8_t *dst, const uint8_t *src[4], int width, int32_t *rgb2yuv)
int width
Slice line width.
int(* process)(SwsContext *c, struct SwsFilterDescriptor *desc, int sliceY, int sliceH)
Function for processing input slice sliceH lines starting from line sliceY.
Struct which defines a slice of an image to be scaled or an output for a scaled slice.
void * instance
Filter instance data.
Scaler instance data.
Definition: hscale.c:24
enum AVPixelFormat fmt
planes pixel format
uint32_t * pal
Definition: hscale.c:35
void(* readLumPlanar)(uint8_t *dst, const uint8_t *src[4], int width, int32_t *rgb2yuv)
Functions to read planar input, such as planar RGB, and convert internally to Y/UV/A.
void(* lumToYV12)(uint8_t *dst, const uint8_t *src, const uint8_t *src2, const uint8_t *src3, int width, uint32_t *pal)
Unscaled conversion of luma plane to YV12 for horizontal scaler.
int32_t input_rgb2yuv_table[16+40 *4]
SwsSlice * src
Source slice.
int sliceY
index of first line
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
int xInc
Definition: hscale.c:29
int * filter_pos
Definition: hscale.c:27
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58