1 #include "swscale_internal.h"
3 static void free_lines(SwsSlice *s)
6 for (i = 0; i < 2; ++i) {
7 int n = s->plane[i].available_lines;
9 for (j = 0; j < n; ++j) {
10 av_freep(&s->plane[i].line[j]);
12 s->plane[i].line[j+n] = NULL;
16 for (i = 0; i < 4; ++i)
17 memset(s->plane[i].line, 0, sizeof(uint8_t*) * s->plane[i].available_lines * (s->is_ring ? 3 : 1));
18 s->should_free_lines = 0;
22 slice lines contains extra bytes for vetorial code thus @size
23 is the allocated memory size and @width is the number of pixels
25 static int alloc_lines(SwsSlice *s, int size, int width)
30 s->should_free_lines = 1;
33 for (i = 0; i < 2; ++i) {
34 int n = s->plane[i].available_lines;
38 av_assert0(n == s->plane[ii].available_lines);
39 for (j = 0; j < n; ++j) {
40 // chroma plane line U and V are expected to be contiguous in memory
41 // by mmx vertical scaler code
42 s->plane[i].line[j] = av_malloc(size * 2 + 32);
43 if (!s->plane[i].line[j]) {
45 return AVERROR(ENOMEM);
47 s->plane[ii].line[j] = s->plane[i].line[j] + size + 16;
49 s->plane[i].line[j+n] = s->plane[i].line[j];
50 s->plane[ii].line[j+n] = s->plane[ii].line[j];
58 static int alloc_slice(SwsSlice *s, enum AVPixelFormat fmt, int lumLines, int chrLines, int h_sub_sample, int v_sub_sample, int ring)
61 int size[4] = { lumLines,
66 s->h_chr_sub_sample = h_sub_sample;
67 s->v_chr_sub_sample = v_sub_sample;
70 s->should_free_lines = 0;
72 for (i = 0; i < 4; ++i) {
73 int n = size[i] * ( ring == 0 ? 1 : 3);
74 s->plane[i].line = av_mallocz_array(sizeof(uint8_t*), n);
75 if (!s->plane[i].line)
76 return AVERROR(ENOMEM);
78 s->plane[i].tmp = ring ? s->plane[i].line + size[i] * 2 : NULL;
79 s->plane[i].available_lines = size[i];
80 s->plane[i].sliceY = 0;
81 s->plane[i].sliceH = 0;
86 static void free_slice(SwsSlice *s)
90 if (s->should_free_lines)
92 for (i = 0; i < 4; ++i) {
93 av_freep(&s->plane[i].line);
94 s->plane[i].tmp = NULL;
99 int ff_rotate_slice(SwsSlice *s, int lum, int chr)
103 for (i = 0; i < 4; i+=3) {
104 int n = s->plane[i].available_lines;
105 int l = lum - s->plane[i].sliceY;
108 s->plane[i].sliceY += n;
109 s->plane[i].sliceH -= n;
114 for (i = 1; i < 3; ++i) {
115 int n = s->plane[i].available_lines;
116 int l = chr - s->plane[i].sliceY;
119 s->plane[i].sliceY += n;
120 s->plane[i].sliceH -= n;
127 int ff_init_slice_from_src(SwsSlice * s, uint8_t *src[4], int stride[4], int srcW, int lumY, int lumH, int chrY, int chrH)
131 const int start[4] = {lumY,
136 const int end[4] = {lumY +lumH,
143 for (i = 0; i < 4; ++i) {
146 lines = s->plane[i].available_lines < lines ? s->plane[i].available_lines : lines;
148 if (end[i] > s->plane[i].sliceY+s->plane[i].sliceH) {
149 if (start[i] <= s->plane[i].sliceY+1)
150 s->plane[i].sliceY = FFMIN(start[i], s->plane[i].sliceY);
152 s->plane[i].sliceY = start[i];
153 s->plane[i].sliceH = end[i] - s->plane[i].sliceY;
155 if (end[i] >= s->plane[i].sliceY)
156 s->plane[i].sliceH = s->plane[i].sliceY + s->plane[i].sliceH - start[i];
158 s->plane[i].sliceH = end[i] - start[i];
159 s->plane[i].sliceY = start[i];
162 for (j = start[i]; j < lines; j+= 1)
163 s->plane[i].line[j] = src[i] + (start[i] + j) * stride[i];
170 static void fill_ones(SwsSlice *s, int n, int is16bit)
173 for (i = 0; i < 4; ++i) {
175 int size = s->plane[i].available_lines;
176 for (j = 0; j < size; ++j) {
178 int end = is16bit ? n>>1: n;
179 // fill also one extra element
182 for (k = 0; k < end; ++k)
183 ((int32_t*)(s->plane[i].line[j]))[k] = 1<<18;
185 for (k = 0; k < end; ++k)
186 ((int16_t*)(s->plane[i].line[j]))[k] = 1<<14;
191 int ff_init_filters(SwsContext * c)
197 int need_lum_conv = c->lumToYV12 || c->readLumPlanar || c->alpToYV12 || c->readAlpPlanar;
198 int need_chr_conv = c->chrToYV12 || c->readChrPlanar;
200 int dst_stride = FFALIGN(c->dstW * sizeof(int16_t) + 66, 16);
202 uint32_t * pal = usePal(c->srcFormat) ? c->pal_yuv : (uint32_t*)c->input_rgb2yuv_table;
208 num_ydesc = need_lum_conv ? 2 : 1;
209 num_cdesc = need_chr_conv ? 2 : 1;
211 c->numSlice = FFMAX(num_ydesc, num_cdesc) + 1;
212 c->numDesc = num_ydesc + num_cdesc;
213 c->descIndex[0] = num_ydesc;
214 c->descIndex[1] = num_ydesc + num_cdesc;
218 c->desc = av_mallocz_array(sizeof(SwsFilterDescriptor), c->numDesc);
220 return AVERROR(ENOMEM);
221 c->slice = av_mallocz_array(sizeof(SwsSlice), c->numSlice);
224 res = alloc_slice(&c->slice[0], c->srcFormat, c->srcH, c->chrSrcH, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
225 if (res < 0) goto cleanup;
226 for (i = 1; i < c->numSlice-1; ++i) {
227 res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize + MAX_LINES_AHEAD, c->vChrFilterSize + MAX_LINES_AHEAD, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
228 if (res < 0) goto cleanup;
229 res = alloc_lines(&c->slice[i], FFALIGN(c->srcW*2+78, 16), c->srcW);
230 if (res < 0) goto cleanup;
232 res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize + MAX_LINES_AHEAD, c->vChrFilterSize + MAX_LINES_AHEAD, c->chrDstHSubSample, c->chrDstVSubSample, 1);
233 if (res < 0) goto cleanup;
234 res = alloc_lines(&c->slice[i], dst_stride, c->dstW);
235 if (res < 0) goto cleanup;
237 fill_ones(&c->slice[i], dst_stride>>1, c->dstBpc == 16);
244 ff_init_desc_fmt_convert(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], pal);
245 c->desc[index].alpha = c->alpPixBuf != 0;
251 dstIdx = FFMAX(num_ydesc, num_cdesc);
252 ff_init_desc_hscale(&c->desc[index], &c->slice[index], &c->slice[dstIdx], c->hLumFilter, c->hLumFilterPos, c->hLumFilterSize, c->lumXInc);
253 c->desc[index].alpha = c->alpPixBuf != 0;
261 ff_init_desc_cfmt_convert(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], pal);
266 dstIdx = FFMAX(num_ydesc, num_cdesc);
267 if (c->needs_hcscale)
268 ff_init_desc_chscale(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], c->hChrFilter, c->hChrFilterPos, c->hChrFilterSize, c->chrXInc);
270 ff_init_desc_no_chr(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx]);
280 int ff_free_filters(SwsContext *c)
284 for (i = 0; i < c->numDesc; ++i)
285 av_freep(&c->desc[i].instance);
290 for (i = 0; i < c->numSlice; ++i)
291 free_slice(&c->slice[i]);