1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (C) 2004-2010 Michael Niedermayer <michaelni@gmx.at> 3cabdff1aSopenharmony_ci * Copyright (C) 2008 David Conrad 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "libavutil/attributes.h" 23cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 24cabdff1aSopenharmony_ci#include "libavutil/common.h" 25cabdff1aSopenharmony_ci#include "me_cmp.h" 26cabdff1aSopenharmony_ci#include "snow_dwt.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ciint ff_slice_buffer_init(slice_buffer *buf, int line_count, 29cabdff1aSopenharmony_ci int max_allocated_lines, int line_width, 30cabdff1aSopenharmony_ci IDWTELEM *base_buffer) 31cabdff1aSopenharmony_ci{ 32cabdff1aSopenharmony_ci int i; 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci buf->base_buffer = base_buffer; 35cabdff1aSopenharmony_ci buf->line_count = line_count; 36cabdff1aSopenharmony_ci buf->line_width = line_width; 37cabdff1aSopenharmony_ci buf->data_count = max_allocated_lines; 38cabdff1aSopenharmony_ci buf->line = av_calloc(line_count, sizeof(*buf->line)); 39cabdff1aSopenharmony_ci if (!buf->line) 40cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 41cabdff1aSopenharmony_ci buf->data_stack = av_malloc_array(max_allocated_lines, sizeof(IDWTELEM *)); 42cabdff1aSopenharmony_ci if (!buf->data_stack) { 43cabdff1aSopenharmony_ci av_freep(&buf->line); 44cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 45cabdff1aSopenharmony_ci } 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci for (i = 0; i < max_allocated_lines; i++) { 48cabdff1aSopenharmony_ci buf->data_stack[i] = av_malloc_array(line_width, sizeof(IDWTELEM)); 49cabdff1aSopenharmony_ci if (!buf->data_stack[i]) { 50cabdff1aSopenharmony_ci for (i--; i >=0; i--) 51cabdff1aSopenharmony_ci av_freep(&buf->data_stack[i]); 52cabdff1aSopenharmony_ci av_freep(&buf->data_stack); 53cabdff1aSopenharmony_ci av_freep(&buf->line); 54cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 55cabdff1aSopenharmony_ci } 56cabdff1aSopenharmony_ci } 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci buf->data_stack_top = max_allocated_lines - 1; 59cabdff1aSopenharmony_ci return 0; 60cabdff1aSopenharmony_ci} 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ciIDWTELEM *ff_slice_buffer_load_line(slice_buffer *buf, int line) 63cabdff1aSopenharmony_ci{ 64cabdff1aSopenharmony_ci IDWTELEM *buffer; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci av_assert0(buf->data_stack_top >= 0); 67cabdff1aSopenharmony_ci// av_assert1(!buf->line[line]); 68cabdff1aSopenharmony_ci if (buf->line[line]) 69cabdff1aSopenharmony_ci return buf->line[line]; 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci buffer = buf->data_stack[buf->data_stack_top]; 72cabdff1aSopenharmony_ci buf->data_stack_top--; 73cabdff1aSopenharmony_ci buf->line[line] = buffer; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci return buffer; 76cabdff1aSopenharmony_ci} 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_civoid ff_slice_buffer_release(slice_buffer *buf, int line) 79cabdff1aSopenharmony_ci{ 80cabdff1aSopenharmony_ci IDWTELEM *buffer; 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci av_assert1(line >= 0 && line < buf->line_count); 83cabdff1aSopenharmony_ci av_assert1(buf->line[line]); 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci buffer = buf->line[line]; 86cabdff1aSopenharmony_ci buf->data_stack_top++; 87cabdff1aSopenharmony_ci buf->data_stack[buf->data_stack_top] = buffer; 88cabdff1aSopenharmony_ci buf->line[line] = NULL; 89cabdff1aSopenharmony_ci} 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_civoid ff_slice_buffer_flush(slice_buffer *buf) 92cabdff1aSopenharmony_ci{ 93cabdff1aSopenharmony_ci int i; 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci if (!buf->line) 96cabdff1aSopenharmony_ci return; 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci for (i = 0; i < buf->line_count; i++) 99cabdff1aSopenharmony_ci if (buf->line[i]) 100cabdff1aSopenharmony_ci ff_slice_buffer_release(buf, i); 101cabdff1aSopenharmony_ci} 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_civoid ff_slice_buffer_destroy(slice_buffer *buf) 104cabdff1aSopenharmony_ci{ 105cabdff1aSopenharmony_ci int i; 106cabdff1aSopenharmony_ci ff_slice_buffer_flush(buf); 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci if (buf->data_stack) 109cabdff1aSopenharmony_ci for (i = buf->data_count - 1; i >= 0; i--) 110cabdff1aSopenharmony_ci av_freep(&buf->data_stack[i]); 111cabdff1aSopenharmony_ci av_freep(&buf->data_stack); 112cabdff1aSopenharmony_ci av_freep(&buf->line); 113cabdff1aSopenharmony_ci} 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_cistatic av_always_inline void lift(DWTELEM *dst, DWTELEM *src, DWTELEM *ref, 116cabdff1aSopenharmony_ci int dst_step, int src_step, int ref_step, 117cabdff1aSopenharmony_ci int width, int mul, int add, int shift, 118cabdff1aSopenharmony_ci int highpass, int inverse) 119cabdff1aSopenharmony_ci{ 120cabdff1aSopenharmony_ci const int mirror_left = !highpass; 121cabdff1aSopenharmony_ci const int mirror_right = (width & 1) ^ highpass; 122cabdff1aSopenharmony_ci const int w = (width >> 1) - 1 + (highpass & width); 123cabdff1aSopenharmony_ci int i; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci#define LIFT(src, ref, inv) ((src) + ((inv) ? -(ref) : +(ref))) 126cabdff1aSopenharmony_ci if (mirror_left) { 127cabdff1aSopenharmony_ci dst[0] = LIFT(src[0], ((mul * 2 * ref[0] + add) >> shift), inverse); 128cabdff1aSopenharmony_ci dst += dst_step; 129cabdff1aSopenharmony_ci src += src_step; 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci for (i = 0; i < w; i++) 133cabdff1aSopenharmony_ci dst[i * dst_step] = LIFT(src[i * src_step], 134cabdff1aSopenharmony_ci ((mul * (ref[i * ref_step] + 135cabdff1aSopenharmony_ci ref[(i + 1) * ref_step]) + 136cabdff1aSopenharmony_ci add) >> shift), 137cabdff1aSopenharmony_ci inverse); 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci if (mirror_right) 140cabdff1aSopenharmony_ci dst[w * dst_step] = LIFT(src[w * src_step], 141cabdff1aSopenharmony_ci ((mul * 2 * ref[w * ref_step] + add) >> shift), 142cabdff1aSopenharmony_ci inverse); 143cabdff1aSopenharmony_ci} 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_cistatic av_always_inline void liftS(DWTELEM *dst, DWTELEM *src, DWTELEM *ref, 146cabdff1aSopenharmony_ci int dst_step, int src_step, int ref_step, 147cabdff1aSopenharmony_ci int width, int mul, int add, int shift, 148cabdff1aSopenharmony_ci int highpass, int inverse) 149cabdff1aSopenharmony_ci{ 150cabdff1aSopenharmony_ci const int mirror_left = !highpass; 151cabdff1aSopenharmony_ci const int mirror_right = (width & 1) ^ highpass; 152cabdff1aSopenharmony_ci const int w = (width >> 1) - 1 + (highpass & width); 153cabdff1aSopenharmony_ci int i; 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci av_assert1(shift == 4); 156cabdff1aSopenharmony_ci#define LIFTS(src, ref, inv) \ 157cabdff1aSopenharmony_ci ((inv) ? (src) + (((ref) + 4 * (src)) >> shift) \ 158cabdff1aSopenharmony_ci : -((-16 * (src) + (ref) + add / \ 159cabdff1aSopenharmony_ci 4 + 1 + (5 << 25)) / (5 * 4) - (1 << 23))) 160cabdff1aSopenharmony_ci if (mirror_left) { 161cabdff1aSopenharmony_ci dst[0] = LIFTS(src[0], mul * 2 * ref[0] + add, inverse); 162cabdff1aSopenharmony_ci dst += dst_step; 163cabdff1aSopenharmony_ci src += src_step; 164cabdff1aSopenharmony_ci } 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci for (i = 0; i < w; i++) 167cabdff1aSopenharmony_ci dst[i * dst_step] = LIFTS(src[i * src_step], 168cabdff1aSopenharmony_ci mul * (ref[i * ref_step] + 169cabdff1aSopenharmony_ci ref[(i + 1) * ref_step]) + add, 170cabdff1aSopenharmony_ci inverse); 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci if (mirror_right) 173cabdff1aSopenharmony_ci dst[w * dst_step] = LIFTS(src[w * src_step], 174cabdff1aSopenharmony_ci mul * 2 * ref[w * ref_step] + add, 175cabdff1aSopenharmony_ci inverse); 176cabdff1aSopenharmony_ci} 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_cistatic void horizontal_decompose53i(DWTELEM *b, DWTELEM *temp, int width) 179cabdff1aSopenharmony_ci{ 180cabdff1aSopenharmony_ci const int width2 = width >> 1; 181cabdff1aSopenharmony_ci int x; 182cabdff1aSopenharmony_ci const int w2 = (width + 1) >> 1; 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci for (x = 0; x < width2; x++) { 185cabdff1aSopenharmony_ci temp[x] = b[2 * x]; 186cabdff1aSopenharmony_ci temp[x + w2] = b[2 * x + 1]; 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci if (width & 1) 189cabdff1aSopenharmony_ci temp[x] = b[2 * x]; 190cabdff1aSopenharmony_ci lift(b + w2, temp + w2, temp, 1, 1, 1, width, -1, 0, 1, 1, 0); 191cabdff1aSopenharmony_ci lift(b, temp, b + w2, 1, 1, 1, width, 1, 2, 2, 0, 0); 192cabdff1aSopenharmony_ci} 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_cistatic void vertical_decompose53iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, 195cabdff1aSopenharmony_ci int width) 196cabdff1aSopenharmony_ci{ 197cabdff1aSopenharmony_ci int i; 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 200cabdff1aSopenharmony_ci b1[i] -= (b0[i] + b2[i]) >> 1; 201cabdff1aSopenharmony_ci} 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_cistatic void vertical_decompose53iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, 204cabdff1aSopenharmony_ci int width) 205cabdff1aSopenharmony_ci{ 206cabdff1aSopenharmony_ci int i; 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 209cabdff1aSopenharmony_ci b1[i] += (b0[i] + b2[i] + 2) >> 2; 210cabdff1aSopenharmony_ci} 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_cistatic void spatial_decompose53i(DWTELEM *buffer, DWTELEM *temp, 213cabdff1aSopenharmony_ci int width, int height, int stride) 214cabdff1aSopenharmony_ci{ 215cabdff1aSopenharmony_ci int y; 216cabdff1aSopenharmony_ci DWTELEM *b0 = buffer + avpriv_mirror(-2 - 1, height - 1) * stride; 217cabdff1aSopenharmony_ci DWTELEM *b1 = buffer + avpriv_mirror(-2, height - 1) * stride; 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci for (y = -2; y < height; y += 2) { 220cabdff1aSopenharmony_ci DWTELEM *b2 = buffer + avpriv_mirror(y + 1, height - 1) * stride; 221cabdff1aSopenharmony_ci DWTELEM *b3 = buffer + avpriv_mirror(y + 2, height - 1) * stride; 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ci if (y + 1 < (unsigned)height) 224cabdff1aSopenharmony_ci horizontal_decompose53i(b2, temp, width); 225cabdff1aSopenharmony_ci if (y + 2 < (unsigned)height) 226cabdff1aSopenharmony_ci horizontal_decompose53i(b3, temp, width); 227cabdff1aSopenharmony_ci 228cabdff1aSopenharmony_ci if (y + 1 < (unsigned)height) 229cabdff1aSopenharmony_ci vertical_decompose53iH0(b1, b2, b3, width); 230cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 231cabdff1aSopenharmony_ci vertical_decompose53iL0(b0, b1, b2, width); 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_ci b0 = b2; 234cabdff1aSopenharmony_ci b1 = b3; 235cabdff1aSopenharmony_ci } 236cabdff1aSopenharmony_ci} 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_cistatic void horizontal_decompose97i(DWTELEM *b, DWTELEM *temp, int width) 239cabdff1aSopenharmony_ci{ 240cabdff1aSopenharmony_ci const int w2 = (width + 1) >> 1; 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci lift(temp + w2, b + 1, b, 1, 2, 2, width, W_AM, W_AO, W_AS, 1, 1); 243cabdff1aSopenharmony_ci liftS(temp, b, temp + w2, 1, 2, 1, width, W_BM, W_BO, W_BS, 0, 0); 244cabdff1aSopenharmony_ci lift(b + w2, temp + w2, temp, 1, 1, 1, width, W_CM, W_CO, W_CS, 1, 0); 245cabdff1aSopenharmony_ci lift(b, temp, b + w2, 1, 1, 1, width, W_DM, W_DO, W_DS, 0, 0); 246cabdff1aSopenharmony_ci} 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_cistatic void vertical_decompose97iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, 249cabdff1aSopenharmony_ci int width) 250cabdff1aSopenharmony_ci{ 251cabdff1aSopenharmony_ci int i; 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 254cabdff1aSopenharmony_ci b1[i] -= (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS; 255cabdff1aSopenharmony_ci} 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_cistatic void vertical_decompose97iH1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, 258cabdff1aSopenharmony_ci int width) 259cabdff1aSopenharmony_ci{ 260cabdff1aSopenharmony_ci int i; 261cabdff1aSopenharmony_ci 262cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 263cabdff1aSopenharmony_ci b1[i] += (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS; 264cabdff1aSopenharmony_ci} 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_cistatic void vertical_decompose97iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, 267cabdff1aSopenharmony_ci int width) 268cabdff1aSopenharmony_ci{ 269cabdff1aSopenharmony_ci int i; 270cabdff1aSopenharmony_ci 271cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 272cabdff1aSopenharmony_ci b1[i] = (16 * 4 * b1[i] - 4 * (b0[i] + b2[i]) + W_BO * 5 + (5 << 27)) / 273cabdff1aSopenharmony_ci (5 * 16) - (1 << 23); 274cabdff1aSopenharmony_ci} 275cabdff1aSopenharmony_ci 276cabdff1aSopenharmony_cistatic void vertical_decompose97iL1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, 277cabdff1aSopenharmony_ci int width) 278cabdff1aSopenharmony_ci{ 279cabdff1aSopenharmony_ci int i; 280cabdff1aSopenharmony_ci 281cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 282cabdff1aSopenharmony_ci b1[i] += (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS; 283cabdff1aSopenharmony_ci} 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_cistatic void spatial_decompose97i(DWTELEM *buffer, DWTELEM *temp, 286cabdff1aSopenharmony_ci int width, int height, int stride) 287cabdff1aSopenharmony_ci{ 288cabdff1aSopenharmony_ci int y; 289cabdff1aSopenharmony_ci DWTELEM *b0 = buffer + avpriv_mirror(-4 - 1, height - 1) * stride; 290cabdff1aSopenharmony_ci DWTELEM *b1 = buffer + avpriv_mirror(-4, height - 1) * stride; 291cabdff1aSopenharmony_ci DWTELEM *b2 = buffer + avpriv_mirror(-4 + 1, height - 1) * stride; 292cabdff1aSopenharmony_ci DWTELEM *b3 = buffer + avpriv_mirror(-4 + 2, height - 1) * stride; 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci for (y = -4; y < height; y += 2) { 295cabdff1aSopenharmony_ci DWTELEM *b4 = buffer + avpriv_mirror(y + 3, height - 1) * stride; 296cabdff1aSopenharmony_ci DWTELEM *b5 = buffer + avpriv_mirror(y + 4, height - 1) * stride; 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci if (y + 3 < (unsigned)height) 299cabdff1aSopenharmony_ci horizontal_decompose97i(b4, temp, width); 300cabdff1aSopenharmony_ci if (y + 4 < (unsigned)height) 301cabdff1aSopenharmony_ci horizontal_decompose97i(b5, temp, width); 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci if (y + 3 < (unsigned)height) 304cabdff1aSopenharmony_ci vertical_decompose97iH0(b3, b4, b5, width); 305cabdff1aSopenharmony_ci if (y + 2 < (unsigned)height) 306cabdff1aSopenharmony_ci vertical_decompose97iL0(b2, b3, b4, width); 307cabdff1aSopenharmony_ci if (y + 1 < (unsigned)height) 308cabdff1aSopenharmony_ci vertical_decompose97iH1(b1, b2, b3, width); 309cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 310cabdff1aSopenharmony_ci vertical_decompose97iL1(b0, b1, b2, width); 311cabdff1aSopenharmony_ci 312cabdff1aSopenharmony_ci b0 = b2; 313cabdff1aSopenharmony_ci b1 = b3; 314cabdff1aSopenharmony_ci b2 = b4; 315cabdff1aSopenharmony_ci b3 = b5; 316cabdff1aSopenharmony_ci } 317cabdff1aSopenharmony_ci} 318cabdff1aSopenharmony_ci 319cabdff1aSopenharmony_civoid ff_spatial_dwt(DWTELEM *buffer, DWTELEM *temp, int width, int height, 320cabdff1aSopenharmony_ci int stride, int type, int decomposition_count) 321cabdff1aSopenharmony_ci{ 322cabdff1aSopenharmony_ci int level; 323cabdff1aSopenharmony_ci 324cabdff1aSopenharmony_ci for (level = 0; level < decomposition_count; level++) { 325cabdff1aSopenharmony_ci switch (type) { 326cabdff1aSopenharmony_ci case DWT_97: 327cabdff1aSopenharmony_ci spatial_decompose97i(buffer, temp, 328cabdff1aSopenharmony_ci width >> level, height >> level, 329cabdff1aSopenharmony_ci stride << level); 330cabdff1aSopenharmony_ci break; 331cabdff1aSopenharmony_ci case DWT_53: 332cabdff1aSopenharmony_ci spatial_decompose53i(buffer, temp, 333cabdff1aSopenharmony_ci width >> level, height >> level, 334cabdff1aSopenharmony_ci stride << level); 335cabdff1aSopenharmony_ci break; 336cabdff1aSopenharmony_ci } 337cabdff1aSopenharmony_ci } 338cabdff1aSopenharmony_ci} 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_cistatic void horizontal_compose53i(IDWTELEM *b, IDWTELEM *temp, int width) 341cabdff1aSopenharmony_ci{ 342cabdff1aSopenharmony_ci const int width2 = width >> 1; 343cabdff1aSopenharmony_ci const int w2 = (width + 1) >> 1; 344cabdff1aSopenharmony_ci int x; 345cabdff1aSopenharmony_ci 346cabdff1aSopenharmony_ci for (x = 0; x < width2; x++) { 347cabdff1aSopenharmony_ci temp[2 * x] = b[x]; 348cabdff1aSopenharmony_ci temp[2 * x + 1] = b[x + w2]; 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci if (width & 1) 351cabdff1aSopenharmony_ci temp[2 * x] = b[x]; 352cabdff1aSopenharmony_ci 353cabdff1aSopenharmony_ci b[0] = temp[0] - ((temp[1] + 1) >> 1); 354cabdff1aSopenharmony_ci for (x = 2; x < width - 1; x += 2) { 355cabdff1aSopenharmony_ci b[x] = temp[x] - ((temp[x - 1] + temp[x + 1] + 2) >> 2); 356cabdff1aSopenharmony_ci b[x - 1] = temp[x - 1] + ((b[x - 2] + b[x] + 1) >> 1); 357cabdff1aSopenharmony_ci } 358cabdff1aSopenharmony_ci if (width & 1) { 359cabdff1aSopenharmony_ci b[x] = temp[x] - ((temp[x - 1] + 1) >> 1); 360cabdff1aSopenharmony_ci b[x - 1] = temp[x - 1] + ((b[x - 2] + b[x] + 1) >> 1); 361cabdff1aSopenharmony_ci } else 362cabdff1aSopenharmony_ci b[x - 1] = temp[x - 1] + b[x - 2]; 363cabdff1aSopenharmony_ci} 364cabdff1aSopenharmony_ci 365cabdff1aSopenharmony_cistatic void vertical_compose53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, 366cabdff1aSopenharmony_ci int width) 367cabdff1aSopenharmony_ci{ 368cabdff1aSopenharmony_ci int i; 369cabdff1aSopenharmony_ci 370cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 371cabdff1aSopenharmony_ci b1[i] += (b0[i] + b2[i]) >> 1; 372cabdff1aSopenharmony_ci} 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_cistatic void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, 375cabdff1aSopenharmony_ci int width) 376cabdff1aSopenharmony_ci{ 377cabdff1aSopenharmony_ci int i; 378cabdff1aSopenharmony_ci 379cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 380cabdff1aSopenharmony_ci b1[i] -= (b0[i] + b2[i] + 2) >> 2; 381cabdff1aSopenharmony_ci} 382cabdff1aSopenharmony_ci 383cabdff1aSopenharmony_cistatic void spatial_compose53i_buffered_init(DWTCompose *cs, slice_buffer *sb, 384cabdff1aSopenharmony_ci int height, int stride_line) 385cabdff1aSopenharmony_ci{ 386cabdff1aSopenharmony_ci cs->b0 = slice_buffer_get_line(sb, 387cabdff1aSopenharmony_ci avpriv_mirror(-1 - 1, height - 1) * stride_line); 388cabdff1aSopenharmony_ci cs->b1 = slice_buffer_get_line(sb, avpriv_mirror(-1, height - 1) * stride_line); 389cabdff1aSopenharmony_ci cs->y = -1; 390cabdff1aSopenharmony_ci} 391cabdff1aSopenharmony_ci 392cabdff1aSopenharmony_cistatic void spatial_compose53i_init(DWTCompose *cs, IDWTELEM *buffer, 393cabdff1aSopenharmony_ci int height, int stride) 394cabdff1aSopenharmony_ci{ 395cabdff1aSopenharmony_ci cs->b0 = buffer + avpriv_mirror(-1 - 1, height - 1) * stride; 396cabdff1aSopenharmony_ci cs->b1 = buffer + avpriv_mirror(-1, height - 1) * stride; 397cabdff1aSopenharmony_ci cs->y = -1; 398cabdff1aSopenharmony_ci} 399cabdff1aSopenharmony_ci 400cabdff1aSopenharmony_cistatic void spatial_compose53i_dy_buffered(DWTCompose *cs, slice_buffer *sb, 401cabdff1aSopenharmony_ci IDWTELEM *temp, 402cabdff1aSopenharmony_ci int width, int height, 403cabdff1aSopenharmony_ci int stride_line) 404cabdff1aSopenharmony_ci{ 405cabdff1aSopenharmony_ci int y = cs->y; 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ci IDWTELEM *b0 = cs->b0; 408cabdff1aSopenharmony_ci IDWTELEM *b1 = cs->b1; 409cabdff1aSopenharmony_ci IDWTELEM *b2 = slice_buffer_get_line(sb, 410cabdff1aSopenharmony_ci avpriv_mirror(y + 1, height - 1) * 411cabdff1aSopenharmony_ci stride_line); 412cabdff1aSopenharmony_ci IDWTELEM *b3 = slice_buffer_get_line(sb, 413cabdff1aSopenharmony_ci avpriv_mirror(y + 2, height - 1) * 414cabdff1aSopenharmony_ci stride_line); 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci if (y + 1 < (unsigned)height && y < (unsigned)height) { 417cabdff1aSopenharmony_ci int x; 418cabdff1aSopenharmony_ci 419cabdff1aSopenharmony_ci for (x = 0; x < width; x++) { 420cabdff1aSopenharmony_ci b2[x] -= (b1[x] + b3[x] + 2) >> 2; 421cabdff1aSopenharmony_ci b1[x] += (b0[x] + b2[x]) >> 1; 422cabdff1aSopenharmony_ci } 423cabdff1aSopenharmony_ci } else { 424cabdff1aSopenharmony_ci if (y + 1 < (unsigned)height) 425cabdff1aSopenharmony_ci vertical_compose53iL0(b1, b2, b3, width); 426cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 427cabdff1aSopenharmony_ci vertical_compose53iH0(b0, b1, b2, width); 428cabdff1aSopenharmony_ci } 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci if (y - 1 < (unsigned)height) 431cabdff1aSopenharmony_ci horizontal_compose53i(b0, temp, width); 432cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 433cabdff1aSopenharmony_ci horizontal_compose53i(b1, temp, width); 434cabdff1aSopenharmony_ci 435cabdff1aSopenharmony_ci cs->b0 = b2; 436cabdff1aSopenharmony_ci cs->b1 = b3; 437cabdff1aSopenharmony_ci cs->y += 2; 438cabdff1aSopenharmony_ci} 439cabdff1aSopenharmony_ci 440cabdff1aSopenharmony_cistatic void spatial_compose53i_dy(DWTCompose *cs, IDWTELEM *buffer, 441cabdff1aSopenharmony_ci IDWTELEM *temp, int width, int height, 442cabdff1aSopenharmony_ci int stride) 443cabdff1aSopenharmony_ci{ 444cabdff1aSopenharmony_ci int y = cs->y; 445cabdff1aSopenharmony_ci IDWTELEM *b0 = cs->b0; 446cabdff1aSopenharmony_ci IDWTELEM *b1 = cs->b1; 447cabdff1aSopenharmony_ci IDWTELEM *b2 = buffer + avpriv_mirror(y + 1, height - 1) * stride; 448cabdff1aSopenharmony_ci IDWTELEM *b3 = buffer + avpriv_mirror(y + 2, height - 1) * stride; 449cabdff1aSopenharmony_ci 450cabdff1aSopenharmony_ci if (y + 1 < (unsigned)height) 451cabdff1aSopenharmony_ci vertical_compose53iL0(b1, b2, b3, width); 452cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 453cabdff1aSopenharmony_ci vertical_compose53iH0(b0, b1, b2, width); 454cabdff1aSopenharmony_ci 455cabdff1aSopenharmony_ci if (y - 1 < (unsigned)height) 456cabdff1aSopenharmony_ci horizontal_compose53i(b0, temp, width); 457cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 458cabdff1aSopenharmony_ci horizontal_compose53i(b1, temp, width); 459cabdff1aSopenharmony_ci 460cabdff1aSopenharmony_ci cs->b0 = b2; 461cabdff1aSopenharmony_ci cs->b1 = b3; 462cabdff1aSopenharmony_ci cs->y += 2; 463cabdff1aSopenharmony_ci} 464cabdff1aSopenharmony_ci 465cabdff1aSopenharmony_cistatic void snow_horizontal_compose97i(IDWTELEM *b, IDWTELEM *temp, int width) 466cabdff1aSopenharmony_ci{ 467cabdff1aSopenharmony_ci const int w2 = (width + 1) >> 1; 468cabdff1aSopenharmony_ci int x; 469cabdff1aSopenharmony_ci 470cabdff1aSopenharmony_ci temp[0] = b[0] - ((3 * b[w2] + 2) >> 2); 471cabdff1aSopenharmony_ci for (x = 1; x < (width >> 1); x++) { 472cabdff1aSopenharmony_ci temp[2 * x] = b[x] - ((3 * (b[x + w2 - 1] + b[x + w2]) + 4) >> 3); 473cabdff1aSopenharmony_ci temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x]; 474cabdff1aSopenharmony_ci } 475cabdff1aSopenharmony_ci if (width & 1) { 476cabdff1aSopenharmony_ci temp[2 * x] = b[x] - ((3 * b[x + w2 - 1] + 2) >> 2); 477cabdff1aSopenharmony_ci temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x]; 478cabdff1aSopenharmony_ci } else 479cabdff1aSopenharmony_ci temp[2 * x - 1] = b[x + w2 - 1] - 2 * temp[2 * x - 2]; 480cabdff1aSopenharmony_ci 481cabdff1aSopenharmony_ci b[0] = temp[0] + ((2 * temp[0] + temp[1] + 4) >> 3); 482cabdff1aSopenharmony_ci for (x = 2; x < width - 1; x += 2) { 483cabdff1aSopenharmony_ci b[x] = temp[x] + ((4 * temp[x] + temp[x - 1] + temp[x + 1] + 8) >> 4); 484cabdff1aSopenharmony_ci b[x - 1] = temp[x - 1] + ((3 * (b[x - 2] + b[x])) >> 1); 485cabdff1aSopenharmony_ci } 486cabdff1aSopenharmony_ci if (width & 1) { 487cabdff1aSopenharmony_ci b[x] = temp[x] + ((2 * temp[x] + temp[x - 1] + 4) >> 3); 488cabdff1aSopenharmony_ci b[x - 1] = temp[x - 1] + ((3 * (b[x - 2] + b[x])) >> 1); 489cabdff1aSopenharmony_ci } else 490cabdff1aSopenharmony_ci b[x - 1] = temp[x - 1] + 3 * b[x - 2]; 491cabdff1aSopenharmony_ci} 492cabdff1aSopenharmony_ci 493cabdff1aSopenharmony_cistatic void vertical_compose97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, 494cabdff1aSopenharmony_ci int width) 495cabdff1aSopenharmony_ci{ 496cabdff1aSopenharmony_ci int i; 497cabdff1aSopenharmony_ci 498cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 499cabdff1aSopenharmony_ci b1[i] += (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS; 500cabdff1aSopenharmony_ci} 501cabdff1aSopenharmony_ci 502cabdff1aSopenharmony_cistatic void vertical_compose97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, 503cabdff1aSopenharmony_ci int width) 504cabdff1aSopenharmony_ci{ 505cabdff1aSopenharmony_ci int i; 506cabdff1aSopenharmony_ci 507cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 508cabdff1aSopenharmony_ci b1[i] -= (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS; 509cabdff1aSopenharmony_ci} 510cabdff1aSopenharmony_ci 511cabdff1aSopenharmony_cistatic void vertical_compose97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, 512cabdff1aSopenharmony_ci int width) 513cabdff1aSopenharmony_ci{ 514cabdff1aSopenharmony_ci int i; 515cabdff1aSopenharmony_ci 516cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 517cabdff1aSopenharmony_ci b1[i] += (W_BM * (b0[i] + b2[i]) + 4 * b1[i] + W_BO) >> W_BS; 518cabdff1aSopenharmony_ci} 519cabdff1aSopenharmony_ci 520cabdff1aSopenharmony_cistatic void vertical_compose97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, 521cabdff1aSopenharmony_ci int width) 522cabdff1aSopenharmony_ci{ 523cabdff1aSopenharmony_ci int i; 524cabdff1aSopenharmony_ci 525cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 526cabdff1aSopenharmony_ci b1[i] -= (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS; 527cabdff1aSopenharmony_ci} 528cabdff1aSopenharmony_ci 529cabdff1aSopenharmony_cistatic void snow_vertical_compose97i(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, 530cabdff1aSopenharmony_ci IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, 531cabdff1aSopenharmony_ci int width) 532cabdff1aSopenharmony_ci{ 533cabdff1aSopenharmony_ci int i; 534cabdff1aSopenharmony_ci 535cabdff1aSopenharmony_ci for (i = 0; i < width; i++) { 536cabdff1aSopenharmony_ci b4[i] -= (W_DM * (b3[i] + b5[i]) + W_DO) >> W_DS; 537cabdff1aSopenharmony_ci b3[i] -= (W_CM * (b2[i] + b4[i]) + W_CO) >> W_CS; 538cabdff1aSopenharmony_ci b2[i] += (W_BM * (b1[i] + b3[i]) + 4 * b2[i] + W_BO) >> W_BS; 539cabdff1aSopenharmony_ci b1[i] += (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS; 540cabdff1aSopenharmony_ci } 541cabdff1aSopenharmony_ci} 542cabdff1aSopenharmony_ci 543cabdff1aSopenharmony_cistatic void spatial_compose97i_buffered_init(DWTCompose *cs, slice_buffer *sb, 544cabdff1aSopenharmony_ci int height, int stride_line) 545cabdff1aSopenharmony_ci{ 546cabdff1aSopenharmony_ci cs->b0 = slice_buffer_get_line(sb, avpriv_mirror(-3 - 1, height - 1) * stride_line); 547cabdff1aSopenharmony_ci cs->b1 = slice_buffer_get_line(sb, avpriv_mirror(-3, height - 1) * stride_line); 548cabdff1aSopenharmony_ci cs->b2 = slice_buffer_get_line(sb, avpriv_mirror(-3 + 1, height - 1) * stride_line); 549cabdff1aSopenharmony_ci cs->b3 = slice_buffer_get_line(sb, avpriv_mirror(-3 + 2, height - 1) * stride_line); 550cabdff1aSopenharmony_ci cs->y = -3; 551cabdff1aSopenharmony_ci} 552cabdff1aSopenharmony_ci 553cabdff1aSopenharmony_cistatic void spatial_compose97i_init(DWTCompose *cs, IDWTELEM *buffer, int height, 554cabdff1aSopenharmony_ci int stride) 555cabdff1aSopenharmony_ci{ 556cabdff1aSopenharmony_ci cs->b0 = buffer + avpriv_mirror(-3 - 1, height - 1) * stride; 557cabdff1aSopenharmony_ci cs->b1 = buffer + avpriv_mirror(-3, height - 1) * stride; 558cabdff1aSopenharmony_ci cs->b2 = buffer + avpriv_mirror(-3 + 1, height - 1) * stride; 559cabdff1aSopenharmony_ci cs->b3 = buffer + avpriv_mirror(-3 + 2, height - 1) * stride; 560cabdff1aSopenharmony_ci cs->y = -3; 561cabdff1aSopenharmony_ci} 562cabdff1aSopenharmony_ci 563cabdff1aSopenharmony_cistatic void spatial_compose97i_dy_buffered(SnowDWTContext *dsp, DWTCompose *cs, 564cabdff1aSopenharmony_ci slice_buffer * sb, IDWTELEM *temp, 565cabdff1aSopenharmony_ci int width, int height, 566cabdff1aSopenharmony_ci int stride_line) 567cabdff1aSopenharmony_ci{ 568cabdff1aSopenharmony_ci int y = cs->y; 569cabdff1aSopenharmony_ci 570cabdff1aSopenharmony_ci IDWTELEM *b0 = cs->b0; 571cabdff1aSopenharmony_ci IDWTELEM *b1 = cs->b1; 572cabdff1aSopenharmony_ci IDWTELEM *b2 = cs->b2; 573cabdff1aSopenharmony_ci IDWTELEM *b3 = cs->b3; 574cabdff1aSopenharmony_ci IDWTELEM *b4 = slice_buffer_get_line(sb, 575cabdff1aSopenharmony_ci avpriv_mirror(y + 3, height - 1) * 576cabdff1aSopenharmony_ci stride_line); 577cabdff1aSopenharmony_ci IDWTELEM *b5 = slice_buffer_get_line(sb, 578cabdff1aSopenharmony_ci avpriv_mirror(y + 4, height - 1) * 579cabdff1aSopenharmony_ci stride_line); 580cabdff1aSopenharmony_ci 581cabdff1aSopenharmony_ci if (y > 0 && y + 4 < height) { 582cabdff1aSopenharmony_ci dsp->vertical_compose97i(b0, b1, b2, b3, b4, b5, width); 583cabdff1aSopenharmony_ci } else { 584cabdff1aSopenharmony_ci if (y + 3 < (unsigned)height) 585cabdff1aSopenharmony_ci vertical_compose97iL1(b3, b4, b5, width); 586cabdff1aSopenharmony_ci if (y + 2 < (unsigned)height) 587cabdff1aSopenharmony_ci vertical_compose97iH1(b2, b3, b4, width); 588cabdff1aSopenharmony_ci if (y + 1 < (unsigned)height) 589cabdff1aSopenharmony_ci vertical_compose97iL0(b1, b2, b3, width); 590cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 591cabdff1aSopenharmony_ci vertical_compose97iH0(b0, b1, b2, width); 592cabdff1aSopenharmony_ci } 593cabdff1aSopenharmony_ci 594cabdff1aSopenharmony_ci if (y - 1 < (unsigned)height) 595cabdff1aSopenharmony_ci dsp->horizontal_compose97i(b0, temp, width); 596cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 597cabdff1aSopenharmony_ci dsp->horizontal_compose97i(b1, temp, width); 598cabdff1aSopenharmony_ci 599cabdff1aSopenharmony_ci cs->b0 = b2; 600cabdff1aSopenharmony_ci cs->b1 = b3; 601cabdff1aSopenharmony_ci cs->b2 = b4; 602cabdff1aSopenharmony_ci cs->b3 = b5; 603cabdff1aSopenharmony_ci cs->y += 2; 604cabdff1aSopenharmony_ci} 605cabdff1aSopenharmony_ci 606cabdff1aSopenharmony_cistatic void spatial_compose97i_dy(DWTCompose *cs, IDWTELEM *buffer, 607cabdff1aSopenharmony_ci IDWTELEM *temp, int width, int height, 608cabdff1aSopenharmony_ci int stride) 609cabdff1aSopenharmony_ci{ 610cabdff1aSopenharmony_ci int y = cs->y; 611cabdff1aSopenharmony_ci IDWTELEM *b0 = cs->b0; 612cabdff1aSopenharmony_ci IDWTELEM *b1 = cs->b1; 613cabdff1aSopenharmony_ci IDWTELEM *b2 = cs->b2; 614cabdff1aSopenharmony_ci IDWTELEM *b3 = cs->b3; 615cabdff1aSopenharmony_ci IDWTELEM *b4 = buffer + avpriv_mirror(y + 3, height - 1) * stride; 616cabdff1aSopenharmony_ci IDWTELEM *b5 = buffer + avpriv_mirror(y + 4, height - 1) * stride; 617cabdff1aSopenharmony_ci 618cabdff1aSopenharmony_ci if (y + 3 < (unsigned)height) 619cabdff1aSopenharmony_ci vertical_compose97iL1(b3, b4, b5, width); 620cabdff1aSopenharmony_ci if (y + 2 < (unsigned)height) 621cabdff1aSopenharmony_ci vertical_compose97iH1(b2, b3, b4, width); 622cabdff1aSopenharmony_ci if (y + 1 < (unsigned)height) 623cabdff1aSopenharmony_ci vertical_compose97iL0(b1, b2, b3, width); 624cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 625cabdff1aSopenharmony_ci vertical_compose97iH0(b0, b1, b2, width); 626cabdff1aSopenharmony_ci 627cabdff1aSopenharmony_ci if (y - 1 < (unsigned)height) 628cabdff1aSopenharmony_ci snow_horizontal_compose97i(b0, temp, width); 629cabdff1aSopenharmony_ci if (y + 0 < (unsigned)height) 630cabdff1aSopenharmony_ci snow_horizontal_compose97i(b1, temp, width); 631cabdff1aSopenharmony_ci 632cabdff1aSopenharmony_ci cs->b0 = b2; 633cabdff1aSopenharmony_ci cs->b1 = b3; 634cabdff1aSopenharmony_ci cs->b2 = b4; 635cabdff1aSopenharmony_ci cs->b3 = b5; 636cabdff1aSopenharmony_ci cs->y += 2; 637cabdff1aSopenharmony_ci} 638cabdff1aSopenharmony_ci 639cabdff1aSopenharmony_civoid ff_spatial_idwt_buffered_init(DWTCompose *cs, slice_buffer *sb, int width, 640cabdff1aSopenharmony_ci int height, int stride_line, int type, 641cabdff1aSopenharmony_ci int decomposition_count) 642cabdff1aSopenharmony_ci{ 643cabdff1aSopenharmony_ci int level; 644cabdff1aSopenharmony_ci for (level = decomposition_count - 1; level >= 0; level--) { 645cabdff1aSopenharmony_ci switch (type) { 646cabdff1aSopenharmony_ci case DWT_97: 647cabdff1aSopenharmony_ci spatial_compose97i_buffered_init(cs + level, sb, height >> level, 648cabdff1aSopenharmony_ci stride_line << level); 649cabdff1aSopenharmony_ci break; 650cabdff1aSopenharmony_ci case DWT_53: 651cabdff1aSopenharmony_ci spatial_compose53i_buffered_init(cs + level, sb, height >> level, 652cabdff1aSopenharmony_ci stride_line << level); 653cabdff1aSopenharmony_ci break; 654cabdff1aSopenharmony_ci } 655cabdff1aSopenharmony_ci } 656cabdff1aSopenharmony_ci} 657cabdff1aSopenharmony_ci 658cabdff1aSopenharmony_civoid ff_spatial_idwt_buffered_slice(SnowDWTContext *dsp, DWTCompose *cs, 659cabdff1aSopenharmony_ci slice_buffer *slice_buf, IDWTELEM *temp, 660cabdff1aSopenharmony_ci int width, int height, int stride_line, 661cabdff1aSopenharmony_ci int type, int decomposition_count, int y) 662cabdff1aSopenharmony_ci{ 663cabdff1aSopenharmony_ci const int support = type == 1 ? 3 : 5; 664cabdff1aSopenharmony_ci int level; 665cabdff1aSopenharmony_ci if (type == 2) 666cabdff1aSopenharmony_ci return; 667cabdff1aSopenharmony_ci 668cabdff1aSopenharmony_ci for (level = decomposition_count - 1; level >= 0; level--) 669cabdff1aSopenharmony_ci while (cs[level].y <= FFMIN((y >> level) + support, height >> level)) { 670cabdff1aSopenharmony_ci switch (type) { 671cabdff1aSopenharmony_ci case DWT_97: 672cabdff1aSopenharmony_ci spatial_compose97i_dy_buffered(dsp, cs + level, slice_buf, temp, 673cabdff1aSopenharmony_ci width >> level, 674cabdff1aSopenharmony_ci height >> level, 675cabdff1aSopenharmony_ci stride_line << level); 676cabdff1aSopenharmony_ci break; 677cabdff1aSopenharmony_ci case DWT_53: 678cabdff1aSopenharmony_ci spatial_compose53i_dy_buffered(cs + level, slice_buf, temp, 679cabdff1aSopenharmony_ci width >> level, 680cabdff1aSopenharmony_ci height >> level, 681cabdff1aSopenharmony_ci stride_line << level); 682cabdff1aSopenharmony_ci break; 683cabdff1aSopenharmony_ci } 684cabdff1aSopenharmony_ci } 685cabdff1aSopenharmony_ci} 686cabdff1aSopenharmony_ci 687cabdff1aSopenharmony_cistatic void spatial_idwt_init(DWTCompose *cs, IDWTELEM *buffer, int width, 688cabdff1aSopenharmony_ci int height, int stride, int type, 689cabdff1aSopenharmony_ci int decomposition_count) 690cabdff1aSopenharmony_ci{ 691cabdff1aSopenharmony_ci int level; 692cabdff1aSopenharmony_ci for (level = decomposition_count - 1; level >= 0; level--) { 693cabdff1aSopenharmony_ci switch (type) { 694cabdff1aSopenharmony_ci case DWT_97: 695cabdff1aSopenharmony_ci spatial_compose97i_init(cs + level, buffer, height >> level, 696cabdff1aSopenharmony_ci stride << level); 697cabdff1aSopenharmony_ci break; 698cabdff1aSopenharmony_ci case DWT_53: 699cabdff1aSopenharmony_ci spatial_compose53i_init(cs + level, buffer, height >> level, 700cabdff1aSopenharmony_ci stride << level); 701cabdff1aSopenharmony_ci break; 702cabdff1aSopenharmony_ci } 703cabdff1aSopenharmony_ci } 704cabdff1aSopenharmony_ci} 705cabdff1aSopenharmony_ci 706cabdff1aSopenharmony_cistatic void spatial_idwt_slice(DWTCompose *cs, IDWTELEM *buffer, 707cabdff1aSopenharmony_ci IDWTELEM *temp, int width, int height, 708cabdff1aSopenharmony_ci int stride, int type, 709cabdff1aSopenharmony_ci int decomposition_count, int y) 710cabdff1aSopenharmony_ci{ 711cabdff1aSopenharmony_ci const int support = type == 1 ? 3 : 5; 712cabdff1aSopenharmony_ci int level; 713cabdff1aSopenharmony_ci if (type == 2) 714cabdff1aSopenharmony_ci return; 715cabdff1aSopenharmony_ci 716cabdff1aSopenharmony_ci for (level = decomposition_count - 1; level >= 0; level--) 717cabdff1aSopenharmony_ci while (cs[level].y <= FFMIN((y >> level) + support, height >> level)) { 718cabdff1aSopenharmony_ci switch (type) { 719cabdff1aSopenharmony_ci case DWT_97: 720cabdff1aSopenharmony_ci spatial_compose97i_dy(cs + level, buffer, temp, width >> level, 721cabdff1aSopenharmony_ci height >> level, stride << level); 722cabdff1aSopenharmony_ci break; 723cabdff1aSopenharmony_ci case DWT_53: 724cabdff1aSopenharmony_ci spatial_compose53i_dy(cs + level, buffer, temp, width >> level, 725cabdff1aSopenharmony_ci height >> level, stride << level); 726cabdff1aSopenharmony_ci break; 727cabdff1aSopenharmony_ci } 728cabdff1aSopenharmony_ci } 729cabdff1aSopenharmony_ci} 730cabdff1aSopenharmony_ci 731cabdff1aSopenharmony_civoid ff_spatial_idwt(IDWTELEM *buffer, IDWTELEM *temp, int width, int height, 732cabdff1aSopenharmony_ci int stride, int type, int decomposition_count) 733cabdff1aSopenharmony_ci{ 734cabdff1aSopenharmony_ci DWTCompose cs[MAX_DECOMPOSITIONS]; 735cabdff1aSopenharmony_ci int y; 736cabdff1aSopenharmony_ci spatial_idwt_init(cs, buffer, width, height, stride, type, 737cabdff1aSopenharmony_ci decomposition_count); 738cabdff1aSopenharmony_ci for (y = 0; y < height; y += 4) 739cabdff1aSopenharmony_ci spatial_idwt_slice(cs, buffer, temp, width, height, stride, type, 740cabdff1aSopenharmony_ci decomposition_count, y); 741cabdff1aSopenharmony_ci} 742cabdff1aSopenharmony_ci 743cabdff1aSopenharmony_cistatic inline int w_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, 744cabdff1aSopenharmony_ci int w, int h, int type) 745cabdff1aSopenharmony_ci{ 746cabdff1aSopenharmony_ci int s, i, j; 747cabdff1aSopenharmony_ci const int dec_count = w == 8 ? 3 : 4; 748cabdff1aSopenharmony_ci int tmp[32 * 32], tmp2[32]; 749cabdff1aSopenharmony_ci int level, ori; 750cabdff1aSopenharmony_ci static const int scale[2][2][4][4] = { 751cabdff1aSopenharmony_ci { 752cabdff1aSopenharmony_ci { // 9/7 8x8 dec=3 753cabdff1aSopenharmony_ci { 268, 239, 239, 213 }, 754cabdff1aSopenharmony_ci { 0, 224, 224, 152 }, 755cabdff1aSopenharmony_ci { 0, 135, 135, 110 }, 756cabdff1aSopenharmony_ci }, 757cabdff1aSopenharmony_ci { // 9/7 16x16 or 32x32 dec=4 758cabdff1aSopenharmony_ci { 344, 310, 310, 280 }, 759cabdff1aSopenharmony_ci { 0, 320, 320, 228 }, 760cabdff1aSopenharmony_ci { 0, 175, 175, 136 }, 761cabdff1aSopenharmony_ci { 0, 129, 129, 102 }, 762cabdff1aSopenharmony_ci } 763cabdff1aSopenharmony_ci }, 764cabdff1aSopenharmony_ci { 765cabdff1aSopenharmony_ci { // 5/3 8x8 dec=3 766cabdff1aSopenharmony_ci { 275, 245, 245, 218 }, 767cabdff1aSopenharmony_ci { 0, 230, 230, 156 }, 768cabdff1aSopenharmony_ci { 0, 138, 138, 113 }, 769cabdff1aSopenharmony_ci }, 770cabdff1aSopenharmony_ci { // 5/3 16x16 or 32x32 dec=4 771cabdff1aSopenharmony_ci { 352, 317, 317, 286 }, 772cabdff1aSopenharmony_ci { 0, 328, 328, 233 }, 773cabdff1aSopenharmony_ci { 0, 180, 180, 140 }, 774cabdff1aSopenharmony_ci { 0, 132, 132, 105 }, 775cabdff1aSopenharmony_ci } 776cabdff1aSopenharmony_ci } 777cabdff1aSopenharmony_ci }; 778cabdff1aSopenharmony_ci 779cabdff1aSopenharmony_ci for (i = 0; i < h; i++) { 780cabdff1aSopenharmony_ci for (j = 0; j < w; j += 4) { 781cabdff1aSopenharmony_ci tmp[32 * i + j + 0] = (pix1[j + 0] - pix2[j + 0]) << 4; 782cabdff1aSopenharmony_ci tmp[32 * i + j + 1] = (pix1[j + 1] - pix2[j + 1]) << 4; 783cabdff1aSopenharmony_ci tmp[32 * i + j + 2] = (pix1[j + 2] - pix2[j + 2]) << 4; 784cabdff1aSopenharmony_ci tmp[32 * i + j + 3] = (pix1[j + 3] - pix2[j + 3]) << 4; 785cabdff1aSopenharmony_ci } 786cabdff1aSopenharmony_ci pix1 += line_size; 787cabdff1aSopenharmony_ci pix2 += line_size; 788cabdff1aSopenharmony_ci } 789cabdff1aSopenharmony_ci 790cabdff1aSopenharmony_ci ff_spatial_dwt(tmp, tmp2, w, h, 32, type, dec_count); 791cabdff1aSopenharmony_ci 792cabdff1aSopenharmony_ci s = 0; 793cabdff1aSopenharmony_ci av_assert1(w == h); 794cabdff1aSopenharmony_ci for (level = 0; level < dec_count; level++) 795cabdff1aSopenharmony_ci for (ori = level ? 1 : 0; ori < 4; ori++) { 796cabdff1aSopenharmony_ci int size = w >> (dec_count - level); 797cabdff1aSopenharmony_ci int sx = (ori & 1) ? size : 0; 798cabdff1aSopenharmony_ci int stride = 32 << (dec_count - level); 799cabdff1aSopenharmony_ci int sy = (ori & 2) ? stride >> 1 : 0; 800cabdff1aSopenharmony_ci 801cabdff1aSopenharmony_ci for (i = 0; i < size; i++) 802cabdff1aSopenharmony_ci for (j = 0; j < size; j++) { 803cabdff1aSopenharmony_ci int v = tmp[sx + sy + i * stride + j] * 804cabdff1aSopenharmony_ci scale[type][dec_count - 3][level][ori]; 805cabdff1aSopenharmony_ci s += FFABS(v); 806cabdff1aSopenharmony_ci } 807cabdff1aSopenharmony_ci } 808cabdff1aSopenharmony_ci av_assert1(s >= 0); 809cabdff1aSopenharmony_ci return s >> 9; 810cabdff1aSopenharmony_ci} 811cabdff1aSopenharmony_ci 812cabdff1aSopenharmony_cistatic int w53_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h) 813cabdff1aSopenharmony_ci{ 814cabdff1aSopenharmony_ci return w_c(v, pix1, pix2, line_size, 8, h, 1); 815cabdff1aSopenharmony_ci} 816cabdff1aSopenharmony_ci 817cabdff1aSopenharmony_cistatic int w97_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h) 818cabdff1aSopenharmony_ci{ 819cabdff1aSopenharmony_ci return w_c(v, pix1, pix2, line_size, 8, h, 0); 820cabdff1aSopenharmony_ci} 821cabdff1aSopenharmony_ci 822cabdff1aSopenharmony_cistatic int w53_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h) 823cabdff1aSopenharmony_ci{ 824cabdff1aSopenharmony_ci return w_c(v, pix1, pix2, line_size, 16, h, 1); 825cabdff1aSopenharmony_ci} 826cabdff1aSopenharmony_ci 827cabdff1aSopenharmony_cistatic int w97_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h) 828cabdff1aSopenharmony_ci{ 829cabdff1aSopenharmony_ci return w_c(v, pix1, pix2, line_size, 16, h, 0); 830cabdff1aSopenharmony_ci} 831cabdff1aSopenharmony_ci 832cabdff1aSopenharmony_ciint ff_w53_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h) 833cabdff1aSopenharmony_ci{ 834cabdff1aSopenharmony_ci return w_c(v, pix1, pix2, line_size, 32, h, 1); 835cabdff1aSopenharmony_ci} 836cabdff1aSopenharmony_ci 837cabdff1aSopenharmony_ciint ff_w97_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h) 838cabdff1aSopenharmony_ci{ 839cabdff1aSopenharmony_ci return w_c(v, pix1, pix2, line_size, 32, h, 0); 840cabdff1aSopenharmony_ci} 841cabdff1aSopenharmony_ci 842cabdff1aSopenharmony_ciav_cold void ff_dsputil_init_dwt(MECmpContext *c) 843cabdff1aSopenharmony_ci{ 844cabdff1aSopenharmony_ci c->w53[0] = w53_16_c; 845cabdff1aSopenharmony_ci c->w53[1] = w53_8_c; 846cabdff1aSopenharmony_ci c->w97[0] = w97_16_c; 847cabdff1aSopenharmony_ci c->w97[1] = w97_8_c; 848cabdff1aSopenharmony_ci} 849cabdff1aSopenharmony_ci 850cabdff1aSopenharmony_ciav_cold void ff_dwt_init(SnowDWTContext *c) 851cabdff1aSopenharmony_ci{ 852cabdff1aSopenharmony_ci c->vertical_compose97i = snow_vertical_compose97i; 853cabdff1aSopenharmony_ci c->horizontal_compose97i = snow_horizontal_compose97i; 854cabdff1aSopenharmony_ci c->inner_add_yblock = ff_snow_inner_add_yblock; 855cabdff1aSopenharmony_ci 856cabdff1aSopenharmony_ci#if ARCH_X86 && HAVE_MMX 857cabdff1aSopenharmony_ci ff_dwt_init_x86(c); 858cabdff1aSopenharmony_ci#endif 859cabdff1aSopenharmony_ci} 860cabdff1aSopenharmony_ci 861cabdff1aSopenharmony_ci 862