FFmpeg  4.0
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:65
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.
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 AVERROR(e)
Definition: error.h:43
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.
static double c[64]
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
int xInc
Definition: hscale.c:29
int * filter_pos
Definition: hscale.c:27
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58