summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/SCsub2
-rw-r--r--drivers/register_driver_types.cpp16
-rw-r--r--drivers/webp/AUTHORS26
-rw-r--r--drivers/webp/COPYING30
-rw-r--r--drivers/webp/PATENTS23
-rw-r--r--drivers/webp/SCsub115
-rw-r--r--drivers/webp/config.h150
-rw-r--r--drivers/webp/dec/alpha.c232
-rw-r--r--drivers/webp/dec/alphai.h54
-rw-r--r--drivers/webp/dec/buffer.c300
-rw-r--r--drivers/webp/dec/common.h54
-rw-r--r--drivers/webp/dec/decode_vp8.h185
-rw-r--r--drivers/webp/dec/frame.c812
-rw-r--r--drivers/webp/dec/idec.c892
-rw-r--r--drivers/webp/dec/io.c624
-rw-r--r--drivers/webp/dec/quant.c110
-rw-r--r--drivers/webp/dec/tree.c525
-rw-r--r--drivers/webp/dec/vp8.c667
-rw-r--r--drivers/webp/dec/vp8i.h320
-rw-r--r--drivers/webp/dec/vp8l.c1660
-rw-r--r--drivers/webp/dec/vp8li.h135
-rw-r--r--drivers/webp/dec/webp.c846
-rw-r--r--drivers/webp/dec/webpi.h142
-rw-r--r--drivers/webp/decode.h493
-rw-r--r--drivers/webp/demux.h358
-rw-r--r--drivers/webp/demux/anim_decode.c442
-rw-r--r--drivers/webp/demux/demux.c966
-rw-r--r--drivers/webp/dsp/alpha_processing.c383
-rw-r--r--drivers/webp/dsp/alpha_processing_mips_dsp_r2.c141
-rw-r--r--drivers/webp/dsp/alpha_processing_sse2.c298
-rw-r--r--drivers/webp/dsp/alpha_processing_sse41.c92
-rw-r--r--drivers/webp/dsp/argb.c68
-rw-r--r--drivers/webp/dsp/argb_mips_dsp_r2.c110
-rw-r--r--drivers/webp/dsp/argb_sse2.c67
-rw-r--r--drivers/webp/dsp/common_sse2.h109
-rw-r--r--drivers/webp/dsp/cost.c412
-rw-r--r--drivers/webp/dsp/cost_mips32.c154
-rw-r--r--drivers/webp/dsp/cost_mips_dsp_r2.c107
-rw-r--r--drivers/webp/dsp/cost_sse2.c119
-rw-r--r--drivers/webp/dsp/cpu.c187
-rw-r--r--drivers/webp/dsp/dec.c795
-rw-r--r--drivers/webp/dsp/dec_clip_tables.c366
-rw-r--r--drivers/webp/dsp/dec_mips32.c587
-rw-r--r--drivers/webp/dsp/dec_mips_dsp_r2.c994
-rw-r--r--drivers/webp/dsp/dec_msa.c172
-rw-r--r--drivers/webp/dsp/dec_neon.c1639
-rw-r--r--drivers/webp/dsp/dec_sse2.c1231
-rw-r--r--drivers/webp/dsp/dec_sse41.c46
-rw-r--r--drivers/webp/dsp/dsp.h569
-rw-r--r--drivers/webp/dsp/enc.c863
-rw-r--r--drivers/webp/dsp/enc_avx2.c21
-rw-r--r--drivers/webp/dsp/enc_mips32.c672
-rw-r--r--drivers/webp/dsp/enc_mips_dsp_r2.c1510
-rw-r--r--drivers/webp/dsp/enc_neon.c920
-rw-r--r--drivers/webp/dsp/enc_sse2.c1340
-rw-r--r--drivers/webp/dsp/enc_sse41.c339
-rw-r--r--drivers/webp/dsp/filters.c261
-rw-r--r--drivers/webp/dsp/filters_mips_dsp_r2.c395
-rw-r--r--drivers/webp/dsp/filters_sse2.c330
-rw-r--r--drivers/webp/dsp/lossless.c633
-rw-r--r--drivers/webp/dsp/lossless.h372
-rw-r--r--drivers/webp/dsp/lossless_enc.c1439
-rw-r--r--drivers/webp/dsp/lossless_enc_mips32.c386
-rw-r--r--drivers/webp/dsp/lossless_enc_mips_dsp_r2.c275
-rw-r--r--drivers/webp/dsp/lossless_enc_neon.c143
-rw-r--r--drivers/webp/dsp/lossless_enc_sse2.c397
-rw-r--r--drivers/webp/dsp/lossless_enc_sse41.c51
-rw-r--r--drivers/webp/dsp/lossless_mips_dsp_r2.c680
-rw-r--r--drivers/webp/dsp/lossless_neon.c269
-rw-r--r--drivers/webp/dsp/lossless_sse2.c372
-rw-r--r--drivers/webp/dsp/mips_macro.h200
-rw-r--r--drivers/webp/dsp/msa_macro.h555
-rw-r--r--drivers/webp/dsp/neon.h82
-rw-r--r--drivers/webp/dsp/rescaler.c238
-rw-r--r--drivers/webp/dsp/rescaler_mips32.c291
-rw-r--r--drivers/webp/dsp/rescaler_mips_dsp_r2.c314
-rw-r--r--drivers/webp/dsp/rescaler_neon.c186
-rw-r--r--drivers/webp/dsp/rescaler_sse2.c375
-rw-r--r--drivers/webp/dsp/upsampling.c260
-rw-r--r--drivers/webp/dsp/upsampling_mips_dsp_r2.c282
-rw-r--r--drivers/webp/dsp/upsampling_neon.c300
-rw-r--r--drivers/webp/dsp/upsampling_sse2.c249
-rw-r--r--drivers/webp/dsp/yuv.c280
-rw-r--r--drivers/webp/dsp/yuv.h238
-rw-r--r--drivers/webp/dsp/yuv_mips32.c103
-rw-r--r--drivers/webp/dsp/yuv_mips_dsp_r2.c134
-rw-r--r--drivers/webp/dsp/yuv_sse2.c775
-rw-r--r--drivers/webp/dsp/yuv_tables_sse2.h536
-rw-r--r--drivers/webp/enc/alpha.c433
-rw-r--r--drivers/webp/enc/analysis.c501
-rw-r--r--drivers/webp/enc/backward_references.c1715
-rw-r--r--drivers/webp/enc/backward_references.h206
-rw-r--r--drivers/webp/enc/config.c173
-rw-r--r--drivers/webp/enc/cost.c354
-rw-r--r--drivers/webp/enc/cost.h68
-rw-r--r--drivers/webp/enc/delta_palettization.c455
-rw-r--r--drivers/webp/enc/delta_palettization.h25
-rw-r--r--drivers/webp/enc/filter.c306
-rw-r--r--drivers/webp/enc/frame.c850
-rw-r--r--drivers/webp/enc/histogram.c937
-rw-r--r--drivers/webp/enc/histogram.h123
-rw-r--r--drivers/webp/enc/iterator.c456
-rw-r--r--drivers/webp/enc/near_lossless.c122
-rw-r--r--drivers/webp/enc/picture.c292
-rw-r--r--drivers/webp/enc/picture_csp.c1168
-rw-r--r--drivers/webp/enc/picture_psnr.c177
-rw-r--r--drivers/webp/enc/picture_rescale.c264
-rw-r--r--drivers/webp/enc/picture_tools.c226
-rw-r--r--drivers/webp/enc/quant.c1283
-rw-r--r--drivers/webp/enc/syntax.c383
-rw-r--r--drivers/webp/enc/token.c285
-rw-r--r--drivers/webp/enc/tree.c504
-rw-r--r--drivers/webp/enc/vp8enci.h531
-rw-r--r--drivers/webp/enc/vp8l.c1603
-rw-r--r--drivers/webp/enc/vp8li.h81
-rw-r--r--drivers/webp/enc/webpenc.c395
-rw-r--r--drivers/webp/encode.h527
-rw-r--r--drivers/webp/extras.h51
-rw-r--r--drivers/webp/format_constants.h88
-rw-r--r--drivers/webp/image_loader_webp.cpp182
-rw-r--r--drivers/webp/image_loader_webp.h49
-rw-r--r--drivers/webp/mux.h530
-rw-r--r--drivers/webp/mux/anim_encode.c1534
-rw-r--r--drivers/webp/mux/muxedit.c696
-rw-r--r--drivers/webp/mux/muxi.h232
-rw-r--r--drivers/webp/mux/muxinternal.c551
-rw-r--r--drivers/webp/mux/muxread.c544
-rw-r--r--drivers/webp/mux_types.h97
-rw-r--r--drivers/webp/types.h52
-rw-r--r--drivers/webp/utils/bit_reader.c227
-rw-r--r--drivers/webp/utils/bit_reader.h182
-rw-r--r--drivers/webp/utils/bit_reader_inl.h173
-rw-r--r--drivers/webp/utils/bit_writer.c319
-rw-r--r--drivers/webp/utils/bit_writer.h145
-rw-r--r--drivers/webp/utils/color_cache.c49
-rw-r--r--drivers/webp/utils/color_cache.h80
-rw-r--r--drivers/webp/utils/endian_inl.h100
-rw-r--r--drivers/webp/utils/filters.c76
-rw-r--r--drivers/webp/utils/filters.h32
-rw-r--r--drivers/webp/utils/huffman.c205
-rw-r--r--drivers/webp/utils/huffman.h88
-rw-r--r--drivers/webp/utils/huffman_encode.c417
-rw-r--r--drivers/webp/utils/huffman_encode.h60
-rw-r--r--drivers/webp/utils/quant_levels.c140
-rw-r--r--drivers/webp/utils/quant_levels.h36
-rw-r--r--drivers/webp/utils/quant_levels_dec.c284
-rw-r--r--drivers/webp/utils/quant_levels_dec.h35
-rw-r--r--drivers/webp/utils/random.c43
-rw-r--r--drivers/webp/utils/random.h63
-rw-r--r--drivers/webp/utils/rescaler.c142
-rw-r--r--drivers/webp/utils/rescaler.h101
-rw-r--r--drivers/webp/utils/thread.c358
-rw-r--r--drivers/webp/utils/thread.h93
-rw-r--r--drivers/webp/utils/utils.c305
-rw-r--r--drivers/webp/utils/utils.h182
155 files changed, 0 insertions, 58875 deletions
diff --git a/drivers/SCsub b/drivers/SCsub
index 98849b431e..5effc6b2d4 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -26,8 +26,6 @@ if (env['openssl']!='no'):
SConscript("png/SCsub");
-if (env["webp"]=="yes"):
- SConscript("webp/SCsub");
if (env["builtin_zlib"]=="yes"):
SConscript("builtin_zlib/SCsub");
diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp
index 9623c29b1a..cd4fcd18f2 100644
--- a/drivers/register_driver_types.cpp
+++ b/drivers/register_driver_types.cpp
@@ -30,7 +30,6 @@
#include "png/image_loader_png.h"
#include "png/resource_saver_png.h"
-#include "webp/image_loader_webp.h"
#include "chibi/event_stream_chibi.h"
@@ -72,10 +71,6 @@
static ImageLoaderPNG *image_loader_png=NULL;
static ResourceSaverPNG *resource_saver_png=NULL;
-#ifdef WEBP_ENABLED
-static ImageLoaderWEBP *image_loader_webp=NULL;
-#endif
-
#ifdef TREMOR_ENABLED
static ResourceFormatLoaderAudioStreamOGG *vorbis_stream_loader=NULL;
#endif
@@ -109,11 +104,6 @@ void register_core_driver_types() {
resource_saver_png = memnew( ResourceSaverPNG );
ResourceSaver::add_resource_format_saver(resource_saver_png);
-#ifdef WEBP_ENABLED
- image_loader_webp = memnew( ImageLoaderWEBP );
- ImageLoader::add_image_format_loader( image_loader_webp );
-#endif
-
ObjectTypeDB::register_type<RegEx>();
}
@@ -123,12 +113,6 @@ void unregister_core_driver_types() {
memdelete( image_loader_png );
if (resource_saver_png)
memdelete( resource_saver_png );
-
-#ifdef WEBP_ENABLED
- if (image_loader_webp)
- memdelete( image_loader_webp );
-#endif
-
}
diff --git a/drivers/webp/AUTHORS b/drivers/webp/AUTHORS
deleted file mode 100644
index 70423cb4dd..0000000000
--- a/drivers/webp/AUTHORS
+++ /dev/null
@@ -1,26 +0,0 @@
-Contributors:
-- Charles Munger (clm at google dot com)
-- Christian Duvivier (cduvivier at google dot com)
-- Djordje Pesut (djordje dot pesut at imgtec dot com)
-- James Zern (jzern at google dot com)
-- Jan Engelhardt (jengelh at medozas dot de)
-- Johann (johann dot koenig at duck dot com)
-- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
-- Jyrki Alakuijala (jyrki at google dot com)
-- levytamar82 (tamar dot levy at intel dot com)
-- Lou Quillio (louquillio at google dot com)
-- Mans Rullgard (mans at mansr dot com)
-- Martin Olsson (mnemo at minimum dot se)
-- Mikołaj Zalewski (mikolajz at google dot com)
-- Noel Chromium (noel at chromium dot org)
-- Pascal Massimino (pascal dot massimino at gmail dot com)
-- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
-- Pierre Joye (pierre dot php at gmail dot com)
-- Sam Clegg (sbc at chromium dot org)
-- Scott LaVarnway (slavarnway at google dot com)
-- Scott Talbot (s at chikachow dot org)
-- Slobodan Prijic (slobodan dot prijic at imgtec dot com)
-- Somnath Banerjee (somnath dot banerjee at gmail dot com)
-- Timothy Gu (timothygu99 at gmail dot com)
-- Urvang Joshi (urvang at google dot com)
-- Vikas Arora (vikasa at google dot com)
diff --git a/drivers/webp/COPYING b/drivers/webp/COPYING
deleted file mode 100644
index 7a6f99547d..0000000000
--- a/drivers/webp/COPYING
+++ /dev/null
@@ -1,30 +0,0 @@
-Copyright (c) 2010, Google Inc. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- * Neither the name of Google nor the names of its contributors may
- be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/drivers/webp/PATENTS b/drivers/webp/PATENTS
deleted file mode 100644
index caedf607e9..0000000000
--- a/drivers/webp/PATENTS
+++ /dev/null
@@ -1,23 +0,0 @@
-Additional IP Rights Grant (Patents)
-------------------------------------
-
-"These implementations" means the copyrightable works that implement the WebM
-codecs distributed by Google as part of the WebM Project.
-
-Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
-royalty-free, irrevocable (except as stated in this section) patent license to
-make, have made, use, offer to sell, sell, import, transfer, and otherwise
-run, modify and propagate the contents of these implementations of WebM, where
-such license applies only to those patent claims, both currently owned by
-Google and acquired in the future, licensable by Google that are necessarily
-infringed by these implementations of WebM. This grant does not include claims
-that would be infringed only as a consequence of further modification of these
-implementations. If you or your agent or exclusive licensee institute or order
-or agree to the institution of patent litigation or any other patent
-enforcement activity against any entity (including a cross-claim or
-counterclaim in a lawsuit) alleging that any of these implementations of WebM
-or any code incorporated within any of these implementations of WebM
-constitute direct or contributory patent infringement, or inducement of
-patent infringement, then any patent rights granted to you under this License
-for these implementations of WebM shall terminate as of the date such
-litigation is filed.
diff --git a/drivers/webp/SCsub b/drivers/webp/SCsub
deleted file mode 100644
index f65bd13dba..0000000000
--- a/drivers/webp/SCsub
+++ /dev/null
@@ -1,115 +0,0 @@
-Import('env')
-
-webp_sources = [
-"webp/enc/webpenc.c",\
-"webp/enc/near_lossless.c",\
-"webp/enc/frame.c",\
-"webp/enc/alpha.c",\
-"webp/enc/picture_csp.c",\
-"webp/enc/vp8l.c",\
-"webp/enc/picture_psnr.c",\
-"webp/enc/delta_palettization.c",\
-"webp/enc/syntax.c",\
-"webp/enc/backward_references.c",\
-"webp/enc/token.c",\
-"webp/enc/analysis.c",\
-"webp/enc/iterator.c",\
-"webp/enc/picture_tools.c",\
-"webp/enc/picture_rescale.c",\
-"webp/enc/config.c",\
-"webp/enc/tree.c",\
-"webp/enc/cost.c",\
-"webp/enc/picture.c",\
-"webp/enc/quant.c",\
-"webp/enc/filter.c",\
-"webp/enc/histogram.c",\
-"webp/image_loader_webp.cpp",\
-"webp/utils/rescaler.c",\
-"webp/utils/filters.c",\
-"webp/utils/quant_levels_dec.c",\
-"webp/utils/huffman.c",\
-"webp/utils/thread.c",\
-"webp/utils/quant_levels.c",\
-"webp/utils/bit_writer.c",\
-"webp/utils/bit_reader.c",\
-"webp/utils/random.c",\
-"webp/utils/utils.c",\
-"webp/utils/huffman_encode.c",\
-"webp/utils/color_cache.c",\
-"webp/mux/muxinternal.c",\
-"webp/mux/muxread.c",\
-"webp/mux/anim_encode.c",\
-"webp/mux/muxedit.c",\
-"webp/dec/webp.c",\
-"webp/dec/frame.c",\
-"webp/dec/alpha.c",\
-"webp/dec/vp8l.c",\
-"webp/dec/io.c",\
-"webp/dec/vp8.c",\
-"webp/dec/idec.c",\
-"webp/dec/tree.c",\
-"webp/dec/buffer.c",\
-"webp/dec/quant.c",\
-"webp/demux/demux.c",\
-"webp/demux/anim_decode.c",\
-"webp/dsp/yuv.c",\
-"webp/dsp/filters_sse2.c",\
-"webp/dsp/dec_sse41.c",\
-"webp/dsp/rescaler.c",\
-"webp/dsp/lossless_sse2.c",\
-"webp/dsp/alpha_processing_sse41.c",\
-"webp/dsp/alpha_processing_sse2.c",\
-"webp/dsp/filters.c",\
-"webp/dsp/upsampling_mips_dsp_r2.c",\
-"webp/dsp/dec_neon.c",\
-"webp/dsp/enc_neon.c",\
-"webp/dsp/lossless_enc_mips32.c",\
-"webp/dsp/lossless_enc_sse2.c",\
-"webp/dsp/upsampling.c",\
-"webp/dsp/lossless_enc_neon.c",\
-"webp/dsp/alpha_processing.c",\
-"webp/dsp/cost_sse2.c",\
-"webp/dsp/dec_mips32.c",\
-"webp/dsp/enc_avx2.c",\
-"webp/dsp/rescaler_mips32.c",\
-"webp/dsp/enc.c",\
-"webp/dsp/lossless_enc_sse41.c",\
-"webp/dsp/cost_mips32.c",\
-"webp/dsp/lossless_mips_dsp_r2.c",\
-"webp/dsp/filters_mips_dsp_r2.c",\
-"webp/dsp/upsampling_neon.c",\
-"webp/dsp/alpha_processing_mips_dsp_r2.c",\
-"webp/dsp/enc_mips_dsp_r2.c",\
-"webp/dsp/lossless.c",\
-"webp/dsp/yuv_mips_dsp_r2.c",\
-"webp/dsp/cost_mips_dsp_r2.c",\
-"webp/dsp/argb.c",\
-"webp/dsp/dec_sse2.c",\
-"webp/dsp/rescaler_sse2.c",\
-"webp/dsp/enc_sse41.c",\
-"webp/dsp/argb_mips_dsp_r2.c",\
-"webp/dsp/lossless_enc_mips_dsp_r2.c",\
-"webp/dsp/dec_clip_tables.c",\
-"webp/dsp/yuv_mips32.c",\
-"webp/dsp/cpu.c",\
-"webp/dsp/dec.c",\
-"webp/dsp/argb_sse2.c",\
-"webp/dsp/lossless_neon.c",\
-"webp/dsp/lossless_enc.c",\
-"webp/dsp/enc_mips32.c",\
-"webp/dsp/cost.c",\
-"webp/dsp/rescaler_mips_dsp_r2.c",\
-"webp/dsp/dec_mips_dsp_r2.c",\
-"webp/dsp/rescaler_neon.c",\
-"webp/dsp/yuv_sse2.c",\
-"webp/dsp/enc_sse2.c",\
-"webp/dsp/upsampling_sse2.c"
-]
-
-env.drivers_sources+=webp_sources
-
-#env.add_source_files(env.drivers_sources, webp_sources)
-
-
-Export('env')
-
diff --git a/drivers/webp/config.h b/drivers/webp/config.h
deleted file mode 100644
index 0ce1c7064d..0000000000
--- a/drivers/webp/config.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/* src/webp/config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define if building universal (internal helper macro) */
-#undef AC_APPLE_UNIVERSAL_BUILD
-
-/* Set to 1 if __builtin_bswap16 is available */
-#undef HAVE_BUILTIN_BSWAP16
-
-/* Set to 1 if __builtin_bswap32 is available */
-#undef HAVE_BUILTIN_BSWAP32
-
-/* Set to 1 if __builtin_bswap64 is available */
-#undef HAVE_BUILTIN_BSWAP64
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you have the <GLUT/glut.h> header file. */
-#undef HAVE_GLUT_GLUT_H
-
-/* Define to 1 if you have the <GL/glut.h> header file. */
-#undef HAVE_GL_GLUT_H
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the <OpenGL/glut.h> header file. */
-#undef HAVE_OPENGL_GLUT_H
-
-/* Have PTHREAD_PRIO_INHERIT. */
-#undef HAVE_PTHREAD_PRIO_INHERIT
-
-/* Define to 1 if you have the <shlwapi.h> header file. */
-#undef HAVE_SHLWAPI_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the <wincodec.h> header file. */
-#undef HAVE_WINCODEC_H
-
-/* Define to 1 if you have the <windows.h> header file. */
-#undef HAVE_WINDOWS_H
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#undef LT_OBJDIR
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define to necessary symbol if this constant uses a non-standard name on
- your system. */
-#undef PTHREAD_CREATE_JOINABLE
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Version number of package */
-#undef VERSION
-
-/* Enable experimental code */
-#undef WEBP_EXPERIMENTAL_FEATURES
-
-/* Define to 1 to force aligned memory operations */
-#undef WEBP_FORCE_ALIGNED
-
-/* Set to 1 if AVX2 is supported */
-#undef WEBP_HAVE_AVX2
-
-/* Set to 1 if GIF library is installed */
-#undef WEBP_HAVE_GIF
-
-/* Set to 1 if OpenGL is supported */
-#undef WEBP_HAVE_GL
-
-/* Set to 1 if JPEG library is installed */
-#undef WEBP_HAVE_JPEG
-
-/* Set to 1 if NEON is supported */
-#undef WEBP_HAVE_NEON
-
-/* Set to 1 if runtime detection of NEON is enabled */
-#undef WEBP_HAVE_NEON_RTCD
-
-/* Set to 1 if PNG library is installed */
-#undef WEBP_HAVE_PNG
-
-/* Set to 1 if SSE2 is supported */
-#undef WEBP_HAVE_SSE2
-
-/* Set to 1 if SSE4.1 is supported */
-#undef WEBP_HAVE_SSE41
-
-/* Set to 1 if TIFF library is installed */
-#undef WEBP_HAVE_TIFF
-
-/* Undefine this to disable thread support. */
-#undef WEBP_USE_THREAD
-
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
- significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-# define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-# undef WORDS_BIGENDIAN
-# endif
-#endif
diff --git a/drivers/webp/dec/alpha.c b/drivers/webp/dec/alpha.c
deleted file mode 100644
index 19ce548e96..0000000000
--- a/drivers/webp/dec/alpha.c
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Alpha-plane decompression.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-#include "./alphai.h"
-#include "./vp8i.h"
-#include "./vp8li.h"
-#include "../dsp/dsp.h"
-#include "../utils/quant_levels_dec.h"
-#include "../utils/utils.h"
-#include "webp/format_constants.h"
-
-//------------------------------------------------------------------------------
-// ALPHDecoder object.
-
-// Allocates a new alpha decoder instance.
-static ALPHDecoder* ALPHNew(void) {
- ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
- return dec;
-}
-
-// Clears and deallocates an alpha decoder instance.
-static void ALPHDelete(ALPHDecoder* const dec) {
- if (dec != NULL) {
- VP8LDelete(dec->vp8l_dec_);
- dec->vp8l_dec_ = NULL;
- WebPSafeFree(dec);
- }
-}
-
-//------------------------------------------------------------------------------
-// Decoding.
-
-// Initialize alpha decoding by parsing the alpha header and decoding the image
-// header for alpha data stored using lossless compression.
-// Returns false in case of error in alpha header (data too short, invalid
-// compression method or filter, error in lossless header data etc).
-static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
- size_t data_size, const VP8Io* const src_io,
- uint8_t* output) {
- int ok = 0;
- const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
- const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
- int rsrv;
- VP8Io* const io = &dec->io_;
-
- assert(data != NULL && output != NULL && src_io != NULL);
-
- VP8FiltersInit();
- dec->output_ = output;
- dec->width_ = src_io->width;
- dec->height_ = src_io->height;
- assert(dec->width_ > 0 && dec->height_ > 0);
-
- if (data_size <= ALPHA_HEADER_LEN) {
- return 0;
- }
-
- dec->method_ = (data[0] >> 0) & 0x03;
- dec->filter_ = (data[0] >> 2) & 0x03;
- dec->pre_processing_ = (data[0] >> 4) & 0x03;
- rsrv = (data[0] >> 6) & 0x03;
- if (dec->method_ < ALPHA_NO_COMPRESSION ||
- dec->method_ > ALPHA_LOSSLESS_COMPRESSION ||
- dec->filter_ >= WEBP_FILTER_LAST ||
- dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS ||
- rsrv != 0) {
- return 0;
- }
-
- // Copy the necessary parameters from src_io to io
- VP8InitIo(io);
- WebPInitCustomIo(NULL, io);
- io->opaque = dec;
- io->width = src_io->width;
- io->height = src_io->height;
-
- io->use_cropping = src_io->use_cropping;
- io->crop_left = src_io->crop_left;
- io->crop_right = src_io->crop_right;
- io->crop_top = src_io->crop_top;
- io->crop_bottom = src_io->crop_bottom;
- // No need to copy the scaling parameters.
-
- if (dec->method_ == ALPHA_NO_COMPRESSION) {
- const size_t alpha_decoded_size = dec->width_ * dec->height_;
- ok = (alpha_data_size >= alpha_decoded_size);
- } else {
- assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION);
- ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size);
- }
-
- return ok;
-}
-
-// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha
-// starting from row number 'row'. It assumes that rows up to (row - 1) have
-// already been decoded.
-// Returns false in case of bitstream error.
-static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
- ALPHDecoder* const alph_dec = dec->alph_dec_;
- const int width = alph_dec->width_;
- const int height = alph_dec->io_.crop_bottom;
- if (alph_dec->method_ == ALPHA_NO_COMPRESSION) {
- int y;
- const uint8_t* prev_line = dec->alpha_prev_line_;
- const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width;
- uint8_t* dst = dec->alpha_plane_ + row * width;
- assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]);
- if (alph_dec->filter_ != WEBP_FILTER_NONE) {
- assert(WebPUnfilters[alph_dec->filter_] != NULL);
- for (y = 0; y < num_rows; ++y) {
- WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width);
- prev_line = dst;
- dst += width;
- deltas += width;
- }
- } else {
- for (y = 0; y < num_rows; ++y) {
- memcpy(dst, deltas, width * sizeof(*dst));
- prev_line = dst;
- dst += width;
- deltas += width;
- }
- }
- dec->alpha_prev_line_ = prev_line;
- } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
- assert(alph_dec->vp8l_dec_ != NULL);
- if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) {
- return 0;
- }
- }
-
- if (row + num_rows >= height) {
- dec->is_alpha_decoded_ = 1;
- }
- return 1;
-}
-
-static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) {
- const int stride = io->width;
- const int height = io->crop_bottom;
- const uint64_t alpha_size = (uint64_t)stride * height;
- assert(dec->alpha_plane_mem_ == NULL);
- dec->alpha_plane_mem_ =
- (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_));
- if (dec->alpha_plane_mem_ == NULL) {
- return 0;
- }
- dec->alpha_plane_ = dec->alpha_plane_mem_;
- dec->alpha_prev_line_ = NULL;
- return 1;
-}
-
-void WebPDeallocateAlphaMemory(VP8Decoder* const dec) {
- assert(dec != NULL);
- WebPSafeFree(dec->alpha_plane_mem_);
- dec->alpha_plane_mem_ = NULL;
- dec->alpha_plane_ = NULL;
- ALPHDelete(dec->alph_dec_);
- dec->alph_dec_ = NULL;
-}
-
-//------------------------------------------------------------------------------
-// Main entry point.
-
-const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
- const VP8Io* const io,
- int row, int num_rows) {
- const int width = io->width;
- const int height = io->crop_bottom;
-
- assert(dec != NULL && io != NULL);
-
- if (row < 0 || num_rows <= 0 || row + num_rows > height) {
- return NULL; // sanity check.
- }
-
- if (!dec->is_alpha_decoded_) {
- if (dec->alph_dec_ == NULL) { // Initialize decoder.
- dec->alph_dec_ = ALPHNew();
- if (dec->alph_dec_ == NULL) return NULL;
- if (!AllocateAlphaPlane(dec, io)) goto Error;
- if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
- io, dec->alpha_plane_)) {
- goto Error;
- }
- // if we allowed use of alpha dithering, check whether it's needed at all
- if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) {
- dec->alpha_dithering_ = 0; // disable dithering
- } else {
- num_rows = height - row; // decode everything in one pass
- }
- }
-
- assert(dec->alph_dec_ != NULL);
- assert(row + num_rows <= height);
- if (!ALPHDecode(dec, row, num_rows)) goto Error;
-
- if (dec->is_alpha_decoded_) { // finished?
- ALPHDelete(dec->alph_dec_);
- dec->alph_dec_ = NULL;
- if (dec->alpha_dithering_ > 0) {
- uint8_t* const alpha = dec->alpha_plane_ + io->crop_top * width
- + io->crop_left;
- if (!WebPDequantizeLevels(alpha,
- io->crop_right - io->crop_left,
- io->crop_bottom - io->crop_top,
- width, dec->alpha_dithering_)) {
- goto Error;
- }
- }
- }
- }
-
- // Return a pointer to the current decoded row.
- return dec->alpha_plane_ + row * width;
-
- Error:
- WebPDeallocateAlphaMemory(dec);
- return NULL;
-}
diff --git a/drivers/webp/dec/alphai.h b/drivers/webp/dec/alphai.h
deleted file mode 100644
index 69dd7c0f5d..0000000000
--- a/drivers/webp/dec/alphai.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Alpha decoder: internal header.
-//
-// Author: Urvang (urvang@google.com)
-
-#ifndef WEBP_DEC_ALPHAI_H_
-#define WEBP_DEC_ALPHAI_H_
-
-#include "./webpi.h"
-#include "../utils/filters.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct VP8LDecoder; // Defined in dec/vp8li.h.
-
-typedef struct ALPHDecoder ALPHDecoder;
-struct ALPHDecoder {
- int width_;
- int height_;
- int method_;
- WEBP_FILTER_TYPE filter_;
- int pre_processing_;
- struct VP8LDecoder* vp8l_dec_;
- VP8Io io_;
- int use_8b_decode_; // Although alpha channel requires only 1 byte per
- // pixel, sometimes VP8LDecoder may need to allocate
- // 4 bytes per pixel internally during decode.
- uint8_t* output_;
- const uint8_t* prev_line_; // last output row (or NULL)
-};
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
-// Deallocate memory associated to dec->alpha_plane_ decoding
-void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_ALPHAI_H_ */
diff --git a/drivers/webp/dec/buffer.c b/drivers/webp/dec/buffer.c
deleted file mode 100644
index 547e69b434..0000000000
--- a/drivers/webp/dec/buffer.c
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Everything about WebPDecBuffer
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-
-#include "./vp8i.h"
-#include "./webpi.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// WebPDecBuffer
-
-// Number of bytes per pixel for the different color-spaces.
-static const int kModeBpp[MODE_LAST] = {
- 3, 4, 3, 4, 4, 2, 2,
- 4, 4, 4, 2, // pre-multiplied modes
- 1, 1 };
-
-// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
-// Convert to an integer to handle both the unsigned/signed enum cases
-// without the need for casting to remove type limit warnings.
-static int IsValidColorspace(int webp_csp_mode) {
- return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST);
-}
-
-// strictly speaking, the very last (or first, if flipped) row
-// doesn't require padding.
-#define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \
- (uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH)
-
-static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
- int ok = 1;
- const WEBP_CSP_MODE mode = buffer->colorspace;
- const int width = buffer->width;
- const int height = buffer->height;
- if (!IsValidColorspace(mode)) {
- ok = 0;
- } else if (!WebPIsRGBMode(mode)) { // YUV checks
- const WebPYUVABuffer* const buf = &buffer->u.YUVA;
- const int uv_width = (width + 1) / 2;
- const int uv_height = (height + 1) / 2;
- const int y_stride = abs(buf->y_stride);
- const int u_stride = abs(buf->u_stride);
- const int v_stride = abs(buf->v_stride);
- const int a_stride = abs(buf->a_stride);
- const uint64_t y_size = MIN_BUFFER_SIZE(width, height, y_stride);
- const uint64_t u_size = MIN_BUFFER_SIZE(uv_width, uv_height, u_stride);
- const uint64_t v_size = MIN_BUFFER_SIZE(uv_width, uv_height, v_stride);
- const uint64_t a_size = MIN_BUFFER_SIZE(width, height, a_stride);
- ok &= (y_size <= buf->y_size);
- ok &= (u_size <= buf->u_size);
- ok &= (v_size <= buf->v_size);
- ok &= (y_stride >= width);
- ok &= (u_stride >= uv_width);
- ok &= (v_stride >= uv_width);
- ok &= (buf->y != NULL);
- ok &= (buf->u != NULL);
- ok &= (buf->v != NULL);
- if (mode == MODE_YUVA) {
- ok &= (a_stride >= width);
- ok &= (a_size <= buf->a_size);
- ok &= (buf->a != NULL);
- }
- } else { // RGB checks
- const WebPRGBABuffer* const buf = &buffer->u.RGBA;
- const int stride = abs(buf->stride);
- const uint64_t size = MIN_BUFFER_SIZE(width, height, stride);
- ok &= (size <= buf->size);
- ok &= (stride >= width * kModeBpp[mode]);
- ok &= (buf->rgba != NULL);
- }
- return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM;
-}
-#undef MIN_BUFFER_SIZE
-
-static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
- const int w = buffer->width;
- const int h = buffer->height;
- const WEBP_CSP_MODE mode = buffer->colorspace;
-
- if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) {
- return VP8_STATUS_INVALID_PARAM;
- }
-
- if (buffer->is_external_memory <= 0 && buffer->private_memory == NULL) {
- uint8_t* output;
- int uv_stride = 0, a_stride = 0;
- uint64_t uv_size = 0, a_size = 0, total_size;
- // We need memory and it hasn't been allocated yet.
- // => initialize output buffer, now that dimensions are known.
- const int stride = w * kModeBpp[mode];
- const uint64_t size = (uint64_t)stride * h;
-
- if (!WebPIsRGBMode(mode)) {
- uv_stride = (w + 1) / 2;
- uv_size = (uint64_t)uv_stride * ((h + 1) / 2);
- if (mode == MODE_YUVA) {
- a_stride = w;
- a_size = (uint64_t)a_stride * h;
- }
- }
- total_size = size + 2 * uv_size + a_size;
-
- // Security/sanity checks
- output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output));
- if (output == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- buffer->private_memory = output;
-
- if (!WebPIsRGBMode(mode)) { // YUVA initialization
- WebPYUVABuffer* const buf = &buffer->u.YUVA;
- buf->y = output;
- buf->y_stride = stride;
- buf->y_size = (size_t)size;
- buf->u = output + size;
- buf->u_stride = uv_stride;
- buf->u_size = (size_t)uv_size;
- buf->v = output + size + uv_size;
- buf->v_stride = uv_stride;
- buf->v_size = (size_t)uv_size;
- if (mode == MODE_YUVA) {
- buf->a = output + size + 2 * uv_size;
- }
- buf->a_size = (size_t)a_size;
- buf->a_stride = a_stride;
- } else { // RGBA initialization
- WebPRGBABuffer* const buf = &buffer->u.RGBA;
- buf->rgba = output;
- buf->stride = stride;
- buf->size = (size_t)size;
- }
- }
- return CheckDecBuffer(buffer);
-}
-
-VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) {
- if (buffer == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
- if (WebPIsRGBMode(buffer->colorspace)) {
- WebPRGBABuffer* const buf = &buffer->u.RGBA;
- buf->rgba += (buffer->height - 1) * buf->stride;
- buf->stride = -buf->stride;
- } else {
- WebPYUVABuffer* const buf = &buffer->u.YUVA;
- const int H = buffer->height;
- buf->y += (H - 1) * buf->y_stride;
- buf->y_stride = -buf->y_stride;
- buf->u += ((H - 1) >> 1) * buf->u_stride;
- buf->u_stride = -buf->u_stride;
- buf->v += ((H - 1) >> 1) * buf->v_stride;
- buf->v_stride = -buf->v_stride;
- if (buf->a != NULL) {
- buf->a += (H - 1) * buf->a_stride;
- buf->a_stride = -buf->a_stride;
- }
- }
- return VP8_STATUS_OK;
-}
-
-VP8StatusCode WebPAllocateDecBuffer(int w, int h,
- const WebPDecoderOptions* const options,
- WebPDecBuffer* const out) {
- VP8StatusCode status;
- if (out == NULL || w <= 0 || h <= 0) {
- return VP8_STATUS_INVALID_PARAM;
- }
- if (options != NULL) { // First, apply options if there is any.
- if (options->use_cropping) {
- const int cw = options->crop_width;
- const int ch = options->crop_height;
- const int x = options->crop_left & ~1;
- const int y = options->crop_top & ~1;
- if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) {
- return VP8_STATUS_INVALID_PARAM; // out of frame boundary.
- }
- w = cw;
- h = ch;
- }
- if (options->use_scaling) {
- int scaled_width = options->scaled_width;
- int scaled_height = options->scaled_height;
- if (!WebPRescalerGetScaledDimensions(
- w, h, &scaled_width, &scaled_height)) {
- return VP8_STATUS_INVALID_PARAM;
- }
- w = scaled_width;
- h = scaled_height;
- }
- }
- out->width = w;
- out->height = h;
-
- // Then, allocate buffer for real.
- status = AllocateBuffer(out);
- if (status != VP8_STATUS_OK) return status;
-
- // Use the stride trick if vertical flip is needed.
- if (options != NULL && options->flip) {
- status = WebPFlipBuffer(out);
- }
- return status;
-}
-
-//------------------------------------------------------------------------------
-// constructors / destructors
-
-int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
- return 0; // version mismatch
- }
- if (buffer == NULL) return 0;
- memset(buffer, 0, sizeof(*buffer));
- return 1;
-}
-
-void WebPFreeDecBuffer(WebPDecBuffer* buffer) {
- if (buffer != NULL) {
- if (buffer->is_external_memory <= 0) {
- WebPSafeFree(buffer->private_memory);
- }
- buffer->private_memory = NULL;
- }
-}
-
-void WebPCopyDecBuffer(const WebPDecBuffer* const src,
- WebPDecBuffer* const dst) {
- if (src != NULL && dst != NULL) {
- *dst = *src;
- if (src->private_memory != NULL) {
- dst->is_external_memory = 1; // dst buffer doesn't own the memory.
- dst->private_memory = NULL;
- }
- }
-}
-
-// Copy and transfer ownership from src to dst (beware of parameter order!)
-void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) {
- if (src != NULL && dst != NULL) {
- *dst = *src;
- if (src->private_memory != NULL) {
- src->is_external_memory = 1; // src relinquishes ownership
- src->private_memory = NULL;
- }
- }
-}
-
-VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src_buf,
- WebPDecBuffer* const dst_buf) {
- assert(src_buf != NULL && dst_buf != NULL);
- assert(src_buf->colorspace == dst_buf->colorspace);
-
- dst_buf->width = src_buf->width;
- dst_buf->height = src_buf->height;
- if (CheckDecBuffer(dst_buf) != VP8_STATUS_OK) {
- return VP8_STATUS_INVALID_PARAM;
- }
- if (WebPIsRGBMode(src_buf->colorspace)) {
- const WebPRGBABuffer* const src = &src_buf->u.RGBA;
- const WebPRGBABuffer* const dst = &dst_buf->u.RGBA;
- WebPCopyPlane(src->rgba, src->stride, dst->rgba, dst->stride,
- src_buf->width * kModeBpp[src_buf->colorspace],
- src_buf->height);
- } else {
- const WebPYUVABuffer* const src = &src_buf->u.YUVA;
- const WebPYUVABuffer* const dst = &dst_buf->u.YUVA;
- WebPCopyPlane(src->y, src->y_stride, dst->y, dst->y_stride,
- src_buf->width, src_buf->height);
- WebPCopyPlane(src->u, src->u_stride, dst->u, dst->u_stride,
- (src_buf->width + 1) / 2, (src_buf->height + 1) / 2);
- WebPCopyPlane(src->v, src->v_stride, dst->v, dst->v_stride,
- (src_buf->width + 1) / 2, (src_buf->height + 1) / 2);
- if (WebPIsAlphaMode(src_buf->colorspace)) {
- WebPCopyPlane(src->a, src->a_stride, dst->a, dst->a_stride,
- src_buf->width, src_buf->height);
- }
- }
- return VP8_STATUS_OK;
-}
-
-int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
- const WebPBitstreamFeatures* const features) {
- assert(output != NULL);
- return (output->is_external_memory >= 2) &&
- WebPIsPremultipliedMode(output->colorspace) &&
- (features != NULL && features->has_alpha);
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dec/common.h b/drivers/webp/dec/common.h
deleted file mode 100644
index 6961e22470..0000000000
--- a/drivers/webp/dec/common.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Definitions and macros common to encoding and decoding
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_DEC_COMMON_H_
-#define WEBP_DEC_COMMON_H_
-
-// intra prediction modes
-enum { B_DC_PRED = 0, // 4x4 modes
- B_TM_PRED = 1,
- B_VE_PRED = 2,
- B_HE_PRED = 3,
- B_RD_PRED = 4,
- B_VR_PRED = 5,
- B_LD_PRED = 6,
- B_VL_PRED = 7,
- B_HD_PRED = 8,
- B_HU_PRED = 9,
- NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
-
- // Luma16 or UV modes
- DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
- H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
- B_PRED = NUM_BMODES, // refined I4x4 mode
- NUM_PRED_MODES = 4,
-
- // special modes
- B_DC_PRED_NOTOP = 4,
- B_DC_PRED_NOLEFT = 5,
- B_DC_PRED_NOTOPLEFT = 6,
- NUM_B_DC_MODES = 7 };
-
-enum { MB_FEATURE_TREE_PROBS = 3,
- NUM_MB_SEGMENTS = 4,
- NUM_REF_LF_DELTAS = 4,
- NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
- MAX_NUM_PARTITIONS = 8,
- // Probabilities
- NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC
- NUM_BANDS = 8,
- NUM_CTX = 3,
- NUM_PROBAS = 11
- };
-
-#endif // WEBP_DEC_COMMON_H_
diff --git a/drivers/webp/dec/decode_vp8.h b/drivers/webp/dec/decode_vp8.h
deleted file mode 100644
index 2bf1bdbbf5..0000000000
--- a/drivers/webp/dec/decode_vp8.h
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Low-level API for VP8 decoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_WEBP_DECODE_VP8_H_
-#define WEBP_WEBP_DECODE_VP8_H_
-
-#include "webp/decode.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Lower-level API
-//
-// These functions provide fine-grained control of the decoding process.
-// The call flow should resemble:
-//
-// VP8Io io;
-// VP8InitIo(&io);
-// io.data = data;
-// io.data_size = size;
-// /* customize io's functions (setup()/put()/teardown()) if needed. */
-//
-// VP8Decoder* dec = VP8New();
-// bool ok = VP8Decode(dec);
-// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec));
-// VP8Delete(dec);
-// return ok;
-
-// Input / Output
-typedef struct VP8Io VP8Io;
-typedef int (*VP8IoPutHook)(const VP8Io* io);
-typedef int (*VP8IoSetupHook)(VP8Io* io);
-typedef void (*VP8IoTeardownHook)(const VP8Io* io);
-
-struct VP8Io {
- // set by VP8GetHeaders()
- int width, height; // picture dimensions, in pixels (invariable).
- // These are the original, uncropped dimensions.
- // The actual area passed to put() is stored
- // in mb_w / mb_h fields.
-
- // set before calling put()
- int mb_y; // position of the current rows (in pixels)
- int mb_w; // number of columns in the sample
- int mb_h; // number of rows in the sample
- const uint8_t* y, *u, *v; // rows to copy (in yuv420 format)
- int y_stride; // row stride for luma
- int uv_stride; // row stride for chroma
-
- void* opaque; // user data
-
- // called when fresh samples are available. Currently, samples are in
- // YUV420 format, and can be up to width x 24 in size (depending on the
- // in-loop filtering level, e.g.). Should return false in case of error
- // or abort request. The actual size of the area to update is mb_w x mb_h
- // in size, taking cropping into account.
- VP8IoPutHook put;
-
- // called just before starting to decode the blocks.
- // Must return false in case of setup error, true otherwise. If false is
- // returned, teardown() will NOT be called. But if the setup succeeded
- // and true is returned, then teardown() will always be called afterward.
- VP8IoSetupHook setup;
-
- // Called just after block decoding is finished (or when an error occurred
- // during put()). Is NOT called if setup() failed.
- VP8IoTeardownHook teardown;
-
- // this is a recommendation for the user-side yuv->rgb converter. This flag
- // is set when calling setup() hook and can be overwritten by it. It then
- // can be taken into consideration during the put() method.
- int fancy_upsampling;
-
- // Input buffer.
- size_t data_size;
- const uint8_t* data;
-
- // If true, in-loop filtering will not be performed even if present in the
- // bitstream. Switching off filtering may speed up decoding at the expense
- // of more visible blocking. Note that output will also be non-compliant
- // with the VP8 specifications.
- int bypass_filtering;
-
- // Cropping parameters.
- int use_cropping;
- int crop_left, crop_right, crop_top, crop_bottom;
-
- // Scaling parameters.
- int use_scaling;
- int scaled_width, scaled_height;
-
- // If non NULL, pointer to the alpha data (if present) corresponding to the
- // start of the current row (That is: it is pre-offset by mb_y and takes
- // cropping into account).
- const uint8_t* a;
-};
-
-// Internal, version-checked, entry point
-int VP8InitIoInternal(VP8Io* const, int);
-
-// Set the custom IO function pointers and user-data. The setter for IO hooks
-// should be called before initiating incremental decoding. Returns true if
-// WebPIDecoder object is successfully modified, false otherwise.
-int WebPISetIOHooks(WebPIDecoder* const idec,
- VP8IoPutHook put,
- VP8IoSetupHook setup,
- VP8IoTeardownHook teardown,
- void* user_data);
-
-// Main decoding object. This is an opaque structure.
-typedef struct VP8Decoder VP8Decoder;
-
-// Create a new decoder object.
-VP8Decoder* VP8New(void);
-
-// Must be called to make sure 'io' is initialized properly.
-// Returns false in case of version mismatch. Upon such failure, no other
-// decoding function should be called (VP8Decode, VP8GetHeaders, ...)
-static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
- return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION);
-}
-
-// Decode the VP8 frame header. Returns true if ok.
-// Note: 'io->data' must be pointing to the start of the VP8 frame header.
-int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
-
-// Decode a picture. Will call VP8GetHeaders() if it wasn't done already.
-// Returns false in case of error.
-int VP8Decode(VP8Decoder* const dec, VP8Io* const io);
-
-// Return current status of the decoder:
-VP8StatusCode VP8Status(VP8Decoder* const dec);
-
-// return readable string corresponding to the last status.
-const char* VP8StatusMessage(VP8Decoder* const dec);
-
-// Resets the decoder in its initial state, reclaiming memory.
-// Not a mandatory call between calls to VP8Decode().
-void VP8Clear(VP8Decoder* const dec);
-
-// Destroy the decoder object.
-void VP8Delete(VP8Decoder* const dec);
-
-//------------------------------------------------------------------------------
-// Miscellaneous VP8/VP8L bitstream probing functions.
-
-// Returns true if the next 3 bytes in data contain the VP8 signature.
-WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size);
-
-// Validates the VP8 data-header and retrieves basic header information viz
-// width and height. Returns 0 in case of formatting error. *width/*height
-// can be passed NULL.
-WEBP_EXTERN(int) VP8GetInfo(
- const uint8_t* data,
- size_t data_size, // data available so far
- size_t chunk_size, // total data size expected in the chunk
- int* const width, int* const height);
-
-// Returns true if the next byte(s) in data is a VP8L signature.
-WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size);
-
-// Validates the VP8L data-header and retrieves basic header information viz
-// width, height and alpha. Returns 0 in case of formatting error.
-// width/height/has_alpha can be passed NULL.
-WEBP_EXTERN(int) VP8LGetInfo(
- const uint8_t* data, size_t data_size, // data available so far
- int* const width, int* const height, int* const has_alpha);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_WEBP_DECODE_VP8_H_ */
diff --git a/drivers/webp/dec/frame.c b/drivers/webp/dec/frame.c
deleted file mode 100644
index 22d291d2cd..0000000000
--- a/drivers/webp/dec/frame.c
+++ /dev/null
@@ -1,812 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Frame-reconstruction function. Memory allocation.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-#include "./vp8i.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// Main reconstruction function.
-
-static const int kScan[16] = {
- 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
- 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
- 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
- 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS
-};
-
-static int CheckMode(int mb_x, int mb_y, int mode) {
- if (mode == B_DC_PRED) {
- if (mb_x == 0) {
- return (mb_y == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT;
- } else {
- return (mb_y == 0) ? B_DC_PRED_NOTOP : B_DC_PRED;
- }
- }
- return mode;
-}
-
-static void Copy32b(uint8_t* const dst, const uint8_t* const src) {
- memcpy(dst, src, 4);
-}
-
-static WEBP_INLINE void DoTransform(uint32_t bits, const int16_t* const src,
- uint8_t* const dst) {
- switch (bits >> 30) {
- case 3:
- VP8Transform(src, dst, 0);
- break;
- case 2:
- VP8TransformAC3(src, dst);
- break;
- case 1:
- VP8TransformDC(src, dst);
- break;
- default:
- break;
- }
-}
-
-static void DoUVTransform(uint32_t bits, const int16_t* const src,
- uint8_t* const dst) {
- if (bits & 0xff) { // any non-zero coeff at all?
- if (bits & 0xaa) { // any non-zero AC coefficient?
- VP8TransformUV(src, dst); // note we don't use the AC3 variant for U/V
- } else {
- VP8TransformDCUV(src, dst);
- }
- }
-}
-
-static void ReconstructRow(const VP8Decoder* const dec,
- const VP8ThreadContext* ctx) {
- int j;
- int mb_x;
- const int mb_y = ctx->mb_y_;
- const int cache_id = ctx->id_;
- uint8_t* const y_dst = dec->yuv_b_ + Y_OFF;
- uint8_t* const u_dst = dec->yuv_b_ + U_OFF;
- uint8_t* const v_dst = dec->yuv_b_ + V_OFF;
-
- // Initialize left-most block.
- for (j = 0; j < 16; ++j) {
- y_dst[j * BPS - 1] = 129;
- }
- for (j = 0; j < 8; ++j) {
- u_dst[j * BPS - 1] = 129;
- v_dst[j * BPS - 1] = 129;
- }
-
- // Init top-left sample on left column too.
- if (mb_y > 0) {
- y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129;
- } else {
- // we only need to do this init once at block (0,0).
- // Afterward, it remains valid for the whole topmost row.
- memset(y_dst - BPS - 1, 127, 16 + 4 + 1);
- memset(u_dst - BPS - 1, 127, 8 + 1);
- memset(v_dst - BPS - 1, 127, 8 + 1);
- }
-
- // Reconstruct one row.
- for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) {
- const VP8MBData* const block = ctx->mb_data_ + mb_x;
-
- // Rotate in the left samples from previously decoded block. We move four
- // pixels at a time for alignment reason, and because of in-loop filter.
- if (mb_x > 0) {
- for (j = -1; j < 16; ++j) {
- Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]);
- }
- for (j = -1; j < 8; ++j) {
- Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]);
- Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]);
- }
- }
- {
- // bring top samples into the cache
- VP8TopSamples* const top_yuv = dec->yuv_t_ + mb_x;
- const int16_t* const coeffs = block->coeffs_;
- uint32_t bits = block->non_zero_y_;
- int n;
-
- if (mb_y > 0) {
- memcpy(y_dst - BPS, top_yuv[0].y, 16);
- memcpy(u_dst - BPS, top_yuv[0].u, 8);
- memcpy(v_dst - BPS, top_yuv[0].v, 8);
- }
-
- // predict and add residuals
- if (block->is_i4x4_) { // 4x4
- uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16);
-
- if (mb_y > 0) {
- if (mb_x >= dec->mb_w_ - 1) { // on rightmost border
- memset(top_right, top_yuv[0].y[15], sizeof(*top_right));
- } else {
- memcpy(top_right, top_yuv[1].y, sizeof(*top_right));
- }
- }
- // replicate the top-right pixels below
- top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0];
-
- // predict and add residuals for all 4x4 blocks in turn.
- for (n = 0; n < 16; ++n, bits <<= 2) {
- uint8_t* const dst = y_dst + kScan[n];
- VP8PredLuma4[block->imodes_[n]](dst);
- DoTransform(bits, coeffs + n * 16, dst);
- }
- } else { // 16x16
- const int pred_func = CheckMode(mb_x, mb_y, block->imodes_[0]);
- VP8PredLuma16[pred_func](y_dst);
- if (bits != 0) {
- for (n = 0; n < 16; ++n, bits <<= 2) {
- DoTransform(bits, coeffs + n * 16, y_dst + kScan[n]);
- }
- }
- }
- {
- // Chroma
- const uint32_t bits_uv = block->non_zero_uv_;
- const int pred_func = CheckMode(mb_x, mb_y, block->uvmode_);
- VP8PredChroma8[pred_func](u_dst);
- VP8PredChroma8[pred_func](v_dst);
- DoUVTransform(bits_uv >> 0, coeffs + 16 * 16, u_dst);
- DoUVTransform(bits_uv >> 8, coeffs + 20 * 16, v_dst);
- }
-
- // stash away top samples for next block
- if (mb_y < dec->mb_h_ - 1) {
- memcpy(top_yuv[0].y, y_dst + 15 * BPS, 16);
- memcpy(top_yuv[0].u, u_dst + 7 * BPS, 8);
- memcpy(top_yuv[0].v, v_dst + 7 * BPS, 8);
- }
- }
- // Transfer reconstructed samples from yuv_b_ cache to final destination.
- {
- const int y_offset = cache_id * 16 * dec->cache_y_stride_;
- const int uv_offset = cache_id * 8 * dec->cache_uv_stride_;
- uint8_t* const y_out = dec->cache_y_ + mb_x * 16 + y_offset;
- uint8_t* const u_out = dec->cache_u_ + mb_x * 8 + uv_offset;
- uint8_t* const v_out = dec->cache_v_ + mb_x * 8 + uv_offset;
- for (j = 0; j < 16; ++j) {
- memcpy(y_out + j * dec->cache_y_stride_, y_dst + j * BPS, 16);
- }
- for (j = 0; j < 8; ++j) {
- memcpy(u_out + j * dec->cache_uv_stride_, u_dst + j * BPS, 8);
- memcpy(v_out + j * dec->cache_uv_stride_, v_dst + j * BPS, 8);
- }
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// Filtering
-
-// kFilterExtraRows[] = How many extra lines are needed on the MB boundary
-// for caching, given a filtering level.
-// Simple filter: up to 2 luma samples are read and 1 is written.
-// Complex filter: up to 4 luma samples are read and 3 are written. Same for
-// U/V, so it's 8 samples total (because of the 2x upsampling).
-static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 };
-
-static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) {
- const VP8ThreadContext* const ctx = &dec->thread_ctx_;
- const int cache_id = ctx->id_;
- const int y_bps = dec->cache_y_stride_;
- const VP8FInfo* const f_info = ctx->f_info_ + mb_x;
- uint8_t* const y_dst = dec->cache_y_ + cache_id * 16 * y_bps + mb_x * 16;
- const int ilevel = f_info->f_ilevel_;
- const int limit = f_info->f_limit_;
- if (limit == 0) {
- return;
- }
- assert(limit >= 3);
- if (dec->filter_type_ == 1) { // simple
- if (mb_x > 0) {
- VP8SimpleHFilter16(y_dst, y_bps, limit + 4);
- }
- if (f_info->f_inner_) {
- VP8SimpleHFilter16i(y_dst, y_bps, limit);
- }
- if (mb_y > 0) {
- VP8SimpleVFilter16(y_dst, y_bps, limit + 4);
- }
- if (f_info->f_inner_) {
- VP8SimpleVFilter16i(y_dst, y_bps, limit);
- }
- } else { // complex
- const int uv_bps = dec->cache_uv_stride_;
- uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8;
- uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8;
- const int hev_thresh = f_info->hev_thresh_;
- if (mb_x > 0) {
- VP8HFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh);
- VP8HFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh);
- }
- if (f_info->f_inner_) {
- VP8HFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh);
- VP8HFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh);
- }
- if (mb_y > 0) {
- VP8VFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh);
- VP8VFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh);
- }
- if (f_info->f_inner_) {
- VP8VFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh);
- VP8VFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh);
- }
- }
-}
-
-// Filter the decoded macroblock row (if needed)
-static void FilterRow(const VP8Decoder* const dec) {
- int mb_x;
- const int mb_y = dec->thread_ctx_.mb_y_;
- assert(dec->thread_ctx_.filter_row_);
- for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) {
- DoFilter(dec, mb_x, mb_y);
- }
-}
-
-//------------------------------------------------------------------------------
-// Precompute the filtering strength for each segment and each i4x4/i16x16 mode.
-
-static void PrecomputeFilterStrengths(VP8Decoder* const dec) {
- if (dec->filter_type_ > 0) {
- int s;
- const VP8FilterHeader* const hdr = &dec->filter_hdr_;
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- int i4x4;
- // First, compute the initial level
- int base_level;
- if (dec->segment_hdr_.use_segment_) {
- base_level = dec->segment_hdr_.filter_strength_[s];
- if (!dec->segment_hdr_.absolute_delta_) {
- base_level += hdr->level_;
- }
- } else {
- base_level = hdr->level_;
- }
- for (i4x4 = 0; i4x4 <= 1; ++i4x4) {
- VP8FInfo* const info = &dec->fstrengths_[s][i4x4];
- int level = base_level;
- if (hdr->use_lf_delta_) {
- level += hdr->ref_lf_delta_[0];
- if (i4x4) {
- level += hdr->mode_lf_delta_[0];
- }
- }
- level = (level < 0) ? 0 : (level > 63) ? 63 : level;
- if (level > 0) {
- int ilevel = level;
- if (hdr->sharpness_ > 0) {
- if (hdr->sharpness_ > 4) {
- ilevel >>= 2;
- } else {
- ilevel >>= 1;
- }
- if (ilevel > 9 - hdr->sharpness_) {
- ilevel = 9 - hdr->sharpness_;
- }
- }
- if (ilevel < 1) ilevel = 1;
- info->f_ilevel_ = ilevel;
- info->f_limit_ = 2 * level + ilevel;
- info->hev_thresh_ = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
- } else {
- info->f_limit_ = 0; // no filtering
- }
- info->f_inner_ = i4x4;
- }
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// Dithering
-
-// minimal amp that will provide a non-zero dithering effect
-#define MIN_DITHER_AMP 4
-
-#define DITHER_AMP_TAB_SIZE 12
-static const int kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = {
- // roughly, it's dqm->uv_mat_[1]
- 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1
-};
-
-void VP8InitDithering(const WebPDecoderOptions* const options,
- VP8Decoder* const dec) {
- assert(dec != NULL);
- if (options != NULL) {
- const int d = options->dithering_strength;
- const int max_amp = (1 << VP8_RANDOM_DITHER_FIX) - 1;
- const int f = (d < 0) ? 0 : (d > 100) ? max_amp : (d * max_amp / 100);
- if (f > 0) {
- int s;
- int all_amp = 0;
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- VP8QuantMatrix* const dqm = &dec->dqm_[s];
- if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) {
- // TODO(skal): should we specially dither more for uv_quant_ < 0?
- const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_;
- dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3;
- }
- all_amp |= dqm->dither_;
- }
- if (all_amp != 0) {
- VP8InitRandom(&dec->dithering_rg_, 1.0f);
- dec->dither_ = 1;
- }
- }
- // potentially allow alpha dithering
- dec->alpha_dithering_ = options->alpha_dithering_strength;
- if (dec->alpha_dithering_ > 100) {
- dec->alpha_dithering_ = 100;
- } else if (dec->alpha_dithering_ < 0) {
- dec->alpha_dithering_ = 0;
- }
- }
-}
-
-// Convert to range: [-2,2] for dither=50, [-4,4] for dither=100
-static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) {
- uint8_t dither[64];
- int i;
- for (i = 0; i < 8 * 8; ++i) {
- dither[i] = VP8RandomBits2(rg, VP8_DITHER_AMP_BITS + 1, amp);
- }
- VP8DitherCombine8x8(dither, dst, bps);
-}
-
-static void DitherRow(VP8Decoder* const dec) {
- int mb_x;
- assert(dec->dither_);
- for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) {
- const VP8ThreadContext* const ctx = &dec->thread_ctx_;
- const VP8MBData* const data = ctx->mb_data_ + mb_x;
- const int cache_id = ctx->id_;
- const int uv_bps = dec->cache_uv_stride_;
- if (data->dither_ >= MIN_DITHER_AMP) {
- uint8_t* const u_dst = dec->cache_u_ + cache_id * 8 * uv_bps + mb_x * 8;
- uint8_t* const v_dst = dec->cache_v_ + cache_id * 8 * uv_bps + mb_x * 8;
- Dither8x8(&dec->dithering_rg_, u_dst, uv_bps, data->dither_);
- Dither8x8(&dec->dithering_rg_, v_dst, uv_bps, data->dither_);
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// This function is called after a row of macroblocks is finished decoding.
-// It also takes into account the following restrictions:
-// * In case of in-loop filtering, we must hold off sending some of the bottom
-// pixels as they are yet unfiltered. They will be when the next macroblock
-// row is decoded. Meanwhile, we must preserve them by rotating them in the
-// cache area. This doesn't hold for the very bottom row of the uncropped
-// picture of course.
-// * we must clip the remaining pixels against the cropping area. The VP8Io
-// struct must have the following fields set correctly before calling put():
-
-#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB
-
-// Finalize and transmit a complete row. Return false in case of user-abort.
-static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 1;
- const VP8ThreadContext* const ctx = &dec->thread_ctx_;
- const int cache_id = ctx->id_;
- const int extra_y_rows = kFilterExtraRows[dec->filter_type_];
- const int ysize = extra_y_rows * dec->cache_y_stride_;
- const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_;
- const int y_offset = cache_id * 16 * dec->cache_y_stride_;
- const int uv_offset = cache_id * 8 * dec->cache_uv_stride_;
- uint8_t* const ydst = dec->cache_y_ - ysize + y_offset;
- uint8_t* const udst = dec->cache_u_ - uvsize + uv_offset;
- uint8_t* const vdst = dec->cache_v_ - uvsize + uv_offset;
- const int mb_y = ctx->mb_y_;
- const int is_first_row = (mb_y == 0);
- const int is_last_row = (mb_y >= dec->br_mb_y_ - 1);
-
- if (dec->mt_method_ == 2) {
- ReconstructRow(dec, ctx);
- }
-
- if (ctx->filter_row_) {
- FilterRow(dec);
- }
-
- if (dec->dither_) {
- DitherRow(dec);
- }
-
- if (io->put != NULL) {
- int y_start = MACROBLOCK_VPOS(mb_y);
- int y_end = MACROBLOCK_VPOS(mb_y + 1);
- if (!is_first_row) {
- y_start -= extra_y_rows;
- io->y = ydst;
- io->u = udst;
- io->v = vdst;
- } else {
- io->y = dec->cache_y_ + y_offset;
- io->u = dec->cache_u_ + uv_offset;
- io->v = dec->cache_v_ + uv_offset;
- }
-
- if (!is_last_row) {
- y_end -= extra_y_rows;
- }
- if (y_end > io->crop_bottom) {
- y_end = io->crop_bottom; // make sure we don't overflow on last row.
- }
- io->a = NULL;
- if (dec->alpha_data_ != NULL && y_start < y_end) {
- // TODO(skal): testing presence of alpha with dec->alpha_data_ is not a
- // good idea.
- io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start);
- if (io->a == NULL) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "Could not decode alpha data.");
- }
- }
- if (y_start < io->crop_top) {
- const int delta_y = io->crop_top - y_start;
- y_start = io->crop_top;
- assert(!(delta_y & 1));
- io->y += dec->cache_y_stride_ * delta_y;
- io->u += dec->cache_uv_stride_ * (delta_y >> 1);
- io->v += dec->cache_uv_stride_ * (delta_y >> 1);
- if (io->a != NULL) {
- io->a += io->width * delta_y;
- }
- }
- if (y_start < y_end) {
- io->y += io->crop_left;
- io->u += io->crop_left >> 1;
- io->v += io->crop_left >> 1;
- if (io->a != NULL) {
- io->a += io->crop_left;
- }
- io->mb_y = y_start - io->crop_top;
- io->mb_w = io->crop_right - io->crop_left;
- io->mb_h = y_end - y_start;
- ok = io->put(io);
- }
- }
- // rotate top samples if needed
- if (cache_id + 1 == dec->num_caches_) {
- if (!is_last_row) {
- memcpy(dec->cache_y_ - ysize, ydst + 16 * dec->cache_y_stride_, ysize);
- memcpy(dec->cache_u_ - uvsize, udst + 8 * dec->cache_uv_stride_, uvsize);
- memcpy(dec->cache_v_ - uvsize, vdst + 8 * dec->cache_uv_stride_, uvsize);
- }
- }
-
- return ok;
-}
-
-#undef MACROBLOCK_VPOS
-
-//------------------------------------------------------------------------------
-
-int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 1;
- VP8ThreadContext* const ctx = &dec->thread_ctx_;
- const int filter_row =
- (dec->filter_type_ > 0) &&
- (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_);
- if (dec->mt_method_ == 0) {
- // ctx->id_ and ctx->f_info_ are already set
- ctx->mb_y_ = dec->mb_y_;
- ctx->filter_row_ = filter_row;
- ReconstructRow(dec, ctx);
- ok = FinishRow(dec, io);
- } else {
- WebPWorker* const worker = &dec->worker_;
- // Finish previous job *before* updating context
- ok &= WebPGetWorkerInterface()->Sync(worker);
- assert(worker->status_ == OK);
- if (ok) { // spawn a new deblocking/output job
- ctx->io_ = *io;
- ctx->id_ = dec->cache_id_;
- ctx->mb_y_ = dec->mb_y_;
- ctx->filter_row_ = filter_row;
- if (dec->mt_method_ == 2) { // swap macroblock data
- VP8MBData* const tmp = ctx->mb_data_;
- ctx->mb_data_ = dec->mb_data_;
- dec->mb_data_ = tmp;
- } else {
- // perform reconstruction directly in main thread
- ReconstructRow(dec, ctx);
- }
- if (filter_row) { // swap filter info
- VP8FInfo* const tmp = ctx->f_info_;
- ctx->f_info_ = dec->f_info_;
- dec->f_info_ = tmp;
- }
- // (reconstruct)+filter in parallel
- WebPGetWorkerInterface()->Launch(worker);
- if (++dec->cache_id_ == dec->num_caches_) {
- dec->cache_id_ = 0;
- }
- }
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// Finish setting up the decoding parameter once user's setup() is called.
-
-VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
- // Call setup() first. This may trigger additional decoding features on 'io'.
- // Note: Afterward, we must call teardown() no matter what.
- if (io->setup != NULL && !io->setup(io)) {
- VP8SetError(dec, VP8_STATUS_USER_ABORT, "Frame setup failed");
- return dec->status_;
- }
-
- // Disable filtering per user request
- if (io->bypass_filtering) {
- dec->filter_type_ = 0;
- }
- // TODO(skal): filter type / strength / sharpness forcing
-
- // Define the area where we can skip in-loop filtering, in case of cropping.
- //
- // 'Simple' filter reads two luma samples outside of the macroblock
- // and filters one. It doesn't filter the chroma samples. Hence, we can
- // avoid doing the in-loop filtering before crop_top/crop_left position.
- // For the 'Complex' filter, 3 samples are read and up to 3 are filtered.
- // Means: there's a dependency chain that goes all the way up to the
- // top-left corner of the picture (MB #0). We must filter all the previous
- // macroblocks.
- // TODO(skal): add an 'approximate_decoding' option, that won't produce
- // a 1:1 bit-exactness for complex filtering?
- {
- const int extra_pixels = kFilterExtraRows[dec->filter_type_];
- if (dec->filter_type_ == 2) {
- // For complex filter, we need to preserve the dependency chain.
- dec->tl_mb_x_ = 0;
- dec->tl_mb_y_ = 0;
- } else {
- // For simple filter, we can filter only the cropped region.
- // We include 'extra_pixels' on the other side of the boundary, since
- // vertical or horizontal filtering of the previous macroblock can
- // modify some abutting pixels.
- dec->tl_mb_x_ = (io->crop_left - extra_pixels) >> 4;
- dec->tl_mb_y_ = (io->crop_top - extra_pixels) >> 4;
- if (dec->tl_mb_x_ < 0) dec->tl_mb_x_ = 0;
- if (dec->tl_mb_y_ < 0) dec->tl_mb_y_ = 0;
- }
- // We need some 'extra' pixels on the right/bottom.
- dec->br_mb_y_ = (io->crop_bottom + 15 + extra_pixels) >> 4;
- dec->br_mb_x_ = (io->crop_right + 15 + extra_pixels) >> 4;
- if (dec->br_mb_x_ > dec->mb_w_) {
- dec->br_mb_x_ = dec->mb_w_;
- }
- if (dec->br_mb_y_ > dec->mb_h_) {
- dec->br_mb_y_ = dec->mb_h_;
- }
- }
- PrecomputeFilterStrengths(dec);
- return VP8_STATUS_OK;
-}
-
-int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 1;
- if (dec->mt_method_ > 0) {
- ok = WebPGetWorkerInterface()->Sync(&dec->worker_);
- }
-
- if (io->teardown != NULL) {
- io->teardown(io);
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// For multi-threaded decoding we need to use 3 rows of 16 pixels as delay line.
-//
-// Reason is: the deblocking filter cannot deblock the bottom horizontal edges
-// immediately, and needs to wait for first few rows of the next macroblock to
-// be decoded. Hence, deblocking is lagging behind by 4 or 8 pixels (depending
-// on strength).
-// With two threads, the vertical positions of the rows being decoded are:
-// Decode: [ 0..15][16..31][32..47][48..63][64..79][...
-// Deblock: [ 0..11][12..27][28..43][44..59][...
-// If we use two threads and two caches of 16 pixels, the sequence would be:
-// Decode: [ 0..15][16..31][ 0..15!!][16..31][ 0..15][...
-// Deblock: [ 0..11][12..27!!][-4..11][12..27][...
-// The problem occurs during row [12..15!!] that both the decoding and
-// deblocking threads are writing simultaneously.
-// With 3 cache lines, one get a safe write pattern:
-// Decode: [ 0..15][16..31][32..47][ 0..15][16..31][32..47][0..
-// Deblock: [ 0..11][12..27][28..43][-4..11][12..27][28...
-// Note that multi-threaded output _without_ deblocking can make use of two
-// cache lines of 16 pixels only, since there's no lagging behind. The decoding
-// and output process have non-concurrent writing:
-// Decode: [ 0..15][16..31][ 0..15][16..31][...
-// io->put: [ 0..15][16..31][ 0..15][...
-
-#define MT_CACHE_LINES 3
-#define ST_CACHE_LINES 1 // 1 cache row only for single-threaded case
-
-// Initialize multi/single-thread worker
-static int InitThreadContext(VP8Decoder* const dec) {
- dec->cache_id_ = 0;
- if (dec->mt_method_ > 0) {
- WebPWorker* const worker = &dec->worker_;
- if (!WebPGetWorkerInterface()->Reset(worker)) {
- return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
- "thread initialization failed.");
- }
- worker->data1 = dec;
- worker->data2 = (void*)&dec->thread_ctx_.io_;
- worker->hook = (WebPWorkerHook)FinishRow;
- dec->num_caches_ =
- (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1;
- } else {
- dec->num_caches_ = ST_CACHE_LINES;
- }
- return 1;
-}
-
-int VP8GetThreadMethod(const WebPDecoderOptions* const options,
- const WebPHeaderStructure* const headers,
- int width, int height) {
- if (options == NULL || options->use_threads == 0) {
- return 0;
- }
- (void)headers;
- (void)width;
- (void)height;
- assert(headers == NULL || !headers->is_lossless);
-#if defined(WEBP_USE_THREAD)
- if (width < MIN_WIDTH_FOR_THREADS) return 0;
- // TODO(skal): tune the heuristic further
-#if 0
- if (height < 2 * width) return 2;
-#endif
- return 2;
-#else // !WEBP_USE_THREAD
- return 0;
-#endif
-}
-
-#undef MT_CACHE_LINES
-#undef ST_CACHE_LINES
-
-//------------------------------------------------------------------------------
-// Memory setup
-
-static int AllocateMemory(VP8Decoder* const dec) {
- const int num_caches = dec->num_caches_;
- const int mb_w = dec->mb_w_;
- // Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise.
- const size_t intra_pred_mode_size = 4 * mb_w * sizeof(uint8_t);
- const size_t top_size = sizeof(VP8TopSamples) * mb_w;
- const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB);
- const size_t f_info_size =
- (dec->filter_type_ > 0) ?
- mb_w * (dec->mt_method_ > 0 ? 2 : 1) * sizeof(VP8FInfo)
- : 0;
- const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_);
- const size_t mb_data_size =
- (dec->mt_method_ == 2 ? 2 : 1) * mb_w * sizeof(*dec->mb_data_);
- const size_t cache_height = (16 * num_caches
- + kFilterExtraRows[dec->filter_type_]) * 3 / 2;
- const size_t cache_size = top_size * cache_height;
- // alpha_size is the only one that scales as width x height.
- const uint64_t alpha_size = (dec->alpha_data_ != NULL) ?
- (uint64_t)dec->pic_hdr_.width_ * dec->pic_hdr_.height_ : 0ULL;
- const uint64_t needed = (uint64_t)intra_pred_mode_size
- + top_size + mb_info_size + f_info_size
- + yuv_size + mb_data_size
- + cache_size + alpha_size + WEBP_ALIGN_CST;
- uint8_t* mem;
-
- if (needed != (size_t)needed) return 0; // check for overflow
- if (needed > dec->mem_size_) {
- WebPSafeFree(dec->mem_);
- dec->mem_size_ = 0;
- dec->mem_ = WebPSafeMalloc(needed, sizeof(uint8_t));
- if (dec->mem_ == NULL) {
- return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
- "no memory during frame initialization.");
- }
- // down-cast is ok, thanks to WebPSafeAlloc() above.
- dec->mem_size_ = (size_t)needed;
- }
-
- mem = (uint8_t*)dec->mem_;
- dec->intra_t_ = (uint8_t*)mem;
- mem += intra_pred_mode_size;
-
- dec->yuv_t_ = (VP8TopSamples*)mem;
- mem += top_size;
-
- dec->mb_info_ = ((VP8MB*)mem) + 1;
- mem += mb_info_size;
-
- dec->f_info_ = f_info_size ? (VP8FInfo*)mem : NULL;
- mem += f_info_size;
- dec->thread_ctx_.id_ = 0;
- dec->thread_ctx_.f_info_ = dec->f_info_;
- if (dec->mt_method_ > 0) {
- // secondary cache line. The deblocking process need to make use of the
- // filtering strength from previous macroblock row, while the new ones
- // are being decoded in parallel. We'll just swap the pointers.
- dec->thread_ctx_.f_info_ += mb_w;
- }
-
- mem = (uint8_t*)WEBP_ALIGN(mem);
- assert((yuv_size & WEBP_ALIGN_CST) == 0);
- dec->yuv_b_ = (uint8_t*)mem;
- mem += yuv_size;
-
- dec->mb_data_ = (VP8MBData*)mem;
- dec->thread_ctx_.mb_data_ = (VP8MBData*)mem;
- if (dec->mt_method_ == 2) {
- dec->thread_ctx_.mb_data_ += mb_w;
- }
- mem += mb_data_size;
-
- dec->cache_y_stride_ = 16 * mb_w;
- dec->cache_uv_stride_ = 8 * mb_w;
- {
- const int extra_rows = kFilterExtraRows[dec->filter_type_];
- const int extra_y = extra_rows * dec->cache_y_stride_;
- const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_;
- dec->cache_y_ = ((uint8_t*)mem) + extra_y;
- dec->cache_u_ = dec->cache_y_
- + 16 * num_caches * dec->cache_y_stride_ + extra_uv;
- dec->cache_v_ = dec->cache_u_
- + 8 * num_caches * dec->cache_uv_stride_ + extra_uv;
- dec->cache_id_ = 0;
- }
- mem += cache_size;
-
- // alpha plane
- dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL;
- mem += alpha_size;
- assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_);
-
- // note: left/top-info is initialized once for all.
- memset(dec->mb_info_ - 1, 0, mb_info_size);
- VP8InitScanline(dec); // initialize left too.
-
- // initialize top
- memset(dec->intra_t_, B_DC_PRED, intra_pred_mode_size);
-
- return 1;
-}
-
-static void InitIo(VP8Decoder* const dec, VP8Io* io) {
- // prepare 'io'
- io->mb_y = 0;
- io->y = dec->cache_y_;
- io->u = dec->cache_u_;
- io->v = dec->cache_v_;
- io->y_stride = dec->cache_y_stride_;
- io->uv_stride = dec->cache_uv_stride_;
- io->a = NULL;
-}
-
-int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io) {
- if (!InitThreadContext(dec)) return 0; // call first. Sets dec->num_caches_.
- if (!AllocateMemory(dec)) return 0;
- InitIo(dec, io);
- VP8DspInit(); // Init critical function pointers and look-up tables.
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dec/idec.c b/drivers/webp/dec/idec.c
deleted file mode 100644
index 8de131916e..0000000000
--- a/drivers/webp/dec/idec.c
+++ /dev/null
@@ -1,892 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Incremental decoding
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "./alphai.h"
-#include "./webpi.h"
-#include "./vp8i.h"
-#include "../utils/utils.h"
-
-// In append mode, buffer allocations increase as multiples of this value.
-// Needs to be a power of 2.
-#define CHUNK_SIZE 4096
-#define MAX_MB_SIZE 4096
-
-//------------------------------------------------------------------------------
-// Data structures for memory and states
-
-// Decoding states. State normally flows as:
-// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and
-// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image.
-// If there is any error the decoder goes into state ERROR.
-typedef enum {
- STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk.
- STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk).
- STATE_VP8_PARTS0,
- STATE_VP8_DATA,
- STATE_VP8L_HEADER,
- STATE_VP8L_DATA,
- STATE_DONE,
- STATE_ERROR
-} DecState;
-
-// Operating state for the MemBuffer
-typedef enum {
- MEM_MODE_NONE = 0,
- MEM_MODE_APPEND,
- MEM_MODE_MAP
-} MemBufferMode;
-
-// storage for partition #0 and partial data (in a rolling fashion)
-typedef struct {
- MemBufferMode mode_; // Operation mode
- size_t start_; // start location of the data to be decoded
- size_t end_; // end location
- size_t buf_size_; // size of the allocated buffer
- uint8_t* buf_; // We don't own this buffer in case WebPIUpdate()
-
- size_t part0_size_; // size of partition #0
- const uint8_t* part0_buf_; // buffer to store partition #0
-} MemBuffer;
-
-struct WebPIDecoder {
- DecState state_; // current decoding state
- WebPDecParams params_; // Params to store output info
- int is_lossless_; // for down-casting 'dec_'.
- void* dec_; // either a VP8Decoder or a VP8LDecoder instance
- VP8Io io_;
-
- MemBuffer mem_; // input memory buffer.
- WebPDecBuffer output_; // output buffer (when no external one is supplied,
- // or if the external one has slow-memory)
- WebPDecBuffer* final_output_; // Slow-memory output to copy to eventually.
- size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header.
-
- int last_mb_y_; // last row reached for intra-mode decoding
-};
-
-// MB context to restore in case VP8DecodeMB() fails
-typedef struct {
- VP8MB left_;
- VP8MB info_;
- VP8BitReader token_br_;
-} MBContext;
-
-//------------------------------------------------------------------------------
-// MemBuffer: incoming data handling
-
-static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) {
- return (mem->end_ - mem->start_);
-}
-
-// Check if we need to preserve the compressed alpha data, as it may not have
-// been decoded yet.
-static int NeedCompressedAlpha(const WebPIDecoder* const idec) {
- if (idec->state_ == STATE_WEBP_HEADER) {
- // We haven't parsed the headers yet, so we don't know whether the image is
- // lossy or lossless. This also means that we haven't parsed the ALPH chunk.
- return 0;
- }
- if (idec->is_lossless_) {
- return 0; // ALPH chunk is not present for lossless images.
- } else {
- const VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- assert(dec != NULL); // Must be true as idec->state_ != STATE_WEBP_HEADER.
- return (dec->alpha_data_ != NULL) && !dec->is_alpha_decoded_;
- }
-}
-
-static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
- MemBuffer* const mem = &idec->mem_;
- const uint8_t* const new_base = mem->buf_ + mem->start_;
- // note: for VP8, setting up idec->io_ is only really needed at the beginning
- // of the decoding, till partition #0 is complete.
- idec->io_.data = new_base;
- idec->io_.data_size = MemDataSize(mem);
-
- if (idec->dec_ != NULL) {
- if (!idec->is_lossless_) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- const uint32_t last_part = dec->num_parts_minus_one_;
- if (offset != 0) {
- uint32_t p;
- for (p = 0; p <= last_part; ++p) {
- VP8RemapBitReader(dec->parts_ + p, offset);
- }
- // Remap partition #0 data pointer to new offset, but only in MAP
- // mode (in APPEND mode, partition #0 is copied into a fixed memory).
- if (mem->mode_ == MEM_MODE_MAP) {
- VP8RemapBitReader(&dec->br_, offset);
- }
- }
- {
- const uint8_t* const last_start = dec->parts_[last_part].buf_;
- VP8BitReaderSetBuffer(&dec->parts_[last_part], last_start,
- mem->buf_ + mem->end_ - last_start);
- }
- if (NeedCompressedAlpha(idec)) {
- ALPHDecoder* const alph_dec = dec->alph_dec_;
- dec->alpha_data_ += offset;
- if (alph_dec != NULL) {
- if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) {
- VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_;
- assert(alph_vp8l_dec != NULL);
- assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN);
- VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_,
- dec->alpha_data_ + ALPHA_HEADER_LEN,
- dec->alpha_data_size_ - ALPHA_HEADER_LEN);
- } else { // alph_dec->method_ == ALPHA_NO_COMPRESSION
- // Nothing special to do in this case.
- }
- }
- }
- } else { // Resize lossless bitreader
- VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
- VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem));
- }
- }
-}
-
-// Appends data to the end of MemBuffer->buf_. It expands the allocated memory
-// size if required and also updates VP8BitReader's if new memory is allocated.
-static int AppendToMemBuffer(WebPIDecoder* const idec,
- const uint8_t* const data, size_t data_size) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- MemBuffer* const mem = &idec->mem_;
- const int need_compressed_alpha = NeedCompressedAlpha(idec);
- const uint8_t* const old_start = mem->buf_ + mem->start_;
- const uint8_t* const old_base =
- need_compressed_alpha ? dec->alpha_data_ : old_start;
- assert(mem->mode_ == MEM_MODE_APPEND);
- if (data_size > MAX_CHUNK_PAYLOAD) {
- // security safeguard: trying to allocate more than what the format
- // allows for a chunk should be considered a smoke smell.
- return 0;
- }
-
- if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory
- const size_t new_mem_start = old_start - old_base;
- const size_t current_size = MemDataSize(mem) + new_mem_start;
- const uint64_t new_size = (uint64_t)current_size + data_size;
- const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1);
- uint8_t* const new_buf =
- (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
- if (new_buf == NULL) return 0;
- memcpy(new_buf, old_base, current_size);
- WebPSafeFree(mem->buf_);
- mem->buf_ = new_buf;
- mem->buf_size_ = (size_t)extra_size;
- mem->start_ = new_mem_start;
- mem->end_ = current_size;
- }
-
- memcpy(mem->buf_ + mem->end_, data, data_size);
- mem->end_ += data_size;
- assert(mem->end_ <= mem->buf_size_);
-
- DoRemap(idec, mem->buf_ + mem->start_ - old_start);
- return 1;
-}
-
-static int RemapMemBuffer(WebPIDecoder* const idec,
- const uint8_t* const data, size_t data_size) {
- MemBuffer* const mem = &idec->mem_;
- const uint8_t* const old_buf = mem->buf_;
- const uint8_t* const old_start = old_buf + mem->start_;
- assert(mem->mode_ == MEM_MODE_MAP);
-
- if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
-
- mem->buf_ = (uint8_t*)data;
- mem->end_ = mem->buf_size_ = data_size;
-
- DoRemap(idec, mem->buf_ + mem->start_ - old_start);
- return 1;
-}
-
-static void InitMemBuffer(MemBuffer* const mem) {
- mem->mode_ = MEM_MODE_NONE;
- mem->buf_ = NULL;
- mem->buf_size_ = 0;
- mem->part0_buf_ = NULL;
- mem->part0_size_ = 0;
-}
-
-static void ClearMemBuffer(MemBuffer* const mem) {
- assert(mem);
- if (mem->mode_ == MEM_MODE_APPEND) {
- WebPSafeFree(mem->buf_);
- WebPSafeFree((void*)mem->part0_buf_);
- }
-}
-
-static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) {
- if (mem->mode_ == MEM_MODE_NONE) {
- mem->mode_ = expected; // switch to the expected mode
- } else if (mem->mode_ != expected) {
- return 0; // we mixed the modes => error
- }
- assert(mem->mode_ == expected); // mode is ok
- return 1;
-}
-
-// To be called last.
-static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) {
- const WebPDecoderOptions* const options = idec->params_.options;
- WebPDecBuffer* const output = idec->params_.output;
-
- idec->state_ = STATE_DONE;
- if (options != NULL && options->flip) {
- const VP8StatusCode status = WebPFlipBuffer(output);
- if (status != VP8_STATUS_OK) return status;
- }
- if (idec->final_output_ != NULL) {
- WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy
- WebPFreeDecBuffer(&idec->output_);
- *output = *idec->final_output_;
- idec->final_output_ = NULL;
- }
- return VP8_STATUS_OK;
-}
-
-//------------------------------------------------------------------------------
-// Macroblock-decoding contexts
-
-static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br,
- MBContext* const context) {
- context->left_ = dec->mb_info_[-1];
- context->info_ = dec->mb_info_[dec->mb_x_];
- context->token_br_ = *token_br;
-}
-
-static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
- VP8BitReader* const token_br) {
- dec->mb_info_[-1] = context->left_;
- dec->mb_info_[dec->mb_x_] = context->info_;
- *token_br = context->token_br_;
-}
-
-//------------------------------------------------------------------------------
-
-static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
- if (idec->state_ == STATE_VP8_DATA) {
- VP8Io* const io = &idec->io_;
- if (io->teardown != NULL) {
- io->teardown(io);
- }
- }
- idec->state_ = STATE_ERROR;
- return error;
-}
-
-static void ChangeState(WebPIDecoder* const idec, DecState new_state,
- size_t consumed_bytes) {
- MemBuffer* const mem = &idec->mem_;
- idec->state_ = new_state;
- mem->start_ += consumed_bytes;
- assert(mem->start_ <= mem->end_);
- idec->io_.data = mem->buf_ + mem->start_;
- idec->io_.data_size = MemDataSize(mem);
-}
-
-// Headers
-static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) {
- MemBuffer* const mem = &idec->mem_;
- const uint8_t* data = mem->buf_ + mem->start_;
- size_t curr_size = MemDataSize(mem);
- VP8StatusCode status;
- WebPHeaderStructure headers;
-
- headers.data = data;
- headers.data_size = curr_size;
- headers.have_all_data = 0;
- status = WebPParseHeaders(&headers);
- if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet.
- } else if (status != VP8_STATUS_OK) {
- return IDecError(idec, status);
- }
-
- idec->chunk_size_ = headers.compressed_size;
- idec->is_lossless_ = headers.is_lossless;
- if (!idec->is_lossless_) {
- VP8Decoder* const dec = VP8New();
- if (dec == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- idec->dec_ = dec;
- dec->alpha_data_ = headers.alpha_data;
- dec->alpha_data_size_ = headers.alpha_data_size;
- ChangeState(idec, STATE_VP8_HEADER, headers.offset);
- } else {
- VP8LDecoder* const dec = VP8LNew();
- if (dec == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- idec->dec_ = dec;
- ChangeState(idec, STATE_VP8L_HEADER, headers.offset);
- }
- return VP8_STATUS_OK;
-}
-
-static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) {
- const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_;
- const size_t curr_size = MemDataSize(&idec->mem_);
- int width, height;
- uint32_t bits;
-
- if (curr_size < VP8_FRAME_HEADER_SIZE) {
- // Not enough data bytes to extract VP8 Frame Header.
- return VP8_STATUS_SUSPENDED;
- }
- if (!VP8GetInfo(data, curr_size, idec->chunk_size_, &width, &height)) {
- return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
- }
-
- bits = data[0] | (data[1] << 8) | (data[2] << 16);
- idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE;
-
- idec->io_.data = data;
- idec->io_.data_size = curr_size;
- idec->state_ = STATE_VP8_PARTS0;
- return VP8_STATUS_OK;
-}
-
-// Partition #0
-static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- VP8BitReader* const br = &dec->br_;
- const size_t part_size = br->buf_end_ - br->buf_;
- MemBuffer* const mem = &idec->mem_;
- assert(!idec->is_lossless_);
- assert(mem->part0_buf_ == NULL);
- // the following is a format limitation, no need for runtime check:
- assert(part_size <= mem->part0_size_);
- if (part_size == 0) { // can't have zero-size partition #0
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- if (mem->mode_ == MEM_MODE_APPEND) {
- // We copy and grab ownership of the partition #0 data.
- uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size);
- if (part0_buf == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- memcpy(part0_buf, br->buf_, part_size);
- mem->part0_buf_ = part0_buf;
- VP8BitReaderSetBuffer(br, part0_buf, part_size);
- } else {
- // Else: just keep pointers to the partition #0's data in dec_->br_.
- }
- mem->start_ += part_size;
- return VP8_STATUS_OK;
-}
-
-static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- VP8Io* const io = &idec->io_;
- const WebPDecParams* const params = &idec->params_;
- WebPDecBuffer* const output = params->output;
-
- // Wait till we have enough data for the whole partition #0
- if (MemDataSize(&idec->mem_) < idec->mem_.part0_size_) {
- return VP8_STATUS_SUSPENDED;
- }
-
- if (!VP8GetHeaders(dec, io)) {
- const VP8StatusCode status = dec->status_;
- if (status == VP8_STATUS_SUSPENDED ||
- status == VP8_STATUS_NOT_ENOUGH_DATA) {
- // treating NOT_ENOUGH_DATA as SUSPENDED state
- return VP8_STATUS_SUSPENDED;
- }
- return IDecError(idec, status);
- }
-
- // Allocate/Verify output buffer now
- dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options,
- output);
- if (dec->status_ != VP8_STATUS_OK) {
- return IDecError(idec, dec->status_);
- }
- // This change must be done before calling VP8InitFrame()
- dec->mt_method_ = VP8GetThreadMethod(params->options, NULL,
- io->width, io->height);
- VP8InitDithering(params->options, dec);
-
- dec->status_ = CopyParts0Data(idec);
- if (dec->status_ != VP8_STATUS_OK) {
- return IDecError(idec, dec->status_);
- }
-
- // Finish setting up the decoding parameters. Will call io->setup().
- if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) {
- return IDecError(idec, dec->status_);
- }
-
- // Note: past this point, teardown() must always be called
- // in case of error.
- idec->state_ = STATE_VP8_DATA;
- // Allocate memory and prepare everything.
- if (!VP8InitFrame(dec, io)) {
- return IDecError(idec, dec->status_);
- }
- return VP8_STATUS_OK;
-}
-
-// Remaining partitions
-static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- VP8Io* const io = &idec->io_;
-
- assert(dec->ready_);
- for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
- if (idec->last_mb_y_ != dec->mb_y_) {
- if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
- // note: normally, error shouldn't occur since we already have the whole
- // partition0 available here in DecodeRemaining(). Reaching EOF while
- // reading intra modes really means a BITSTREAM_ERROR.
- return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
- }
- idec->last_mb_y_ = dec->mb_y_;
- }
- for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) {
- VP8BitReader* const token_br =
- &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_];
- MBContext context;
- SaveContext(dec, token_br, &context);
- if (!VP8DecodeMB(dec, token_br)) {
- // We shouldn't fail when MAX_MB data was available
- if (dec->num_parts_minus_one_ == 0 &&
- MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
- return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
- }
- RestoreContext(&context, dec, token_br);
- return VP8_STATUS_SUSPENDED;
- }
- // Release buffer only if there is only one partition
- if (dec->num_parts_minus_one_ == 0) {
- idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_;
- assert(idec->mem_.start_ <= idec->mem_.end_);
- }
- }
- VP8InitScanline(dec); // Prepare for next scanline
-
- // Reconstruct, filter and emit the row.
- if (!VP8ProcessRow(dec, io)) {
- return IDecError(idec, VP8_STATUS_USER_ABORT);
- }
- }
- // Synchronize the thread and check for errors.
- if (!VP8ExitCritical(dec, io)) {
- return IDecError(idec, VP8_STATUS_USER_ABORT);
- }
- dec->ready_ = 0;
- return FinishDecoding(idec);
-}
-
-static VP8StatusCode ErrorStatusLossless(WebPIDecoder* const idec,
- VP8StatusCode status) {
- if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return VP8_STATUS_SUSPENDED;
- }
- return IDecError(idec, status);
-}
-
-static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) {
- VP8Io* const io = &idec->io_;
- VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
- const WebPDecParams* const params = &idec->params_;
- WebPDecBuffer* const output = params->output;
- size_t curr_size = MemDataSize(&idec->mem_);
- assert(idec->is_lossless_);
-
- // Wait until there's enough data for decoding header.
- if (curr_size < (idec->chunk_size_ >> 3)) {
- dec->status_ = VP8_STATUS_SUSPENDED;
- return ErrorStatusLossless(idec, dec->status_);
- }
-
- if (!VP8LDecodeHeader(dec, io)) {
- if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR &&
- curr_size < idec->chunk_size_) {
- dec->status_ = VP8_STATUS_SUSPENDED;
- }
- return ErrorStatusLossless(idec, dec->status_);
- }
- // Allocate/verify output buffer now.
- dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options,
- output);
- if (dec->status_ != VP8_STATUS_OK) {
- return IDecError(idec, dec->status_);
- }
-
- idec->state_ = STATE_VP8L_DATA;
- return VP8_STATUS_OK;
-}
-
-static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) {
- VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
- const size_t curr_size = MemDataSize(&idec->mem_);
- assert(idec->is_lossless_);
-
- // Switch to incremental decoding if we don't have all the bytes available.
- dec->incremental_ = (curr_size < idec->chunk_size_);
-
- if (!VP8LDecodeImage(dec)) {
- return ErrorStatusLossless(idec, dec->status_);
- }
- assert(dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED);
- return (dec->status_ == VP8_STATUS_SUSPENDED) ? dec->status_
- : FinishDecoding(idec);
-}
-
- // Main decoding loop
-static VP8StatusCode IDecode(WebPIDecoder* idec) {
- VP8StatusCode status = VP8_STATUS_SUSPENDED;
-
- if (idec->state_ == STATE_WEBP_HEADER) {
- status = DecodeWebPHeaders(idec);
- } else {
- if (idec->dec_ == NULL) {
- return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
- }
- }
- if (idec->state_ == STATE_VP8_HEADER) {
- status = DecodeVP8FrameHeader(idec);
- }
- if (idec->state_ == STATE_VP8_PARTS0) {
- status = DecodePartition0(idec);
- }
- if (idec->state_ == STATE_VP8_DATA) {
- status = DecodeRemaining(idec);
- }
- if (idec->state_ == STATE_VP8L_HEADER) {
- status = DecodeVP8LHeader(idec);
- }
- if (idec->state_ == STATE_VP8L_DATA) {
- status = DecodeVP8LData(idec);
- }
- return status;
-}
-
-//------------------------------------------------------------------------------
-// Internal constructor
-
-static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer,
- const WebPBitstreamFeatures* const features) {
- WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec));
- if (idec == NULL) {
- return NULL;
- }
-
- idec->state_ = STATE_WEBP_HEADER;
- idec->chunk_size_ = 0;
-
- idec->last_mb_y_ = -1;
-
- InitMemBuffer(&idec->mem_);
- WebPInitDecBuffer(&idec->output_);
- VP8InitIo(&idec->io_);
-
- WebPResetDecParams(&idec->params_);
- if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) {
- idec->params_.output = &idec->output_;
- idec->final_output_ = output_buffer;
- if (output_buffer != NULL) {
- idec->params_.output->colorspace = output_buffer->colorspace;
- }
- } else {
- idec->params_.output = output_buffer;
- idec->final_output_ = NULL;
- }
- WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions.
-
- return idec;
-}
-
-//------------------------------------------------------------------------------
-// Public functions
-
-WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) {
- return NewDecoder(output_buffer, NULL);
-}
-
-WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size,
- WebPDecoderConfig* config) {
- WebPIDecoder* idec;
- WebPBitstreamFeatures tmp_features;
- WebPBitstreamFeatures* const features =
- (config == NULL) ? &tmp_features : &config->input;
- memset(&tmp_features, 0, sizeof(tmp_features));
-
- // Parse the bitstream's features, if requested:
- if (data != NULL && data_size > 0) {
- if (WebPGetFeatures(data, data_size, features) != VP8_STATUS_OK) {
- return NULL;
- }
- }
-
- // Create an instance of the incremental decoder
- idec = (config != NULL) ? NewDecoder(&config->output, features)
- : NewDecoder(NULL, features);
- if (idec == NULL) {
- return NULL;
- }
- // Finish initialization
- if (config != NULL) {
- idec->params_.options = &config->options;
- }
- return idec;
-}
-
-void WebPIDelete(WebPIDecoder* idec) {
- if (idec == NULL) return;
- if (idec->dec_ != NULL) {
- if (!idec->is_lossless_) {
- if (idec->state_ == STATE_VP8_DATA) {
- // Synchronize the thread, clean-up and check for errors.
- VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
- }
- VP8Delete((VP8Decoder*)idec->dec_);
- } else {
- VP8LDelete((VP8LDecoder*)idec->dec_);
- }
- }
- ClearMemBuffer(&idec->mem_);
- WebPFreeDecBuffer(&idec->output_);
- WebPSafeFree(idec);
-}
-
-//------------------------------------------------------------------------------
-// Wrapper toward WebPINewDecoder
-
-WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer,
- size_t output_buffer_size, int output_stride) {
- const int is_external_memory = (output_buffer != NULL) ? 1 : 0;
- WebPIDecoder* idec;
-
- if (mode >= MODE_YUV) return NULL;
- if (is_external_memory == 0) { // Overwrite parameters to sane values.
- output_buffer_size = 0;
- output_stride = 0;
- } else { // A buffer was passed. Validate the other params.
- if (output_stride == 0 || output_buffer_size == 0) {
- return NULL; // invalid parameter.
- }
- }
- idec = WebPINewDecoder(NULL);
- if (idec == NULL) return NULL;
- idec->output_.colorspace = mode;
- idec->output_.is_external_memory = is_external_memory;
- idec->output_.u.RGBA.rgba = output_buffer;
- idec->output_.u.RGBA.stride = output_stride;
- idec->output_.u.RGBA.size = output_buffer_size;
- return idec;
-}
-
-WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride,
- uint8_t* a, size_t a_size, int a_stride) {
- const int is_external_memory = (luma != NULL) ? 1 : 0;
- WebPIDecoder* idec;
- WEBP_CSP_MODE colorspace;
-
- if (is_external_memory == 0) { // Overwrite parameters to sane values.
- luma_size = u_size = v_size = a_size = 0;
- luma_stride = u_stride = v_stride = a_stride = 0;
- u = v = a = NULL;
- colorspace = MODE_YUVA;
- } else { // A luma buffer was passed. Validate the other parameters.
- if (u == NULL || v == NULL) return NULL;
- if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL;
- if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL;
- if (a != NULL) {
- if (a_size == 0 || a_stride == 0) return NULL;
- }
- colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA;
- }
-
- idec = WebPINewDecoder(NULL);
- if (idec == NULL) return NULL;
-
- idec->output_.colorspace = colorspace;
- idec->output_.is_external_memory = is_external_memory;
- idec->output_.u.YUVA.y = luma;
- idec->output_.u.YUVA.y_stride = luma_stride;
- idec->output_.u.YUVA.y_size = luma_size;
- idec->output_.u.YUVA.u = u;
- idec->output_.u.YUVA.u_stride = u_stride;
- idec->output_.u.YUVA.u_size = u_size;
- idec->output_.u.YUVA.v = v;
- idec->output_.u.YUVA.v_stride = v_stride;
- idec->output_.u.YUVA.v_size = v_size;
- idec->output_.u.YUVA.a = a;
- idec->output_.u.YUVA.a_stride = a_stride;
- idec->output_.u.YUVA.a_size = a_size;
- return idec;
-}
-
-WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride) {
- return WebPINewYUVA(luma, luma_size, luma_stride,
- u, u_size, u_stride,
- v, v_size, v_stride,
- NULL, 0, 0);
-}
-
-//------------------------------------------------------------------------------
-
-static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) {
- assert(idec);
- if (idec->state_ == STATE_ERROR) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- if (idec->state_ == STATE_DONE) {
- return VP8_STATUS_OK;
- }
- return VP8_STATUS_SUSPENDED;
-}
-
-VP8StatusCode WebPIAppend(WebPIDecoder* idec,
- const uint8_t* data, size_t data_size) {
- VP8StatusCode status;
- if (idec == NULL || data == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
- status = IDecCheckStatus(idec);
- if (status != VP8_STATUS_SUSPENDED) {
- return status;
- }
- // Check mixed calls between RemapMemBuffer and AppendToMemBuffer.
- if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) {
- return VP8_STATUS_INVALID_PARAM;
- }
- // Append data to memory buffer
- if (!AppendToMemBuffer(idec, data, data_size)) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- return IDecode(idec);
-}
-
-VP8StatusCode WebPIUpdate(WebPIDecoder* idec,
- const uint8_t* data, size_t data_size) {
- VP8StatusCode status;
- if (idec == NULL || data == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
- status = IDecCheckStatus(idec);
- if (status != VP8_STATUS_SUSPENDED) {
- return status;
- }
- // Check mixed calls between RemapMemBuffer and AppendToMemBuffer.
- if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) {
- return VP8_STATUS_INVALID_PARAM;
- }
- // Make the memory buffer point to the new buffer
- if (!RemapMemBuffer(idec, data, data_size)) {
- return VP8_STATUS_INVALID_PARAM;
- }
- return IDecode(idec);
-}
-
-//------------------------------------------------------------------------------
-
-static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) {
- if (idec == NULL || idec->dec_ == NULL) {
- return NULL;
- }
- if (idec->state_ <= STATE_VP8_PARTS0) {
- return NULL;
- }
- if (idec->final_output_ != NULL) {
- return NULL; // not yet slow-copied
- }
- return idec->params_.output;
-}
-
-const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec,
- int* left, int* top,
- int* width, int* height) {
- const WebPDecBuffer* const src = GetOutputBuffer(idec);
- if (left != NULL) *left = 0;
- if (top != NULL) *top = 0;
- if (src != NULL) {
- if (width != NULL) *width = src->width;
- if (height != NULL) *height = idec->params_.last_y;
- } else {
- if (width != NULL) *width = 0;
- if (height != NULL) *height = 0;
- }
- return src;
-}
-
-uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
- int* width, int* height, int* stride) {
- const WebPDecBuffer* const src = GetOutputBuffer(idec);
- if (src == NULL) return NULL;
- if (src->colorspace >= MODE_YUV) {
- return NULL;
- }
-
- if (last_y != NULL) *last_y = idec->params_.last_y;
- if (width != NULL) *width = src->width;
- if (height != NULL) *height = src->height;
- if (stride != NULL) *stride = src->u.RGBA.stride;
-
- return src->u.RGBA.rgba;
-}
-
-uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
- uint8_t** u, uint8_t** v, uint8_t** a,
- int* width, int* height,
- int* stride, int* uv_stride, int* a_stride) {
- const WebPDecBuffer* const src = GetOutputBuffer(idec);
- if (src == NULL) return NULL;
- if (src->colorspace < MODE_YUV) {
- return NULL;
- }
-
- if (last_y != NULL) *last_y = idec->params_.last_y;
- if (u != NULL) *u = src->u.YUVA.u;
- if (v != NULL) *v = src->u.YUVA.v;
- if (a != NULL) *a = src->u.YUVA.a;
- if (width != NULL) *width = src->width;
- if (height != NULL) *height = src->height;
- if (stride != NULL) *stride = src->u.YUVA.y_stride;
- if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride;
- if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride;
-
- return src->u.YUVA.y;
-}
-
-int WebPISetIOHooks(WebPIDecoder* const idec,
- VP8IoPutHook put,
- VP8IoSetupHook setup,
- VP8IoTeardownHook teardown,
- void* user_data) {
- if (idec == NULL || idec->state_ > STATE_WEBP_HEADER) {
- return 0;
- }
-
- idec->io_.put = put;
- idec->io_.setup = setup;
- idec->io_.teardown = teardown;
- idec->io_.opaque = user_data;
-
- return 1;
-}
diff --git a/drivers/webp/dec/io.c b/drivers/webp/dec/io.c
deleted file mode 100644
index 8d5c43f325..0000000000
--- a/drivers/webp/dec/io.c
+++ /dev/null
@@ -1,624 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// functions for sample output.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include "../dec/vp8i.h"
-#include "./webpi.h"
-#include "../dsp/dsp.h"
-#include "../dsp/yuv.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// Main YUV<->RGB conversion functions
-
-static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
- WebPDecBuffer* output = p->output;
- const WebPYUVABuffer* const buf = &output->u.YUVA;
- uint8_t* const y_dst = buf->y + io->mb_y * buf->y_stride;
- uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_stride;
- uint8_t* const v_dst = buf->v + (io->mb_y >> 1) * buf->v_stride;
- const int mb_w = io->mb_w;
- const int mb_h = io->mb_h;
- const int uv_w = (mb_w + 1) / 2;
- const int uv_h = (mb_h + 1) / 2;
- int j;
- for (j = 0; j < mb_h; ++j) {
- memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w);
- }
- for (j = 0; j < uv_h; ++j) {
- memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w);
- memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w);
- }
- return io->mb_h;
-}
-
-// Point-sampling U/V sampler.
-static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
- WebPDecBuffer* const output = p->output;
- WebPRGBABuffer* const buf = &output->u.RGBA;
- uint8_t* const dst = buf->rgba + io->mb_y * buf->stride;
- WebPSamplerProcessPlane(io->y, io->y_stride,
- io->u, io->v, io->uv_stride,
- dst, buf->stride, io->mb_w, io->mb_h,
- WebPSamplers[output->colorspace]);
- return io->mb_h;
-}
-
-//------------------------------------------------------------------------------
-// Fancy upsampling
-
-#ifdef FANCY_UPSAMPLING
-static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
- int num_lines_out = io->mb_h; // a priori guess
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
- WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace];
- const uint8_t* cur_y = io->y;
- const uint8_t* cur_u = io->u;
- const uint8_t* cur_v = io->v;
- const uint8_t* top_u = p->tmp_u;
- const uint8_t* top_v = p->tmp_v;
- int y = io->mb_y;
- const int y_end = io->mb_y + io->mb_h;
- const int mb_w = io->mb_w;
- const int uv_w = (mb_w + 1) / 2;
-
- if (y == 0) {
- // First line is special cased. We mirror the u/v samples at boundary.
- upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w);
- } else {
- // We can finish the left-over line from previous call.
- upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
- dst - buf->stride, dst, mb_w);
- ++num_lines_out;
- }
- // Loop over each output pairs of row.
- for (; y + 2 < y_end; y += 2) {
- top_u = cur_u;
- top_v = cur_v;
- cur_u += io->uv_stride;
- cur_v += io->uv_stride;
- dst += 2 * buf->stride;
- cur_y += 2 * io->y_stride;
- upsample(cur_y - io->y_stride, cur_y,
- top_u, top_v, cur_u, cur_v,
- dst - buf->stride, dst, mb_w);
- }
- // move to last row
- cur_y += io->y_stride;
- if (io->crop_top + y_end < io->crop_bottom) {
- // Save the unfinished samples for next call (as we're not done yet).
- memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y));
- memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u));
- memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v));
- // The fancy upsampler leaves a row unfinished behind
- // (except for the very last row)
- num_lines_out--;
- } else {
- // Process the very last row of even-sized picture
- if (!(y_end & 1)) {
- upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v,
- dst + buf->stride, NULL, mb_w);
- }
- }
- return num_lines_out;
-}
-
-#endif /* FANCY_UPSAMPLING */
-
-//------------------------------------------------------------------------------
-
-static void FillAlphaPlane(uint8_t* dst, int w, int h, int stride) {
- int j;
- for (j = 0; j < h; ++j) {
- memset(dst, 0xff, w * sizeof(*dst));
- dst += stride;
- }
-}
-
-static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
- int expected_num_lines_out) {
- const uint8_t* alpha = io->a;
- const WebPYUVABuffer* const buf = &p->output->u.YUVA;
- const int mb_w = io->mb_w;
- const int mb_h = io->mb_h;
- uint8_t* dst = buf->a + io->mb_y * buf->a_stride;
- int j;
- (void)expected_num_lines_out;
- assert(expected_num_lines_out == mb_h);
- if (alpha != NULL) {
- for (j = 0; j < mb_h; ++j) {
- memcpy(dst, alpha, mb_w * sizeof(*dst));
- alpha += io->width;
- dst += buf->a_stride;
- }
- } else if (buf->a != NULL) {
- // the user requested alpha, but there is none, set it to opaque.
- FillAlphaPlane(dst, mb_w, mb_h, buf->a_stride);
- }
- return 0;
-}
-
-static int GetAlphaSourceRow(const VP8Io* const io,
- const uint8_t** alpha, int* const num_rows) {
- int start_y = io->mb_y;
- *num_rows = io->mb_h;
-
- // Compensate for the 1-line delay of the fancy upscaler.
- // This is similar to EmitFancyRGB().
- if (io->fancy_upsampling) {
- if (start_y == 0) {
- // We don't process the last row yet. It'll be done during the next call.
- --*num_rows;
- } else {
- --start_y;
- // Fortunately, *alpha data is persistent, so we can go back
- // one row and finish alpha blending, now that the fancy upscaler
- // completed the YUV->RGB interpolation.
- *alpha -= io->width;
- }
- if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) {
- // If it's the very last call, we process all the remaining rows!
- *num_rows = io->crop_bottom - io->crop_top - start_y;
- }
- }
- return start_y;
-}
-
-static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
- int expected_num_lines_out) {
- const uint8_t* alpha = io->a;
- if (alpha != NULL) {
- const int mb_w = io->mb_w;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const int alpha_first =
- (colorspace == MODE_ARGB || colorspace == MODE_Argb);
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- int num_rows;
- const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
- uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
- uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3);
- const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w,
- num_rows, dst, buf->stride);
- (void)expected_num_lines_out;
- assert(expected_num_lines_out == num_rows);
- // has_alpha is true if there's non-trivial alpha to premultiply with.
- if (has_alpha && WebPIsPremultipliedMode(colorspace)) {
- WebPApplyAlphaMultiply(base_rgba, alpha_first,
- mb_w, num_rows, buf->stride);
- }
- }
- return 0;
-}
-
-static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p,
- int expected_num_lines_out) {
- const uint8_t* alpha = io->a;
- if (alpha != NULL) {
- const int mb_w = io->mb_w;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- int num_rows;
- const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
- uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
-#ifdef WEBP_SWAP_16BIT_CSP
- uint8_t* alpha_dst = base_rgba;
-#else
- uint8_t* alpha_dst = base_rgba + 1;
-#endif
- uint32_t alpha_mask = 0x0f;
- int i, j;
- for (j = 0; j < num_rows; ++j) {
- for (i = 0; i < mb_w; ++i) {
- // Fill in the alpha value (converted to 4 bits).
- const uint32_t alpha_value = alpha[i] >> 4;
- alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
- alpha_mask &= alpha_value;
- }
- alpha += io->width;
- alpha_dst += buf->stride;
- }
- (void)expected_num_lines_out;
- assert(expected_num_lines_out == num_rows);
- if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) {
- WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride);
- }
- }
- return 0;
-}
-
-//------------------------------------------------------------------------------
-// YUV rescaling (no final RGB conversion needed)
-
-static int Rescale(const uint8_t* src, int src_stride,
- int new_lines, WebPRescaler* const wrk) {
- int num_lines_out = 0;
- while (new_lines > 0) { // import new contributions of source rows.
- const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride);
- src += lines_in * src_stride;
- new_lines -= lines_in;
- num_lines_out += WebPRescalerExport(wrk); // emit output row(s)
- }
- return num_lines_out;
-}
-
-static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
- const int mb_h = io->mb_h;
- const int uv_mb_h = (mb_h + 1) >> 1;
- WebPRescaler* const scaler = &p->scaler_y;
- int num_lines_out = 0;
- if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) {
- // Before rescaling, we premultiply the luma directly into the io->y
- // internal buffer. This is OK since these samples are not used for
- // intra-prediction (the top samples are saved in cache_y_/u_/v_).
- // But we need to cast the const away, though.
- WebPMultRows((uint8_t*)io->y, io->y_stride,
- io->a, io->width, io->mb_w, mb_h, 0);
- }
- num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler);
- Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u);
- Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v);
- return num_lines_out;
-}
-
-static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
- int expected_num_lines_out) {
- const WebPYUVABuffer* const buf = &p->output->u.YUVA;
- if (io->a != NULL) {
- uint8_t* dst_y = buf->y + p->last_y * buf->y_stride;
- const uint8_t* src_a = buf->a + p->last_y * buf->a_stride;
- const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
- (void)expected_num_lines_out;
- assert(expected_num_lines_out == num_lines_out);
- if (num_lines_out > 0) { // unmultiply the Y
- WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride,
- p->scaler_a.dst_width, num_lines_out, 1);
- }
- } else if (buf->a != NULL) {
- // the user requested alpha, but there is none, set it to opaque.
- assert(p->last_y + expected_num_lines_out <= io->scaled_height);
- FillAlphaPlane(buf->a + p->last_y * buf->a_stride,
- io->scaled_width, expected_num_lines_out, buf->a_stride);
- }
- return 0;
-}
-
-static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
- const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
- const WebPYUVABuffer* const buf = &p->output->u.YUVA;
- const int out_width = io->scaled_width;
- const int out_height = io->scaled_height;
- const int uv_out_width = (out_width + 1) >> 1;
- const int uv_out_height = (out_height + 1) >> 1;
- const int uv_in_width = (io->mb_w + 1) >> 1;
- const int uv_in_height = (io->mb_h + 1) >> 1;
- const size_t work_size = 2 * out_width; // scratch memory for luma rescaler
- const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones
- size_t tmp_size;
- rescaler_t* work;
-
- tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
- if (has_alpha) {
- tmp_size += work_size * sizeof(*work);
- }
- p->memory = WebPSafeMalloc(1ULL, tmp_size);
- if (p->memory == NULL) {
- return 0; // memory error
- }
- work = (rescaler_t*)p->memory;
- WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
- buf->y, out_width, out_height, buf->y_stride, 1,
- work);
- WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
- buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
- work + work_size);
- WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
- buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
- work + work_size + uv_work_size);
- p->emit = EmitRescaledYUV;
-
- if (has_alpha) {
- WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
- buf->a, out_width, out_height, buf->a_stride, 1,
- work + work_size + 2 * uv_work_size);
- p->emit_alpha = EmitRescaledAlphaYUV;
- WebPInitAlphaProcessing();
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// RGBA rescaling
-
-static int ExportRGB(WebPDecParams* const p, int y_pos) {
- const WebPYUV444Converter convert =
- WebPYUV444Converters[p->output->colorspace];
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* dst = buf->rgba + y_pos * buf->stride;
- int num_lines_out = 0;
- // For RGB rescaling, because of the YUV420, current scan position
- // U/V can be +1/-1 line from the Y one. Hence the double test.
- while (WebPRescalerHasPendingOutput(&p->scaler_y) &&
- WebPRescalerHasPendingOutput(&p->scaler_u)) {
- assert(y_pos + num_lines_out < p->output->height);
- assert(p->scaler_u.y_accum == p->scaler_v.y_accum);
- WebPRescalerExportRow(&p->scaler_y);
- WebPRescalerExportRow(&p->scaler_u);
- WebPRescalerExportRow(&p->scaler_v);
- convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst,
- dst, p->scaler_y.dst_width);
- dst += buf->stride;
- ++num_lines_out;
- }
- return num_lines_out;
-}
-
-static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
- const int mb_h = io->mb_h;
- const int uv_mb_h = (mb_h + 1) >> 1;
- int j = 0, uv_j = 0;
- int num_lines_out = 0;
- while (j < mb_h) {
- const int y_lines_in =
- WebPRescalerImport(&p->scaler_y, mb_h - j,
- io->y + j * io->y_stride, io->y_stride);
- j += y_lines_in;
- if (WebPRescaleNeededLines(&p->scaler_u, uv_mb_h - uv_j)) {
- const int u_lines_in =
- WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j,
- io->u + uv_j * io->uv_stride, io->uv_stride);
- const int v_lines_in =
- WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j,
- io->v + uv_j * io->uv_stride, io->uv_stride);
- (void)v_lines_in; // remove a gcc warning
- assert(u_lines_in == v_lines_in);
- uv_j += u_lines_in;
- }
- num_lines_out += ExportRGB(p, p->last_y + num_lines_out);
- }
- return num_lines_out;
-}
-
-static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const int alpha_first =
- (colorspace == MODE_ARGB || colorspace == MODE_Argb);
- uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
- int num_lines_out = 0;
- const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
- uint32_t non_opaque = 0;
- const int width = p->scaler_a.dst_width;
-
- while (WebPRescalerHasPendingOutput(&p->scaler_a) &&
- num_lines_out < max_lines_out) {
- assert(y_pos + num_lines_out < p->output->height);
- WebPRescalerExportRow(&p->scaler_a);
- non_opaque |= WebPDispatchAlpha(p->scaler_a.dst, 0, width, 1, dst, 0);
- dst += buf->stride;
- ++num_lines_out;
- }
- if (is_premult_alpha && non_opaque) {
- WebPApplyAlphaMultiply(base_rgba, alpha_first,
- width, num_lines_out, buf->stride);
- }
- return num_lines_out;
-}
-
-static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos,
- int max_lines_out) {
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
-#ifdef WEBP_SWAP_16BIT_CSP
- uint8_t* alpha_dst = base_rgba;
-#else
- uint8_t* alpha_dst = base_rgba + 1;
-#endif
- int num_lines_out = 0;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const int width = p->scaler_a.dst_width;
- const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
- uint32_t alpha_mask = 0x0f;
-
- while (WebPRescalerHasPendingOutput(&p->scaler_a) &&
- num_lines_out < max_lines_out) {
- int i;
- assert(y_pos + num_lines_out < p->output->height);
- WebPRescalerExportRow(&p->scaler_a);
- for (i = 0; i < width; ++i) {
- // Fill in the alpha value (converted to 4 bits).
- const uint32_t alpha_value = p->scaler_a.dst[i] >> 4;
- alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
- alpha_mask &= alpha_value;
- }
- alpha_dst += buf->stride;
- ++num_lines_out;
- }
- if (is_premult_alpha && alpha_mask != 0x0f) {
- WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride);
- }
- return num_lines_out;
-}
-
-static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
- int expected_num_out_lines) {
- if (io->a != NULL) {
- WebPRescaler* const scaler = &p->scaler_a;
- int lines_left = expected_num_out_lines;
- const int y_end = p->last_y + lines_left;
- while (lines_left > 0) {
- const int row_offset = scaler->src_y - io->mb_y;
- WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y,
- io->a + row_offset * io->width, io->width);
- lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left);
- }
- }
- return 0;
-}
-
-static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
- const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
- const int out_width = io->scaled_width;
- const int out_height = io->scaled_height;
- const int uv_in_width = (io->mb_w + 1) >> 1;
- const int uv_in_height = (io->mb_h + 1) >> 1;
- const size_t work_size = 2 * out_width; // scratch memory for one rescaler
- rescaler_t* work; // rescalers work area
- uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
- size_t tmp_size1, tmp_size2, total_size;
-
- tmp_size1 = 3 * work_size;
- tmp_size2 = 3 * out_width;
- if (has_alpha) {
- tmp_size1 += work_size;
- tmp_size2 += out_width;
- }
- total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp);
- p->memory = WebPSafeMalloc(1ULL, total_size);
- if (p->memory == NULL) {
- return 0; // memory error
- }
- work = (rescaler_t*)p->memory;
- tmp = (uint8_t*)(work + tmp_size1);
- WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
- tmp + 0 * out_width, out_width, out_height, 0, 1,
- work + 0 * work_size);
- WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
- tmp + 1 * out_width, out_width, out_height, 0, 1,
- work + 1 * work_size);
- WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
- tmp + 2 * out_width, out_width, out_height, 0, 1,
- work + 2 * work_size);
- p->emit = EmitRescaledRGB;
- WebPInitYUV444Converters();
-
- if (has_alpha) {
- WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
- tmp + 3 * out_width, out_width, out_height, 0, 1,
- work + 3 * work_size);
- p->emit_alpha = EmitRescaledAlphaRGB;
- if (p->output->colorspace == MODE_RGBA_4444 ||
- p->output->colorspace == MODE_rgbA_4444) {
- p->emit_alpha_row = ExportAlphaRGBA4444;
- } else {
- p->emit_alpha_row = ExportAlpha;
- }
- WebPInitAlphaProcessing();
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Default custom functions
-
-static int CustomSetup(VP8Io* io) {
- WebPDecParams* const p = (WebPDecParams*)io->opaque;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const int is_rgb = WebPIsRGBMode(colorspace);
- const int is_alpha = WebPIsAlphaMode(colorspace);
-
- p->memory = NULL;
- p->emit = NULL;
- p->emit_alpha = NULL;
- p->emit_alpha_row = NULL;
- if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) {
- return 0;
- }
- if (is_alpha && WebPIsPremultipliedMode(colorspace)) {
- WebPInitUpsamplers();
- }
- if (io->use_scaling) {
- const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p);
- if (!ok) {
- return 0; // memory error
- }
- } else {
- if (is_rgb) {
- WebPInitSamplers();
- p->emit = EmitSampledRGB; // default
- if (io->fancy_upsampling) {
-#ifdef FANCY_UPSAMPLING
- const int uv_width = (io->mb_w + 1) >> 1;
- p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width));
- if (p->memory == NULL) {
- return 0; // memory error.
- }
- p->tmp_y = (uint8_t*)p->memory;
- p->tmp_u = p->tmp_y + io->mb_w;
- p->tmp_v = p->tmp_u + uv_width;
- p->emit = EmitFancyRGB;
- WebPInitUpsamplers();
-#endif
- }
- } else {
- p->emit = EmitYUV;
- }
- if (is_alpha) { // need transparency output
- p->emit_alpha =
- (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
- EmitAlphaRGBA4444
- : is_rgb ? EmitAlphaRGB
- : EmitAlphaYUV;
- if (is_rgb) {
- WebPInitAlphaProcessing();
- }
- }
- }
-
- if (is_rgb) {
- VP8YUVInit();
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-static int CustomPut(const VP8Io* io) {
- WebPDecParams* const p = (WebPDecParams*)io->opaque;
- const int mb_w = io->mb_w;
- const int mb_h = io->mb_h;
- int num_lines_out;
- assert(!(io->mb_y & 1));
-
- if (mb_w <= 0 || mb_h <= 0) {
- return 0;
- }
- num_lines_out = p->emit(io, p);
- if (p->emit_alpha != NULL) {
- p->emit_alpha(io, p, num_lines_out);
- }
- p->last_y += num_lines_out;
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-static void CustomTeardown(const VP8Io* io) {
- WebPDecParams* const p = (WebPDecParams*)io->opaque;
- WebPSafeFree(p->memory);
- p->memory = NULL;
-}
-
-//------------------------------------------------------------------------------
-// Main entry point
-
-void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) {
- io->put = CustomPut;
- io->setup = CustomSetup;
- io->teardown = CustomTeardown;
- io->opaque = params;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dec/quant.c b/drivers/webp/dec/quant.c
deleted file mode 100644
index 5b648f942c..0000000000
--- a/drivers/webp/dec/quant.c
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Quantizer initialization
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./vp8i.h"
-
-static WEBP_INLINE int clip(int v, int M) {
- return v < 0 ? 0 : v > M ? M : v;
-}
-
-// Paragraph 14.1
-static const uint8_t kDcTable[128] = {
- 4, 5, 6, 7, 8, 9, 10, 10,
- 11, 12, 13, 14, 15, 16, 17, 17,
- 18, 19, 20, 20, 21, 21, 22, 22,
- 23, 23, 24, 25, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36,
- 37, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 63, 64, 65, 66,
- 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 76, 77, 78, 79, 80, 81,
- 82, 83, 84, 85, 86, 87, 88, 89,
- 91, 93, 95, 96, 98, 100, 101, 102,
- 104, 106, 108, 110, 112, 114, 116, 118,
- 122, 124, 126, 128, 130, 132, 134, 136,
- 138, 140, 143, 145, 148, 151, 154, 157
-};
-
-static const uint16_t kAcTable[128] = {
- 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 60,
- 62, 64, 66, 68, 70, 72, 74, 76,
- 78, 80, 82, 84, 86, 88, 90, 92,
- 94, 96, 98, 100, 102, 104, 106, 108,
- 110, 112, 114, 116, 119, 122, 125, 128,
- 131, 134, 137, 140, 143, 146, 149, 152,
- 155, 158, 161, 164, 167, 170, 173, 177,
- 181, 185, 189, 193, 197, 201, 205, 209,
- 213, 217, 221, 225, 229, 234, 239, 245,
- 249, 254, 259, 264, 269, 274, 279, 284
-};
-
-//------------------------------------------------------------------------------
-// Paragraph 9.6
-
-void VP8ParseQuant(VP8Decoder* const dec) {
- VP8BitReader* const br = &dec->br_;
- const int base_q0 = VP8GetValue(br, 7);
- const int dqy1_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
- const int dqy2_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
- const int dqy2_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
- const int dquv_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
- const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
-
- const VP8SegmentHeader* const hdr = &dec->segment_hdr_;
- int i;
-
- for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
- int q;
- if (hdr->use_segment_) {
- q = hdr->quantizer_[i];
- if (!hdr->absolute_delta_) {
- q += base_q0;
- }
- } else {
- if (i > 0) {
- dec->dqm_[i] = dec->dqm_[0];
- continue;
- } else {
- q = base_q0;
- }
- }
- {
- VP8QuantMatrix* const m = &dec->dqm_[i];
- m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)];
- m->y1_mat_[1] = kAcTable[clip(q + 0, 127)];
-
- m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2;
- // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16.
- // The smallest precision for that is '(x*6349) >> 12' but 16 is a good
- // word size.
- m->y2_mat_[1] = (kAcTable[clip(q + dqy2_ac, 127)] * 101581) >> 16;
- if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8;
-
- m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)];
- m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)];
-
- m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
diff --git a/drivers/webp/dec/tree.c b/drivers/webp/dec/tree.c
deleted file mode 100644
index c2007ea733..0000000000
--- a/drivers/webp/dec/tree.c
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Coding trees and probas
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./vp8i.h"
-#include "../utils/bit_reader_inl.h"
-
-#define USE_GENERIC_TREE
-
-#ifdef USE_GENERIC_TREE
-static const int8_t kYModesIntra4[18] = {
- -B_DC_PRED, 1,
- -B_TM_PRED, 2,
- -B_VE_PRED, 3,
- 4, 6,
- -B_HE_PRED, 5,
- -B_RD_PRED, -B_VR_PRED,
- -B_LD_PRED, 7,
- -B_VL_PRED, 8,
- -B_HD_PRED, -B_HU_PRED
-};
-#endif
-
-//------------------------------------------------------------------------------
-// Default probabilities
-
-// Paragraph 13.5
-static const uint8_t
- CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 },
- { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 },
- { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 }
- },
- { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 },
- { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 },
- { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 },
- },
- { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 },
- { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 },
- { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 },
- },
- { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 },
- { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 },
- { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 }
- },
- { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 },
- { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 },
- { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 }
- },
- { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 },
- { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 },
- { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 }
- },
- { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- },
- { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 },
- { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 },
- { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 }
- },
- { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 },
- { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 },
- { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 }
- },
- { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 },
- { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 },
- { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 }
- },
- { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 },
- { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 },
- { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 }
- },
- { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 },
- { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 },
- { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 }
- },
- { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 },
- { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 },
- { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 }
- },
- { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 },
- { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 },
- { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 }
- },
- { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 },
- { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 }
- }
- },
- { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 },
- { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 },
- { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 }
- },
- { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 },
- { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 },
- { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 }
- },
- { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 },
- { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 },
- { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 }
- },
- { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 },
- { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 },
- { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- },
- { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 },
- { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 },
- { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 }
- },
- { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 },
- { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 },
- { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 }
- },
- { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 },
- { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 },
- { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 }
- },
- { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 },
- { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 },
- { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 }
- },
- { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 },
- { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 },
- { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 }
- },
- { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 },
- { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 },
- { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 }
- },
- { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 },
- { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 },
- { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 }
- },
- { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- }
-};
-
-// Paragraph 11.5
-static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
- { { 231, 120, 48, 89, 115, 113, 120, 152, 112 },
- { 152, 179, 64, 126, 170, 118, 46, 70, 95 },
- { 175, 69, 143, 80, 85, 82, 72, 155, 103 },
- { 56, 58, 10, 171, 218, 189, 17, 13, 152 },
- { 114, 26, 17, 163, 44, 195, 21, 10, 173 },
- { 121, 24, 80, 195, 26, 62, 44, 64, 85 },
- { 144, 71, 10, 38, 171, 213, 144, 34, 26 },
- { 170, 46, 55, 19, 136, 160, 33, 206, 71 },
- { 63, 20, 8, 114, 114, 208, 12, 9, 226 },
- { 81, 40, 11, 96, 182, 84, 29, 16, 36 } },
- { { 134, 183, 89, 137, 98, 101, 106, 165, 148 },
- { 72, 187, 100, 130, 157, 111, 32, 75, 80 },
- { 66, 102, 167, 99, 74, 62, 40, 234, 128 },
- { 41, 53, 9, 178, 241, 141, 26, 8, 107 },
- { 74, 43, 26, 146, 73, 166, 49, 23, 157 },
- { 65, 38, 105, 160, 51, 52, 31, 115, 128 },
- { 104, 79, 12, 27, 217, 255, 87, 17, 7 },
- { 87, 68, 71, 44, 114, 51, 15, 186, 23 },
- { 47, 41, 14, 110, 182, 183, 21, 17, 194 },
- { 66, 45, 25, 102, 197, 189, 23, 18, 22 } },
- { { 88, 88, 147, 150, 42, 46, 45, 196, 205 },
- { 43, 97, 183, 117, 85, 38, 35, 179, 61 },
- { 39, 53, 200, 87, 26, 21, 43, 232, 171 },
- { 56, 34, 51, 104, 114, 102, 29, 93, 77 },
- { 39, 28, 85, 171, 58, 165, 90, 98, 64 },
- { 34, 22, 116, 206, 23, 34, 43, 166, 73 },
- { 107, 54, 32, 26, 51, 1, 81, 43, 31 },
- { 68, 25, 106, 22, 64, 171, 36, 225, 114 },
- { 34, 19, 21, 102, 132, 188, 16, 76, 124 },
- { 62, 18, 78, 95, 85, 57, 50, 48, 51 } },
- { { 193, 101, 35, 159, 215, 111, 89, 46, 111 },
- { 60, 148, 31, 172, 219, 228, 21, 18, 111 },
- { 112, 113, 77, 85, 179, 255, 38, 120, 114 },
- { 40, 42, 1, 196, 245, 209, 10, 25, 109 },
- { 88, 43, 29, 140, 166, 213, 37, 43, 154 },
- { 61, 63, 30, 155, 67, 45, 68, 1, 209 },
- { 100, 80, 8, 43, 154, 1, 51, 26, 71 },
- { 142, 78, 78, 16, 255, 128, 34, 197, 171 },
- { 41, 40, 5, 102, 211, 183, 4, 1, 221 },
- { 51, 50, 17, 168, 209, 192, 23, 25, 82 } },
- { { 138, 31, 36, 171, 27, 166, 38, 44, 229 },
- { 67, 87, 58, 169, 82, 115, 26, 59, 179 },
- { 63, 59, 90, 180, 59, 166, 93, 73, 154 },
- { 40, 40, 21, 116, 143, 209, 34, 39, 175 },
- { 47, 15, 16, 183, 34, 223, 49, 45, 183 },
- { 46, 17, 33, 183, 6, 98, 15, 32, 183 },
- { 57, 46, 22, 24, 128, 1, 54, 17, 37 },
- { 65, 32, 73, 115, 28, 128, 23, 128, 205 },
- { 40, 3, 9, 115, 51, 192, 18, 6, 223 },
- { 87, 37, 9, 115, 59, 77, 64, 21, 47 } },
- { { 104, 55, 44, 218, 9, 54, 53, 130, 226 },
- { 64, 90, 70, 205, 40, 41, 23, 26, 57 },
- { 54, 57, 112, 184, 5, 41, 38, 166, 213 },
- { 30, 34, 26, 133, 152, 116, 10, 32, 134 },
- { 39, 19, 53, 221, 26, 114, 32, 73, 255 },
- { 31, 9, 65, 234, 2, 15, 1, 118, 73 },
- { 75, 32, 12, 51, 192, 255, 160, 43, 51 },
- { 88, 31, 35, 67, 102, 85, 55, 186, 85 },
- { 56, 21, 23, 111, 59, 205, 45, 37, 192 },
- { 55, 38, 70, 124, 73, 102, 1, 34, 98 } },
- { { 125, 98, 42, 88, 104, 85, 117, 175, 82 },
- { 95, 84, 53, 89, 128, 100, 113, 101, 45 },
- { 75, 79, 123, 47, 51, 128, 81, 171, 1 },
- { 57, 17, 5, 71, 102, 57, 53, 41, 49 },
- { 38, 33, 13, 121, 57, 73, 26, 1, 85 },
- { 41, 10, 67, 138, 77, 110, 90, 47, 114 },
- { 115, 21, 2, 10, 102, 255, 166, 23, 6 },
- { 101, 29, 16, 10, 85, 128, 101, 196, 26 },
- { 57, 18, 10, 102, 102, 213, 34, 20, 43 },
- { 117, 20, 15, 36, 163, 128, 68, 1, 26 } },
- { { 102, 61, 71, 37, 34, 53, 31, 243, 192 },
- { 69, 60, 71, 38, 73, 119, 28, 222, 37 },
- { 68, 45, 128, 34, 1, 47, 11, 245, 171 },
- { 62, 17, 19, 70, 146, 85, 55, 62, 70 },
- { 37, 43, 37, 154, 100, 163, 85, 160, 1 },
- { 63, 9, 92, 136, 28, 64, 32, 201, 85 },
- { 75, 15, 9, 9, 64, 255, 184, 119, 16 },
- { 86, 6, 28, 5, 64, 255, 25, 248, 1 },
- { 56, 8, 17, 132, 137, 255, 55, 116, 128 },
- { 58, 15, 20, 82, 135, 57, 26, 121, 40 } },
- { { 164, 50, 31, 137, 154, 133, 25, 35, 218 },
- { 51, 103, 44, 131, 131, 123, 31, 6, 158 },
- { 86, 40, 64, 135, 148, 224, 45, 183, 128 },
- { 22, 26, 17, 131, 240, 154, 14, 1, 209 },
- { 45, 16, 21, 91, 64, 222, 7, 1, 197 },
- { 56, 21, 39, 155, 60, 138, 23, 102, 213 },
- { 83, 12, 13, 54, 192, 255, 68, 47, 28 },
- { 85, 26, 85, 85, 128, 128, 32, 146, 171 },
- { 18, 11, 7, 63, 144, 171, 4, 4, 246 },
- { 35, 27, 10, 146, 174, 171, 12, 26, 128 } },
- { { 190, 80, 35, 99, 180, 80, 126, 54, 45 },
- { 85, 126, 47, 87, 176, 51, 41, 20, 32 },
- { 101, 75, 128, 139, 118, 146, 116, 128, 85 },
- { 56, 41, 15, 176, 236, 85, 37, 9, 62 },
- { 71, 30, 17, 119, 118, 255, 17, 18, 138 },
- { 101, 38, 60, 138, 55, 70, 43, 26, 142 },
- { 146, 36, 19, 30, 171, 255, 97, 27, 20 },
- { 138, 45, 61, 62, 219, 1, 81, 188, 64 },
- { 32, 41, 20, 117, 151, 142, 20, 21, 163 },
- { 112, 19, 12, 61, 195, 128, 48, 4, 24 } }
-};
-
-void VP8ResetProba(VP8Proba* const proba) {
- memset(proba->segments_, 255u, sizeof(proba->segments_));
- // proba->bands_[][] is initialized later
-}
-
-static void ParseIntraMode(VP8BitReader* const br,
- VP8Decoder* const dec, int mb_x) {
- uint8_t* const top = dec->intra_t_ + 4 * mb_x;
- uint8_t* const left = dec->intra_l_;
- VP8MBData* const block = dec->mb_data_ + mb_x;
-
- // Note: we don't save segment map (yet), as we don't expect
- // to decode more than 1 keyframe.
- if (dec->segment_hdr_.update_map_) {
- // Hardcoded tree parsing
- block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0])
- ? VP8GetBit(br, dec->proba_.segments_[1])
- : 2 + VP8GetBit(br, dec->proba_.segments_[2]);
- } else {
- block->segment_ = 0; // default for intra
- }
- if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_);
-
- block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
- if (!block->is_i4x4_) {
- // Hardcoded 16x16 intra-mode decision tree.
- const int ymode =
- VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED)
- : (VP8GetBit(br, 163) ? V_PRED : DC_PRED);
- block->imodes_[0] = ymode;
- memset(top, ymode, 4 * sizeof(*top));
- memset(left, ymode, 4 * sizeof(*left));
- } else {
- uint8_t* modes = block->imodes_;
- int y;
- for (y = 0; y < 4; ++y) {
- int ymode = left[y];
- int x;
- for (x = 0; x < 4; ++x) {
- const uint8_t* const prob = kBModesProba[top[x]][ymode];
-#ifdef USE_GENERIC_TREE
- // Generic tree-parsing
- int i = kYModesIntra4[VP8GetBit(br, prob[0])];
- while (i > 0) {
- i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
- }
- ymode = -i;
-#else
- // Hardcoded tree parsing
- ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED :
- !VP8GetBit(br, prob[1]) ? B_TM_PRED :
- !VP8GetBit(br, prob[2]) ? B_VE_PRED :
- !VP8GetBit(br, prob[3]) ?
- (!VP8GetBit(br, prob[4]) ? B_HE_PRED :
- (!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) :
- (!VP8GetBit(br, prob[6]) ? B_LD_PRED :
- (!VP8GetBit(br, prob[7]) ? B_VL_PRED :
- (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED)));
-#endif // USE_GENERIC_TREE
- top[x] = ymode;
- }
- memcpy(modes, top, 4 * sizeof(*top));
- modes += 4;
- left[y] = ymode;
- }
- }
- // Hardcoded UVMode decision tree
- block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
- : !VP8GetBit(br, 114) ? V_PRED
- : VP8GetBit(br, 183) ? TM_PRED : H_PRED;
-}
-
-int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
- int mb_x;
- for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) {
- ParseIntraMode(br, dec, mb_x);
- }
- return !dec->br_.eof_;
-}
-
-//------------------------------------------------------------------------------
-// Paragraph 13
-
-static const uint8_t
- CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 },
- { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 }
- },
- { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 },
- { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- }
-};
-
-// Paragraph 9.9
-
-static const int kBands[16 + 1] = {
- 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
- 0 // extra entry as sentinel
-};
-
-void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
- VP8Proba* const proba = &dec->proba_;
- int t, b, c, p;
- for (t = 0; t < NUM_TYPES; ++t) {
- for (b = 0; b < NUM_BANDS; ++b) {
- for (c = 0; c < NUM_CTX; ++c) {
- for (p = 0; p < NUM_PROBAS; ++p) {
- const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ?
- VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p];
- proba->bands_[t][b].probas_[c][p] = v;
- }
- }
- }
- for (b = 0; b < 16 + 1; ++b) {
- proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]];
- }
- }
- dec->use_skip_proba_ = VP8Get(br);
- if (dec->use_skip_proba_) {
- dec->skip_p_ = VP8GetValue(br, 8);
- }
-}
-
diff --git a/drivers/webp/dec/vp8.c b/drivers/webp/dec/vp8.c
deleted file mode 100644
index 336680c38c..0000000000
--- a/drivers/webp/dec/vp8.c
+++ /dev/null
@@ -1,667 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// main entry for the decoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-
-#include "./alphai.h"
-#include "./vp8i.h"
-#include "./vp8li.h"
-#include "./webpi.h"
-#include "../utils/bit_reader_inl.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-
-int WebPGetDecoderVersion(void) {
- return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION;
-}
-
-//------------------------------------------------------------------------------
-// VP8Decoder
-
-static void SetOk(VP8Decoder* const dec) {
- dec->status_ = VP8_STATUS_OK;
- dec->error_msg_ = "OK";
-}
-
-int VP8InitIoInternal(VP8Io* const io, int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
- return 0; // mismatch error
- }
- if (io != NULL) {
- memset(io, 0, sizeof(*io));
- }
- return 1;
-}
-
-VP8Decoder* VP8New(void) {
- VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
- if (dec != NULL) {
- SetOk(dec);
- WebPGetWorkerInterface()->Init(&dec->worker_);
- dec->ready_ = 0;
- dec->num_parts_minus_one_ = 0;
- }
- return dec;
-}
-
-VP8StatusCode VP8Status(VP8Decoder* const dec) {
- if (!dec) return VP8_STATUS_INVALID_PARAM;
- return dec->status_;
-}
-
-const char* VP8StatusMessage(VP8Decoder* const dec) {
- if (dec == NULL) return "no object";
- if (!dec->error_msg_) return "OK";
- return dec->error_msg_;
-}
-
-void VP8Delete(VP8Decoder* const dec) {
- if (dec != NULL) {
- VP8Clear(dec);
- WebPSafeFree(dec);
- }
-}
-
-int VP8SetError(VP8Decoder* const dec,
- VP8StatusCode error, const char* const msg) {
- // The oldest error reported takes precedence over the new one.
- if (dec->status_ == VP8_STATUS_OK) {
- dec->status_ = error;
- dec->error_msg_ = msg;
- dec->ready_ = 0;
- }
- return 0;
-}
-
-//------------------------------------------------------------------------------
-
-int VP8CheckSignature(const uint8_t* const data, size_t data_size) {
- return (data_size >= 3 &&
- data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a);
-}
-
-int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size,
- int* const width, int* const height) {
- if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) {
- return 0; // not enough data
- }
- // check signature
- if (!VP8CheckSignature(data + 3, data_size - 3)) {
- return 0; // Wrong signature.
- } else {
- const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16);
- const int key_frame = !(bits & 1);
- const int w = ((data[7] << 8) | data[6]) & 0x3fff;
- const int h = ((data[9] << 8) | data[8]) & 0x3fff;
-
- if (!key_frame) { // Not a keyframe.
- return 0;
- }
-
- if (((bits >> 1) & 7) > 3) {
- return 0; // unknown profile
- }
- if (!((bits >> 4) & 1)) {
- return 0; // first frame is invisible!
- }
- if (((bits >> 5)) >= chunk_size) { // partition_length
- return 0; // inconsistent size information.
- }
- if (w == 0 || h == 0) {
- return 0; // We don't support both width and height to be zero.
- }
-
- if (width) {
- *width = w;
- }
- if (height) {
- *height = h;
- }
-
- return 1;
- }
-}
-
-//------------------------------------------------------------------------------
-// Header parsing
-
-static void ResetSegmentHeader(VP8SegmentHeader* const hdr) {
- assert(hdr != NULL);
- hdr->use_segment_ = 0;
- hdr->update_map_ = 0;
- hdr->absolute_delta_ = 1;
- memset(hdr->quantizer_, 0, sizeof(hdr->quantizer_));
- memset(hdr->filter_strength_, 0, sizeof(hdr->filter_strength_));
-}
-
-// Paragraph 9.3
-static int ParseSegmentHeader(VP8BitReader* br,
- VP8SegmentHeader* hdr, VP8Proba* proba) {
- assert(br != NULL);
- assert(hdr != NULL);
- hdr->use_segment_ = VP8Get(br);
- if (hdr->use_segment_) {
- hdr->update_map_ = VP8Get(br);
- if (VP8Get(br)) { // update data
- int s;
- hdr->absolute_delta_ = VP8Get(br);
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
- }
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;
- }
- }
- if (hdr->update_map_) {
- int s;
- for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
- proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u;
- }
- }
- } else {
- hdr->update_map_ = 0;
- }
- return !br->eof_;
-}
-
-// Paragraph 9.5
-// This function returns VP8_STATUS_SUSPENDED if we don't have all the
-// necessary data in 'buf'.
-// This case is not necessarily an error (for incremental decoding).
-// Still, no bitreader is ever initialized to make it possible to read
-// unavailable memory.
-// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA
-// is returned, and this is an unrecoverable error.
-// If the partitions were positioned ok, VP8_STATUS_OK is returned.
-static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
- const uint8_t* buf, size_t size) {
- VP8BitReader* const br = &dec->br_;
- const uint8_t* sz = buf;
- const uint8_t* buf_end = buf + size;
- const uint8_t* part_start;
- size_t size_left = size;
- size_t last_part;
- size_t p;
-
- dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2)) - 1;
- last_part = dec->num_parts_minus_one_;
- if (size < 3 * last_part) {
- // we can't even read the sizes with sz[]! That's a failure.
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
- part_start = buf + last_part * 3;
- size_left -= last_part * 3;
- for (p = 0; p < last_part; ++p) {
- size_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16);
- if (psize > size_left) psize = size_left;
- VP8InitBitReader(dec->parts_ + p, part_start, psize);
- part_start += psize;
- size_left -= psize;
- sz += 3;
- }
- VP8InitBitReader(dec->parts_ + last_part, part_start, size_left);
- return (part_start < buf_end) ? VP8_STATUS_OK :
- VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data
-}
-
-// Paragraph 9.4
-static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) {
- VP8FilterHeader* const hdr = &dec->filter_hdr_;
- hdr->simple_ = VP8Get(br);
- hdr->level_ = VP8GetValue(br, 6);
- hdr->sharpness_ = VP8GetValue(br, 3);
- hdr->use_lf_delta_ = VP8Get(br);
- if (hdr->use_lf_delta_) {
- if (VP8Get(br)) { // update lf-delta?
- int i;
- for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
- if (VP8Get(br)) {
- hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6);
- }
- }
- for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
- if (VP8Get(br)) {
- hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6);
- }
- }
- }
- }
- dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2;
- return !br->eof_;
-}
-
-// Topmost call
-int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
- const uint8_t* buf;
- size_t buf_size;
- VP8FrameHeader* frm_hdr;
- VP8PictureHeader* pic_hdr;
- VP8BitReader* br;
- VP8StatusCode status;
-
- if (dec == NULL) {
- return 0;
- }
- SetOk(dec);
- if (io == NULL) {
- return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
- "null VP8Io passed to VP8GetHeaders()");
- }
- buf = io->data;
- buf_size = io->data_size;
- if (buf_size < 4) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "Truncated header.");
- }
-
- // Paragraph 9.1
- {
- const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);
- frm_hdr = &dec->frm_hdr_;
- frm_hdr->key_frame_ = !(bits & 1);
- frm_hdr->profile_ = (bits >> 1) & 7;
- frm_hdr->show_ = (bits >> 4) & 1;
- frm_hdr->partition_length_ = (bits >> 5);
- if (frm_hdr->profile_ > 3)
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "Incorrect keyframe parameters.");
- if (!frm_hdr->show_)
- return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
- "Frame not displayable.");
- buf += 3;
- buf_size -= 3;
- }
-
- pic_hdr = &dec->pic_hdr_;
- if (frm_hdr->key_frame_) {
- // Paragraph 9.2
- if (buf_size < 7) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "cannot parse picture header");
- }
- if (!VP8CheckSignature(buf, buf_size)) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "Bad code word");
- }
- pic_hdr->width_ = ((buf[4] << 8) | buf[3]) & 0x3fff;
- pic_hdr->xscale_ = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2
- pic_hdr->height_ = ((buf[6] << 8) | buf[5]) & 0x3fff;
- pic_hdr->yscale_ = buf[6] >> 6;
- buf += 7;
- buf_size -= 7;
-
- dec->mb_w_ = (pic_hdr->width_ + 15) >> 4;
- dec->mb_h_ = (pic_hdr->height_ + 15) >> 4;
-
- // Setup default output area (can be later modified during io->setup())
- io->width = pic_hdr->width_;
- io->height = pic_hdr->height_;
- // IMPORTANT! use some sane dimensions in crop_* and scaled_* fields.
- // So they can be used interchangeably without always testing for
- // 'use_cropping'.
- io->use_cropping = 0;
- io->crop_top = 0;
- io->crop_left = 0;
- io->crop_right = io->width;
- io->crop_bottom = io->height;
- io->use_scaling = 0;
- io->scaled_width = io->width;
- io->scaled_height = io->height;
-
- io->mb_w = io->width; // sanity check
- io->mb_h = io->height; // ditto
-
- VP8ResetProba(&dec->proba_);
- ResetSegmentHeader(&dec->segment_hdr_);
- }
-
- // Check if we have all the partition #0 available, and initialize dec->br_
- // to read this partition (and this partition only).
- if (frm_hdr->partition_length_ > buf_size) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "bad partition length");
- }
-
- br = &dec->br_;
- VP8InitBitReader(br, buf, frm_hdr->partition_length_);
- buf += frm_hdr->partition_length_;
- buf_size -= frm_hdr->partition_length_;
-
- if (frm_hdr->key_frame_) {
- pic_hdr->colorspace_ = VP8Get(br);
- pic_hdr->clamp_type_ = VP8Get(br);
- }
- if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "cannot parse segment header");
- }
- // Filter specs
- if (!ParseFilterHeader(br, dec)) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "cannot parse filter header");
- }
- status = ParsePartitions(dec, buf, buf_size);
- if (status != VP8_STATUS_OK) {
- return VP8SetError(dec, status, "cannot parse partitions");
- }
-
- // quantizer change
- VP8ParseQuant(dec);
-
- // Frame buffer marking
- if (!frm_hdr->key_frame_) {
- return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
- "Not a key frame.");
- }
-
- VP8Get(br); // ignore the value of update_proba_
-
- VP8ParseProba(br, dec);
-
- // sanitized state
- dec->ready_ = 1;
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Residual decoding (Paragraph 13.2 / 13.3)
-
-static const uint8_t kCat3[] = { 173, 148, 140, 0 };
-static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 };
-static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 };
-static const uint8_t kCat6[] =
- { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 };
-static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 };
-static const uint8_t kZigzag[16] = {
- 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
-};
-
-// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
-static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
- int v;
- if (!VP8GetBit(br, p[3])) {
- if (!VP8GetBit(br, p[4])) {
- v = 2;
- } else {
- v = 3 + VP8GetBit(br, p[5]);
- }
- } else {
- if (!VP8GetBit(br, p[6])) {
- if (!VP8GetBit(br, p[7])) {
- v = 5 + VP8GetBit(br, 159);
- } else {
- v = 7 + 2 * VP8GetBit(br, 165);
- v += VP8GetBit(br, 145);
- }
- } else {
- const uint8_t* tab;
- const int bit1 = VP8GetBit(br, p[8]);
- const int bit0 = VP8GetBit(br, p[9 + bit1]);
- const int cat = 2 * bit1 + bit0;
- v = 0;
- for (tab = kCat3456[cat]; *tab; ++tab) {
- v += v + VP8GetBit(br, *tab);
- }
- v += 3 + (8 << cat);
- }
- }
- return v;
-}
-
-// Returns the position of the last non-zero coeff plus one
-static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob[],
- int ctx, const quant_t dq, int n, int16_t* out) {
- const uint8_t* p = prob[n]->probas_[ctx];
- for (; n < 16; ++n) {
- if (!VP8GetBit(br, p[0])) {
- return n; // previous coeff was last non-zero coeff
- }
- while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs
- p = prob[++n]->probas_[0];
- if (n == 16) return 16;
- }
- { // non zero coeff
- const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
- int v;
- if (!VP8GetBit(br, p[2])) {
- v = 1;
- p = p_ctx[1];
- } else {
- v = GetLargeValue(br, p);
- p = p_ctx[2];
- }
- out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
- }
- }
- return 16;
-}
-
-static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) {
- nz_coeffs <<= 2;
- nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz;
- return nz_coeffs;
-}
-
-static int ParseResiduals(VP8Decoder* const dec,
- VP8MB* const mb, VP8BitReader* const token_br) {
- const VP8BandProbas* (* const bands)[16 + 1] = dec->proba_.bands_ptr_;
- const VP8BandProbas* const * ac_proba;
- VP8MBData* const block = dec->mb_data_ + dec->mb_x_;
- const VP8QuantMatrix* const q = &dec->dqm_[block->segment_];
- int16_t* dst = block->coeffs_;
- VP8MB* const left_mb = dec->mb_info_ - 1;
- uint8_t tnz, lnz;
- uint32_t non_zero_y = 0;
- uint32_t non_zero_uv = 0;
- int x, y, ch;
- uint32_t out_t_nz, out_l_nz;
- int first;
-
- memset(dst, 0, 384 * sizeof(*dst));
- if (!block->is_i4x4_) { // parse DC
- int16_t dc[16] = { 0 };
- const int ctx = mb->nz_dc_ + left_mb->nz_dc_;
- const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc);
- mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0);
- if (nz > 1) { // more than just the DC -> perform the full transform
- VP8TransformWHT(dc, dst);
- } else { // only DC is non-zero -> inlined simplified transform
- int i;
- const int dc0 = (dc[0] + 3) >> 3;
- for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0;
- }
- first = 1;
- ac_proba = bands[0];
- } else {
- first = 0;
- ac_proba = bands[3];
- }
-
- tnz = mb->nz_ & 0x0f;
- lnz = left_mb->nz_ & 0x0f;
- for (y = 0; y < 4; ++y) {
- int l = lnz & 1;
- uint32_t nz_coeffs = 0;
- for (x = 0; x < 4; ++x) {
- const int ctx = l + (tnz & 1);
- const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst);
- l = (nz > first);
- tnz = (tnz >> 1) | (l << 7);
- nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);
- dst += 16;
- }
- tnz >>= 4;
- lnz = (lnz >> 1) | (l << 7);
- non_zero_y = (non_zero_y << 8) | nz_coeffs;
- }
- out_t_nz = tnz;
- out_l_nz = lnz >> 4;
-
- for (ch = 0; ch < 4; ch += 2) {
- uint32_t nz_coeffs = 0;
- tnz = mb->nz_ >> (4 + ch);
- lnz = left_mb->nz_ >> (4 + ch);
- for (y = 0; y < 2; ++y) {
- int l = lnz & 1;
- for (x = 0; x < 2; ++x) {
- const int ctx = l + (tnz & 1);
- const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst);
- l = (nz > 0);
- tnz = (tnz >> 1) | (l << 3);
- nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);
- dst += 16;
- }
- tnz >>= 2;
- lnz = (lnz >> 1) | (l << 5);
- }
- // Note: we don't really need the per-4x4 details for U/V blocks.
- non_zero_uv |= nz_coeffs << (4 * ch);
- out_t_nz |= (tnz << 4) << ch;
- out_l_nz |= (lnz & 0xf0) << ch;
- }
- mb->nz_ = out_t_nz;
- left_mb->nz_ = out_l_nz;
-
- block->non_zero_y_ = non_zero_y;
- block->non_zero_uv_ = non_zero_uv;
-
- // We look at the mode-code of each block and check if some blocks have less
- // than three non-zero coeffs (code < 2). This is to avoid dithering flat and
- // empty blocks.
- block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_;
-
- return !(non_zero_y | non_zero_uv); // will be used for further optimization
-}
-
-//------------------------------------------------------------------------------
-// Main loop
-
-int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
- VP8MB* const left = dec->mb_info_ - 1;
- VP8MB* const mb = dec->mb_info_ + dec->mb_x_;
- VP8MBData* const block = dec->mb_data_ + dec->mb_x_;
- int skip = dec->use_skip_proba_ ? block->skip_ : 0;
-
- if (!skip) {
- skip = ParseResiduals(dec, mb, token_br);
- } else {
- left->nz_ = mb->nz_ = 0;
- if (!block->is_i4x4_) {
- left->nz_dc_ = mb->nz_dc_ = 0;
- }
- block->non_zero_y_ = 0;
- block->non_zero_uv_ = 0;
- block->dither_ = 0;
- }
-
- if (dec->filter_type_ > 0) { // store filter info
- VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_;
- *finfo = dec->fstrengths_[block->segment_][block->is_i4x4_];
- finfo->f_inner_ |= !skip;
- }
-
- return !token_br->eof_;
-}
-
-void VP8InitScanline(VP8Decoder* const dec) {
- VP8MB* const left = dec->mb_info_ - 1;
- left->nz_ = 0;
- left->nz_dc_ = 0;
- memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));
- dec->mb_x_ = 0;
-}
-
-static int ParseFrame(VP8Decoder* const dec, VP8Io* io) {
- for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) {
- // Parse bitstream for this row.
- VP8BitReader* const token_br =
- &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_];
- if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "Premature end-of-partition0 encountered.");
- }
- for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) {
- if (!VP8DecodeMB(dec, token_br)) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "Premature end-of-file encountered.");
- }
- }
- VP8InitScanline(dec); // Prepare for next scanline
-
- // Reconstruct, filter and emit the row.
- if (!VP8ProcessRow(dec, io)) {
- return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted.");
- }
- }
- if (dec->mt_method_ > 0) {
- if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0;
- }
-
- return 1;
-}
-
-// Main entry point
-int VP8Decode(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 0;
- if (dec == NULL) {
- return 0;
- }
- if (io == NULL) {
- return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
- "NULL VP8Io parameter in VP8Decode().");
- }
-
- if (!dec->ready_) {
- if (!VP8GetHeaders(dec, io)) {
- return 0;
- }
- }
- assert(dec->ready_);
-
- // Finish setting up the decoding parameter. Will call io->setup().
- ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK);
- if (ok) { // good to go.
- // Will allocate memory and prepare everything.
- if (ok) ok = VP8InitFrame(dec, io);
-
- // Main decoding loop
- if (ok) ok = ParseFrame(dec, io);
-
- // Exit.
- ok &= VP8ExitCritical(dec, io);
- }
-
- if (!ok) {
- VP8Clear(dec);
- return 0;
- }
-
- dec->ready_ = 0;
- return ok;
-}
-
-void VP8Clear(VP8Decoder* const dec) {
- if (dec == NULL) {
- return;
- }
- WebPGetWorkerInterface()->End(&dec->worker_);
- WebPDeallocateAlphaMemory(dec);
- WebPSafeFree(dec->mem_);
- dec->mem_ = NULL;
- dec->mem_size_ = 0;
- memset(&dec->br_, 0, sizeof(dec->br_));
- dec->ready_ = 0;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dec/vp8i.h b/drivers/webp/dec/vp8i.h
deleted file mode 100644
index 00da02badc..0000000000
--- a/drivers/webp/dec/vp8i.h
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// VP8 decoder: internal header.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_DEC_VP8I_H_
-#define WEBP_DEC_VP8I_H_
-
-#include <string.h> // for memcpy()
-#include "./common.h"
-#include "./vp8li.h"
-#include "../utils/bit_reader.h"
-#include "../utils/random.h"
-#include "../utils/thread.h"
-#include "../dsp/dsp.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Various defines and enums
-
-// version numbers
-#define DEC_MAJ_VERSION 0
-#define DEC_MIN_VERSION 5
-#define DEC_REV_VERSION 1
-
-// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
-// Constraints are: We need to store one 16x16 block of luma samples (y),
-// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned,
-// in order to be SIMD-friendly. We also need to store the top, left and
-// top-left samples (from previously decoded blocks), along with four
-// extra top-right samples for luma (intra4x4 prediction only).
-// One possible layout is, using 32 * (17 + 9) bytes:
-//
-// .+------ <- only 1 pixel high
-// .|yyyyt.
-// .|yyyyt.
-// .|yyyyt.
-// .|yyyy..
-// .+--.+-- <- only 1 pixel high
-// .|uu.|vv
-// .|uu.|vv
-//
-// Every character is a 4x4 block, with legend:
-// '.' = unused
-// 'y' = y-samples 'u' = u-samples 'v' = u-samples
-// '|' = left sample, '-' = top sample, '+' = top-left sample
-// 't' = extra top-right sample for 4x4 modes
-#define YUV_SIZE (BPS * 17 + BPS * 9)
-#define Y_SIZE (BPS * 17)
-#define Y_OFF (BPS * 1 + 8)
-#define U_OFF (Y_OFF + BPS * 16 + BPS)
-#define V_OFF (U_OFF + 16)
-
-// minimal width under which lossy multi-threading is always disabled
-#define MIN_WIDTH_FOR_THREADS 512
-
-//------------------------------------------------------------------------------
-// Headers
-
-typedef struct {
- uint8_t key_frame_;
- uint8_t profile_;
- uint8_t show_;
- uint32_t partition_length_;
-} VP8FrameHeader;
-
-typedef struct {
- uint16_t width_;
- uint16_t height_;
- uint8_t xscale_;
- uint8_t yscale_;
- uint8_t colorspace_; // 0 = YCbCr
- uint8_t clamp_type_;
-} VP8PictureHeader;
-
-// segment features
-typedef struct {
- int use_segment_;
- int update_map_; // whether to update the segment map or not
- int absolute_delta_; // absolute or delta values for quantizer and filter
- int8_t quantizer_[NUM_MB_SEGMENTS]; // quantization changes
- int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments
-} VP8SegmentHeader;
-
-// probas associated to one of the contexts
-typedef uint8_t VP8ProbaArray[NUM_PROBAS];
-
-typedef struct { // all the probas associated to one band
- VP8ProbaArray probas_[NUM_CTX];
-} VP8BandProbas;
-
-// Struct collecting all frame-persistent probabilities.
-typedef struct {
- uint8_t segments_[MB_FEATURE_TREE_PROBS];
- // Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4
- VP8BandProbas bands_[NUM_TYPES][NUM_BANDS];
- const VP8BandProbas* bands_ptr_[NUM_TYPES][16 + 1];
-} VP8Proba;
-
-// Filter parameters
-typedef struct {
- int simple_; // 0=complex, 1=simple
- int level_; // [0..63]
- int sharpness_; // [0..7]
- int use_lf_delta_;
- int ref_lf_delta_[NUM_REF_LF_DELTAS];
- int mode_lf_delta_[NUM_MODE_LF_DELTAS];
-} VP8FilterHeader;
-
-//------------------------------------------------------------------------------
-// Informations about the macroblocks.
-
-typedef struct { // filter specs
- uint8_t f_limit_; // filter limit in [3..189], or 0 if no filtering
- uint8_t f_ilevel_; // inner limit in [1..63]
- uint8_t f_inner_; // do inner filtering?
- uint8_t hev_thresh_; // high edge variance threshold in [0..2]
-} VP8FInfo;
-
-typedef struct { // Top/Left Contexts used for syntax-parsing
- uint8_t nz_; // non-zero AC/DC coeffs (4bit for luma + 4bit for chroma)
- uint8_t nz_dc_; // non-zero DC coeff (1bit)
-} VP8MB;
-
-// Dequantization matrices
-typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower).
-typedef struct {
- quant_t y1_mat_, y2_mat_, uv_mat_;
-
- int uv_quant_; // U/V quantizer value
- int dither_; // dithering amplitude (0 = off, max=255)
-} VP8QuantMatrix;
-
-// Data needed to reconstruct a macroblock
-typedef struct {
- int16_t coeffs_[384]; // 384 coeffs = (16+4+4) * 4*4
- uint8_t is_i4x4_; // true if intra4x4
- uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes
- uint8_t uvmode_; // chroma prediction mode
- // bit-wise info about the content of each sub-4x4 blocks (in decoding order).
- // Each of the 4x4 blocks for y/u/v is associated with a 2b code according to:
- // code=0 -> no coefficient
- // code=1 -> only DC
- // code=2 -> first three coefficients are non-zero
- // code=3 -> more than three coefficients are non-zero
- // This allows to call specialized transform functions.
- uint32_t non_zero_y_;
- uint32_t non_zero_uv_;
- uint8_t dither_; // local dithering strength (deduced from non_zero_*)
- uint8_t skip_;
- uint8_t segment_;
-} VP8MBData;
-
-// Persistent information needed by the parallel processing
-typedef struct {
- int id_; // cache row to process (in [0..2])
- int mb_y_; // macroblock position of the row
- int filter_row_; // true if row-filtering is needed
- VP8FInfo* f_info_; // filter strengths (swapped with dec->f_info_)
- VP8MBData* mb_data_; // reconstruction data (swapped with dec->mb_data_)
- VP8Io io_; // copy of the VP8Io to pass to put()
-} VP8ThreadContext;
-
-// Saved top samples, per macroblock. Fits into a cache-line.
-typedef struct {
- uint8_t y[16], u[8], v[8];
-} VP8TopSamples;
-
-//------------------------------------------------------------------------------
-// VP8Decoder: the main opaque structure handed over to user
-
-struct VP8Decoder {
- VP8StatusCode status_;
- int ready_; // true if ready to decode a picture with VP8Decode()
- const char* error_msg_; // set when status_ is not OK.
-
- // Main data source
- VP8BitReader br_;
-
- // headers
- VP8FrameHeader frm_hdr_;
- VP8PictureHeader pic_hdr_;
- VP8FilterHeader filter_hdr_;
- VP8SegmentHeader segment_hdr_;
-
- // Worker
- WebPWorker worker_;
- int mt_method_; // multi-thread method: 0=off, 1=[parse+recon][filter]
- // 2=[parse][recon+filter]
- int cache_id_; // current cache row
- int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3)
- VP8ThreadContext thread_ctx_; // Thread context
-
- // dimension, in macroblock units.
- int mb_w_, mb_h_;
-
- // Macroblock to process/filter, depending on cropping and filter_type.
- int tl_mb_x_, tl_mb_y_; // top-left MB that must be in-loop filtered
- int br_mb_x_, br_mb_y_; // last bottom-right MB that must be decoded
-
- // number of partitions minus one.
- uint32_t num_parts_minus_one_;
- // per-partition boolean decoders.
- VP8BitReader parts_[MAX_NUM_PARTITIONS];
-
- // Dithering strength, deduced from decoding options
- int dither_; // whether to use dithering or not
- VP8Random dithering_rg_; // random generator for dithering
-
- // dequantization (one set of DC/AC dequant factor per segment)
- VP8QuantMatrix dqm_[NUM_MB_SEGMENTS];
-
- // probabilities
- VP8Proba proba_;
- int use_skip_proba_;
- uint8_t skip_p_;
-
- // Boundary data cache and persistent buffers.
- uint8_t* intra_t_; // top intra modes values: 4 * mb_w_
- uint8_t intra_l_[4]; // left intra modes values
-
- VP8TopSamples* yuv_t_; // top y/u/v samples
-
- VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1)
- VP8FInfo* f_info_; // filter strength info
- uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE)
-
- uint8_t* cache_y_; // macroblock row for storing unfiltered samples
- uint8_t* cache_u_;
- uint8_t* cache_v_;
- int cache_y_stride_;
- int cache_uv_stride_;
-
- // main memory chunk for the above data. Persistent.
- void* mem_;
- size_t mem_size_;
-
- // Per macroblock non-persistent infos.
- int mb_x_, mb_y_; // current position, in macroblock units
- VP8MBData* mb_data_; // parsed reconstruction data
-
- // Filtering side-info
- int filter_type_; // 0=off, 1=simple, 2=complex
- VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type
-
- // Alpha
- struct ALPHDecoder* alph_dec_; // alpha-plane decoder object
- const uint8_t* alpha_data_; // compressed alpha data (if present)
- size_t alpha_data_size_;
- int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_
- uint8_t* alpha_plane_mem_; // memory allocated for alpha_plane_
- uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
- const uint8_t* alpha_prev_line_; // last decoded alpha row (or NULL)
- int alpha_dithering_; // derived from decoding options (0=off, 100=full)
-};
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
-// in vp8.c
-int VP8SetError(VP8Decoder* const dec,
- VP8StatusCode error, const char* const msg);
-
-// in tree.c
-void VP8ResetProba(VP8Proba* const proba);
-void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec);
-// parses one row of intra mode data in partition 0, returns !eof
-int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec);
-
-// in quant.c
-void VP8ParseQuant(VP8Decoder* const dec);
-
-// in frame.c
-int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io);
-// Call io->setup() and finish setting up scan parameters.
-// After this call returns, one must always call VP8ExitCritical() with the
-// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK
-// if ok, otherwise sets and returns the error status on *dec.
-VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io);
-// Must always be called in pair with VP8EnterCritical().
-// Returns false in case of error.
-int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
-// Return the multi-threading method to use (0=off), depending
-// on options and bitstream size. Only for lossy decoding.
-int VP8GetThreadMethod(const WebPDecoderOptions* const options,
- const WebPHeaderStructure* const headers,
- int width, int height);
-// Initialize dithering post-process if needed.
-void VP8InitDithering(const WebPDecoderOptions* const options,
- VP8Decoder* const dec);
-// Process the last decoded row (filtering + output).
-int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
-// To be called at the start of a new scanline, to initialize predictors.
-void VP8InitScanline(VP8Decoder* const dec);
-// Decode one macroblock. Returns false if there is not enough data.
-int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
-
-// in alpha.c
-const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
- const VP8Io* const io,
- int row, int num_rows);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_VP8I_H_ */
diff --git a/drivers/webp/dec/vp8l.c b/drivers/webp/dec/vp8l.c
deleted file mode 100644
index cb2e3176b6..0000000000
--- a/drivers/webp/dec/vp8l.c
+++ /dev/null
@@ -1,1660 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// main entry for the decoder
-//
-// Authors: Vikas Arora (vikaas.arora@gmail.com)
-// Jyrki Alakuijala (jyrki@google.com)
-
-#include <stdlib.h>
-
-#include "./alphai.h"
-#include "./vp8li.h"
-#include "../dsp/dsp.h"
-#include "../dsp/lossless.h"
-#include "../dsp/yuv.h"
-#include "../utils/endian_inl.h"
-#include "../utils/huffman.h"
-#include "../utils/utils.h"
-
-#define NUM_ARGB_CACHE_ROWS 16
-
-static const int kCodeLengthLiterals = 16;
-static const int kCodeLengthRepeatCode = 16;
-static const int kCodeLengthExtraBits[3] = { 2, 3, 7 };
-static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
-
-// -----------------------------------------------------------------------------
-// Five Huffman codes are used at each meta code:
-// 1. green + length prefix codes + color cache codes,
-// 2. alpha,
-// 3. red,
-// 4. blue, and,
-// 5. distance prefix codes.
-typedef enum {
- GREEN = 0,
- RED = 1,
- BLUE = 2,
- ALPHA = 3,
- DIST = 4
-} HuffIndex;
-
-static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
- NUM_LITERAL_CODES + NUM_LENGTH_CODES,
- NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
- NUM_DISTANCE_CODES
-};
-
-static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {
- 0, 1, 1, 1, 0
-};
-
-#define NUM_CODE_LENGTH_CODES 19
-static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
- 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
-};
-
-#define CODE_TO_PLANE_CODES 120
-static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
- 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
- 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
- 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
- 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
- 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
- 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
- 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
- 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
- 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
- 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
- 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
- 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
-};
-
-// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha
-// and distance alphabets are constant (256 for red, blue and alpha, 40 for
-// distance) and lookup table sizes for them in worst case are 630 and 410
-// respectively. Size of green alphabet depends on color cache size and is equal
-// to 256 (green component values) + 24 (length prefix values)
-// + color_cache_size (between 0 and 2048).
-// All values computed for 8-bit first level lookup with Mark Adler's tool:
-// http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c
-#define FIXED_TABLE_SIZE (630 * 3 + 410)
-static const int kTableSize[12] = {
- FIXED_TABLE_SIZE + 654,
- FIXED_TABLE_SIZE + 656,
- FIXED_TABLE_SIZE + 658,
- FIXED_TABLE_SIZE + 662,
- FIXED_TABLE_SIZE + 670,
- FIXED_TABLE_SIZE + 686,
- FIXED_TABLE_SIZE + 718,
- FIXED_TABLE_SIZE + 782,
- FIXED_TABLE_SIZE + 912,
- FIXED_TABLE_SIZE + 1168,
- FIXED_TABLE_SIZE + 1680,
- FIXED_TABLE_SIZE + 2704
-};
-
-static int DecodeImageStream(int xsize, int ysize,
- int is_level0,
- VP8LDecoder* const dec,
- uint32_t** const decoded_data);
-
-//------------------------------------------------------------------------------
-
-int VP8LCheckSignature(const uint8_t* const data, size_t size) {
- return (size >= VP8L_FRAME_HEADER_SIZE &&
- data[0] == VP8L_MAGIC_BYTE &&
- (data[4] >> 5) == 0); // version
-}
-
-static int ReadImageInfo(VP8LBitReader* const br,
- int* const width, int* const height,
- int* const has_alpha) {
- if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;
- *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
- *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
- *has_alpha = VP8LReadBits(br, 1);
- if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;
- return !br->eos_;
-}
-
-int VP8LGetInfo(const uint8_t* data, size_t data_size,
- int* const width, int* const height, int* const has_alpha) {
- if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
- return 0; // not enough data
- } else if (!VP8LCheckSignature(data, data_size)) {
- return 0; // bad signature
- } else {
- int w, h, a;
- VP8LBitReader br;
- VP8LInitBitReader(&br, data, data_size);
- if (!ReadImageInfo(&br, &w, &h, &a)) {
- return 0;
- }
- if (width != NULL) *width = w;
- if (height != NULL) *height = h;
- if (has_alpha != NULL) *has_alpha = a;
- return 1;
- }
-}
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE int GetCopyDistance(int distance_symbol,
- VP8LBitReader* const br) {
- int extra_bits, offset;
- if (distance_symbol < 4) {
- return distance_symbol + 1;
- }
- extra_bits = (distance_symbol - 2) >> 1;
- offset = (2 + (distance_symbol & 1)) << extra_bits;
- return offset + VP8LReadBits(br, extra_bits) + 1;
-}
-
-static WEBP_INLINE int GetCopyLength(int length_symbol,
- VP8LBitReader* const br) {
- // Length and distance prefixes are encoded the same way.
- return GetCopyDistance(length_symbol, br);
-}
-
-static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
- if (plane_code > CODE_TO_PLANE_CODES) {
- return plane_code - CODE_TO_PLANE_CODES;
- } else {
- const int dist_code = kCodeToPlane[plane_code - 1];
- const int yoffset = dist_code >> 4;
- const int xoffset = 8 - (dist_code & 0xf);
- const int dist = yoffset * xsize + xoffset;
- return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small
- }
-}
-
-//------------------------------------------------------------------------------
-// Decodes the next Huffman code from bit-stream.
-// FillBitWindow(br) needs to be called at minimum every second call
-// to ReadSymbol, in order to pre-fetch enough bits.
-static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,
- VP8LBitReader* const br) {
- int nbits;
- uint32_t val = VP8LPrefetchBits(br);
- table += val & HUFFMAN_TABLE_MASK;
- nbits = table->bits - HUFFMAN_TABLE_BITS;
- if (nbits > 0) {
- VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS);
- val = VP8LPrefetchBits(br);
- table += table->value;
- table += val & ((1 << nbits) - 1);
- }
- VP8LSetBitPos(br, br->bit_pos_ + table->bits);
- return table->value;
-}
-
-// Reads packed symbol depending on GREEN channel
-#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask)
-#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES
-static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group,
- VP8LBitReader* const br,
- uint32_t* const dst) {
- const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1);
- const HuffmanCode32 code = group->packed_table[val];
- assert(group->use_packed_table);
- if (code.bits < BITS_SPECIAL_MARKER) {
- VP8LSetBitPos(br, br->bit_pos_ + code.bits);
- *dst = code.value;
- return PACKED_NON_LITERAL_CODE;
- } else {
- VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER);
- assert(code.value >= NUM_LITERAL_CODES);
- return code.value;
- }
-}
-
-static int AccumulateHCode(HuffmanCode hcode, int shift,
- HuffmanCode32* const huff) {
- huff->bits += hcode.bits;
- huff->value |= (uint32_t)hcode.value << shift;
- assert(huff->bits <= HUFFMAN_TABLE_BITS);
- return hcode.bits;
-}
-
-static void BuildPackedTable(HTreeGroup* const htree_group) {
- uint32_t code;
- for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) {
- uint32_t bits = code;
- HuffmanCode32* const huff = &htree_group->packed_table[bits];
- HuffmanCode hcode = htree_group->htrees[GREEN][bits];
- if (hcode.value >= NUM_LITERAL_CODES) {
- huff->bits = hcode.bits + BITS_SPECIAL_MARKER;
- huff->value = hcode.value;
- } else {
- huff->bits = 0;
- huff->value = 0;
- bits >>= AccumulateHCode(hcode, 8, huff);
- bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff);
- bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff);
- bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff);
- (void)bits;
- }
- }
-}
-
-static int ReadHuffmanCodeLengths(
- VP8LDecoder* const dec, const int* const code_length_code_lengths,
- int num_symbols, int* const code_lengths) {
- int ok = 0;
- VP8LBitReader* const br = &dec->br_;
- int symbol;
- int max_symbol;
- int prev_code_len = DEFAULT_CODE_LENGTH;
- HuffmanCode table[1 << LENGTHS_TABLE_BITS];
-
- if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
- code_length_code_lengths,
- NUM_CODE_LENGTH_CODES)) {
- goto End;
- }
-
- if (VP8LReadBits(br, 1)) { // use length
- const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);
- max_symbol = 2 + VP8LReadBits(br, length_nbits);
- if (max_symbol > num_symbols) {
- goto End;
- }
- } else {
- max_symbol = num_symbols;
- }
-
- symbol = 0;
- while (symbol < num_symbols) {
- const HuffmanCode* p;
- int code_len;
- if (max_symbol-- == 0) break;
- VP8LFillBitWindow(br);
- p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
- VP8LSetBitPos(br, br->bit_pos_ + p->bits);
- code_len = p->value;
- if (code_len < kCodeLengthLiterals) {
- code_lengths[symbol++] = code_len;
- if (code_len != 0) prev_code_len = code_len;
- } else {
- const int use_prev = (code_len == kCodeLengthRepeatCode);
- const int slot = code_len - kCodeLengthLiterals;
- const int extra_bits = kCodeLengthExtraBits[slot];
- const int repeat_offset = kCodeLengthRepeatOffsets[slot];
- int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;
- if (symbol + repeat > num_symbols) {
- goto End;
- } else {
- const int length = use_prev ? prev_code_len : 0;
- while (repeat-- > 0) code_lengths[symbol++] = length;
- }
- }
- }
- ok = 1;
-
- End:
- if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return ok;
-}
-
-// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
-// tree.
-static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
- int* const code_lengths, HuffmanCode* const table) {
- int ok = 0;
- int size = 0;
- VP8LBitReader* const br = &dec->br_;
- const int simple_code = VP8LReadBits(br, 1);
-
- memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));
-
- if (simple_code) { // Read symbols, codes & code lengths directly.
- const int num_symbols = VP8LReadBits(br, 1) + 1;
- const int first_symbol_len_code = VP8LReadBits(br, 1);
- // The first code is either 1 bit or 8 bit code.
- int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
- code_lengths[symbol] = 1;
- // The second code (if present), is always 8 bit long.
- if (num_symbols == 2) {
- symbol = VP8LReadBits(br, 8);
- code_lengths[symbol] = 1;
- }
- ok = 1;
- } else { // Decode Huffman-coded code lengths.
- int i;
- int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
- const int num_codes = VP8LReadBits(br, 4) + 4;
- if (num_codes > NUM_CODE_LENGTH_CODES) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return 0;
- }
-
- for (i = 0; i < num_codes; ++i) {
- code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
- }
- ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
- code_lengths);
- }
-
- ok = ok && !br->eos_;
- if (ok) {
- size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,
- code_lengths, alphabet_size);
- }
- if (!ok || size == 0) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return 0;
- }
- return size;
-}
-
-static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
- int color_cache_bits, int allow_recursion) {
- int i, j;
- VP8LBitReader* const br = &dec->br_;
- VP8LMetadata* const hdr = &dec->hdr_;
- uint32_t* huffman_image = NULL;
- HTreeGroup* htree_groups = NULL;
- HuffmanCode* huffman_tables = NULL;
- HuffmanCode* next = NULL;
- int num_htree_groups = 1;
- int max_alphabet_size = 0;
- int* code_lengths = NULL;
- const int table_size = kTableSize[color_cache_bits];
-
- if (allow_recursion && VP8LReadBits(br, 1)) {
- // use meta Huffman codes.
- const int huffman_precision = VP8LReadBits(br, 3) + 2;
- const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
- const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
- const int huffman_pixs = huffman_xsize * huffman_ysize;
- if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
- &huffman_image)) {
- goto Error;
- }
- hdr->huffman_subsample_bits_ = huffman_precision;
- for (i = 0; i < huffman_pixs; ++i) {
- // The huffman data is stored in red and green bytes.
- const int group = (huffman_image[i] >> 8) & 0xffff;
- huffman_image[i] = group;
- if (group >= num_htree_groups) {
- num_htree_groups = group + 1;
- }
- }
- }
-
- if (br->eos_) goto Error;
-
- // Find maximum alphabet size for the htree group.
- for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
- int alphabet_size = kAlphabetSize[j];
- if (j == 0 && color_cache_bits > 0) {
- alphabet_size += 1 << color_cache_bits;
- }
- if (max_alphabet_size < alphabet_size) {
- max_alphabet_size = alphabet_size;
- }
- }
-
- huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
- sizeof(*huffman_tables));
- htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
- code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
- sizeof(*code_lengths));
-
- if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- goto Error;
- }
-
- next = huffman_tables;
- for (i = 0; i < num_htree_groups; ++i) {
- HTreeGroup* const htree_group = &htree_groups[i];
- HuffmanCode** const htrees = htree_group->htrees;
- int size;
- int total_size = 0;
- int is_trivial_literal = 1;
- int max_bits = 0;
- for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
- int alphabet_size = kAlphabetSize[j];
- htrees[j] = next;
- if (j == 0 && color_cache_bits > 0) {
- alphabet_size += 1 << color_cache_bits;
- }
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);
- if (size == 0) {
- goto Error;
- }
- if (is_trivial_literal && kLiteralMap[j] == 1) {
- is_trivial_literal = (next->bits == 0);
- }
- total_size += next->bits;
- next += size;
- if (j <= ALPHA) {
- int local_max_bits = code_lengths[0];
- int k;
- for (k = 1; k < alphabet_size; ++k) {
- if (code_lengths[k] > local_max_bits) {
- local_max_bits = code_lengths[k];
- }
- }
- max_bits += local_max_bits;
- }
- }
- htree_group->is_trivial_literal = is_trivial_literal;
- htree_group->is_trivial_code = 0;
- if (is_trivial_literal) {
- const int red = htrees[RED][0].value;
- const int blue = htrees[BLUE][0].value;
- const int alpha = htrees[ALPHA][0].value;
- htree_group->literal_arb =
- ((uint32_t)alpha << 24) | (red << 16) | blue;
- if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
- htree_group->is_trivial_code = 1;
- htree_group->literal_arb |= htrees[GREEN][0].value << 8;
- }
- }
- htree_group->use_packed_table = !htree_group->is_trivial_code &&
- (max_bits < HUFFMAN_PACKED_BITS);
- if (htree_group->use_packed_table) BuildPackedTable(htree_group);
- }
- WebPSafeFree(code_lengths);
-
- // All OK. Finalize pointers and return.
- hdr->huffman_image_ = huffman_image;
- hdr->num_htree_groups_ = num_htree_groups;
- hdr->htree_groups_ = htree_groups;
- hdr->huffman_tables_ = huffman_tables;
- return 1;
-
- Error:
- WebPSafeFree(code_lengths);
- WebPSafeFree(huffman_image);
- WebPSafeFree(huffman_tables);
- VP8LHtreeGroupsFree(htree_groups);
- return 0;
-}
-
-//------------------------------------------------------------------------------
-// Scaling.
-
-static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
- const int num_channels = 4;
- const int in_width = io->mb_w;
- const int out_width = io->scaled_width;
- const int in_height = io->mb_h;
- const int out_height = io->scaled_height;
- const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
- rescaler_t* work; // Rescaler work area.
- const uint64_t scaled_data_size = (uint64_t)out_width;
- uint32_t* scaled_data; // Temporary storage for scaled BGRA data.
- const uint64_t memory_size = sizeof(*dec->rescaler) +
- work_size * sizeof(*work) +
- scaled_data_size * sizeof(*scaled_data);
- uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));
- if (memory == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- return 0;
- }
- assert(dec->rescaler_memory == NULL);
- dec->rescaler_memory = memory;
-
- dec->rescaler = (WebPRescaler*)memory;
- memory += sizeof(*dec->rescaler);
- work = (rescaler_t*)memory;
- memory += work_size * sizeof(*work);
- scaled_data = (uint32_t*)memory;
-
- WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
- out_width, out_height, 0, num_channels, work);
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Export to ARGB
-
-// We have special "export" function since we need to convert from BGRA
-static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
- int rgba_stride, uint8_t* const rgba) {
- uint32_t* const src = (uint32_t*)rescaler->dst;
- const int dst_width = rescaler->dst_width;
- int num_lines_out = 0;
- while (WebPRescalerHasPendingOutput(rescaler)) {
- uint8_t* const dst = rgba + num_lines_out * rgba_stride;
- WebPRescalerExportRow(rescaler);
- WebPMultARGBRow(src, dst_width, 1);
- VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
- ++num_lines_out;
- }
- return num_lines_out;
-}
-
-// Emit scaled rows.
-static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
- uint8_t* in, int in_stride, int mb_h,
- uint8_t* const out, int out_stride) {
- const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
- int num_lines_in = 0;
- int num_lines_out = 0;
- while (num_lines_in < mb_h) {
- uint8_t* const row_in = in + num_lines_in * in_stride;
- uint8_t* const row_out = out + num_lines_out * out_stride;
- const int lines_left = mb_h - num_lines_in;
- const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
- assert(needed_lines > 0 && needed_lines <= lines_left);
- WebPMultARGBRows(row_in, in_stride,
- dec->rescaler->src_width, needed_lines, 0);
- WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
- num_lines_in += needed_lines;
- num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
- }
- return num_lines_out;
-}
-
-// Emit rows without any scaling.
-static int EmitRows(WEBP_CSP_MODE colorspace,
- const uint8_t* row_in, int in_stride,
- int mb_w, int mb_h,
- uint8_t* const out, int out_stride) {
- int lines = mb_h;
- uint8_t* row_out = out;
- while (lines-- > 0) {
- VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
- row_in += in_stride;
- row_out += out_stride;
- }
- return mb_h; // Num rows out == num rows in.
-}
-
-//------------------------------------------------------------------------------
-// Export to YUVA
-
-static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
- const WebPDecBuffer* const output) {
- const WebPYUVABuffer* const buf = &output->u.YUVA;
-
- // first, the luma plane
- WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width);
-
- // then U/V planes
- {
- uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
- uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
- // even lines: store values
- // odd lines: average with previous values
- WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1));
- }
- // Lastly, store alpha if needed.
- if (buf->a != NULL) {
- uint8_t* const a = buf->a + y_pos * buf->a_stride;
-#if defined(WORDS_BIGENDIAN)
- WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0);
-#else
- WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0);
-#endif
- }
-}
-
-static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
- WebPRescaler* const rescaler = dec->rescaler;
- uint32_t* const src = (uint32_t*)rescaler->dst;
- const int dst_width = rescaler->dst_width;
- int num_lines_out = 0;
- while (WebPRescalerHasPendingOutput(rescaler)) {
- WebPRescalerExportRow(rescaler);
- WebPMultARGBRow(src, dst_width, 1);
- ConvertToYUVA(src, dst_width, y_pos, dec->output_);
- ++y_pos;
- ++num_lines_out;
- }
- return num_lines_out;
-}
-
-static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
- uint8_t* in, int in_stride, int mb_h) {
- int num_lines_in = 0;
- int y_pos = dec->last_out_row_;
- while (num_lines_in < mb_h) {
- const int lines_left = mb_h - num_lines_in;
- const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
- WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
- WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
- num_lines_in += needed_lines;
- in += needed_lines * in_stride;
- y_pos += ExportYUVA(dec, y_pos);
- }
- return y_pos;
-}
-
-static int EmitRowsYUVA(const VP8LDecoder* const dec,
- const uint8_t* in, int in_stride,
- int mb_w, int num_rows) {
- int y_pos = dec->last_out_row_;
- while (num_rows-- > 0) {
- ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
- in += in_stride;
- ++y_pos;
- }
- return y_pos;
-}
-
-//------------------------------------------------------------------------------
-// Cropping.
-
-// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
-// crop options. Also updates the input data pointer, so that it points to the
-// start of the cropped window. Note that pixels are in ARGB format even if
-// 'in_data' is uint8_t*.
-// Returns true if the crop window is not empty.
-static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
- uint8_t** const in_data, int pixel_stride) {
- assert(y_start < y_end);
- assert(io->crop_left < io->crop_right);
- if (y_end > io->crop_bottom) {
- y_end = io->crop_bottom; // make sure we don't overflow on last row.
- }
- if (y_start < io->crop_top) {
- const int delta = io->crop_top - y_start;
- y_start = io->crop_top;
- *in_data += delta * pixel_stride;
- }
- if (y_start >= y_end) return 0; // Crop window is empty.
-
- *in_data += io->crop_left * sizeof(uint32_t);
-
- io->mb_y = y_start - io->crop_top;
- io->mb_w = io->crop_right - io->crop_left;
- io->mb_h = y_end - y_start;
- return 1; // Non-empty crop window.
-}
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE int GetMetaIndex(
- const uint32_t* const image, int xsize, int bits, int x, int y) {
- if (bits == 0) return 0;
- return image[xsize * (y >> bits) + (x >> bits)];
-}
-
-static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
- int x, int y) {
- const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,
- hdr->huffman_subsample_bits_, x, y);
- assert(meta_index < hdr->num_htree_groups_);
- return hdr->htree_groups_ + meta_index;
-}
-
-//------------------------------------------------------------------------------
-// Main loop, with custom row-processing function
-
-typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
-
-static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
- const uint32_t* const rows) {
- int n = dec->next_transform_;
- const int cache_pixs = dec->width_ * num_rows;
- const int start_row = dec->last_row_;
- const int end_row = start_row + num_rows;
- const uint32_t* rows_in = rows;
- uint32_t* const rows_out = dec->argb_cache_;
-
- // Inverse transforms.
- // TODO: most transforms only need to operate on the cropped region only.
- memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
- while (n-- > 0) {
- VP8LTransform* const transform = &dec->transforms_[n];
- VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
- rows_in = rows_out;
- }
-}
-
-// Processes (transforms, scales & color-converts) the rows decoded after the
-// last call.
-static void ProcessRows(VP8LDecoder* const dec, int row) {
- const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;
- const int num_rows = row - dec->last_row_;
-
- assert(row <= dec->io_->crop_bottom);
- // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size
- // of argb_cache_), but we currently don't need more than that.
- assert(num_rows <= NUM_ARGB_CACHE_ROWS);
- if (num_rows > 0) { // Emit output.
- VP8Io* const io = dec->io_;
- uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
- const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
-
- ApplyInverseTransforms(dec, num_rows, rows);
- if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
- // Nothing to output (this time).
- } else {
- const WebPDecBuffer* const output = dec->output_;
- if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA
- const WebPRGBABuffer* const buf = &output->u.RGBA;
- uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
- const int num_rows_out = io->use_scaling ?
- EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
- rgba, buf->stride) :
- EmitRows(output->colorspace, rows_data, in_stride,
- io->mb_w, io->mb_h, rgba, buf->stride);
- // Update 'last_out_row_'.
- dec->last_out_row_ += num_rows_out;
- } else { // convert to YUVA
- dec->last_out_row_ = io->use_scaling ?
- EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
- EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
- }
- assert(dec->last_out_row_ <= output->height);
- }
- }
-
- // Update 'last_row_'.
- dec->last_row_ = row;
- assert(dec->last_row_ <= dec->height_);
-}
-
-// Row-processing for the special case when alpha data contains only one
-// transform (color indexing), and trivial non-green literals.
-static int Is8bOptimizable(const VP8LMetadata* const hdr) {
- int i;
- if (hdr->color_cache_size_ > 0) return 0;
- // When the Huffman tree contains only one symbol, we can skip the
- // call to ReadSymbol() for red/blue/alpha channels.
- for (i = 0; i < hdr->num_htree_groups_; ++i) {
- HuffmanCode** const htrees = hdr->htree_groups_[i].htrees;
- if (htrees[RED][0].bits > 0) return 0;
- if (htrees[BLUE][0].bits > 0) return 0;
- if (htrees[ALPHA][0].bits > 0) return 0;
- }
- return 1;
-}
-
-static void AlphaApplyFilter(ALPHDecoder* const alph_dec,
- int first_row, int last_row,
- uint8_t* out, int stride) {
- if (alph_dec->filter_ != WEBP_FILTER_NONE) {
- int y;
- const uint8_t* prev_line = alph_dec->prev_line_;
- assert(WebPUnfilters[alph_dec->filter_] != NULL);
- for (y = first_row; y < last_row; ++y) {
- WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride);
- prev_line = out;
- out += stride;
- }
- alph_dec->prev_line_ = prev_line;
- }
-}
-
-static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {
- // For vertical and gradient filtering, we need to decode the part above the
- // crop_top row, in order to have the correct spatial predictors.
- ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
- const int top_row =
- (alph_dec->filter_ == WEBP_FILTER_NONE ||
- alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top
- : dec->last_row_;
- const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_;
- assert(last_row <= dec->io_->crop_bottom);
- if (last_row > first_row) {
- // Special method for paletted alpha data. We only process the cropped area.
- const int width = dec->io_->width;
- uint8_t* out = alph_dec->output_ + width * first_row;
- const uint8_t* const in =
- (uint8_t*)dec->pixels_ + dec->width_ * first_row;
- VP8LTransform* const transform = &dec->transforms_[0];
- assert(dec->next_transform_ == 1);
- assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
- VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,
- in, out);
- AlphaApplyFilter(alph_dec, first_row, last_row, out, width);
- }
- dec->last_row_ = dec->last_out_row_ = last_row;
-}
-
-//------------------------------------------------------------------------------
-// Helper functions for fast pattern copy (8b and 32b)
-
-// cyclic rotation of pattern word
-static WEBP_INLINE uint32_t Rotate8b(uint32_t V) {
-#if defined(WORDS_BIGENDIAN)
- return ((V & 0xff000000u) >> 24) | (V << 8);
-#else
- return ((V & 0xffu) << 24) | (V >> 8);
-#endif
-}
-
-// copy 1, 2 or 4-bytes pattern
-static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst,
- int length, uint32_t pattern) {
- int i;
- // align 'dst' to 4-bytes boundary. Adjust the pattern along the way.
- while ((uintptr_t)dst & 3) {
- *dst++ = *src++;
- pattern = Rotate8b(pattern);
- --length;
- }
- // Copy the pattern 4 bytes at a time.
- for (i = 0; i < (length >> 2); ++i) {
- ((uint32_t*)dst)[i] = pattern;
- }
- // Finish with left-overs. 'pattern' is still correctly positioned,
- // so no Rotate8b() call is needed.
- for (i <<= 2; i < length; ++i) {
- dst[i] = src[i];
- }
-}
-
-static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
- const uint8_t* src = dst - dist;
- if (length >= 8) {
- uint32_t pattern = 0;
- switch (dist) {
- case 1:
- pattern = src[0];
-#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much
- pattern |= pattern << 8;
- pattern |= pattern << 16;
-#elif defined(WEBP_USE_MIPS_DSP_R2)
- __asm__ volatile ("replv.qb %0, %0" : "+r"(pattern));
-#else
- pattern = 0x01010101u * pattern;
-#endif
- break;
- case 2:
- memcpy(&pattern, src, sizeof(uint16_t));
-#if defined(__arm__) || defined(_M_ARM)
- pattern |= pattern << 16;
-#elif defined(WEBP_USE_MIPS_DSP_R2)
- __asm__ volatile ("replv.ph %0, %0" : "+r"(pattern));
-#else
- pattern = 0x00010001u * pattern;
-#endif
- break;
- case 4:
- memcpy(&pattern, src, sizeof(uint32_t));
- break;
- default:
- goto Copy;
- break;
- }
- CopySmallPattern8b(src, dst, length, pattern);
- return;
- }
- Copy:
- if (dist >= length) { // no overlap -> use memcpy()
- memcpy(dst, src, length * sizeof(*dst));
- } else {
- int i;
- for (i = 0; i < length; ++i) dst[i] = src[i];
- }
-}
-
-// copy pattern of 1 or 2 uint32_t's
-static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,
- uint32_t* dst,
- int length, uint64_t pattern) {
- int i;
- if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary.
- *dst++ = *src++;
- pattern = (pattern >> 32) | (pattern << 32);
- --length;
- }
- assert(0 == ((uintptr_t)dst & 7));
- for (i = 0; i < (length >> 1); ++i) {
- ((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time.
- }
- if (length & 1) { // Finish with left-over.
- dst[i << 1] = src[i << 1];
- }
-}
-
-static WEBP_INLINE void CopyBlock32b(uint32_t* const dst,
- int dist, int length) {
- const uint32_t* const src = dst - dist;
- if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {
- uint64_t pattern;
- if (dist == 1) {
- pattern = (uint64_t)src[0];
- pattern |= pattern << 32;
- } else {
- memcpy(&pattern, src, sizeof(pattern));
- }
- CopySmallPattern32b(src, dst, length, pattern);
- } else if (dist >= length) { // no overlap
- memcpy(dst, src, length * sizeof(*dst));
- } else {
- int i;
- for (i = 0; i < length; ++i) dst[i] = src[i];
- }
-}
-
-//------------------------------------------------------------------------------
-
-static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
- int width, int height, int last_row) {
- int ok = 1;
- int row = dec->last_pixel_ / width;
- int col = dec->last_pixel_ % width;
- VP8LBitReader* const br = &dec->br_;
- VP8LMetadata* const hdr = &dec->hdr_;
- int pos = dec->last_pixel_; // current position
- const int end = width * height; // End of data
- const int last = width * last_row; // Last pixel to decode
- const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
- const int mask = hdr->huffman_mask_;
- const HTreeGroup* htree_group =
- (pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
- assert(pos <= end);
- assert(last_row <= height);
- assert(Is8bOptimizable(hdr));
-
- while (!br->eos_ && pos < last) {
- int code;
- // Only update when changing tile.
- if ((col & mask) == 0) {
- htree_group = GetHtreeGroupForPos(hdr, col, row);
- }
- assert(htree_group != NULL);
- VP8LFillBitWindow(br);
- code = ReadSymbol(htree_group->htrees[GREEN], br);
- if (code < NUM_LITERAL_CODES) { // Literal
- data[pos] = code;
- ++pos;
- ++col;
- if (col >= width) {
- col = 0;
- ++row;
- if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
- ExtractPalettedAlphaRows(dec, row);
- }
- }
- } else if (code < len_code_limit) { // Backward reference
- int dist_code, dist;
- const int length_sym = code - NUM_LITERAL_CODES;
- const int length = GetCopyLength(length_sym, br);
- const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);
- VP8LFillBitWindow(br);
- dist_code = GetCopyDistance(dist_symbol, br);
- dist = PlaneCodeToDistance(width, dist_code);
- if (pos >= dist && end - pos >= length) {
- CopyBlock8b(data + pos, dist, length);
- } else {
- ok = 0;
- goto End;
- }
- pos += length;
- col += length;
- while (col >= width) {
- col -= width;
- ++row;
- if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
- ExtractPalettedAlphaRows(dec, row);
- }
- }
- if (pos < last && (col & mask)) {
- htree_group = GetHtreeGroupForPos(hdr, col, row);
- }
- } else { // Not reached
- ok = 0;
- goto End;
- }
- assert(br->eos_ == VP8LIsEndOfStream(br));
- }
- // Process the remaining rows corresponding to last row-block.
- ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);
-
- End:
- if (!ok || (br->eos_ && pos < end)) {
- ok = 0;
- dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
- : VP8_STATUS_BITSTREAM_ERROR;
- } else {
- dec->last_pixel_ = pos;
- }
- return ok;
-}
-
-static void SaveState(VP8LDecoder* const dec, int last_pixel) {
- assert(dec->incremental_);
- dec->saved_br_ = dec->br_;
- dec->saved_last_pixel_ = last_pixel;
- if (dec->hdr_.color_cache_size_ > 0) {
- VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_);
- }
-}
-
-static void RestoreState(VP8LDecoder* const dec) {
- assert(dec->br_.eos_);
- dec->status_ = VP8_STATUS_SUSPENDED;
- dec->br_ = dec->saved_br_;
- dec->last_pixel_ = dec->saved_last_pixel_;
- if (dec->hdr_.color_cache_size_ > 0) {
- VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_);
- }
-}
-
-#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points
-static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
- int width, int height, int last_row,
- ProcessRowsFunc process_func) {
- int row = dec->last_pixel_ / width;
- int col = dec->last_pixel_ % width;
- VP8LBitReader* const br = &dec->br_;
- VP8LMetadata* const hdr = &dec->hdr_;
- uint32_t* src = data + dec->last_pixel_;
- uint32_t* last_cached = src;
- uint32_t* const src_end = data + width * height; // End of data
- uint32_t* const src_last = data + width * last_row; // Last pixel to decode
- const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
- const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
- int next_sync_row = dec->incremental_ ? row : 1 << 24;
- VP8LColorCache* const color_cache =
- (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
- const int mask = hdr->huffman_mask_;
- const HTreeGroup* htree_group =
- (src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
- assert(dec->last_row_ < last_row);
- assert(src_last <= src_end);
-
- while (src < src_last) {
- int code;
- if (row >= next_sync_row) {
- SaveState(dec, (int)(src - data));
- next_sync_row = row + SYNC_EVERY_N_ROWS;
- }
- // Only update when changing tile. Note we could use this test:
- // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
- // but that's actually slower and needs storing the previous col/row.
- if ((col & mask) == 0) {
- htree_group = GetHtreeGroupForPos(hdr, col, row);
- }
- assert(htree_group != NULL);
- if (htree_group->is_trivial_code) {
- *src = htree_group->literal_arb;
- goto AdvanceByOne;
- }
- VP8LFillBitWindow(br);
- if (htree_group->use_packed_table) {
- code = ReadPackedSymbols(htree_group, br, src);
- if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne;
- } else {
- code = ReadSymbol(htree_group->htrees[GREEN], br);
- }
- if (br->eos_) break; // early out
- if (code < NUM_LITERAL_CODES) { // Literal
- if (htree_group->is_trivial_literal) {
- *src = htree_group->literal_arb | (code << 8);
- } else {
- int red, blue, alpha;
- red = ReadSymbol(htree_group->htrees[RED], br);
- VP8LFillBitWindow(br);
- blue = ReadSymbol(htree_group->htrees[BLUE], br);
- alpha = ReadSymbol(htree_group->htrees[ALPHA], br);
- if (br->eos_) break;
- *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue;
- }
- AdvanceByOne:
- ++src;
- ++col;
- if (col >= width) {
- col = 0;
- ++row;
- if (process_func != NULL) {
- if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
- process_func(dec, row);
- }
- }
- if (color_cache != NULL) {
- while (last_cached < src) {
- VP8LColorCacheInsert(color_cache, *last_cached++);
- }
- }
- }
- } else if (code < len_code_limit) { // Backward reference
- int dist_code, dist;
- const int length_sym = code - NUM_LITERAL_CODES;
- const int length = GetCopyLength(length_sym, br);
- const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);
- VP8LFillBitWindow(br);
- dist_code = GetCopyDistance(dist_symbol, br);
- dist = PlaneCodeToDistance(width, dist_code);
- if (br->eos_) break;
- if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
- goto Error;
- } else {
- CopyBlock32b(src, dist, length);
- }
- src += length;
- col += length;
- while (col >= width) {
- col -= width;
- ++row;
- if (process_func != NULL) {
- if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
- process_func(dec, row);
- }
- }
- }
- // Because of the check done above (before 'src' was incremented by
- // 'length'), the following holds true.
- assert(src <= src_end);
- if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
- if (color_cache != NULL) {
- while (last_cached < src) {
- VP8LColorCacheInsert(color_cache, *last_cached++);
- }
- }
- } else if (code < color_cache_limit) { // Color cache
- const int key = code - len_code_limit;
- assert(color_cache != NULL);
- while (last_cached < src) {
- VP8LColorCacheInsert(color_cache, *last_cached++);
- }
- *src = VP8LColorCacheLookup(color_cache, key);
- goto AdvanceByOne;
- } else { // Not reached
- goto Error;
- }
- assert(br->eos_ == VP8LIsEndOfStream(br));
- }
-
- if (dec->incremental_ && br->eos_ && src < src_end) {
- RestoreState(dec);
- } else if (!br->eos_) {
- // Process the remaining rows corresponding to last row-block.
- if (process_func != NULL) {
- process_func(dec, row > last_row ? last_row : row);
- }
- dec->status_ = VP8_STATUS_OK;
- dec->last_pixel_ = (int)(src - data); // end-of-scan marker
- } else {
- // if not incremental, and we are past the end of buffer (eos_=1), then this
- // is a real bitstream error.
- goto Error;
- }
- return 1;
-
- Error:
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return 0;
-}
-
-// -----------------------------------------------------------------------------
-// VP8LTransform
-
-static void ClearTransform(VP8LTransform* const transform) {
- WebPSafeFree(transform->data_);
- transform->data_ = NULL;
-}
-
-// For security reason, we need to remap the color map to span
-// the total possible bundled values, and not just the num_colors.
-static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
- int i;
- const int final_num_colors = 1 << (8 >> transform->bits_);
- uint32_t* const new_color_map =
- (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
- sizeof(*new_color_map));
- if (new_color_map == NULL) {
- return 0;
- } else {
- uint8_t* const data = (uint8_t*)transform->data_;
- uint8_t* const new_data = (uint8_t*)new_color_map;
- new_color_map[0] = transform->data_[0];
- for (i = 4; i < 4 * num_colors; ++i) {
- // Equivalent to AddPixelEq(), on a byte-basis.
- new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
- }
- for (; i < 4 * final_num_colors; ++i)
- new_data[i] = 0; // black tail.
- WebPSafeFree(transform->data_);
- transform->data_ = new_color_map;
- }
- return 1;
-}
-
-static int ReadTransform(int* const xsize, int const* ysize,
- VP8LDecoder* const dec) {
- int ok = 1;
- VP8LBitReader* const br = &dec->br_;
- VP8LTransform* transform = &dec->transforms_[dec->next_transform_];
- const VP8LImageTransformType type =
- (VP8LImageTransformType)VP8LReadBits(br, 2);
-
- // Each transform type can only be present once in the stream.
- if (dec->transforms_seen_ & (1U << type)) {
- return 0; // Already there, let's not accept the second same transform.
- }
- dec->transforms_seen_ |= (1U << type);
-
- transform->type_ = type;
- transform->xsize_ = *xsize;
- transform->ysize_ = *ysize;
- transform->data_ = NULL;
- ++dec->next_transform_;
- assert(dec->next_transform_ <= NUM_TRANSFORMS);
-
- switch (type) {
- case PREDICTOR_TRANSFORM:
- case CROSS_COLOR_TRANSFORM:
- transform->bits_ = VP8LReadBits(br, 3) + 2;
- ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
- transform->bits_),
- VP8LSubSampleSize(transform->ysize_,
- transform->bits_),
- 0, dec, &transform->data_);
- break;
- case COLOR_INDEXING_TRANSFORM: {
- const int num_colors = VP8LReadBits(br, 8) + 1;
- const int bits = (num_colors > 16) ? 0
- : (num_colors > 4) ? 1
- : (num_colors > 2) ? 2
- : 3;
- *xsize = VP8LSubSampleSize(transform->xsize_, bits);
- transform->bits_ = bits;
- ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);
- ok = ok && ExpandColorMap(num_colors, transform);
- break;
- }
- case SUBTRACT_GREEN:
- break;
- default:
- assert(0); // can't happen
- break;
- }
-
- return ok;
-}
-
-// -----------------------------------------------------------------------------
-// VP8LMetadata
-
-static void InitMetadata(VP8LMetadata* const hdr) {
- assert(hdr != NULL);
- memset(hdr, 0, sizeof(*hdr));
-}
-
-static void ClearMetadata(VP8LMetadata* const hdr) {
- assert(hdr != NULL);
-
- WebPSafeFree(hdr->huffman_image_);
- WebPSafeFree(hdr->huffman_tables_);
- VP8LHtreeGroupsFree(hdr->htree_groups_);
- VP8LColorCacheClear(&hdr->color_cache_);
- VP8LColorCacheClear(&hdr->saved_color_cache_);
- InitMetadata(hdr);
-}
-
-// -----------------------------------------------------------------------------
-// VP8LDecoder
-
-VP8LDecoder* VP8LNew(void) {
- VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
- if (dec == NULL) return NULL;
- dec->status_ = VP8_STATUS_OK;
- dec->state_ = READ_DIM;
-
- VP8LDspInit(); // Init critical function pointers.
-
- return dec;
-}
-
-void VP8LClear(VP8LDecoder* const dec) {
- int i;
- if (dec == NULL) return;
- ClearMetadata(&dec->hdr_);
-
- WebPSafeFree(dec->pixels_);
- dec->pixels_ = NULL;
- for (i = 0; i < dec->next_transform_; ++i) {
- ClearTransform(&dec->transforms_[i]);
- }
- dec->next_transform_ = 0;
- dec->transforms_seen_ = 0;
-
- WebPSafeFree(dec->rescaler_memory);
- dec->rescaler_memory = NULL;
-
- dec->output_ = NULL; // leave no trace behind
-}
-
-void VP8LDelete(VP8LDecoder* const dec) {
- if (dec != NULL) {
- VP8LClear(dec);
- WebPSafeFree(dec);
- }
-}
-
-static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
- VP8LMetadata* const hdr = &dec->hdr_;
- const int num_bits = hdr->huffman_subsample_bits_;
- dec->width_ = width;
- dec->height_ = height;
-
- hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);
- hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
-}
-
-static int DecodeImageStream(int xsize, int ysize,
- int is_level0,
- VP8LDecoder* const dec,
- uint32_t** const decoded_data) {
- int ok = 1;
- int transform_xsize = xsize;
- int transform_ysize = ysize;
- VP8LBitReader* const br = &dec->br_;
- VP8LMetadata* const hdr = &dec->hdr_;
- uint32_t* data = NULL;
- int color_cache_bits = 0;
-
- // Read the transforms (may recurse).
- if (is_level0) {
- while (ok && VP8LReadBits(br, 1)) {
- ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
- }
- }
-
- // Color cache
- if (ok && VP8LReadBits(br, 1)) {
- color_cache_bits = VP8LReadBits(br, 4);
- ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
- if (!ok) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto End;
- }
- }
-
- // Read the Huffman codes (may recurse).
- ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
- color_cache_bits, is_level0);
- if (!ok) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto End;
- }
-
- // Finish setting up the color-cache
- if (color_cache_bits > 0) {
- hdr->color_cache_size_ = 1 << color_cache_bits;
- if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- ok = 0;
- goto End;
- }
- } else {
- hdr->color_cache_size_ = 0;
- }
- UpdateDecoder(dec, transform_xsize, transform_ysize);
-
- if (is_level0) { // level 0 complete
- dec->state_ = READ_HDR;
- goto End;
- }
-
- {
- const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
- data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
- if (data == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- ok = 0;
- goto End;
- }
- }
-
- // Use the Huffman trees to decode the LZ77 encoded data.
- ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
- transform_ysize, NULL);
- ok = ok && !br->eos_;
-
- End:
- if (!ok) {
- WebPSafeFree(data);
- ClearMetadata(hdr);
- } else {
- if (decoded_data != NULL) {
- *decoded_data = data;
- } else {
- // We allocate image data in this function only for transforms. At level 0
- // (that is: not the transforms), we shouldn't have allocated anything.
- assert(data == NULL);
- assert(is_level0);
- }
- dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.
- if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// Allocate internal buffers dec->pixels_ and dec->argb_cache_.
-static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
- const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
- // Scratch buffer corresponding to top-prediction row for transforming the
- // first row in the row-blocks. Not needed for paletted alpha.
- const uint64_t cache_top_pixels = (uint16_t)final_width;
- // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
- const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
- const uint64_t total_num_pixels =
- num_pixels + cache_top_pixels + cache_pixels;
-
- assert(dec->width_ <= final_width);
- dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
- if (dec->pixels_ == NULL) {
- dec->argb_cache_ = NULL; // for sanity check
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- return 0;
- }
- dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
- return 1;
-}
-
-static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
- const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
- dec->argb_cache_ = NULL; // for sanity check
- dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
- if (dec->pixels_ == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- return 0;
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-// Special row-processing that only stores the alpha data.
-static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
- int cur_row = dec->last_row_;
- int num_rows = last_row - cur_row;
- const uint32_t* in = dec->pixels_ + dec->width_ * cur_row;
-
- assert(last_row <= dec->io_->crop_bottom);
- while (num_rows > 0) {
- const int num_rows_to_process =
- (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;
- // Extract alpha (which is stored in the green plane).
- ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
- uint8_t* const output = alph_dec->output_;
- const int width = dec->io_->width; // the final width (!= dec->width_)
- const int cache_pixs = width * num_rows_to_process;
- uint8_t* const dst = output + width * cur_row;
- const uint32_t* const src = dec->argb_cache_;
- int i;
- ApplyInverseTransforms(dec, num_rows_to_process, in);
- for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
- AlphaApplyFilter(alph_dec,
- cur_row, cur_row + num_rows_to_process, dst, width);
- num_rows -= num_rows_to_process;
- in += num_rows_to_process * dec->width_;
- cur_row += num_rows_to_process;
- }
- assert(cur_row == last_row);
- dec->last_row_ = dec->last_out_row_ = last_row;
-}
-
-int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
- const uint8_t* const data, size_t data_size) {
- int ok = 0;
- VP8LDecoder* dec = VP8LNew();
-
- if (dec == NULL) return 0;
-
- assert(alph_dec != NULL);
- alph_dec->vp8l_dec_ = dec;
-
- dec->width_ = alph_dec->width_;
- dec->height_ = alph_dec->height_;
- dec->io_ = &alph_dec->io_;
- dec->io_->opaque = alph_dec;
- dec->io_->width = alph_dec->width_;
- dec->io_->height = alph_dec->height_;
-
- dec->status_ = VP8_STATUS_OK;
- VP8LInitBitReader(&dec->br_, data, data_size);
-
- if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
- goto Err;
- }
-
- // Special case: if alpha data uses only the color indexing transform and
- // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
- // method that only needs allocation of 1 byte per pixel (alpha channel).
- if (dec->next_transform_ == 1 &&
- dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&
- Is8bOptimizable(&dec->hdr_)) {
- alph_dec->use_8b_decode_ = 1;
- ok = AllocateInternalBuffers8b(dec);
- } else {
- // Allocate internal buffers (note that dec->width_ may have changed here).
- alph_dec->use_8b_decode_ = 0;
- ok = AllocateInternalBuffers32b(dec, alph_dec->width_);
- }
-
- if (!ok) goto Err;
-
- return 1;
-
- Err:
- VP8LDelete(alph_dec->vp8l_dec_);
- alph_dec->vp8l_dec_ = NULL;
- return 0;
-}
-
-int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
- VP8LDecoder* const dec = alph_dec->vp8l_dec_;
- assert(dec != NULL);
- assert(last_row <= dec->height_);
-
- if (dec->last_row_ >= last_row) {
- return 1; // done
- }
-
- // Decode (with special row processing).
- return alph_dec->use_8b_decode_ ?
- DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,
- last_row) :
- DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
- last_row, ExtractAlphaRows);
-}
-
-//------------------------------------------------------------------------------
-
-int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
- int width, height, has_alpha;
-
- if (dec == NULL) return 0;
- if (io == NULL) {
- dec->status_ = VP8_STATUS_INVALID_PARAM;
- return 0;
- }
-
- dec->io_ = io;
- dec->status_ = VP8_STATUS_OK;
- VP8LInitBitReader(&dec->br_, io->data, io->data_size);
- if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto Error;
- }
- dec->state_ = READ_DIM;
- io->width = width;
- io->height = height;
-
- if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
- return 1;
-
- Error:
- VP8LClear(dec);
- assert(dec->status_ != VP8_STATUS_OK);
- return 0;
-}
-
-int VP8LDecodeImage(VP8LDecoder* const dec) {
- VP8Io* io = NULL;
- WebPDecParams* params = NULL;
-
- // Sanity checks.
- if (dec == NULL) return 0;
-
- assert(dec->hdr_.huffman_tables_ != NULL);
- assert(dec->hdr_.htree_groups_ != NULL);
- assert(dec->hdr_.num_htree_groups_ > 0);
-
- io = dec->io_;
- assert(io != NULL);
- params = (WebPDecParams*)io->opaque;
- assert(params != NULL);
-
- // Initialization.
- if (dec->state_ != READ_DATA) {
- dec->output_ = params->output;
- assert(dec->output_ != NULL);
-
- if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
- dec->status_ = VP8_STATUS_INVALID_PARAM;
- goto Err;
- }
-
- if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
-
- if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
-
- if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
- // need the alpha-multiply functions for premultiplied output or rescaling
- WebPInitAlphaProcessing();
- }
- if (!WebPIsRGBMode(dec->output_->colorspace)) {
- WebPInitConvertARGBToYUV();
- if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();
- }
- if (dec->incremental_) {
- if (dec->hdr_.color_cache_size_ > 0 &&
- dec->hdr_.saved_color_cache_.colors_ == NULL) {
- if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_,
- dec->hdr_.color_cache_.hash_bits_)) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- goto Err;
- }
- }
- }
- dec->state_ = READ_DATA;
- }
-
- // Decode.
- if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
- io->crop_bottom, ProcessRows)) {
- goto Err;
- }
-
- params->last_y = dec->last_out_row_;
- return 1;
-
- Err:
- VP8LClear(dec);
- assert(dec->status_ != VP8_STATUS_OK);
- return 0;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dec/vp8li.h b/drivers/webp/dec/vp8li.h
deleted file mode 100644
index 9313bdc0af..0000000000
--- a/drivers/webp/dec/vp8li.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Lossless decoder: internal header.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-// Vikas Arora(vikaas.arora@gmail.com)
-
-#ifndef WEBP_DEC_VP8LI_H_
-#define WEBP_DEC_VP8LI_H_
-
-#include <string.h> // for memcpy()
-#include "./webpi.h"
-#include "../utils/bit_reader.h"
-#include "../utils/color_cache.h"
-#include "../utils/huffman.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum {
- READ_DATA = 0,
- READ_HDR = 1,
- READ_DIM = 2
-} VP8LDecodeState;
-
-typedef struct VP8LTransform VP8LTransform;
-struct VP8LTransform {
- VP8LImageTransformType type_; // transform type.
- int bits_; // subsampling bits defining transform window.
- int xsize_; // transform window X index.
- int ysize_; // transform window Y index.
- uint32_t *data_; // transform data.
-};
-
-typedef struct {
- int color_cache_size_;
- VP8LColorCache color_cache_;
- VP8LColorCache saved_color_cache_; // for incremental
-
- int huffman_mask_;
- int huffman_subsample_bits_;
- int huffman_xsize_;
- uint32_t *huffman_image_;
- int num_htree_groups_;
- HTreeGroup *htree_groups_;
- HuffmanCode *huffman_tables_;
-} VP8LMetadata;
-
-typedef struct VP8LDecoder VP8LDecoder;
-struct VP8LDecoder {
- VP8StatusCode status_;
- VP8LDecodeState state_;
- VP8Io *io_;
-
- const WebPDecBuffer *output_; // shortcut to io->opaque->output
-
- uint32_t *pixels_; // Internal data: either uint8_t* for alpha
- // or uint32_t* for BGRA.
- uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
-
- VP8LBitReader br_;
- int incremental_; // if true, incremental decoding is expected
- VP8LBitReader saved_br_; // note: could be local variables too
- int saved_last_pixel_;
-
- int width_;
- int height_;
- int last_row_; // last input row decoded so far.
- int last_pixel_; // last pixel decoded so far. However, it may
- // not be transformed, scaled and
- // color-converted yet.
- int last_out_row_; // last row output so far.
-
- VP8LMetadata hdr_;
-
- int next_transform_;
- VP8LTransform transforms_[NUM_TRANSFORMS];
- // or'd bitset storing the transforms types.
- uint32_t transforms_seen_;
-
- uint8_t *rescaler_memory; // Working memory for rescaling work.
- WebPRescaler *rescaler; // Common rescaler for all channels.
-};
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
-struct ALPHDecoder; // Defined in dec/alphai.h.
-
-// in vp8l.c
-
-// Decodes image header for alpha data stored using lossless compression.
-// Returns false in case of error.
-int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec,
- const uint8_t* const data, size_t data_size);
-
-// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are
-// already decoded in previous call(s), it will resume decoding from where it
-// was paused.
-// Returns false in case of bitstream error.
-int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec,
- int last_row);
-
-// Allocates and initialize a new lossless decoder instance.
-VP8LDecoder* VP8LNew(void);
-
-// Decodes the image header. Returns false in case of error.
-int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io);
-
-// Decodes an image. It's required to decode the lossless header before calling
-// this function. Returns false in case of error, with updated dec->status_.
-int VP8LDecodeImage(VP8LDecoder* const dec);
-
-// Resets the decoder in its initial state, reclaiming memory.
-// Preserves the dec->status_ value.
-void VP8LClear(VP8LDecoder* const dec);
-
-// Clears and deallocate a lossless decoder instance.
-void VP8LDelete(VP8LDecoder* const dec);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_VP8LI_H_ */
diff --git a/drivers/webp/dec/webp.c b/drivers/webp/dec/webp.c
deleted file mode 100644
index dd6c090f00..0000000000
--- a/drivers/webp/dec/webp.c
+++ /dev/null
@@ -1,846 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Main decoding functions for WEBP images.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-
-#include "./vp8i.h"
-#include "./vp8li.h"
-#include "./webpi.h"
-#include "../utils/utils.h"
-#include "webp/mux_types.h" // ALPHA_FLAG
-
-//------------------------------------------------------------------------------
-// RIFF layout is:
-// Offset tag
-// 0...3 "RIFF" 4-byte tag
-// 4...7 size of image data (including metadata) starting at offset 8
-// 8...11 "WEBP" our form-type signature
-// The RIFF container (12 bytes) is followed by appropriate chunks:
-// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format
-// 16..19 size of the raw VP8 image data, starting at offset 20
-// 20.... the VP8 bytes
-// Or,
-// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format
-// 16..19 size of the raw VP8L image data, starting at offset 20
-// 20.... the VP8L bytes
-// Or,
-// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk.
-// 16..19 size of the VP8X chunk starting at offset 20.
-// 20..23 VP8X flags bit-map corresponding to the chunk-types present.
-// 24..26 Width of the Canvas Image.
-// 27..29 Height of the Canvas Image.
-// There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8,
-// VP8L, XMP, EXIF ...)
-// All sizes are in little-endian order.
-// Note: chunk data size must be padded to multiple of 2 when written.
-
-// Validates the RIFF container (if detected) and skips over it.
-// If a RIFF container is detected, returns:
-// VP8_STATUS_BITSTREAM_ERROR for invalid header,
-// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true,
-// and VP8_STATUS_OK otherwise.
-// In case there are not enough bytes (partial RIFF container), return 0 for
-// *riff_size. Else return the RIFF size extracted from the header.
-static VP8StatusCode ParseRIFF(const uint8_t** const data,
- size_t* const data_size, int have_all_data,
- size_t* const riff_size) {
- assert(data != NULL);
- assert(data_size != NULL);
- assert(riff_size != NULL);
-
- *riff_size = 0; // Default: no RIFF present.
- if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) {
- if (memcmp(*data + 8, "WEBP", TAG_SIZE)) {
- return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature.
- } else {
- const uint32_t size = GetLE32(*data + TAG_SIZE);
- // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn").
- if (size < TAG_SIZE + CHUNK_HEADER_SIZE) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- if (size > MAX_CHUNK_PAYLOAD) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) {
- return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream.
- }
- // We have a RIFF container. Skip it.
- *riff_size = size;
- *data += RIFF_HEADER_SIZE;
- *data_size -= RIFF_HEADER_SIZE;
- }
- }
- return VP8_STATUS_OK;
-}
-
-// Validates the VP8X header and skips over it.
-// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header,
-// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
-// VP8_STATUS_OK otherwise.
-// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr,
-// *height_ptr and *flags_ptr are set to the corresponding values extracted
-// from the VP8X chunk.
-static VP8StatusCode ParseVP8X(const uint8_t** const data,
- size_t* const data_size,
- int* const found_vp8x,
- int* const width_ptr, int* const height_ptr,
- uint32_t* const flags_ptr) {
- const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
- assert(data != NULL);
- assert(data_size != NULL);
- assert(found_vp8x != NULL);
-
- *found_vp8x = 0;
-
- if (*data_size < CHUNK_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
- }
-
- if (!memcmp(*data, "VP8X", TAG_SIZE)) {
- int width, height;
- uint32_t flags;
- const uint32_t chunk_size = GetLE32(*data + TAG_SIZE);
- if (chunk_size != VP8X_CHUNK_SIZE) {
- return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size.
- }
-
- // Verify if enough data is available to validate the VP8X chunk.
- if (*data_size < vp8x_size) {
- return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
- }
- flags = GetLE32(*data + 8);
- width = 1 + GetLE24(*data + 12);
- height = 1 + GetLE24(*data + 15);
- if (width * (uint64_t)height >= MAX_IMAGE_AREA) {
- return VP8_STATUS_BITSTREAM_ERROR; // image is too large
- }
-
- if (flags_ptr != NULL) *flags_ptr = flags;
- if (width_ptr != NULL) *width_ptr = width;
- if (height_ptr != NULL) *height_ptr = height;
- // Skip over VP8X header bytes.
- *data += vp8x_size;
- *data_size -= vp8x_size;
- *found_vp8x = 1;
- }
- return VP8_STATUS_OK;
-}
-
-// Skips to the next VP8/VP8L chunk header in the data given the size of the
-// RIFF chunk 'riff_size'.
-// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered,
-// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
-// VP8_STATUS_OK otherwise.
-// If an alpha chunk is found, *alpha_data and *alpha_size are set
-// appropriately.
-static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
- size_t* const data_size,
- size_t const riff_size,
- const uint8_t** const alpha_data,
- size_t* const alpha_size) {
- const uint8_t* buf;
- size_t buf_size;
- uint32_t total_size = TAG_SIZE + // "WEBP".
- CHUNK_HEADER_SIZE + // "VP8Xnnnn".
- VP8X_CHUNK_SIZE; // data.
- assert(data != NULL);
- assert(data_size != NULL);
- buf = *data;
- buf_size = *data_size;
-
- assert(alpha_data != NULL);
- assert(alpha_size != NULL);
- *alpha_data = NULL;
- *alpha_size = 0;
-
- while (1) {
- uint32_t chunk_size;
- uint32_t disk_chunk_size; // chunk_size with padding
-
- *data = buf;
- *data_size = buf_size;
-
- if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data.
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
-
- chunk_size = GetLE32(buf + TAG_SIZE);
- if (chunk_size > MAX_CHUNK_PAYLOAD) {
- return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
- }
- // For odd-sized chunk-payload, there's one byte padding at the end.
- disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1;
- total_size += disk_chunk_size;
-
- // Check that total bytes skipped so far does not exceed riff_size.
- if (riff_size > 0 && (total_size > riff_size)) {
- return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
- }
-
- // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have
- // parsed all the optional chunks.
- // Note: This check must occur before the check 'buf_size < disk_chunk_size'
- // below to allow incomplete VP8/VP8L chunks.
- if (!memcmp(buf, "VP8 ", TAG_SIZE) ||
- !memcmp(buf, "VP8L", TAG_SIZE)) {
- return VP8_STATUS_OK;
- }
-
- if (buf_size < disk_chunk_size) { // Insufficient data.
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
-
- if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header.
- *alpha_data = buf + CHUNK_HEADER_SIZE;
- *alpha_size = chunk_size;
- }
-
- // We have a full and valid chunk; skip it.
- buf += disk_chunk_size;
- buf_size -= disk_chunk_size;
- }
-}
-
-// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it.
-// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than
-// riff_size) VP8/VP8L header,
-// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
-// VP8_STATUS_OK otherwise.
-// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes
-// extracted from the VP8/VP8L chunk header.
-// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data.
-static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr,
- size_t* const data_size, int have_all_data,
- size_t riff_size, size_t* const chunk_size,
- int* const is_lossless) {
- const uint8_t* const data = *data_ptr;
- const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE);
- const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE);
- const uint32_t minimal_size =
- TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR
- // "WEBP" + "VP8Lnnnn"
- assert(data != NULL);
- assert(data_size != NULL);
- assert(chunk_size != NULL);
- assert(is_lossless != NULL);
-
- if (*data_size < CHUNK_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
- }
-
- if (is_vp8 || is_vp8l) {
- // Bitstream contains VP8/VP8L header.
- const uint32_t size = GetLE32(data + TAG_SIZE);
- if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) {
- return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information.
- }
- if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) {
- return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream.
- }
- // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header.
- *chunk_size = size;
- *data_ptr += CHUNK_HEADER_SIZE;
- *data_size -= CHUNK_HEADER_SIZE;
- *is_lossless = is_vp8l;
- } else {
- // Raw VP8/VP8L bitstream (no header).
- *is_lossless = VP8LCheckSignature(data, *data_size);
- *chunk_size = *data_size;
- }
-
- return VP8_STATUS_OK;
-}
-
-//------------------------------------------------------------------------------
-
-// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on
-// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the
-// minimal amount will be read to fetch the remaining parameters.
-// If 'headers' is non-NULL this function will attempt to locate both alpha
-// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L).
-// Note: The following chunk sequences (before the raw VP8/VP8L data) are
-// considered valid by this function:
-// RIFF + VP8(L)
-// RIFF + VP8X + (optional chunks) + VP8(L)
-// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
-// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
-static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
- size_t data_size,
- int* const width,
- int* const height,
- int* const has_alpha,
- int* const has_animation,
- int* const format,
- WebPHeaderStructure* const headers) {
- int canvas_width = 0;
- int canvas_height = 0;
- int image_width = 0;
- int image_height = 0;
- int found_riff = 0;
- int found_vp8x = 0;
- int animation_present = 0;
- int fragments_present = 0;
- const int have_all_data = (headers != NULL) ? headers->have_all_data : 0;
-
- VP8StatusCode status;
- WebPHeaderStructure hdrs;
-
- if (data == NULL || data_size < RIFF_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
- memset(&hdrs, 0, sizeof(hdrs));
- hdrs.data = data;
- hdrs.data_size = data_size;
-
- // Skip over RIFF header.
- status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size);
- if (status != VP8_STATUS_OK) {
- return status; // Wrong RIFF header / insufficient data.
- }
- found_riff = (hdrs.riff_size > 0);
-
- // Skip over VP8X.
- {
- uint32_t flags = 0;
- status = ParseVP8X(&data, &data_size, &found_vp8x,
- &canvas_width, &canvas_height, &flags);
- if (status != VP8_STATUS_OK) {
- return status; // Wrong VP8X / insufficient data.
- }
- animation_present = !!(flags & ANIMATION_FLAG);
- fragments_present = !!(flags & FRAGMENTS_FLAG);
- if (!found_riff && found_vp8x) {
- // Note: This restriction may be removed in the future, if it becomes
- // necessary to send VP8X chunk to the decoder.
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG);
- if (has_animation != NULL) *has_animation = animation_present;
- if (format != NULL) *format = 0; // default = undefined
-
- image_width = canvas_width;
- image_height = canvas_height;
- if (found_vp8x && (animation_present || fragments_present) &&
- headers == NULL) {
- status = VP8_STATUS_OK;
- goto ReturnWidthHeight; // Just return features from VP8X header.
- }
- }
-
- if (data_size < TAG_SIZE) {
- status = VP8_STATUS_NOT_ENOUGH_DATA;
- goto ReturnWidthHeight;
- }
-
- // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH".
- if ((found_riff && found_vp8x) ||
- (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) {
- status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size,
- &hdrs.alpha_data, &hdrs.alpha_data_size);
- if (status != VP8_STATUS_OK) {
- goto ReturnWidthHeight; // Invalid chunk size / insufficient data.
- }
- }
-
- // Skip over VP8/VP8L header.
- status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size,
- &hdrs.compressed_size, &hdrs.is_lossless);
- if (status != VP8_STATUS_OK) {
- goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data.
- }
- if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
-
- if (format != NULL && !(animation_present || fragments_present)) {
- *format = hdrs.is_lossless ? 2 : 1;
- }
-
- if (!hdrs.is_lossless) {
- if (data_size < VP8_FRAME_HEADER_SIZE) {
- status = VP8_STATUS_NOT_ENOUGH_DATA;
- goto ReturnWidthHeight;
- }
- // Validates raw VP8 data.
- if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size,
- &image_width, &image_height)) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- } else {
- if (data_size < VP8L_FRAME_HEADER_SIZE) {
- status = VP8_STATUS_NOT_ENOUGH_DATA;
- goto ReturnWidthHeight;
- }
- // Validates raw VP8L data.
- if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- }
- // Validates image size coherency.
- if (found_vp8x) {
- if (canvas_width != image_width || canvas_height != image_height) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- }
- if (headers != NULL) {
- *headers = hdrs;
- headers->offset = data - headers->data;
- assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD);
- assert(headers->offset == headers->data_size - data_size);
- }
- ReturnWidthHeight:
- if (status == VP8_STATUS_OK ||
- (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == NULL)) {
- if (has_alpha != NULL) {
- // If the data did not contain a VP8X/VP8L chunk the only definitive way
- // to set this is by looking for alpha data (from an ALPH chunk).
- *has_alpha |= (hdrs.alpha_data != NULL);
- }
- if (width != NULL) *width = image_width;
- if (height != NULL) *height = image_height;
- return VP8_STATUS_OK;
- } else {
- return status;
- }
-}
-
-VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) {
- // status is marked volatile as a workaround for a clang-3.8 (aarch64) bug
- volatile VP8StatusCode status;
- int has_animation = 0;
- assert(headers != NULL);
- // fill out headers, ignore width/height/has_alpha.
- status = ParseHeadersInternal(headers->data, headers->data_size,
- NULL, NULL, NULL, &has_animation,
- NULL, headers);
- if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) {
- // TODO(jzern): full support of animation frames will require API additions.
- if (has_animation) {
- status = VP8_STATUS_UNSUPPORTED_FEATURE;
- }
- }
- return status;
-}
-
-//------------------------------------------------------------------------------
-// WebPDecParams
-
-void WebPResetDecParams(WebPDecParams* const params) {
- if (params != NULL) {
- memset(params, 0, sizeof(*params));
- }
-}
-
-//------------------------------------------------------------------------------
-// "Into" decoding variants
-
-// Main flow
-static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
- WebPDecParams* const params) {
- VP8StatusCode status;
- VP8Io io;
- WebPHeaderStructure headers;
-
- headers.data = data;
- headers.data_size = data_size;
- headers.have_all_data = 1;
- status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks.
- if (status != VP8_STATUS_OK) {
- return status;
- }
-
- assert(params != NULL);
- VP8InitIo(&io);
- io.data = headers.data + headers.offset;
- io.data_size = headers.data_size - headers.offset;
- WebPInitCustomIo(params, &io); // Plug the I/O functions.
-
- if (!headers.is_lossless) {
- VP8Decoder* const dec = VP8New();
- if (dec == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- dec->alpha_data_ = headers.alpha_data;
- dec->alpha_data_size_ = headers.alpha_data_size;
-
- // Decode bitstream header, update io->width/io->height.
- if (!VP8GetHeaders(dec, &io)) {
- status = dec->status_; // An error occurred. Grab error status.
- } else {
- // Allocate/check output buffers.
- status = WebPAllocateDecBuffer(io.width, io.height, params->options,
- params->output);
- if (status == VP8_STATUS_OK) { // Decode
- // This change must be done before calling VP8Decode()
- dec->mt_method_ = VP8GetThreadMethod(params->options, &headers,
- io.width, io.height);
- VP8InitDithering(params->options, dec);
- if (!VP8Decode(dec, &io)) {
- status = dec->status_;
- }
- }
- }
- VP8Delete(dec);
- } else {
- VP8LDecoder* const dec = VP8LNew();
- if (dec == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- if (!VP8LDecodeHeader(dec, &io)) {
- status = dec->status_; // An error occurred. Grab error status.
- } else {
- // Allocate/check output buffers.
- status = WebPAllocateDecBuffer(io.width, io.height, params->options,
- params->output);
- if (status == VP8_STATUS_OK) { // Decode
- if (!VP8LDecodeImage(dec)) {
- status = dec->status_;
- }
- }
- }
- VP8LDelete(dec);
- }
-
- if (status != VP8_STATUS_OK) {
- WebPFreeDecBuffer(params->output);
- } else {
- if (params->options != NULL && params->options->flip) {
- // This restores the original stride values if options->flip was used
- // during the call to WebPAllocateDecBuffer above.
- status = WebPFlipBuffer(params->output);
- }
- }
- return status;
-}
-
-// Helpers
-static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace,
- const uint8_t* const data,
- size_t data_size,
- uint8_t* const rgba,
- int stride, size_t size) {
- WebPDecParams params;
- WebPDecBuffer buf;
- if (rgba == NULL) {
- return NULL;
- }
- WebPInitDecBuffer(&buf);
- WebPResetDecParams(&params);
- params.output = &buf;
- buf.colorspace = colorspace;
- buf.u.RGBA.rgba = rgba;
- buf.u.RGBA.stride = stride;
- buf.u.RGBA.size = size;
- buf.is_external_memory = 1;
- if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
- return NULL;
- }
- return rgba;
-}
-
-uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size,
- uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride) {
- WebPDecParams params;
- WebPDecBuffer output;
- if (luma == NULL) return NULL;
- WebPInitDecBuffer(&output);
- WebPResetDecParams(&params);
- params.output = &output;
- output.colorspace = MODE_YUV;
- output.u.YUVA.y = luma;
- output.u.YUVA.y_stride = luma_stride;
- output.u.YUVA.y_size = luma_size;
- output.u.YUVA.u = u;
- output.u.YUVA.u_stride = u_stride;
- output.u.YUVA.u_size = u_size;
- output.u.YUVA.v = v;
- output.u.YUVA.v_stride = v_stride;
- output.u.YUVA.v_size = v_size;
- output.is_external_memory = 1;
- if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
- return NULL;
- }
- return luma;
-}
-
-//------------------------------------------------------------------------------
-
-static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data,
- size_t data_size, int* const width, int* const height,
- WebPDecBuffer* const keep_info) {
- WebPDecParams params;
- WebPDecBuffer output;
-
- WebPInitDecBuffer(&output);
- WebPResetDecParams(&params);
- params.output = &output;
- output.colorspace = mode;
-
- // Retrieve (and report back) the required dimensions from bitstream.
- if (!WebPGetInfo(data, data_size, &output.width, &output.height)) {
- return NULL;
- }
- if (width != NULL) *width = output.width;
- if (height != NULL) *height = output.height;
-
- // Decode
- if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
- return NULL;
- }
- if (keep_info != NULL) { // keep track of the side-info
- WebPCopyDecBuffer(&output, keep_info);
- }
- // return decoded samples (don't clear 'output'!)
- return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y;
-}
-
-uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_RGB, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_RGBA, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_ARGB, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_BGR, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_BGRA, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
- int* width, int* height, uint8_t** u, uint8_t** v,
- int* stride, int* uv_stride) {
- WebPDecBuffer output; // only to preserve the side-infos
- uint8_t* const out = Decode(MODE_YUV, data, data_size,
- width, height, &output);
-
- if (out != NULL) {
- const WebPYUVABuffer* const buf = &output.u.YUVA;
- *u = buf->u;
- *v = buf->v;
- *stride = buf->y_stride;
- *uv_stride = buf->u_stride;
- assert(buf->u_stride == buf->v_stride);
- }
- return out;
-}
-
-static void DefaultFeatures(WebPBitstreamFeatures* const features) {
- assert(features != NULL);
- memset(features, 0, sizeof(*features));
-}
-
-static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size,
- WebPBitstreamFeatures* const features) {
- if (features == NULL || data == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
- DefaultFeatures(features);
-
- // Only parse enough of the data to retrieve the features.
- return ParseHeadersInternal(data, data_size,
- &features->width, &features->height,
- &features->has_alpha, &features->has_animation,
- &features->format, NULL);
-}
-
-//------------------------------------------------------------------------------
-// WebPGetInfo()
-
-int WebPGetInfo(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- WebPBitstreamFeatures features;
-
- if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) {
- return 0;
- }
-
- if (width != NULL) {
- *width = features.width;
- }
- if (height != NULL) {
- *height = features.height;
- }
-
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Advance decoding API
-
-int WebPInitDecoderConfigInternal(WebPDecoderConfig* config,
- int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
- return 0; // version mismatch
- }
- if (config == NULL) {
- return 0;
- }
- memset(config, 0, sizeof(*config));
- DefaultFeatures(&config->input);
- WebPInitDecBuffer(&config->output);
- return 1;
-}
-
-VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size,
- WebPBitstreamFeatures* features,
- int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
- return VP8_STATUS_INVALID_PARAM; // version mismatch
- }
- if (features == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
- return GetFeatures(data, data_size, features);
-}
-
-VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
- WebPDecoderConfig* config) {
- WebPDecParams params;
- VP8StatusCode status;
-
- if (config == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
-
- status = GetFeatures(data, data_size, &config->input);
- if (status != VP8_STATUS_OK) {
- if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error.
- }
- return status;
- }
-
- WebPResetDecParams(&params);
- params.options = &config->options;
- params.output = &config->output;
- if (WebPAvoidSlowMemory(params.output, &config->input)) {
- // decoding to slow memory: use a temporary in-mem buffer to decode into.
- WebPDecBuffer in_mem_buffer;
- WebPInitDecBuffer(&in_mem_buffer);
- in_mem_buffer.colorspace = config->output.colorspace;
- in_mem_buffer.width = config->input.width;
- in_mem_buffer.height = config->input.height;
- params.output = &in_mem_buffer;
- status = DecodeInto(data, data_size, &params);
- if (status == VP8_STATUS_OK) { // do the slow-copy
- status = WebPCopyDecBufferPixels(&in_mem_buffer, &config->output);
- }
- WebPFreeDecBuffer(&in_mem_buffer);
- } else {
- status = DecodeInto(data, data_size, &params);
- }
-
- return status;
-}
-
-//------------------------------------------------------------------------------
-// Cropping and rescaling.
-
-int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
- VP8Io* const io, WEBP_CSP_MODE src_colorspace) {
- const int W = io->width;
- const int H = io->height;
- int x = 0, y = 0, w = W, h = H;
-
- // Cropping
- io->use_cropping = (options != NULL) && (options->use_cropping > 0);
- if (io->use_cropping) {
- w = options->crop_width;
- h = options->crop_height;
- x = options->crop_left;
- y = options->crop_top;
- if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420
- x &= ~1;
- y &= ~1;
- }
- if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) {
- return 0; // out of frame boundary error
- }
- }
- io->crop_left = x;
- io->crop_top = y;
- io->crop_right = x + w;
- io->crop_bottom = y + h;
- io->mb_w = w;
- io->mb_h = h;
-
- // Scaling
- io->use_scaling = (options != NULL) && (options->use_scaling > 0);
- if (io->use_scaling) {
- int scaled_width = options->scaled_width;
- int scaled_height = options->scaled_height;
- if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) {
- return 0;
- }
- io->scaled_width = scaled_width;
- io->scaled_height = scaled_height;
- }
-
- // Filter
- io->bypass_filtering = (options != NULL) && options->bypass_filtering;
-
- // Fancy upsampler
-#ifdef FANCY_UPSAMPLING
- io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling);
-#endif
-
- if (io->use_scaling) {
- // disable filter (only for large downscaling ratio).
- io->bypass_filtering = (io->scaled_width < W * 3 / 4) &&
- (io->scaled_height < H * 3 / 4);
- io->fancy_upsampling = 0;
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dec/webpi.h b/drivers/webp/dec/webpi.h
deleted file mode 100644
index 991b194c22..0000000000
--- a/drivers/webp/dec/webpi.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Internal header: WebP decoding parameters and custom IO on buffer
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#ifndef WEBP_DEC_WEBPI_H_
-#define WEBP_DEC_WEBPI_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "../utils/rescaler.h"
-#include "./decode_vp8.h"
-
-//------------------------------------------------------------------------------
-// WebPDecParams: Decoding output parameters. Transient internal object.
-
-typedef struct WebPDecParams WebPDecParams;
-typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p);
-typedef int (*OutputAlphaFunc)(const VP8Io* const io, WebPDecParams* const p,
- int expected_num_out_lines);
-typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos,
- int max_out_lines);
-
-struct WebPDecParams {
- WebPDecBuffer* output; // output buffer.
- uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler
- // or used for tmp rescaling
-
- int last_y; // coordinate of the line that was last output
- const WebPDecoderOptions* options; // if not NULL, use alt decoding features
- // rescalers
- WebPRescaler scaler_y, scaler_u, scaler_v, scaler_a;
- void* memory; // overall scratch memory for the output work.
-
- OutputFunc emit; // output RGB or YUV samples
- OutputAlphaFunc emit_alpha; // output alpha channel
- OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values
-
- WebPDecBuffer* final_output; // In case the user supplied a slow-memory
- // output, we decode image in temporary buffer
- // (this::output) and copy it here.
- WebPDecBuffer tmp_buffer; // this::output will point to this one in case
- // of slow memory.
-};
-
-// Should be called first, before any use of the WebPDecParams object.
-void WebPResetDecParams(WebPDecParams* const params);
-
-// Delete all memory (after an error occurred, for instance)
-void WebPFreeDecParams(WebPDecParams* const params);
-
-//------------------------------------------------------------------------------
-// Header parsing helpers
-
-// Structure storing a description of the RIFF headers.
-typedef struct {
- const uint8_t* data; // input buffer
- size_t data_size; // input buffer size
- int have_all_data; // true if all data is known to be available
- size_t offset; // offset to main data chunk (VP8 or VP8L)
- const uint8_t* alpha_data; // points to alpha chunk (if present)
- size_t alpha_data_size; // alpha chunk size
- size_t compressed_size; // VP8/VP8L compressed data size
- size_t riff_size; // size of the riff payload (or 0 if absent)
- int is_lossless; // true if a VP8L chunk is present
-} WebPHeaderStructure;
-
-// Skips over all valid chunks prior to the first VP8/VP8L frame header.
-// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk),
-// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE
-// in the case of non-decodable features (animation for instance).
-// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless
-// fields are updated appropriately upon success.
-VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
-
-//------------------------------------------------------------------------------
-// Misc utils
-
-// Initializes VP8Io with custom setup, io and teardown functions. The default
-// hooks will use the supplied 'params' as io->opaque handle.
-void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io);
-
-// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers
-// to the *compressed* format, not the output one.
-int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
- VP8Io* const io, WEBP_CSP_MODE src_colorspace);
-
-//------------------------------------------------------------------------------
-// Internal functions regarding WebPDecBuffer memory (in buffer.c).
-// Don't really need to be externally visible for now.
-
-// Prepare 'buffer' with the requested initial dimensions width/height.
-// If no external storage is supplied, initializes buffer by allocating output
-// memory and setting up the stride information. Validate the parameters. Return
-// an error code in case of problem (no memory, or invalid stride / size /
-// dimension / etc.). If *options is not NULL, also verify that the options'
-// parameters are valid and apply them to the width/height dimensions of the
-// output buffer. This takes cropping / scaling / rotation into account.
-// Also incorporates the options->flip flag to flip the buffer parameters if
-// needed.
-VP8StatusCode WebPAllocateDecBuffer(int width, int height,
- const WebPDecoderOptions* const options,
- WebPDecBuffer* const buffer);
-
-// Flip buffer vertically by negating the various strides.
-VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer);
-
-// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the
-// memory (still held by 'src'). No pixels are copied.
-void WebPCopyDecBuffer(const WebPDecBuffer* const src,
- WebPDecBuffer* const dst);
-
-// Copy and transfer ownership from src to dst (beware of parameter order!)
-void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst);
-
-// Copy pixels from 'src' into a *preallocated* 'dst' buffer. Returns
-// VP8_STATUS_INVALID_PARAM if the 'dst' is not set up correctly for the copy.
-VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src,
- WebPDecBuffer* const dst);
-
-// Returns true if decoding will be slow with the current configuration
-// and bitstream features.
-int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
- const WebPBitstreamFeatures* const features);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_WEBPI_H_ */
diff --git a/drivers/webp/decode.h b/drivers/webp/decode.h
deleted file mode 100644
index 7a3bed93a4..0000000000
--- a/drivers/webp/decode.h
+++ /dev/null
@@ -1,493 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Main decoding functions for WebP images.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_WEBP_DECODE_H_
-#define WEBP_WEBP_DECODE_H_
-
-#include "./types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b)
-
-// Note: forward declaring enumerations is not allowed in (strict) C and C++,
-// the types are left here for reference.
-// typedef enum VP8StatusCode VP8StatusCode;
-// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE;
-typedef struct WebPRGBABuffer WebPRGBABuffer;
-typedef struct WebPYUVABuffer WebPYUVABuffer;
-typedef struct WebPDecBuffer WebPDecBuffer;
-typedef struct WebPIDecoder WebPIDecoder;
-typedef struct WebPBitstreamFeatures WebPBitstreamFeatures;
-typedef struct WebPDecoderOptions WebPDecoderOptions;
-typedef struct WebPDecoderConfig WebPDecoderConfig;
-
-// Return the decoder's version number, packed in hexadecimal using 8bits for
-// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
-WEBP_EXTERN(int) WebPGetDecoderVersion(void);
-
-// Retrieve basic header information: width, height.
-// This function will also validate the header, returning true on success,
-// false otherwise. '*width' and '*height' are only valid on successful return.
-// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant.
-WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size,
- int* width, int* height);
-
-// Decodes WebP images pointed to by 'data' and returns RGBA samples, along
-// with the dimensions in *width and *height. The ordering of samples in
-// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent).
-// The returned pointer should be deleted calling WebPFree().
-// Returns NULL in case of error.
-WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size,
- int* width, int* height);
-
-// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data.
-WEBP_EXTERN(uint8_t*) WebPDecodeARGB(const uint8_t* data, size_t data_size,
- int* width, int* height);
-
-// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data.
-WEBP_EXTERN(uint8_t*) WebPDecodeBGRA(const uint8_t* data, size_t data_size,
- int* width, int* height);
-
-// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data.
-// If the bitstream contains transparency, it is ignored.
-WEBP_EXTERN(uint8_t*) WebPDecodeRGB(const uint8_t* data, size_t data_size,
- int* width, int* height);
-
-// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data.
-WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size,
- int* width, int* height);
-
-
-// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer
-// returned is the Y samples buffer. Upon return, *u and *v will point to
-// the U and V chroma data. These U and V buffers need NOT be passed to
-// WebPFree(), unlike the returned Y luma one. The dimension of the U and V
-// planes are both (*width + 1) / 2 and (*height + 1)/ 2.
-// Upon return, the Y buffer has a stride returned as '*stride', while U and V
-// have a common stride returned as '*uv_stride'.
-// Return NULL in case of error.
-// (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr
-WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size,
- int* width, int* height,
- uint8_t** u, uint8_t** v,
- int* stride, int* uv_stride);
-
-// Releases memory returned by the WebPDecode*() functions above.
-WEBP_EXTERN(void) WebPFree(void* ptr);
-
-// These five functions are variants of the above ones, that decode the image
-// directly into a pre-allocated buffer 'output_buffer'. The maximum storage
-// available in this buffer is indicated by 'output_buffer_size'. If this
-// storage is not sufficient (or an error occurred), NULL is returned.
-// Otherwise, output_buffer is returned, for convenience.
-// The parameter 'output_stride' specifies the distance (in bytes)
-// between scanlines. Hence, output_buffer_size is expected to be at least
-// output_stride x picture-height.
-WEBP_EXTERN(uint8_t*) WebPDecodeRGBAInto(
- const uint8_t* data, size_t data_size,
- uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
-WEBP_EXTERN(uint8_t*) WebPDecodeARGBInto(
- const uint8_t* data, size_t data_size,
- uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
-WEBP_EXTERN(uint8_t*) WebPDecodeBGRAInto(
- const uint8_t* data, size_t data_size,
- uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
-
-// RGB and BGR variants. Here too the transparency information, if present,
-// will be dropped and ignored.
-WEBP_EXTERN(uint8_t*) WebPDecodeRGBInto(
- const uint8_t* data, size_t data_size,
- uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
-WEBP_EXTERN(uint8_t*) WebPDecodeBGRInto(
- const uint8_t* data, size_t data_size,
- uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
-
-// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly
-// into pre-allocated luma/chroma plane buffers. This function requires the
-// strides to be passed: one for the luma plane and one for each of the
-// chroma ones. The size of each plane buffer is passed as 'luma_size',
-// 'u_size' and 'v_size' respectively.
-// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred
-// during decoding (or because some buffers were found to be too small).
-WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto(
- const uint8_t* data, size_t data_size,
- uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride);
-
-//------------------------------------------------------------------------------
-// Output colorspaces and buffer
-
-// Colorspaces
-// Note: the naming describes the byte-ordering of packed samples in memory.
-// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,...
-// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels.
-// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order:
-// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ...
-// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ...
-// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for
-// these two modes:
-// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ...
-// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ...
-
-typedef enum WEBP_CSP_MODE {
- MODE_RGB = 0, MODE_RGBA = 1,
- MODE_BGR = 2, MODE_BGRA = 3,
- MODE_ARGB = 4, MODE_RGBA_4444 = 5,
- MODE_RGB_565 = 6,
- // RGB-premultiplied transparent modes (alpha value is preserved)
- MODE_rgbA = 7,
- MODE_bgrA = 8,
- MODE_Argb = 9,
- MODE_rgbA_4444 = 10,
- // YUV modes must come after RGB ones.
- MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0
- MODE_LAST = 13
-} WEBP_CSP_MODE;
-
-// Some useful macros:
-static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) {
- return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb ||
- mode == MODE_rgbA_4444);
-}
-
-static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) {
- return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB ||
- mode == MODE_RGBA_4444 || mode == MODE_YUVA ||
- WebPIsPremultipliedMode(mode));
-}
-
-static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) {
- return (mode < MODE_YUV);
-}
-
-//------------------------------------------------------------------------------
-// WebPDecBuffer: Generic structure for describing the output sample buffer.
-
-struct WebPRGBABuffer { // view as RGBA
- uint8_t* rgba; // pointer to RGBA samples
- int stride; // stride in bytes from one scanline to the next.
- size_t size; // total size of the *rgba buffer.
-};
-
-struct WebPYUVABuffer { // view as YUVA
- uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples
- int y_stride; // luma stride
- int u_stride, v_stride; // chroma strides
- int a_stride; // alpha stride
- size_t y_size; // luma plane size
- size_t u_size, v_size; // chroma planes size
- size_t a_size; // alpha-plane size
-};
-
-// Output buffer
-struct WebPDecBuffer {
- WEBP_CSP_MODE colorspace; // Colorspace.
- int width, height; // Dimensions.
- int is_external_memory; // If non-zero, 'internal_memory' pointer is not
- // used. If value is '2' or more, the external
- // memory is considered 'slow' and multiple
- // read/write will be avoided.
- union {
- WebPRGBABuffer RGBA;
- WebPYUVABuffer YUVA;
- } u; // Nameless union of buffer parameters.
- uint32_t pad[4]; // padding for later use
-
- uint8_t* private_memory; // Internally allocated memory (only when
- // is_external_memory is 0). Should not be used
- // externally, but accessed via the buffer union.
-};
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int);
-
-// Initialize the structure as empty. Must be called before any other use.
-// Returns false in case of version mismatch
-static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) {
- return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION);
-}
-
-// Free any memory associated with the buffer. Must always be called last.
-// Note: doesn't free the 'buffer' structure itself.
-WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer);
-
-//------------------------------------------------------------------------------
-// Enumeration of the status codes
-
-typedef enum VP8StatusCode {
- VP8_STATUS_OK = 0,
- VP8_STATUS_OUT_OF_MEMORY,
- VP8_STATUS_INVALID_PARAM,
- VP8_STATUS_BITSTREAM_ERROR,
- VP8_STATUS_UNSUPPORTED_FEATURE,
- VP8_STATUS_SUSPENDED,
- VP8_STATUS_USER_ABORT,
- VP8_STATUS_NOT_ENOUGH_DATA
-} VP8StatusCode;
-
-//------------------------------------------------------------------------------
-// Incremental decoding
-//
-// This API allows streamlined decoding of partial data.
-// Picture can be incrementally decoded as data become available thanks to the
-// WebPIDecoder object. This object can be left in a SUSPENDED state if the
-// picture is only partially decoded, pending additional input.
-// Code example:
-//
-// WebPInitDecBuffer(&buffer);
-// buffer.colorspace = mode;
-// ...
-// WebPIDecoder* idec = WebPINewDecoder(&buffer);
-// while (has_more_data) {
-// // ... (get additional data)
-// status = WebPIAppend(idec, new_data, new_data_size);
-// if (status != VP8_STATUS_SUSPENDED ||
-// break;
-// }
-//
-// // The above call decodes the current available buffer.
-// // Part of the image can now be refreshed by calling to
-// // WebPIDecGetRGB()/WebPIDecGetYUVA() etc.
-// }
-// WebPIDelete(idec);
-
-// Creates a new incremental decoder with the supplied buffer parameter.
-// This output_buffer can be passed NULL, in which case a default output buffer
-// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer'
-// is kept, which means that the lifespan of 'output_buffer' must be larger than
-// that of the returned WebPIDecoder object.
-// The supplied 'output_buffer' content MUST NOT be changed between calls to
-// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is
-// not set to 0. In such a case, it is allowed to modify the pointers, size and
-// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain
-// within valid bounds.
-// All other fields of WebPDecBuffer MUST remain constant between calls.
-// Returns NULL if the allocation failed.
-WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer);
-
-// This function allocates and initializes an incremental-decoder object, which
-// will output the RGB/A samples specified by 'csp' into a preallocated
-// buffer 'output_buffer'. The size of this buffer is at least
-// 'output_buffer_size' and the stride (distance in bytes between two scanlines)
-// is specified by 'output_stride'.
-// Additionally, output_buffer can be passed NULL in which case the output
-// buffer will be allocated automatically when the decoding starts. The
-// colorspace 'csp' is taken into account for allocating this buffer. All other
-// parameters are ignored.
-// Returns NULL if the allocation failed, or if some parameters are invalid.
-WEBP_EXTERN(WebPIDecoder*) WebPINewRGB(
- WEBP_CSP_MODE csp,
- uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
-
-// This function allocates and initializes an incremental-decoder object, which
-// will output the raw luma/chroma samples into a preallocated planes if
-// supplied. The luma plane is specified by its pointer 'luma', its size
-// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane
-// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v
-// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer
-// can be pass NULL in case one is not interested in the transparency plane.
-// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied.
-// In this case, the output buffer will be automatically allocated (using
-// MODE_YUVA) when decoding starts. All parameters are then ignored.
-// Returns NULL if the allocation failed or if a parameter is invalid.
-WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA(
- uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride,
- uint8_t* a, size_t a_size, int a_stride);
-
-// Deprecated version of the above, without the alpha plane.
-// Kept for backward compatibility.
-WEBP_EXTERN(WebPIDecoder*) WebPINewYUV(
- uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride);
-
-// Deletes the WebPIDecoder object and associated memory. Must always be called
-// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded.
-WEBP_EXTERN(void) WebPIDelete(WebPIDecoder* idec);
-
-// Copies and decodes the next available data. Returns VP8_STATUS_OK when
-// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more
-// data is expected. Returns error in other cases.
-WEBP_EXTERN(VP8StatusCode) WebPIAppend(
- WebPIDecoder* idec, const uint8_t* data, size_t data_size);
-
-// A variant of the above function to be used when data buffer contains
-// partial data from the beginning. In this case data buffer is not copied
-// to the internal memory.
-// Note that the value of the 'data' pointer can change between calls to
-// WebPIUpdate, for instance when the data buffer is resized to fit larger data.
-WEBP_EXTERN(VP8StatusCode) WebPIUpdate(
- WebPIDecoder* idec, const uint8_t* data, size_t data_size);
-
-// Returns the RGB/A image decoded so far. Returns NULL if output params
-// are not initialized yet. The RGB/A output type corresponds to the colorspace
-// specified during call to WebPINewDecoder() or WebPINewRGB().
-// *last_y is the index of last decoded row in raster scan order. Some pointers
-// (*last_y, *width etc.) can be NULL if corresponding information is not
-// needed.
-WEBP_EXTERN(uint8_t*) WebPIDecGetRGB(
- const WebPIDecoder* idec, int* last_y,
- int* width, int* height, int* stride);
-
-// Same as above function to get a YUVA image. Returns pointer to the luma
-// plane or NULL in case of error. If there is no alpha information
-// the alpha pointer '*a' will be returned NULL.
-WEBP_EXTERN(uint8_t*) WebPIDecGetYUVA(
- const WebPIDecoder* idec, int* last_y,
- uint8_t** u, uint8_t** v, uint8_t** a,
- int* width, int* height, int* stride, int* uv_stride, int* a_stride);
-
-// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the
-// alpha information (if present). Kept for backward compatibility.
-static WEBP_INLINE uint8_t* WebPIDecGetYUV(
- const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v,
- int* width, int* height, int* stride, int* uv_stride) {
- return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height,
- stride, uv_stride, NULL);
-}
-
-// Generic call to retrieve information about the displayable area.
-// If non NULL, the left/right/width/height pointers are filled with the visible
-// rectangular area so far.
-// Returns NULL in case the incremental decoder object is in an invalid state.
-// Otherwise returns the pointer to the internal representation. This structure
-// is read-only, tied to WebPIDecoder's lifespan and should not be modified.
-WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea(
- const WebPIDecoder* idec, int* left, int* top, int* width, int* height);
-
-//------------------------------------------------------------------------------
-// Advanced decoding parametrization
-//
-// Code sample for using the advanced decoding API
-/*
- // A) Init a configuration object
- WebPDecoderConfig config;
- CHECK(WebPInitDecoderConfig(&config));
-
- // B) optional: retrieve the bitstream's features.
- CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
-
- // C) Adjust 'config', if needed
- config.no_fancy_upsampling = 1;
- config.output.colorspace = MODE_BGRA;
- // etc.
-
- // Note that you can also make config.output point to an externally
- // supplied memory buffer, provided it's big enough to store the decoded
- // picture. Otherwise, config.output will just be used to allocate memory
- // and store the decoded picture.
-
- // D) Decode!
- CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
-
- // E) Decoded image is now in config.output (and config.output.u.RGBA)
-
- // F) Reclaim memory allocated in config's object. It's safe to call
- // this function even if the memory is external and wasn't allocated
- // by WebPDecode().
- WebPFreeDecBuffer(&config.output);
-*/
-
-// Features gathered from the bitstream
-struct WebPBitstreamFeatures {
- int width; // Width in pixels, as read from the bitstream.
- int height; // Height in pixels, as read from the bitstream.
- int has_alpha; // True if the bitstream contains an alpha channel.
- int has_animation; // True if the bitstream is an animation.
- int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless
-
- uint32_t pad[5]; // padding for later use
-};
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal(
- const uint8_t*, size_t, WebPBitstreamFeatures*, int);
-
-// Retrieve features from the bitstream. The *features structure is filled
-// with information gathered from the bitstream.
-// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns
-// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the
-// features from headers. Returns error in other cases.
-static WEBP_INLINE VP8StatusCode WebPGetFeatures(
- const uint8_t* data, size_t data_size,
- WebPBitstreamFeatures* features) {
- return WebPGetFeaturesInternal(data, data_size, features,
- WEBP_DECODER_ABI_VERSION);
-}
-
-// Decoding options
-struct WebPDecoderOptions {
- int bypass_filtering; // if true, skip the in-loop filtering
- int no_fancy_upsampling; // if true, use faster pointwise upsampler
- int use_cropping; // if true, cropping is applied _first_
- int crop_left, crop_top; // top-left position for cropping.
- // Will be snapped to even values.
- int crop_width, crop_height; // dimension of the cropping area
- int use_scaling; // if true, scaling is applied _afterward_
- int scaled_width, scaled_height; // final resolution
- int use_threads; // if true, use multi-threaded decoding
- int dithering_strength; // dithering strength (0=Off, 100=full)
- int flip; // flip output vertically
- int alpha_dithering_strength; // alpha dithering strength in [0..100]
-
- uint32_t pad[5]; // padding for later use
-};
-
-// Main object storing the configuration for advanced decoding.
-struct WebPDecoderConfig {
- WebPBitstreamFeatures input; // Immutable bitstream features (optional)
- WebPDecBuffer output; // Output buffer (can point to external mem)
- WebPDecoderOptions options; // Decoding options
-};
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int);
-
-// Initialize the configuration as empty. This function must always be
-// called first, unless WebPGetFeatures() is to be called.
-// Returns false in case of mismatched version.
-static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) {
- return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION);
-}
-
-// Instantiate a new incremental decoder object with the requested
-// configuration. The bitstream can be passed using 'data' and 'data_size'
-// parameter, in which case the features will be parsed and stored into
-// config->input. Otherwise, 'data' can be NULL and no parsing will occur.
-// Note that 'config' can be NULL too, in which case a default configuration
-// is used. If 'config' is not NULL, it must outlive the WebPIDecoder object
-// as some references to its fields will be used. No internal copy of 'config'
-// is made.
-// The return WebPIDecoder object must always be deleted calling WebPIDelete().
-// Returns NULL in case of error (and config->status will then reflect
-// the error condition, if available).
-WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size,
- WebPDecoderConfig* config);
-
-// Non-incremental version. This version decodes the full data at once, taking
-// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK
-// if the decoding was successful). Note that 'config' cannot be NULL.
-WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size,
- WebPDecoderConfig* config);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_WEBP_DECODE_H_ */
diff --git a/drivers/webp/demux.h b/drivers/webp/demux.h
deleted file mode 100644
index 454f6914b2..0000000000
--- a/drivers/webp/demux.h
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Demux API.
-// Enables extraction of image and extended format data from WebP files.
-
-// Code Example: Demuxing WebP data to extract all the frames, ICC profile
-// and EXIF/XMP metadata.
-/*
- WebPDemuxer* demux = WebPDemux(&webp_data);
-
- uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
- uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
- // ... (Get information about the features present in the WebP file).
- uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
-
- // ... (Iterate over all frames).
- WebPIterator iter;
- if (WebPDemuxGetFrame(demux, 1, &iter)) {
- do {
- // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),
- // ... and get other frame properties like width, height, offsets etc.
- // ... see 'struct WebPIterator' below for more info).
- } while (WebPDemuxNextFrame(&iter));
- WebPDemuxReleaseIterator(&iter);
- }
-
- // ... (Extract metadata).
- WebPChunkIterator chunk_iter;
- if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter);
- // ... (Consume the ICC profile in 'chunk_iter.chunk').
- WebPDemuxReleaseChunkIterator(&chunk_iter);
- if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter);
- // ... (Consume the EXIF metadata in 'chunk_iter.chunk').
- WebPDemuxReleaseChunkIterator(&chunk_iter);
- if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter);
- // ... (Consume the XMP metadata in 'chunk_iter.chunk').
- WebPDemuxReleaseChunkIterator(&chunk_iter);
- WebPDemuxDelete(demux);
-*/
-
-#ifndef WEBP_WEBP_DEMUX_H_
-#define WEBP_WEBP_DEMUX_H_
-
-#include "./decode.h" // for WEBP_CSP_MODE
-#include "./mux_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WEBP_DEMUX_ABI_VERSION 0x0107 // MAJOR(8b) + MINOR(8b)
-
-// Note: forward declaring enumerations is not allowed in (strict) C and C++,
-// the types are left here for reference.
-// typedef enum WebPDemuxState WebPDemuxState;
-// typedef enum WebPFormatFeature WebPFormatFeature;
-typedef struct WebPDemuxer WebPDemuxer;
-typedef struct WebPIterator WebPIterator;
-typedef struct WebPChunkIterator WebPChunkIterator;
-typedef struct WebPAnimInfo WebPAnimInfo;
-typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions;
-
-//------------------------------------------------------------------------------
-
-// Returns the version number of the demux library, packed in hexadecimal using
-// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
-WEBP_EXTERN(int) WebPGetDemuxVersion(void);
-
-//------------------------------------------------------------------------------
-// Life of a Demux object
-
-typedef enum WebPDemuxState {
- WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing.
- WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header.
- WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete,
- // data may be available.
- WEBP_DEMUX_DONE = 2 // Entire file has been parsed.
-} WebPDemuxState;
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
- const WebPData*, int, WebPDemuxState*, int);
-
-// Parses the full WebP file given by 'data'. For single images the WebP file
-// header alone or the file header and the chunk header may be absent.
-// Returns a WebPDemuxer object on successful parse, NULL otherwise.
-static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
- return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);
-}
-
-// Parses the possibly incomplete WebP file given by 'data'.
-// If 'state' is non-NULL it will be set to indicate the status of the demuxer.
-// Returns NULL in case of error or if there isn't enough data to start parsing;
-// and a WebPDemuxer object on successful parse.
-// Note that WebPDemuxer keeps internal pointers to 'data' memory segment.
-// If this data is volatile, the demuxer object should be deleted (by calling
-// WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data.
-// This is usually an inexpensive operation.
-static WEBP_INLINE WebPDemuxer* WebPDemuxPartial(
- const WebPData* data, WebPDemuxState* state) {
- return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION);
-}
-
-// Frees memory associated with 'dmux'.
-WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux);
-
-//------------------------------------------------------------------------------
-// Data/information extraction.
-
-typedef enum WebPFormatFeature {
- WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk.
- WEBP_FF_CANVAS_WIDTH,
- WEBP_FF_CANVAS_HEIGHT,
- WEBP_FF_LOOP_COUNT,
- WEBP_FF_BACKGROUND_COLOR,
- WEBP_FF_FRAME_COUNT // Number of frames present in the demux object.
- // In case of a partial demux, this is the number of
- // frames seen so far, with the last frame possibly
- // being partial.
-} WebPFormatFeature;
-
-// Get the 'feature' value from the 'dmux'.
-// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial()
-// returned a state > WEBP_DEMUX_PARSING_HEADER.
-WEBP_EXTERN(uint32_t) WebPDemuxGetI(
- const WebPDemuxer* dmux, WebPFormatFeature feature);
-
-//------------------------------------------------------------------------------
-// Frame iteration.
-
-struct WebPIterator {
- int frame_num;
- int num_frames; // equivalent to WEBP_FF_FRAME_COUNT.
- int x_offset, y_offset; // offset relative to the canvas.
- int width, height; // dimensions of this frame.
- int duration; // display duration in milliseconds.
- WebPMuxAnimDispose dispose_method; // dispose method for the frame.
- int complete; // true if 'fragment' contains a full frame. partial images
- // may still be decoded with the WebP incremental decoder.
- WebPData fragment; // The frame given by 'frame_num'. Note for historical
- // reasons this is called a fragment.
- int has_alpha; // True if the frame contains transparency.
- WebPMuxAnimBlend blend_method; // Blend operation for the frame.
-
- uint32_t pad[2]; // padding for later use.
- void* private_; // for internal use only.
-};
-
-// Retrieves frame 'frame_number' from 'dmux'.
-// 'iter->fragment' points to the frame on return from this function.
-// Setting 'frame_number' equal to 0 will return the last frame of the image.
-// Returns false if 'dmux' is NULL or frame 'frame_number' is not present.
-// Call WebPDemuxReleaseIterator() when use of the iterator is complete.
-// NOTE: 'dmux' must persist for the lifetime of 'iter'.
-WEBP_EXTERN(int) WebPDemuxGetFrame(
- const WebPDemuxer* dmux, int frame_number, WebPIterator* iter);
-
-// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or
-// previous ('iter->frame_num' - 1) frame. These functions do not loop.
-// Returns true on success, false otherwise.
-WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter);
-WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter);
-
-// Releases any memory associated with 'iter'.
-// Must be called before any subsequent calls to WebPDemuxGetChunk() on the same
-// iter. Also, must be called before destroying the associated WebPDemuxer with
-// WebPDemuxDelete().
-WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter);
-
-//------------------------------------------------------------------------------
-// Chunk iteration.
-
-struct WebPChunkIterator {
- // The current and total number of chunks with the fourcc given to
- // WebPDemuxGetChunk().
- int chunk_num;
- int num_chunks;
- WebPData chunk; // The payload of the chunk.
-
- uint32_t pad[6]; // padding for later use
- void* private_;
-};
-
-// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from
-// 'dmux'.
-// 'fourcc' is a character array containing the fourcc of the chunk to return,
-// e.g., "ICCP", "XMP ", "EXIF", etc.
-// Setting 'chunk_number' equal to 0 will return the last chunk in a set.
-// Returns true if the chunk is found, false otherwise. Image related chunk
-// payloads are accessed through WebPDemuxGetFrame() and related functions.
-// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete.
-// NOTE: 'dmux' must persist for the lifetime of the iterator.
-WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux,
- const char fourcc[4], int chunk_number,
- WebPChunkIterator* iter);
-
-// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous
-// ('iter->chunk_num' - 1) chunk. These functions do not loop.
-// Returns true on success, false otherwise.
-WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter);
-WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter);
-
-// Releases any memory associated with 'iter'.
-// Must be called before destroying the associated WebPDemuxer with
-// WebPDemuxDelete().
-WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter);
-
-//------------------------------------------------------------------------------
-// WebPAnimDecoder API
-//
-// This API allows decoding (possibly) animated WebP images.
-//
-// Code Example:
-/*
- WebPAnimDecoderOptions dec_options;
- WebPAnimDecoderOptionsInit(&dec_options);
- // Tune 'dec_options' as needed.
- WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
- WebPAnimInfo anim_info;
- WebPAnimDecoderGetInfo(dec, &anim_info);
- for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
- while (WebPAnimDecoderHasMoreFrames(dec)) {
- uint8_t* buf;
- int timestamp;
- WebPAnimDecoderGetNext(dec, &buf, &timestamp);
- // ... (Render 'buf' based on 'timestamp').
- // ... (Do NOT free 'buf', as it is owned by 'dec').
- }
- WebPAnimDecoderReset(dec);
- }
- const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
- // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
- WebPAnimDecoderDelete(dec);
-*/
-
-typedef struct WebPAnimDecoder WebPAnimDecoder; // Main opaque object.
-
-// Global options.
-struct WebPAnimDecoderOptions {
- // Output colorspace. Only the following modes are supported:
- // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA.
- WEBP_CSP_MODE color_mode;
- int use_threads; // If true, use multi-threaded decoding.
- uint32_t padding[7]; // Padding for later use.
-};
-
-// Internal, version-checked, entry point.
-WEBP_EXTERN(int) WebPAnimDecoderOptionsInitInternal(
- WebPAnimDecoderOptions*, int);
-
-// Should always be called, to initialize a fresh WebPAnimDecoderOptions
-// structure before modification. Returns false in case of version mismatch.
-// WebPAnimDecoderOptionsInit() must have succeeded before using the
-// 'dec_options' object.
-static WEBP_INLINE int WebPAnimDecoderOptionsInit(
- WebPAnimDecoderOptions* dec_options) {
- return WebPAnimDecoderOptionsInitInternal(dec_options,
- WEBP_DEMUX_ABI_VERSION);
-}
-
-// Internal, version-checked, entry point.
-WEBP_EXTERN(WebPAnimDecoder*) WebPAnimDecoderNewInternal(
- const WebPData*, const WebPAnimDecoderOptions*, int);
-
-// Creates and initializes a WebPAnimDecoder object.
-// Parameters:
-// webp_data - (in) WebP bitstream. This should remain unchanged during the
-// lifetime of the output WebPAnimDecoder object.
-// dec_options - (in) decoding options. Can be passed NULL to choose
-// reasonable defaults (in particular, color mode MODE_RGBA
-// will be picked).
-// Returns:
-// A pointer to the newly created WebPAnimDecoder object, or NULL in case of
-// parsing error, invalid option or memory error.
-static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew(
- const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) {
- return WebPAnimDecoderNewInternal(webp_data, dec_options,
- WEBP_DEMUX_ABI_VERSION);
-}
-
-// Global information about the animation..
-struct WebPAnimInfo {
- uint32_t canvas_width;
- uint32_t canvas_height;
- uint32_t loop_count;
- uint32_t bgcolor;
- uint32_t frame_count;
- uint32_t pad[4]; // padding for later use
-};
-
-// Get global information about the animation.
-// Parameters:
-// dec - (in) decoder instance to get information from.
-// info - (out) global information fetched from the animation.
-// Returns:
-// True on success.
-WEBP_EXTERN(int) WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec,
- WebPAnimInfo* info);
-
-// Fetch the next frame from 'dec' based on options supplied to
-// WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size
-// 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The
-// returned buffer 'buf' is valid only until the next call to
-// WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete().
-// Parameters:
-// dec - (in/out) decoder instance from which the next frame is to be fetched.
-// buf - (out) decoded frame.
-// timestamp - (out) timestamp of the frame in milliseconds.
-// Returns:
-// False if any of the arguments are NULL, or if there is a parsing or
-// decoding error, or if there are no more frames. Otherwise, returns true.
-WEBP_EXTERN(int) WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
- uint8_t** buf, int* timestamp);
-
-// Check if there are more frames left to decode.
-// Parameters:
-// dec - (in) decoder instance to be checked.
-// Returns:
-// True if 'dec' is not NULL and some frames are yet to be decoded.
-// Otherwise, returns false.
-WEBP_EXTERN(int) WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec);
-
-// Resets the WebPAnimDecoder object, so that next call to
-// WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be
-// helpful when all frames need to be decoded multiple times (e.g.
-// info.loop_count times) without destroying and recreating the 'dec' object.
-// Parameters:
-// dec - (in/out) decoder instance to be reset
-WEBP_EXTERN(void) WebPAnimDecoderReset(WebPAnimDecoder* dec);
-
-// Grab the internal demuxer object.
-// Getting the demuxer object can be useful if one wants to use operations only
-// available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned
-// demuxer object is owned by 'dec' and is valid only until the next call to
-// WebPAnimDecoderDelete().
-//
-// Parameters:
-// dec - (in) decoder instance from which the demuxer object is to be fetched.
-WEBP_EXTERN(const WebPDemuxer*) WebPAnimDecoderGetDemuxer(
- const WebPAnimDecoder* dec);
-
-// Deletes the WebPAnimDecoder object.
-// Parameters:
-// dec - (in/out) decoder instance to be deleted
-WEBP_EXTERN(void) WebPAnimDecoderDelete(WebPAnimDecoder* dec);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_WEBP_DEMUX_H_ */
diff --git a/drivers/webp/demux/anim_decode.c b/drivers/webp/demux/anim_decode.c
deleted file mode 100644
index 39cf3de197..0000000000
--- a/drivers/webp/demux/anim_decode.c
+++ /dev/null
@@ -1,442 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// AnimDecoder implementation.
-//
-
-#ifdef HAVE_CONFIG_H
-#include "webp/config.h"
-#endif
-
-#include <assert.h>
-#include <string.h>
-
-#include "../utils/utils.h"
-#include "webp/decode.h"
-#include "webp/demux.h"
-
-#define NUM_CHANNELS 4
-
-typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int);
-static void BlendPixelRowNonPremult(uint32_t* const src,
- const uint32_t* const dst, int num_pixels);
-static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst,
- int num_pixels);
-
-struct WebPAnimDecoder {
- WebPDemuxer* demux_; // Demuxer created from given WebP bitstream.
- WebPDecoderConfig config_; // Decoder config.
- // Note: we use a pointer to a function blending multiple pixels at a time to
- // allow possible inlining of per-pixel blending function.
- BlendRowFunc blend_func_; // Pointer to the chose blend row function.
- WebPAnimInfo info_; // Global info about the animation.
- uint8_t* curr_frame_; // Current canvas (not disposed).
- uint8_t* prev_frame_disposed_; // Previous canvas (properly disposed).
- int prev_frame_timestamp_; // Previous frame timestamp (milliseconds).
- WebPIterator prev_iter_; // Iterator object for previous frame.
- int prev_frame_was_keyframe_; // True if previous frame was a keyframe.
- int next_frame_; // Index of the next frame to be decoded
- // (starting from 1).
-};
-
-static void DefaultDecoderOptions(WebPAnimDecoderOptions* const dec_options) {
- dec_options->color_mode = MODE_RGBA;
- dec_options->use_threads = 0;
-}
-
-int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options,
- int abi_version) {
- if (dec_options == NULL ||
- WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) {
- return 0;
- }
- DefaultDecoderOptions(dec_options);
- return 1;
-}
-
-static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options,
- WebPAnimDecoder* const dec) {
- WEBP_CSP_MODE mode;
- WebPDecoderConfig* config = &dec->config_;
- assert(dec_options != NULL);
-
- mode = dec_options->color_mode;
- if (mode != MODE_RGBA && mode != MODE_BGRA &&
- mode != MODE_rgbA && mode != MODE_bgrA) {
- return 0;
- }
- dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA)
- ? &BlendPixelRowNonPremult
- : &BlendPixelRowPremult;
- WebPInitDecoderConfig(config);
- config->output.colorspace = mode;
- config->output.is_external_memory = 1;
- config->options.use_threads = dec_options->use_threads;
- // Note: config->output.u.RGBA is set at the time of decoding each frame.
- return 1;
-}
-
-WebPAnimDecoder* WebPAnimDecoderNewInternal(
- const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options,
- int abi_version) {
- WebPAnimDecoderOptions options;
- WebPAnimDecoder* dec = NULL;
- if (webp_data == NULL ||
- WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) {
- return NULL;
- }
-
- // Note: calloc() so that the pointer members are initialized to NULL.
- dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
- if (dec == NULL) goto Error;
-
- if (dec_options != NULL) {
- options = *dec_options;
- } else {
- DefaultDecoderOptions(&options);
- }
- if (!ApplyDecoderOptions(&options, dec)) goto Error;
-
- dec->demux_ = WebPDemux(webp_data);
- if (dec->demux_ == NULL) goto Error;
-
- dec->info_.canvas_width = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_WIDTH);
- dec->info_.canvas_height = WebPDemuxGetI(dec->demux_, WEBP_FF_CANVAS_HEIGHT);
- dec->info_.loop_count = WebPDemuxGetI(dec->demux_, WEBP_FF_LOOP_COUNT);
- dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR);
- dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT);
-
- {
- const int canvas_bytes =
- dec->info_.canvas_width * NUM_CHANNELS * dec->info_.canvas_height;
- // Note: calloc() because we fill frame with zeroes as well.
- dec->curr_frame_ = WebPSafeCalloc(1ULL, canvas_bytes);
- if (dec->curr_frame_ == NULL) goto Error;
- dec->prev_frame_disposed_ = WebPSafeCalloc(1ULL, canvas_bytes);
- if (dec->prev_frame_disposed_ == NULL) goto Error;
- }
-
- WebPAnimDecoderReset(dec);
-
- return dec;
-
- Error:
- WebPAnimDecoderDelete(dec);
- return NULL;
-}
-
-int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, WebPAnimInfo* info) {
- if (dec == NULL || info == NULL) return 0;
- *info = dec->info_;
- return 1;
-}
-
-// Returns true if the frame covers the full canvas.
-static int IsFullFrame(int width, int height, int canvas_width,
- int canvas_height) {
- return (width == canvas_width && height == canvas_height);
-}
-
-// Clear the canvas to transparent.
-static void ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width,
- uint32_t canvas_height) {
- memset(buf, 0, canvas_width * NUM_CHANNELS * canvas_height);
-}
-
-// Clear given frame rectangle to transparent.
-static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset,
- int y_offset, int width, int height) {
- int j;
- assert(width * NUM_CHANNELS <= buf_stride);
- buf += y_offset * buf_stride + x_offset * NUM_CHANNELS;
- for (j = 0; j < height; ++j) {
- memset(buf, 0, width * NUM_CHANNELS);
- buf += buf_stride;
- }
-}
-
-// Copy width * height pixels from 'src' to 'dst'.
-static void CopyCanvas(const uint8_t* src, uint8_t* dst,
- uint32_t width, uint32_t height) {
- assert(src != NULL && dst != NULL);
- memcpy(dst, src, width * NUM_CHANNELS * height);
-}
-
-// Returns true if the current frame is a key-frame.
-static int IsKeyFrame(const WebPIterator* const curr,
- const WebPIterator* const prev,
- int prev_frame_was_key_frame,
- int canvas_width, int canvas_height) {
- if (curr->frame_num == 1) {
- return 1;
- } else if ((!curr->has_alpha || curr->blend_method == WEBP_MUX_NO_BLEND) &&
- IsFullFrame(curr->width, curr->height,
- canvas_width, canvas_height)) {
- return 1;
- } else {
- return (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) &&
- (IsFullFrame(prev->width, prev->height, canvas_width,
- canvas_height) ||
- prev_frame_was_key_frame);
- }
-}
-
-
-// Blend a single channel of 'src' over 'dst', given their alpha channel values.
-// 'src' and 'dst' are assumed to be NOT pre-multiplied by alpha.
-static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a,
- uint32_t dst, uint8_t dst_a,
- uint32_t scale, int shift) {
- const uint8_t src_channel = (src >> shift) & 0xff;
- const uint8_t dst_channel = (dst >> shift) & 0xff;
- const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a;
- assert(blend_unscaled < (1ULL << 32) / scale);
- return (blend_unscaled * scale) >> 24;
-}
-
-// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha.
-static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) {
- const uint8_t src_a = (src >> 24) & 0xff;
-
- if (src_a == 0) {
- return dst;
- } else {
- const uint8_t dst_a = (dst >> 24) & 0xff;
- // This is the approximate integer arithmetic for the actual formula:
- // dst_factor_a = (dst_a * (255 - src_a)) / 255.
- const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8;
- const uint8_t blend_a = src_a + dst_factor_a;
- const uint32_t scale = (1UL << 24) / blend_a;
-
- const uint8_t blend_r =
- BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0);
- const uint8_t blend_g =
- BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8);
- const uint8_t blend_b =
- BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16);
- assert(src_a + dst_factor_a < 256);
-
- return (blend_r << 0) |
- (blend_g << 8) |
- (blend_b << 16) |
- ((uint32_t)blend_a << 24);
- }
-}
-
-// Blend 'num_pixels' in 'src' over 'dst' assuming they are NOT pre-multiplied
-// by alpha.
-static void BlendPixelRowNonPremult(uint32_t* const src,
- const uint32_t* const dst, int num_pixels) {
- int i;
- for (i = 0; i < num_pixels; ++i) {
- const uint8_t src_alpha = (src[i] >> 24) & 0xff;
- if (src_alpha != 0xff) {
- src[i] = BlendPixelNonPremult(src[i], dst[i]);
- }
- }
-}
-
-// Individually multiply each channel in 'pix' by 'scale'.
-static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) {
- uint32_t mask = 0x00FF00FF;
- uint32_t rb = ((pix & mask) * scale) >> 8;
- uint32_t ag = ((pix >> 8) & mask) * scale;
- return (rb & mask) | (ag & ~mask);
-}
-
-// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha.
-static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) {
- const uint8_t src_a = (src >> 24) & 0xff;
- return src + ChannelwiseMultiply(dst, 256 - src_a);
-}
-
-// Blend 'num_pixels' in 'src' over 'dst' assuming they are pre-multiplied by
-// alpha.
-static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst,
- int num_pixels) {
- int i;
- for (i = 0; i < num_pixels; ++i) {
- const uint8_t src_alpha = (src[i] >> 24) & 0xff;
- if (src_alpha != 0xff) {
- src[i] = BlendPixelPremult(src[i], dst[i]);
- }
- }
-}
-
-// Returns two ranges (<left, width> pairs) at row 'canvas_y', that belong to
-// 'src' but not 'dst'. A point range is empty if the corresponding width is 0.
-static void FindBlendRangeAtRow(const WebPIterator* const src,
- const WebPIterator* const dst, int canvas_y,
- int* const left1, int* const width1,
- int* const left2, int* const width2) {
- const int src_max_x = src->x_offset + src->width;
- const int dst_max_x = dst->x_offset + dst->width;
- const int dst_max_y = dst->y_offset + dst->height;
- assert(canvas_y >= src->y_offset && canvas_y < (src->y_offset + src->height));
- *left1 = -1;
- *width1 = 0;
- *left2 = -1;
- *width2 = 0;
-
- if (canvas_y < dst->y_offset || canvas_y >= dst_max_y ||
- src->x_offset >= dst_max_x || src_max_x <= dst->x_offset) {
- *left1 = src->x_offset;
- *width1 = src->width;
- return;
- }
-
- if (src->x_offset < dst->x_offset) {
- *left1 = src->x_offset;
- *width1 = dst->x_offset - src->x_offset;
- }
-
- if (src_max_x > dst_max_x) {
- *left2 = dst_max_x;
- *width2 = src_max_x - dst_max_x;
- }
-}
-
-int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
- uint8_t** buf_ptr, int* timestamp_ptr) {
- WebPIterator iter;
- uint32_t width;
- uint32_t height;
- int is_key_frame;
- int timestamp;
- BlendRowFunc blend_row;
-
- if (dec == NULL || buf_ptr == NULL || timestamp_ptr == NULL) return 0;
- if (!WebPAnimDecoderHasMoreFrames(dec)) return 0;
-
- width = dec->info_.canvas_width;
- height = dec->info_.canvas_height;
- blend_row = dec->blend_func_;
-
- // Get compressed frame.
- if (!WebPDemuxGetFrame(dec->demux_, dec->next_frame_, &iter)) {
- return 0;
- }
- timestamp = dec->prev_frame_timestamp_ + iter.duration;
-
- // Initialize.
- is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_,
- dec->prev_frame_was_keyframe_, width, height);
- if (is_key_frame) {
- ZeroFillCanvas(dec->curr_frame_, width, height);
- } else {
- CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, width, height);
- }
-
- // Decode.
- {
- const uint8_t* in = iter.fragment.bytes;
- const size_t in_size = iter.fragment.size;
- const size_t out_offset =
- (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS;
- WebPDecoderConfig* const config = &dec->config_;
- WebPRGBABuffer* const buf = &config->output.u.RGBA;
- buf->stride = NUM_CHANNELS * width;
- buf->size = buf->stride * iter.height;
- buf->rgba = dec->curr_frame_ + out_offset;
-
- if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) {
- goto Error;
- }
- }
-
- // During the decoding of current frame, we may have set some pixels to be
- // transparent (i.e. alpha < 255). However, the value of each of these
- // pixels should have been determined by blending it against the value of
- // that pixel in the previous frame if blending method of is WEBP_MUX_BLEND.
- if (iter.frame_num > 1 && iter.blend_method == WEBP_MUX_BLEND &&
- !is_key_frame) {
- if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_NONE) {
- int y;
- // Blend transparent pixels with pixels in previous canvas.
- for (y = 0; y < iter.height; ++y) {
- const size_t offset =
- (iter.y_offset + y) * width + iter.x_offset;
- blend_row((uint32_t*)dec->curr_frame_ + offset,
- (uint32_t*)dec->prev_frame_disposed_ + offset, iter.width);
- }
- } else {
- int y;
- assert(dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND);
- // We need to blend a transparent pixel with its value just after
- // initialization. That is, blend it with:
- // * Fully transparent pixel if it belongs to prevRect <-- No-op.
- // * The pixel in the previous canvas otherwise <-- Need alpha-blending.
- for (y = 0; y < iter.height; ++y) {
- const int canvas_y = iter.y_offset + y;
- int left1, width1, left2, width2;
- FindBlendRangeAtRow(&iter, &dec->prev_iter_, canvas_y, &left1, &width1,
- &left2, &width2);
- if (width1 > 0) {
- const size_t offset1 = canvas_y * width + left1;
- blend_row((uint32_t*)dec->curr_frame_ + offset1,
- (uint32_t*)dec->prev_frame_disposed_ + offset1, width1);
- }
- if (width2 > 0) {
- const size_t offset2 = canvas_y * width + left2;
- blend_row((uint32_t*)dec->curr_frame_ + offset2,
- (uint32_t*)dec->prev_frame_disposed_ + offset2, width2);
- }
- }
- }
- }
-
- // Update info of the previous frame and dispose it for the next iteration.
- dec->prev_frame_timestamp_ = timestamp;
- dec->prev_iter_ = iter;
- dec->prev_frame_was_keyframe_ = is_key_frame;
- CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height);
- if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
- ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS,
- dec->prev_iter_.x_offset, dec->prev_iter_.y_offset,
- dec->prev_iter_.width, dec->prev_iter_.height);
- }
- ++dec->next_frame_;
-
- // All OK, fill in the values.
- *buf_ptr = dec->curr_frame_;
- *timestamp_ptr = timestamp;
- return 1;
-
- Error:
- WebPDemuxReleaseIterator(&iter);
- return 0;
-}
-
-int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec) {
- if (dec == NULL) return 0;
- return (dec->next_frame_ <= (int)dec->info_.frame_count);
-}
-
-void WebPAnimDecoderReset(WebPAnimDecoder* dec) {
- if (dec != NULL) {
- dec->prev_frame_timestamp_ = 0;
- memset(&dec->prev_iter_, 0, sizeof(dec->prev_iter_));
- dec->prev_frame_was_keyframe_ = 0;
- dec->next_frame_ = 1;
- }
-}
-
-const WebPDemuxer* WebPAnimDecoderGetDemuxer(const WebPAnimDecoder* dec) {
- if (dec == NULL) return NULL;
- return dec->demux_;
-}
-
-void WebPAnimDecoderDelete(WebPAnimDecoder* dec) {
- if (dec != NULL) {
- WebPDemuxDelete(dec->demux_);
- WebPSafeFree(dec->curr_frame_);
- WebPSafeFree(dec->prev_frame_disposed_);
- WebPSafeFree(dec);
- }
-}
diff --git a/drivers/webp/demux/demux.c b/drivers/webp/demux/demux.c
deleted file mode 100644
index df93c5b379..0000000000
--- a/drivers/webp/demux/demux.c
+++ /dev/null
@@ -1,966 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebP container demux.
-//
-
-#ifdef HAVE_CONFIG_H
-#include "webp/config.h"
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../utils/utils.h"
-#include "webp/decode.h" // WebPGetFeatures
-#include "webp/demux.h"
-#include "webp/format_constants.h"
-
-#define DMUX_MAJ_VERSION 0
-#define DMUX_MIN_VERSION 3
-#define DMUX_REV_VERSION 0
-
-typedef struct {
- size_t start_; // start location of the data
- size_t end_; // end location
- size_t riff_end_; // riff chunk end location, can be > end_.
- size_t buf_size_; // size of the buffer
- const uint8_t* buf_;
-} MemBuffer;
-
-typedef struct {
- size_t offset_;
- size_t size_;
-} ChunkData;
-
-typedef struct Frame {
- int x_offset_, y_offset_;
- int width_, height_;
- int has_alpha_;
- int duration_;
- WebPMuxAnimDispose dispose_method_;
- WebPMuxAnimBlend blend_method_;
- int frame_num_;
- int complete_; // img_components_ contains a full image.
- ChunkData img_components_[2]; // 0=VP8{,L} 1=ALPH
- struct Frame* next_;
-} Frame;
-
-typedef struct Chunk {
- ChunkData data_;
- struct Chunk* next_;
-} Chunk;
-
-struct WebPDemuxer {
- MemBuffer mem_;
- WebPDemuxState state_;
- int is_ext_format_;
- uint32_t feature_flags_;
- int canvas_width_, canvas_height_;
- int loop_count_;
- uint32_t bgcolor_;
- int num_frames_;
- Frame* frames_;
- Frame** frames_tail_;
- Chunk* chunks_; // non-image chunks
- Chunk** chunks_tail_;
-};
-
-typedef enum {
- PARSE_OK,
- PARSE_NEED_MORE_DATA,
- PARSE_ERROR
-} ParseStatus;
-
-typedef struct ChunkParser {
- uint8_t id[4];
- ParseStatus (*parse)(WebPDemuxer* const dmux);
- int (*valid)(const WebPDemuxer* const dmux);
-} ChunkParser;
-
-static ParseStatus ParseSingleImage(WebPDemuxer* const dmux);
-static ParseStatus ParseVP8X(WebPDemuxer* const dmux);
-static int IsValidSimpleFormat(const WebPDemuxer* const dmux);
-static int IsValidExtendedFormat(const WebPDemuxer* const dmux);
-
-static const ChunkParser kMasterChunks[] = {
- { { 'V', 'P', '8', ' ' }, ParseSingleImage, IsValidSimpleFormat },
- { { 'V', 'P', '8', 'L' }, ParseSingleImage, IsValidSimpleFormat },
- { { 'V', 'P', '8', 'X' }, ParseVP8X, IsValidExtendedFormat },
- { { '0', '0', '0', '0' }, NULL, NULL },
-};
-
-//------------------------------------------------------------------------------
-
-int WebPGetDemuxVersion(void) {
- return (DMUX_MAJ_VERSION << 16) | (DMUX_MIN_VERSION << 8) | DMUX_REV_VERSION;
-}
-
-// -----------------------------------------------------------------------------
-// MemBuffer
-
-static int RemapMemBuffer(MemBuffer* const mem,
- const uint8_t* data, size_t size) {
- if (size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
-
- mem->buf_ = data;
- mem->end_ = mem->buf_size_ = size;
- return 1;
-}
-
-static int InitMemBuffer(MemBuffer* const mem,
- const uint8_t* data, size_t size) {
- memset(mem, 0, sizeof(*mem));
- return RemapMemBuffer(mem, data, size);
-}
-
-// Return the remaining data size available in 'mem'.
-static WEBP_INLINE size_t MemDataSize(const MemBuffer* const mem) {
- return (mem->end_ - mem->start_);
-}
-
-// Return true if 'size' exceeds the end of the RIFF chunk.
-static WEBP_INLINE int SizeIsInvalid(const MemBuffer* const mem, size_t size) {
- return (size > mem->riff_end_ - mem->start_);
-}
-
-static WEBP_INLINE void Skip(MemBuffer* const mem, size_t size) {
- mem->start_ += size;
-}
-
-static WEBP_INLINE void Rewind(MemBuffer* const mem, size_t size) {
- mem->start_ -= size;
-}
-
-static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) {
- return mem->buf_ + mem->start_;
-}
-
-// Read from 'mem' and skip the read bytes.
-static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) {
- const uint8_t byte = mem->buf_[mem->start_];
- Skip(mem, 1);
- return byte;
-}
-
-static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) {
- const uint8_t* const data = mem->buf_ + mem->start_;
- const int val = GetLE16(data);
- Skip(mem, 2);
- return val;
-}
-
-static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) {
- const uint8_t* const data = mem->buf_ + mem->start_;
- const int val = GetLE24(data);
- Skip(mem, 3);
- return val;
-}
-
-static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) {
- const uint8_t* const data = mem->buf_ + mem->start_;
- const uint32_t val = GetLE32(data);
- Skip(mem, 4);
- return val;
-}
-
-// -----------------------------------------------------------------------------
-// Secondary chunk parsing
-
-static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) {
- *dmux->chunks_tail_ = chunk;
- chunk->next_ = NULL;
- dmux->chunks_tail_ = &chunk->next_;
-}
-
-// Add a frame to the end of the list, ensuring the last frame is complete.
-// Returns true on success, false otherwise.
-static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
- const Frame* const last_frame = *dmux->frames_tail_;
- if (last_frame != NULL && !last_frame->complete_) return 0;
-
- *dmux->frames_tail_ = frame;
- frame->next_ = NULL;
- dmux->frames_tail_ = &frame->next_;
- return 1;
-}
-
-static void SetFrameInfo(size_t start_offset, size_t size,
- int frame_num, int complete,
- const WebPBitstreamFeatures* const features,
- Frame* const frame) {
- frame->img_components_[0].offset_ = start_offset;
- frame->img_components_[0].size_ = size;
- frame->width_ = features->width;
- frame->height_ = features->height;
- frame->has_alpha_ |= features->has_alpha;
- frame->frame_num_ = frame_num;
- frame->complete_ = complete;
-}
-
-// Store image bearing chunks to 'frame'.
-static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
- MemBuffer* const mem, Frame* const frame) {
- int alpha_chunks = 0;
- int image_chunks = 0;
- int done = (MemDataSize(mem) < min_size);
- ParseStatus status = PARSE_OK;
-
- if (done) return PARSE_NEED_MORE_DATA;
-
- do {
- const size_t chunk_start_offset = mem->start_;
- const uint32_t fourcc = ReadLE32(mem);
- const uint32_t payload_size = ReadLE32(mem);
- const uint32_t payload_size_padded = payload_size + (payload_size & 1);
- const size_t payload_available = (payload_size_padded > MemDataSize(mem))
- ? MemDataSize(mem) : payload_size_padded;
- const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available;
-
- if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
- if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR;
- if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA;
-
- switch (fourcc) {
- case MKFOURCC('A', 'L', 'P', 'H'):
- if (alpha_chunks == 0) {
- ++alpha_chunks;
- frame->img_components_[1].offset_ = chunk_start_offset;
- frame->img_components_[1].size_ = chunk_size;
- frame->has_alpha_ = 1;
- frame->frame_num_ = frame_num;
- Skip(mem, payload_available);
- } else {
- goto Done;
- }
- break;
- case MKFOURCC('V', 'P', '8', 'L'):
- if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha
- // fall through
- case MKFOURCC('V', 'P', '8', ' '):
- if (image_chunks == 0) {
- // Extract the bitstream features, tolerating failures when the data
- // is incomplete.
- WebPBitstreamFeatures features;
- const VP8StatusCode vp8_status =
- WebPGetFeatures(mem->buf_ + chunk_start_offset, chunk_size,
- &features);
- if (status == PARSE_NEED_MORE_DATA &&
- vp8_status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return PARSE_NEED_MORE_DATA;
- } else if (vp8_status != VP8_STATUS_OK) {
- // We have enough data, and yet WebPGetFeatures() failed.
- return PARSE_ERROR;
- }
- ++image_chunks;
- SetFrameInfo(chunk_start_offset, chunk_size, frame_num,
- status == PARSE_OK, &features, frame);
- Skip(mem, payload_available);
- } else {
- goto Done;
- }
- break;
- Done:
- default:
- // Restore fourcc/size when moving up one level in parsing.
- Rewind(mem, CHUNK_HEADER_SIZE);
- done = 1;
- break;
- }
-
- if (mem->start_ == mem->riff_end_) {
- done = 1;
- } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
- status = PARSE_NEED_MORE_DATA;
- }
- } while (!done && status == PARSE_OK);
-
- return status;
-}
-
-// Creates a new Frame if 'actual_size' is within bounds and 'mem' contains
-// enough data ('min_size') to parse the payload.
-// Returns PARSE_OK on success with *frame pointing to the new Frame.
-// Returns PARSE_NEED_MORE_DATA with insufficient data, PARSE_ERROR otherwise.
-static ParseStatus NewFrame(const MemBuffer* const mem,
- uint32_t min_size, uint32_t actual_size,
- Frame** frame) {
- if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
- if (actual_size < min_size) return PARSE_ERROR;
- if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
-
- *frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(**frame));
- return (*frame == NULL) ? PARSE_ERROR : PARSE_OK;
-}
-
-// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
-// 'frame_chunk_size' is the previously validated, padded chunk size.
-static ParseStatus ParseAnimationFrame(
- WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
- const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
- const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
- int added_frame = 0;
- int bits;
- MemBuffer* const mem = &dmux->mem_;
- Frame* frame;
- ParseStatus status =
- NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
- if (status != PARSE_OK) return status;
-
- frame->x_offset_ = 2 * ReadLE24s(mem);
- frame->y_offset_ = 2 * ReadLE24s(mem);
- frame->width_ = 1 + ReadLE24s(mem);
- frame->height_ = 1 + ReadLE24s(mem);
- frame->duration_ = ReadLE24s(mem);
- bits = ReadByte(mem);
- frame->dispose_method_ =
- (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
- frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
- if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) {
- WebPSafeFree(frame);
- return PARSE_ERROR;
- }
-
- // Store a frame only if the animation flag is set there is some data for
- // this frame is available.
- status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame);
- if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) {
- added_frame = AddFrame(dmux, frame);
- if (added_frame) {
- ++dmux->num_frames_;
- } else {
- status = PARSE_ERROR;
- }
- }
-
- if (!added_frame) WebPSafeFree(frame);
- return status;
-}
-
-// General chunk storage, starting with the header at 'start_offset', allowing
-// the user to request the payload via a fourcc string. 'size' includes the
-// header and the unpadded payload size.
-// Returns true on success, false otherwise.
-static int StoreChunk(WebPDemuxer* const dmux,
- size_t start_offset, uint32_t size) {
- Chunk* const chunk = (Chunk*)WebPSafeCalloc(1ULL, sizeof(*chunk));
- if (chunk == NULL) return 0;
-
- chunk->data_.offset_ = start_offset;
- chunk->data_.size_ = size;
- AddChunk(dmux, chunk);
- return 1;
-}
-
-// -----------------------------------------------------------------------------
-// Primary chunk parsing
-
-static ParseStatus ReadHeader(MemBuffer* const mem) {
- const size_t min_size = RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE;
- uint32_t riff_size;
-
- // Basic file level validation.
- if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
- if (memcmp(GetBuffer(mem), "RIFF", CHUNK_SIZE_BYTES) ||
- memcmp(GetBuffer(mem) + CHUNK_HEADER_SIZE, "WEBP", CHUNK_SIZE_BYTES)) {
- return PARSE_ERROR;
- }
-
- riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE);
- if (riff_size < CHUNK_HEADER_SIZE) return PARSE_ERROR;
- if (riff_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
-
- // There's no point in reading past the end of the RIFF chunk
- mem->riff_end_ = riff_size + CHUNK_HEADER_SIZE;
- if (mem->buf_size_ > mem->riff_end_) {
- mem->buf_size_ = mem->end_ = mem->riff_end_;
- }
-
- Skip(mem, RIFF_HEADER_SIZE);
- return PARSE_OK;
-}
-
-static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
- const size_t min_size = CHUNK_HEADER_SIZE;
- MemBuffer* const mem = &dmux->mem_;
- Frame* frame;
- ParseStatus status;
- int image_added = 0;
-
- if (dmux->frames_ != NULL) return PARSE_ERROR;
- if (SizeIsInvalid(mem, min_size)) return PARSE_ERROR;
- if (MemDataSize(mem) < min_size) return PARSE_NEED_MORE_DATA;
-
- frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame));
- if (frame == NULL) return PARSE_ERROR;
-
- // For the single image case we allow parsing of a partial frame, but we need
- // at least CHUNK_HEADER_SIZE for parsing.
- status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame);
- if (status != PARSE_ERROR) {
- const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG);
- // Clear any alpha when the alpha flag is missing.
- if (!has_alpha && frame->img_components_[1].size_ > 0) {
- frame->img_components_[1].offset_ = 0;
- frame->img_components_[1].size_ = 0;
- frame->has_alpha_ = 0;
- }
-
- // Use the frame width/height as the canvas values for non-vp8x files.
- // Also, set ALPHA_FLAG if this is a lossless image with alpha.
- if (!dmux->is_ext_format_ && frame->width_ > 0 && frame->height_ > 0) {
- dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
- dmux->canvas_width_ = frame->width_;
- dmux->canvas_height_ = frame->height_;
- dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0;
- }
- if (!AddFrame(dmux, frame)) {
- status = PARSE_ERROR; // last frame was left incomplete
- } else {
- image_added = 1;
- dmux->num_frames_ = 1;
- }
- }
-
- if (!image_added) WebPSafeFree(frame);
- return status;
-}
-
-static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) {
- const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
- MemBuffer* const mem = &dmux->mem_;
- int anim_chunks = 0;
- ParseStatus status = PARSE_OK;
-
- do {
- int store_chunk = 1;
- const size_t chunk_start_offset = mem->start_;
- const uint32_t fourcc = ReadLE32(mem);
- const uint32_t chunk_size = ReadLE32(mem);
- const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1);
-
- if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
- if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR;
-
- switch (fourcc) {
- case MKFOURCC('V', 'P', '8', 'X'): {
- return PARSE_ERROR;
- }
- case MKFOURCC('A', 'L', 'P', 'H'):
- case MKFOURCC('V', 'P', '8', ' '):
- case MKFOURCC('V', 'P', '8', 'L'): {
- // check that this isn't an animation (all frames should be in an ANMF).
- if (anim_chunks > 0 || is_animation) return PARSE_ERROR;
-
- Rewind(mem, CHUNK_HEADER_SIZE);
- status = ParseSingleImage(dmux);
- break;
- }
- case MKFOURCC('A', 'N', 'I', 'M'): {
- if (chunk_size_padded < ANIM_CHUNK_SIZE) return PARSE_ERROR;
-
- if (MemDataSize(mem) < chunk_size_padded) {
- status = PARSE_NEED_MORE_DATA;
- } else if (anim_chunks == 0) {
- ++anim_chunks;
- dmux->bgcolor_ = ReadLE32(mem);
- dmux->loop_count_ = ReadLE16s(mem);
- Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE);
- } else {
- store_chunk = 0;
- goto Skip;
- }
- break;
- }
- case MKFOURCC('A', 'N', 'M', 'F'): {
- if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames.
- status = ParseAnimationFrame(dmux, chunk_size_padded);
- break;
- }
- case MKFOURCC('I', 'C', 'C', 'P'): {
- store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG);
- goto Skip;
- }
- case MKFOURCC('E', 'X', 'I', 'F'): {
- store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG);
- goto Skip;
- }
- case MKFOURCC('X', 'M', 'P', ' '): {
- store_chunk = !!(dmux->feature_flags_ & XMP_FLAG);
- goto Skip;
- }
- Skip:
- default: {
- if (chunk_size_padded <= MemDataSize(mem)) {
- if (store_chunk) {
- // Store only the chunk header and unpadded size as only the payload
- // will be returned to the user.
- if (!StoreChunk(dmux, chunk_start_offset,
- CHUNK_HEADER_SIZE + chunk_size)) {
- return PARSE_ERROR;
- }
- }
- Skip(mem, chunk_size_padded);
- } else {
- status = PARSE_NEED_MORE_DATA;
- }
- }
- }
-
- if (mem->start_ == mem->riff_end_) {
- break;
- } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
- status = PARSE_NEED_MORE_DATA;
- }
- } while (status == PARSE_OK);
-
- return status;
-}
-
-static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
- MemBuffer* const mem = &dmux->mem_;
- uint32_t vp8x_size;
-
- if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA;
-
- dmux->is_ext_format_ = 1;
- Skip(mem, TAG_SIZE); // VP8X
- vp8x_size = ReadLE32(mem);
- if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
- if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR;
- vp8x_size += vp8x_size & 1;
- if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR;
- if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA;
-
- dmux->feature_flags_ = ReadByte(mem);
- Skip(mem, 3); // Reserved.
- dmux->canvas_width_ = 1 + ReadLE24s(mem);
- dmux->canvas_height_ = 1 + ReadLE24s(mem);
- if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) {
- return PARSE_ERROR; // image final dimension is too large
- }
- Skip(mem, vp8x_size - VP8X_CHUNK_SIZE); // skip any trailing data.
- dmux->state_ = WEBP_DEMUX_PARSED_HEADER;
-
- if (SizeIsInvalid(mem, CHUNK_HEADER_SIZE)) return PARSE_ERROR;
- if (MemDataSize(mem) < CHUNK_HEADER_SIZE) return PARSE_NEED_MORE_DATA;
-
- return ParseVP8XChunks(dmux);
-}
-
-// -----------------------------------------------------------------------------
-// Format validation
-
-static int IsValidSimpleFormat(const WebPDemuxer* const dmux) {
- const Frame* const frame = dmux->frames_;
- if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1;
-
- if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0;
- if (dmux->state_ == WEBP_DEMUX_DONE && frame == NULL) return 0;
-
- if (frame->width_ <= 0 || frame->height_ <= 0) return 0;
- return 1;
-}
-
-// If 'exact' is true, check that the image resolution matches the canvas.
-// If 'exact' is false, check that the x/y offsets do not exceed the canvas.
-static int CheckFrameBounds(const Frame* const frame, int exact,
- int canvas_width, int canvas_height) {
- if (exact) {
- if (frame->x_offset_ != 0 || frame->y_offset_ != 0) {
- return 0;
- }
- if (frame->width_ != canvas_width || frame->height_ != canvas_height) {
- return 0;
- }
- } else {
- if (frame->x_offset_ < 0 || frame->y_offset_ < 0) return 0;
- if (frame->width_ + frame->x_offset_ > canvas_width) return 0;
- if (frame->height_ + frame->y_offset_ > canvas_height) return 0;
- }
- return 1;
-}
-
-static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
- const int is_animation = !!(dmux->feature_flags_ & ANIMATION_FLAG);
- const int is_fragmented = !!(dmux->feature_flags_ & FRAGMENTS_FLAG);
- const Frame* f = dmux->frames_;
-
- if (dmux->state_ == WEBP_DEMUX_PARSING_HEADER) return 1;
-
- if (dmux->canvas_width_ <= 0 || dmux->canvas_height_ <= 0) return 0;
- if (dmux->loop_count_ < 0) return 0;
- if (dmux->state_ == WEBP_DEMUX_DONE && dmux->frames_ == NULL) return 0;
- if (is_fragmented) return 0;
-
- while (f != NULL) {
- const int cur_frame_set = f->frame_num_;
- int frame_count = 0;
-
- // Check frame properties.
- for (; f != NULL && f->frame_num_ == cur_frame_set; f = f->next_) {
- const ChunkData* const image = f->img_components_;
- const ChunkData* const alpha = f->img_components_ + 1;
-
- if (!is_animation && f->frame_num_ > 1) return 0;
-
- if (f->complete_) {
- if (alpha->size_ == 0 && image->size_ == 0) return 0;
- // Ensure alpha precedes image bitstream.
- if (alpha->size_ > 0 && alpha->offset_ > image->offset_) {
- return 0;
- }
-
- if (f->width_ <= 0 || f->height_ <= 0) return 0;
- } else {
- // There shouldn't be a partial frame in a complete file.
- if (dmux->state_ == WEBP_DEMUX_DONE) return 0;
-
- // Ensure alpha precedes image bitstream.
- if (alpha->size_ > 0 && image->size_ > 0 &&
- alpha->offset_ > image->offset_) {
- return 0;
- }
- // There shouldn't be any frames after an incomplete one.
- if (f->next_ != NULL) return 0;
- }
-
- if (f->width_ > 0 && f->height_ > 0 &&
- !CheckFrameBounds(f, !is_animation,
- dmux->canvas_width_, dmux->canvas_height_)) {
- return 0;
- }
-
- ++frame_count;
- }
- }
- return 1;
-}
-
-// -----------------------------------------------------------------------------
-// WebPDemuxer object
-
-static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) {
- dmux->state_ = WEBP_DEMUX_PARSING_HEADER;
- dmux->loop_count_ = 1;
- dmux->bgcolor_ = 0xFFFFFFFF; // White background by default.
- dmux->canvas_width_ = -1;
- dmux->canvas_height_ = -1;
- dmux->frames_tail_ = &dmux->frames_;
- dmux->chunks_tail_ = &dmux->chunks_;
- dmux->mem_ = *mem;
-}
-
-static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem,
- WebPDemuxer** demuxer) {
- WebPBitstreamFeatures features;
- const VP8StatusCode status =
- WebPGetFeatures(mem->buf_, mem->buf_size_, &features);
- *demuxer = NULL;
- if (status != VP8_STATUS_OK) {
- return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA
- : PARSE_ERROR;
- }
-
- {
- WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux));
- Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame));
- if (dmux == NULL || frame == NULL) goto Error;
- InitDemux(dmux, mem);
- SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features,
- frame);
- if (!AddFrame(dmux, frame)) goto Error;
- dmux->state_ = WEBP_DEMUX_DONE;
- dmux->canvas_width_ = frame->width_;
- dmux->canvas_height_ = frame->height_;
- dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0;
- dmux->num_frames_ = 1;
- assert(IsValidSimpleFormat(dmux));
- *demuxer = dmux;
- return PARSE_OK;
-
- Error:
- WebPSafeFree(dmux);
- WebPSafeFree(frame);
- return PARSE_ERROR;
- }
-}
-
-WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial,
- WebPDemuxState* state, int version) {
- const ChunkParser* parser;
- int partial;
- ParseStatus status = PARSE_ERROR;
- MemBuffer mem;
- WebPDemuxer* dmux;
-
- if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR;
-
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL;
- if (data == NULL || data->bytes == NULL || data->size == 0) return NULL;
-
- if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL;
- status = ReadHeader(&mem);
- if (status != PARSE_OK) {
- // If parsing of the webp file header fails attempt to handle a raw
- // VP8/VP8L frame. Note 'allow_partial' is ignored in this case.
- if (status == PARSE_ERROR) {
- status = CreateRawImageDemuxer(&mem, &dmux);
- if (status == PARSE_OK) {
- if (state != NULL) *state = WEBP_DEMUX_DONE;
- return dmux;
- }
- }
- if (state != NULL) {
- *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER
- : WEBP_DEMUX_PARSE_ERROR;
- }
- return NULL;
- }
-
- partial = (mem.buf_size_ < mem.riff_end_);
- if (!allow_partial && partial) return NULL;
-
- dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux));
- if (dmux == NULL) return NULL;
- InitDemux(dmux, &mem);
-
- status = PARSE_ERROR;
- for (parser = kMasterChunks; parser->parse != NULL; ++parser) {
- if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) {
- status = parser->parse(dmux);
- if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE;
- if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR;
- if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR;
- if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR;
- break;
- }
- }
- if (state != NULL) *state = dmux->state_;
-
- if (status == PARSE_ERROR) {
- WebPDemuxDelete(dmux);
- return NULL;
- }
- return dmux;
-}
-
-void WebPDemuxDelete(WebPDemuxer* dmux) {
- Chunk* c;
- Frame* f;
- if (dmux == NULL) return;
-
- for (f = dmux->frames_; f != NULL;) {
- Frame* const cur_frame = f;
- f = f->next_;
- WebPSafeFree(cur_frame);
- }
- for (c = dmux->chunks_; c != NULL;) {
- Chunk* const cur_chunk = c;
- c = c->next_;
- WebPSafeFree(cur_chunk);
- }
- WebPSafeFree(dmux);
-}
-
-// -----------------------------------------------------------------------------
-
-uint32_t WebPDemuxGetI(const WebPDemuxer* dmux, WebPFormatFeature feature) {
- if (dmux == NULL) return 0;
-
- switch (feature) {
- case WEBP_FF_FORMAT_FLAGS: return dmux->feature_flags_;
- case WEBP_FF_CANVAS_WIDTH: return (uint32_t)dmux->canvas_width_;
- case WEBP_FF_CANVAS_HEIGHT: return (uint32_t)dmux->canvas_height_;
- case WEBP_FF_LOOP_COUNT: return (uint32_t)dmux->loop_count_;
- case WEBP_FF_BACKGROUND_COLOR: return dmux->bgcolor_;
- case WEBP_FF_FRAME_COUNT: return (uint32_t)dmux->num_frames_;
- }
- return 0;
-}
-
-// -----------------------------------------------------------------------------
-// Frame iteration
-
-static const Frame* GetFrame(const WebPDemuxer* const dmux, int frame_num) {
- const Frame* f;
- for (f = dmux->frames_; f != NULL; f = f->next_) {
- if (frame_num == f->frame_num_) break;
- }
- return f;
-}
-
-static const uint8_t* GetFramePayload(const uint8_t* const mem_buf,
- const Frame* const frame,
- size_t* const data_size) {
- *data_size = 0;
- if (frame != NULL) {
- const ChunkData* const image = frame->img_components_;
- const ChunkData* const alpha = frame->img_components_ + 1;
- size_t start_offset = image->offset_;
- *data_size = image->size_;
-
- // if alpha exists it precedes image, update the size allowing for
- // intervening chunks.
- if (alpha->size_ > 0) {
- const size_t inter_size = (image->offset_ > 0)
- ? image->offset_ - (alpha->offset_ + alpha->size_)
- : 0;
- start_offset = alpha->offset_;
- *data_size += alpha->size_ + inter_size;
- }
- return mem_buf + start_offset;
- }
- return NULL;
-}
-
-// Create a whole 'frame' from VP8 (+ alpha) or lossless.
-static int SynthesizeFrame(const WebPDemuxer* const dmux,
- const Frame* const frame,
- WebPIterator* const iter) {
- const uint8_t* const mem_buf = dmux->mem_.buf_;
- size_t payload_size = 0;
- const uint8_t* const payload = GetFramePayload(mem_buf, frame, &payload_size);
- if (payload == NULL) return 0;
- assert(frame != NULL);
-
- iter->frame_num = frame->frame_num_;
- iter->num_frames = dmux->num_frames_;
- iter->x_offset = frame->x_offset_;
- iter->y_offset = frame->y_offset_;
- iter->width = frame->width_;
- iter->height = frame->height_;
- iter->has_alpha = frame->has_alpha_;
- iter->duration = frame->duration_;
- iter->dispose_method = frame->dispose_method_;
- iter->blend_method = frame->blend_method_;
- iter->complete = frame->complete_;
- iter->fragment.bytes = payload;
- iter->fragment.size = payload_size;
- return 1;
-}
-
-static int SetFrame(int frame_num, WebPIterator* const iter) {
- const Frame* frame;
- const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
- if (dmux == NULL || frame_num < 0) return 0;
- if (frame_num > dmux->num_frames_) return 0;
- if (frame_num == 0) frame_num = dmux->num_frames_;
-
- frame = GetFrame(dmux, frame_num);
- if (frame == NULL) return 0;
-
- return SynthesizeFrame(dmux, frame, iter);
-}
-
-int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) {
- if (iter == NULL) return 0;
-
- memset(iter, 0, sizeof(*iter));
- iter->private_ = (void*)dmux;
- return SetFrame(frame, iter);
-}
-
-int WebPDemuxNextFrame(WebPIterator* iter) {
- if (iter == NULL) return 0;
- return SetFrame(iter->frame_num + 1, iter);
-}
-
-int WebPDemuxPrevFrame(WebPIterator* iter) {
- if (iter == NULL) return 0;
- if (iter->frame_num <= 1) return 0;
- return SetFrame(iter->frame_num - 1, iter);
-}
-
-void WebPDemuxReleaseIterator(WebPIterator* iter) {
- (void)iter;
-}
-
-// -----------------------------------------------------------------------------
-// Chunk iteration
-
-static int ChunkCount(const WebPDemuxer* const dmux, const char fourcc[4]) {
- const uint8_t* const mem_buf = dmux->mem_.buf_;
- const Chunk* c;
- int count = 0;
- for (c = dmux->chunks_; c != NULL; c = c->next_) {
- const uint8_t* const header = mem_buf + c->data_.offset_;
- if (!memcmp(header, fourcc, TAG_SIZE)) ++count;
- }
- return count;
-}
-
-static const Chunk* GetChunk(const WebPDemuxer* const dmux,
- const char fourcc[4], int chunk_num) {
- const uint8_t* const mem_buf = dmux->mem_.buf_;
- const Chunk* c;
- int count = 0;
- for (c = dmux->chunks_; c != NULL; c = c->next_) {
- const uint8_t* const header = mem_buf + c->data_.offset_;
- if (!memcmp(header, fourcc, TAG_SIZE)) ++count;
- if (count == chunk_num) break;
- }
- return c;
-}
-
-static int SetChunk(const char fourcc[4], int chunk_num,
- WebPChunkIterator* const iter) {
- const WebPDemuxer* const dmux = (WebPDemuxer*)iter->private_;
- int count;
-
- if (dmux == NULL || fourcc == NULL || chunk_num < 0) return 0;
- count = ChunkCount(dmux, fourcc);
- if (count == 0) return 0;
- if (chunk_num == 0) chunk_num = count;
-
- if (chunk_num <= count) {
- const uint8_t* const mem_buf = dmux->mem_.buf_;
- const Chunk* const chunk = GetChunk(dmux, fourcc, chunk_num);
- iter->chunk.bytes = mem_buf + chunk->data_.offset_ + CHUNK_HEADER_SIZE;
- iter->chunk.size = chunk->data_.size_ - CHUNK_HEADER_SIZE;
- iter->num_chunks = count;
- iter->chunk_num = chunk_num;
- return 1;
- }
- return 0;
-}
-
-int WebPDemuxGetChunk(const WebPDemuxer* dmux,
- const char fourcc[4], int chunk_num,
- WebPChunkIterator* iter) {
- if (iter == NULL) return 0;
-
- memset(iter, 0, sizeof(*iter));
- iter->private_ = (void*)dmux;
- return SetChunk(fourcc, chunk_num, iter);
-}
-
-int WebPDemuxNextChunk(WebPChunkIterator* iter) {
- if (iter != NULL) {
- const char* const fourcc =
- (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE;
- return SetChunk(fourcc, iter->chunk_num + 1, iter);
- }
- return 0;
-}
-
-int WebPDemuxPrevChunk(WebPChunkIterator* iter) {
- if (iter != NULL && iter->chunk_num > 1) {
- const char* const fourcc =
- (const char*)iter->chunk.bytes - CHUNK_HEADER_SIZE;
- return SetChunk(fourcc, iter->chunk_num - 1, iter);
- }
- return 0;
-}
-
-void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter) {
- (void)iter;
-}
-
diff --git a/drivers/webp/dsp/alpha_processing.c b/drivers/webp/dsp/alpha_processing.c
deleted file mode 100644
index 1716cace8d..0000000000
--- a/drivers/webp/dsp/alpha_processing.c
+++ /dev/null
@@ -1,383 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Utilities for processing transparent channel.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include "./dsp.h"
-
-// Tables can be faster on some platform but incur some extra binary size (~2k).
-// #define USE_TABLES_FOR_ALPHA_MULT
-
-// -----------------------------------------------------------------------------
-
-#define MFIX 24 // 24bit fixed-point arithmetic
-#define HALF ((1u << MFIX) >> 1)
-#define KINV_255 ((1u << MFIX) / 255u)
-
-static uint32_t Mult(uint8_t x, uint32_t mult) {
- const uint32_t v = (x * mult + HALF) >> MFIX;
- assert(v <= 255); // <- 24bit precision is enough to ensure that.
- return v;
-}
-
-#ifdef USE_TABLES_FOR_ALPHA_MULT
-
-static const uint32_t kMultTables[2][256] = {
- { // (255u << MFIX) / alpha
- 0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000,
- 0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2,
- 0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000,
- 0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8,
- 0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3,
- 0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492,
- 0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3,
- 0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8,
- 0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7,
- 0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0,
- 0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4,
- 0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6,
- 0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace,
- 0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a,
- 0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf,
- 0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b,
- 0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d,
- 0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec,
- 0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9,
- 0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249,
- 0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70,
- 0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213,
- 0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10,
- 0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5,
- 0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed,
- 0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a,
- 0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741,
- 0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0,
- 0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e,
- 0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157,
- 0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67,
- 0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4,
- 0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc,
- 0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b,
- 0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830,
- 0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be,
- 0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276,
- 0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc,
- 0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2,
- 0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358,
- 0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0,
- 0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465,
- 0x01030c30, 0x01020612, 0x01010204, 0x01000000 },
- { // alpha * KINV_255
- 0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505,
- 0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b,
- 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111,
- 0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717,
- 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d,
- 0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323,
- 0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929,
- 0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f,
- 0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535,
- 0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b,
- 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141,
- 0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747,
- 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d,
- 0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353,
- 0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959,
- 0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f,
- 0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565,
- 0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b,
- 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171,
- 0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777,
- 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d,
- 0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383,
- 0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989,
- 0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f,
- 0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595,
- 0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b,
- 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1,
- 0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7,
- 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad,
- 0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3,
- 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9,
- 0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf,
- 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5,
- 0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb,
- 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1,
- 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7,
- 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd,
- 0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3,
- 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9,
- 0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef,
- 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5,
- 0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb,
- 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff }
-};
-
-static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
- return kMultTables[!inverse][a];
-}
-
-#else
-
-static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
- return inverse ? (255u << MFIX) / a : a * KINV_255;
-}
-
-#endif // USE_TABLES_FOR_ALPHA_MULT
-
-void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse) {
- int x;
- for (x = 0; x < width; ++x) {
- const uint32_t argb = ptr[x];
- if (argb < 0xff000000u) { // alpha < 255
- if (argb <= 0x00ffffffu) { // alpha == 0
- ptr[x] = 0;
- } else {
- const uint32_t alpha = (argb >> 24) & 0xff;
- const uint32_t scale = GetScale(alpha, inverse);
- uint32_t out = argb & 0xff000000u;
- out |= Mult(argb >> 0, scale) << 0;
- out |= Mult(argb >> 8, scale) << 8;
- out |= Mult(argb >> 16, scale) << 16;
- ptr[x] = out;
- }
- }
- }
-}
-
-void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha,
- int width, int inverse) {
- int x;
- for (x = 0; x < width; ++x) {
- const uint32_t a = alpha[x];
- if (a != 255) {
- if (a == 0) {
- ptr[x] = 0;
- } else {
- const uint32_t scale = GetScale(a, inverse);
- ptr[x] = Mult(ptr[x], scale);
- }
- }
- }
-}
-
-#undef KINV_255
-#undef HALF
-#undef MFIX
-
-void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
-void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
- int width, int inverse);
-
-//------------------------------------------------------------------------------
-// Generic per-plane calls
-
-void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
- int inverse) {
- int n;
- for (n = 0; n < num_rows; ++n) {
- WebPMultARGBRow((uint32_t*)ptr, width, inverse);
- ptr += stride;
- }
-}
-
-void WebPMultRows(uint8_t* ptr, int stride,
- const uint8_t* alpha, int alpha_stride,
- int width, int num_rows, int inverse) {
- int n;
- for (n = 0; n < num_rows; ++n) {
- WebPMultRow(ptr, alpha, width, inverse);
- ptr += stride;
- alpha += alpha_stride;
- }
-}
-
-//------------------------------------------------------------------------------
-// Premultiplied modes
-
-// non dithered-modes
-
-// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.)
-// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5),
-// one can use instead: (x * a * 65793 + (1 << 23)) >> 24
-#if 1 // (int)(x * a / 255.)
-#define MULTIPLIER(a) ((a) * 32897U)
-#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
-#else // (int)(x * a / 255. + .5)
-#define MULTIPLIER(a) ((a) * 65793U)
-#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24)
-#endif
-
-static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
- int w, int h, int stride) {
- while (h-- > 0) {
- uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
- const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
- int i;
- for (i = 0; i < w; ++i) {
- const uint32_t a = alpha[4 * i];
- if (a != 0xff) {
- const uint32_t mult = MULTIPLIER(a);
- rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
- rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
- rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
- }
- }
- rgba += stride;
- }
-}
-#undef MULTIPLIER
-#undef PREMULTIPLY
-
-// rgbA4444
-
-#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15
-
-static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
- return (x & 0xf0) | (x >> 4);
-}
-
-static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
- return (x & 0x0f) | (x << 4);
-}
-
-static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
- return (x * m) >> 16;
-}
-
-static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444,
- int w, int h, int stride,
- int rg_byte_pos /* 0 or 1 */) {
- while (h-- > 0) {
- int i;
- for (i = 0; i < w; ++i) {
- const uint32_t rg = rgba4444[2 * i + rg_byte_pos];
- const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)];
- const uint8_t a = ba & 0x0f;
- const uint32_t mult = MULTIPLIER(a);
- const uint8_t r = multiply(dither_hi(rg), mult);
- const uint8_t g = multiply(dither_lo(rg), mult);
- const uint8_t b = multiply(dither_hi(ba), mult);
- rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f);
- rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a;
- }
- rgba4444 += stride;
- }
-}
-#undef MULTIPLIER
-
-static void ApplyAlphaMultiply_16b(uint8_t* rgba4444,
- int w, int h, int stride) {
-#ifdef WEBP_SWAP_16BIT_CSP
- ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1);
-#else
- ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0);
-#endif
-}
-
-static int DispatchAlpha(const uint8_t* alpha, int alpha_stride,
- int width, int height,
- uint8_t* dst, int dst_stride) {
- uint32_t alpha_mask = 0xff;
- int i, j;
-
- for (j = 0; j < height; ++j) {
- for (i = 0; i < width; ++i) {
- const uint32_t alpha_value = alpha[i];
- dst[4 * i] = alpha_value;
- alpha_mask &= alpha_value;
- }
- alpha += alpha_stride;
- dst += dst_stride;
- }
-
- return (alpha_mask != 0xff);
-}
-
-static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride,
- int width, int height,
- uint32_t* dst, int dst_stride) {
- int i, j;
- for (j = 0; j < height; ++j) {
- for (i = 0; i < width; ++i) {
- dst[i] = alpha[i] << 8; // leave A/R/B channels zero'd.
- }
- alpha += alpha_stride;
- dst += dst_stride;
- }
-}
-
-static int ExtractAlpha(const uint8_t* argb, int argb_stride,
- int width, int height,
- uint8_t* alpha, int alpha_stride) {
- uint8_t alpha_mask = 0xff;
- int i, j;
-
- for (j = 0; j < height; ++j) {
- for (i = 0; i < width; ++i) {
- const uint8_t alpha_value = argb[4 * i];
- alpha[i] = alpha_value;
- alpha_mask &= alpha_value;
- }
- argb += argb_stride;
- alpha += alpha_stride;
- }
- return (alpha_mask == 0xff);
-}
-
-void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int);
-void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
-int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
-void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int);
-int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
-
-//------------------------------------------------------------------------------
-// Init function
-
-extern void WebPInitAlphaProcessingMIPSdspR2(void);
-extern void WebPInitAlphaProcessingSSE2(void);
-extern void WebPInitAlphaProcessingSSE41(void);
-
-static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used =
- (VP8CPUInfo)&alpha_processing_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) {
- if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- WebPMultARGBRow = WebPMultARGBRowC;
- WebPMultRow = WebPMultRowC;
- WebPApplyAlphaMultiply = ApplyAlphaMultiply;
- WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b;
- WebPDispatchAlpha = DispatchAlpha;
- WebPDispatchAlphaToGreen = DispatchAlphaToGreen;
- WebPExtractAlpha = ExtractAlpha;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- WebPInitAlphaProcessingSSE2();
-#if defined(WEBP_USE_SSE41)
- if (VP8GetCPUInfo(kSSE4_1)) {
- WebPInitAlphaProcessingSSE41();
- }
-#endif
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- WebPInitAlphaProcessingMIPSdspR2();
- }
-#endif
- }
- alpha_processing_last_cpuinfo_used = VP8GetCPUInfo;
-}
diff --git a/drivers/webp/dsp/alpha_processing_mips_dsp_r2.c b/drivers/webp/dsp/alpha_processing_mips_dsp_r2.c
deleted file mode 100644
index c631d78905..0000000000
--- a/drivers/webp/dsp/alpha_processing_mips_dsp_r2.c
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Utilities for processing transparent channel.
-//
-// Author(s): Branimir Vasic (branimir.vasic@imgtec.com)
-// Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-static int DispatchAlpha(const uint8_t* alpha, int alpha_stride,
- int width, int height,
- uint8_t* dst, int dst_stride) {
- uint32_t alpha_mask = 0xffffffff;
- int i, j, temp0;
-
- for (j = 0; j < height; ++j) {
- uint8_t* pdst = dst;
- const uint8_t* palpha = alpha;
- for (i = 0; i < (width >> 2); ++i) {
- int temp1, temp2, temp3;
-
- __asm__ volatile (
- "ulw %[temp0], 0(%[palpha]) \n\t"
- "addiu %[palpha], %[palpha], 4 \n\t"
- "addiu %[pdst], %[pdst], 16 \n\t"
- "srl %[temp1], %[temp0], 8 \n\t"
- "srl %[temp2], %[temp0], 16 \n\t"
- "srl %[temp3], %[temp0], 24 \n\t"
- "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
- "sb %[temp0], -16(%[pdst]) \n\t"
- "sb %[temp1], -12(%[pdst]) \n\t"
- "sb %[temp2], -8(%[pdst]) \n\t"
- "sb %[temp3], -4(%[pdst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [palpha]"+r"(palpha), [pdst]"+r"(pdst),
- [alpha_mask]"+r"(alpha_mask)
- :
- : "memory"
- );
- }
-
- for (i = 0; i < (width & 3); ++i) {
- __asm__ volatile (
- "lbu %[temp0], 0(%[palpha]) \n\t"
- "addiu %[palpha], %[palpha], 1 \n\t"
- "sb %[temp0], 0(%[pdst]) \n\t"
- "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
- "addiu %[pdst], %[pdst], 4 \n\t"
- : [temp0]"=&r"(temp0), [palpha]"+r"(palpha), [pdst]"+r"(pdst),
- [alpha_mask]"+r"(alpha_mask)
- :
- : "memory"
- );
- }
- alpha += alpha_stride;
- dst += dst_stride;
- }
-
- __asm__ volatile (
- "ext %[temp0], %[alpha_mask], 0, 16 \n\t"
- "srl %[alpha_mask], %[alpha_mask], 16 \n\t"
- "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
- "ext %[temp0], %[alpha_mask], 0, 8 \n\t"
- "srl %[alpha_mask], %[alpha_mask], 8 \n\t"
- "and %[alpha_mask], %[alpha_mask], %[temp0] \n\t"
- : [temp0]"=&r"(temp0), [alpha_mask]"+r"(alpha_mask)
- :
- );
-
- return (alpha_mask != 0xff);
-}
-
-static void MultARGBRow(uint32_t* const ptr, int width, int inverse) {
- int x;
- const uint32_t c_00ffffff = 0x00ffffffu;
- const uint32_t c_ff000000 = 0xff000000u;
- const uint32_t c_8000000 = 0x00800000u;
- const uint32_t c_8000080 = 0x00800080u;
- for (x = 0; x < width; ++x) {
- const uint32_t argb = ptr[x];
- if (argb < 0xff000000u) { // alpha < 255
- if (argb <= 0x00ffffffu) { // alpha == 0
- ptr[x] = 0;
- } else {
- int temp0, temp1, temp2, temp3, alpha;
- __asm__ volatile (
- "srl %[alpha], %[argb], 24 \n\t"
- "replv.qb %[temp0], %[alpha] \n\t"
- "and %[temp0], %[temp0], %[c_00ffffff] \n\t"
- "beqz %[inverse], 0f \n\t"
- "divu $zero, %[c_ff000000], %[alpha] \n\t"
- "mflo %[temp0] \n\t"
- "0: \n\t"
- "andi %[temp1], %[argb], 0xff \n\t"
- "ext %[temp2], %[argb], 8, 8 \n\t"
- "ext %[temp3], %[argb], 16, 8 \n\t"
- "mul %[temp1], %[temp1], %[temp0] \n\t"
- "mul %[temp2], %[temp2], %[temp0] \n\t"
- "mul %[temp3], %[temp3], %[temp0] \n\t"
- "precrq.ph.w %[temp1], %[temp2], %[temp1] \n\t"
- "addu %[temp3], %[temp3], %[c_8000000] \n\t"
- "addu %[temp1], %[temp1], %[c_8000080] \n\t"
- "precrq.ph.w %[temp3], %[argb], %[temp3] \n\t"
- "precrq.qb.ph %[temp1], %[temp3], %[temp1] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [alpha]"=&r"(alpha)
- : [inverse]"r"(inverse), [c_00ffffff]"r"(c_00ffffff),
- [c_8000000]"r"(c_8000000), [c_8000080]"r"(c_8000080),
- [c_ff000000]"r"(c_ff000000), [argb]"r"(argb)
- : "memory", "hi", "lo"
- );
- ptr[x] = temp1;
- }
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPInitAlphaProcessingMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingMIPSdspR2(void) {
- WebPDispatchAlpha = DispatchAlpha;
- WebPMultARGBRow = MultARGBRow;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/alpha_processing_sse2.c b/drivers/webp/dsp/alpha_processing_sse2.c
deleted file mode 100644
index 5acb481dcd..0000000000
--- a/drivers/webp/dsp/alpha_processing_sse2.c
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Utilities for processing transparent channel.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-#include <emmintrin.h>
-
-//------------------------------------------------------------------------------
-
-static int DispatchAlpha(const uint8_t* alpha, int alpha_stride,
- int width, int height,
- uint8_t* dst, int dst_stride) {
- // alpha_and stores an 'and' operation of all the alpha[] values. The final
- // value is not 0xff if any of the alpha[] is not equal to 0xff.
- uint32_t alpha_and = 0xff;
- int i, j;
- const __m128i zero = _mm_setzero_si128();
- const __m128i rgb_mask = _mm_set1_epi32(0xffffff00u); // to preserve RGB
- const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u);
- __m128i all_alphas = all_0xff;
-
- // We must be able to access 3 extra bytes after the last written byte
- // 'dst[4 * width - 4]', because we don't know if alpha is the first or the
- // last byte of the quadruplet.
- const int limit = (width - 1) & ~7;
-
- for (j = 0; j < height; ++j) {
- __m128i* out = (__m128i*)dst;
- for (i = 0; i < limit; i += 8) {
- // load 8 alpha bytes
- const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[i]);
- const __m128i a1 = _mm_unpacklo_epi8(a0, zero);
- const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero);
- const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero);
- // load 8 dst pixels (32 bytes)
- const __m128i b0_lo = _mm_loadu_si128(out + 0);
- const __m128i b0_hi = _mm_loadu_si128(out + 1);
- // mask dst alpha values
- const __m128i b1_lo = _mm_and_si128(b0_lo, rgb_mask);
- const __m128i b1_hi = _mm_and_si128(b0_hi, rgb_mask);
- // combine
- const __m128i b2_lo = _mm_or_si128(b1_lo, a2_lo);
- const __m128i b2_hi = _mm_or_si128(b1_hi, a2_hi);
- // store
- _mm_storeu_si128(out + 0, b2_lo);
- _mm_storeu_si128(out + 1, b2_hi);
- // accumulate eight alpha 'and' in parallel
- all_alphas = _mm_and_si128(all_alphas, a0);
- out += 2;
- }
- for (; i < width; ++i) {
- const uint32_t alpha_value = alpha[i];
- dst[4 * i] = alpha_value;
- alpha_and &= alpha_value;
- }
- alpha += alpha_stride;
- dst += dst_stride;
- }
- // Combine the eight alpha 'and' into a 8-bit mask.
- alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff));
- return (alpha_and != 0xff);
-}
-
-static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride,
- int width, int height,
- uint32_t* dst, int dst_stride) {
- int i, j;
- const __m128i zero = _mm_setzero_si128();
- const int limit = width & ~15;
- for (j = 0; j < height; ++j) {
- for (i = 0; i < limit; i += 16) { // process 16 alpha bytes
- const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]);
- const __m128i a1 = _mm_unpacklo_epi8(zero, a0); // note the 'zero' first!
- const __m128i b1 = _mm_unpackhi_epi8(zero, a0);
- const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero);
- const __m128i b2_lo = _mm_unpacklo_epi16(b1, zero);
- const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero);
- const __m128i b2_hi = _mm_unpackhi_epi16(b1, zero);
- _mm_storeu_si128((__m128i*)&dst[i + 0], a2_lo);
- _mm_storeu_si128((__m128i*)&dst[i + 4], a2_hi);
- _mm_storeu_si128((__m128i*)&dst[i + 8], b2_lo);
- _mm_storeu_si128((__m128i*)&dst[i + 12], b2_hi);
- }
- for (; i < width; ++i) dst[i] = alpha[i] << 8;
- alpha += alpha_stride;
- dst += dst_stride;
- }
-}
-
-static int ExtractAlpha(const uint8_t* argb, int argb_stride,
- int width, int height,
- uint8_t* alpha, int alpha_stride) {
- // alpha_and stores an 'and' operation of all the alpha[] values. The final
- // value is not 0xff if any of the alpha[] is not equal to 0xff.
- uint32_t alpha_and = 0xff;
- int i, j;
- const __m128i a_mask = _mm_set1_epi32(0xffu); // to preserve alpha
- const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u);
- __m128i all_alphas = all_0xff;
-
- // We must be able to access 3 extra bytes after the last written byte
- // 'src[4 * width - 4]', because we don't know if alpha is the first or the
- // last byte of the quadruplet.
- const int limit = (width - 1) & ~7;
-
- for (j = 0; j < height; ++j) {
- const __m128i* src = (const __m128i*)argb;
- for (i = 0; i < limit; i += 8) {
- // load 32 argb bytes
- const __m128i a0 = _mm_loadu_si128(src + 0);
- const __m128i a1 = _mm_loadu_si128(src + 1);
- const __m128i b0 = _mm_and_si128(a0, a_mask);
- const __m128i b1 = _mm_and_si128(a1, a_mask);
- const __m128i c0 = _mm_packs_epi32(b0, b1);
- const __m128i d0 = _mm_packus_epi16(c0, c0);
- // store
- _mm_storel_epi64((__m128i*)&alpha[i], d0);
- // accumulate eight alpha 'and' in parallel
- all_alphas = _mm_and_si128(all_alphas, d0);
- src += 2;
- }
- for (; i < width; ++i) {
- const uint32_t alpha_value = argb[4 * i];
- alpha[i] = alpha_value;
- alpha_and &= alpha_value;
- }
- argb += argb_stride;
- alpha += alpha_stride;
- }
- // Combine the eight alpha 'and' into a 8-bit mask.
- alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff));
- return (alpha_and == 0xff);
-}
-
-//------------------------------------------------------------------------------
-// Non-dither premultiplied modes
-
-#define MULTIPLIER(a) ((a) * 0x8081)
-#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
-
-// We can't use a 'const int' for the SHUFFLE value, because it has to be an
-// immediate in the _mm_shufflexx_epi16() instruction. We really a macro here.
-#define APPLY_ALPHA(RGBX, SHUFFLE, MASK, MULT) do { \
- const __m128i argb0 = _mm_loadl_epi64((__m128i*)&(RGBX)); \
- const __m128i argb1 = _mm_unpacklo_epi8(argb0, zero); \
- const __m128i alpha0 = _mm_and_si128(argb1, MASK); \
- const __m128i alpha1 = _mm_shufflelo_epi16(alpha0, SHUFFLE); \
- const __m128i alpha2 = _mm_shufflehi_epi16(alpha1, SHUFFLE); \
- /* alpha2 = [0 a0 a0 a0][0 a1 a1 a1] */ \
- const __m128i scale0 = _mm_mullo_epi16(alpha2, MULT); \
- const __m128i scale1 = _mm_mulhi_epu16(alpha2, MULT); \
- const __m128i argb2 = _mm_mulhi_epu16(argb1, scale0); \
- const __m128i argb3 = _mm_mullo_epi16(argb1, scale1); \
- const __m128i argb4 = _mm_adds_epu16(argb2, argb3); \
- const __m128i argb5 = _mm_srli_epi16(argb4, 7); \
- const __m128i argb6 = _mm_or_si128(argb5, alpha0); \
- const __m128i argb7 = _mm_packus_epi16(argb6, zero); \
- _mm_storel_epi64((__m128i*)&(RGBX), argb7); \
-} while (0)
-
-static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
- int w, int h, int stride) {
- const __m128i zero = _mm_setzero_si128();
- const int kSpan = 2;
- const int w2 = w & ~(kSpan - 1);
- while (h-- > 0) {
- uint32_t* const rgbx = (uint32_t*)rgba;
- int i;
- if (!alpha_first) {
- const __m128i kMask = _mm_set_epi16(0xff, 0, 0, 0, 0xff, 0, 0, 0);
- const __m128i kMult =
- _mm_set_epi16(0, 0x8081, 0x8081, 0x8081, 0, 0x8081, 0x8081, 0x8081);
- for (i = 0; i < w2; i += kSpan) {
- APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 3, 3, 3), kMask, kMult);
- }
- } else {
- const __m128i kMask = _mm_set_epi16(0, 0, 0, 0xff, 0, 0, 0, 0xff);
- const __m128i kMult =
- _mm_set_epi16(0x8081, 0x8081, 0x8081, 0, 0x8081, 0x8081, 0x8081, 0);
- for (i = 0; i < w2; i += kSpan) {
- APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 0, 0, 3), kMask, kMult);
- }
- }
- // Finish with left-overs.
- for (; i < w; ++i) {
- uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
- const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
- const uint32_t a = alpha[4 * i];
- if (a != 0xff) {
- const uint32_t mult = MULTIPLIER(a);
- rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
- rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
- rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
- }
- }
- rgba += stride;
- }
-}
-#undef MULTIPLIER
-#undef PREMULTIPLY
-
-// -----------------------------------------------------------------------------
-// Apply alpha value to rows
-
-// We use: kINV255 = (1 << 24) / 255 = 0x010101
-// So: a * kINV255 = (a << 16) | [(a << 8) | a]
-// -> _mm_mulhi_epu16() takes care of the (a<<16) part,
-// and _mm_mullo_epu16(a * 0x0101,...) takes care of the "(a << 8) | a" one.
-
-static void MultARGBRow(uint32_t* const ptr, int width, int inverse) {
- int x = 0;
- if (!inverse) {
- const int kSpan = 2;
- const __m128i zero = _mm_setzero_si128();
- const __m128i kRound =
- _mm_set_epi16(0, 1 << 7, 1 << 7, 1 << 7, 0, 1 << 7, 1 << 7, 1 << 7);
- const __m128i kMult =
- _mm_set_epi16(0, 0x0101, 0x0101, 0x0101, 0, 0x0101, 0x0101, 0x0101);
- const __m128i kOne64 = _mm_set_epi16(1u << 8, 0, 0, 0, 1u << 8, 0, 0, 0);
- const int w2 = width & ~(kSpan - 1);
- for (x = 0; x < w2; x += kSpan) {
- const __m128i argb0 = _mm_loadl_epi64((__m128i*)&ptr[x]);
- const __m128i argb1 = _mm_unpacklo_epi8(argb0, zero);
- const __m128i tmp0 = _mm_shufflelo_epi16(argb1, _MM_SHUFFLE(3, 3, 3, 3));
- const __m128i tmp1 = _mm_shufflehi_epi16(tmp0, _MM_SHUFFLE(3, 3, 3, 3));
- const __m128i tmp2 = _mm_srli_epi64(tmp1, 16);
- const __m128i scale0 = _mm_mullo_epi16(tmp1, kMult);
- const __m128i scale1 = _mm_or_si128(tmp2, kOne64);
- const __m128i argb2 = _mm_mulhi_epu16(argb1, scale0);
- const __m128i argb3 = _mm_mullo_epi16(argb1, scale1);
- const __m128i argb4 = _mm_adds_epu16(argb2, argb3);
- const __m128i argb5 = _mm_adds_epu16(argb4, kRound);
- const __m128i argb6 = _mm_srli_epi16(argb5, 8);
- const __m128i argb7 = _mm_packus_epi16(argb6, zero);
- _mm_storel_epi64((__m128i*)&ptr[x], argb7);
- }
- }
- width -= x;
- if (width > 0) WebPMultARGBRowC(ptr + x, width, inverse);
-}
-
-static void MultRow(uint8_t* const ptr, const uint8_t* const alpha,
- int width, int inverse) {
- int x = 0;
- if (!inverse) {
- const int kSpan = 8;
- const __m128i zero = _mm_setzero_si128();
- const __m128i kRound = _mm_set1_epi16(1 << 7);
- const int w2 = width & ~(kSpan - 1);
- for (x = 0; x < w2; x += kSpan) {
- const __m128i v0 = _mm_loadl_epi64((__m128i*)&ptr[x]);
- const __m128i v1 = _mm_unpacklo_epi8(v0, zero);
- const __m128i alpha0 = _mm_loadl_epi64((const __m128i*)&alpha[x]);
- const __m128i alpha1 = _mm_unpacklo_epi8(alpha0, zero);
- const __m128i alpha2 = _mm_unpacklo_epi8(alpha0, alpha0);
- const __m128i v2 = _mm_mulhi_epu16(v1, alpha2);
- const __m128i v3 = _mm_mullo_epi16(v1, alpha1);
- const __m128i v4 = _mm_adds_epu16(v2, v3);
- const __m128i v5 = _mm_adds_epu16(v4, kRound);
- const __m128i v6 = _mm_srli_epi16(v5, 8);
- const __m128i v7 = _mm_packus_epi16(v6, zero);
- _mm_storel_epi64((__m128i*)&ptr[x], v7);
- }
- }
- width -= x;
- if (width > 0) WebPMultRowC(ptr + x, alpha + x, width, inverse);
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPInitAlphaProcessingSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) {
- WebPMultARGBRow = MultARGBRow;
- WebPMultRow = MultRow;
- WebPApplyAlphaMultiply = ApplyAlphaMultiply;
- WebPDispatchAlpha = DispatchAlpha;
- WebPDispatchAlphaToGreen = DispatchAlphaToGreen;
- WebPExtractAlpha = ExtractAlpha;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/alpha_processing_sse41.c b/drivers/webp/dsp/alpha_processing_sse41.c
deleted file mode 100644
index 986fde94ed..0000000000
--- a/drivers/webp/dsp/alpha_processing_sse41.c
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Utilities for processing transparent channel, SSE4.1 variant.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE41)
-
-#include <smmintrin.h>
-
-//------------------------------------------------------------------------------
-
-static int ExtractAlpha(const uint8_t* argb, int argb_stride,
- int width, int height,
- uint8_t* alpha, int alpha_stride) {
- // alpha_and stores an 'and' operation of all the alpha[] values. The final
- // value is not 0xff if any of the alpha[] is not equal to 0xff.
- uint32_t alpha_and = 0xff;
- int i, j;
- const __m128i all_0xff = _mm_set1_epi32(~0u);
- __m128i all_alphas = all_0xff;
-
- // We must be able to access 3 extra bytes after the last written byte
- // 'src[4 * width - 4]', because we don't know if alpha is the first or the
- // last byte of the quadruplet.
- const int limit = (width - 1) & ~15;
- const __m128i kCstAlpha0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 12, 8, 4, 0);
- const __m128i kCstAlpha1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1,
- 12, 8, 4, 0, -1, -1, -1, -1);
- const __m128i kCstAlpha2 = _mm_set_epi8(-1, -1, -1, -1, 12, 8, 4, 0,
- -1, -1, -1, -1, -1, -1, -1, -1);
- const __m128i kCstAlpha3 = _mm_set_epi8(12, 8, 4, 0, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1);
- for (j = 0; j < height; ++j) {
- const __m128i* src = (const __m128i*)argb;
- for (i = 0; i < limit; i += 16) {
- // load 64 argb bytes
- const __m128i a0 = _mm_loadu_si128(src + 0);
- const __m128i a1 = _mm_loadu_si128(src + 1);
- const __m128i a2 = _mm_loadu_si128(src + 2);
- const __m128i a3 = _mm_loadu_si128(src + 3);
- const __m128i b0 = _mm_shuffle_epi8(a0, kCstAlpha0);
- const __m128i b1 = _mm_shuffle_epi8(a1, kCstAlpha1);
- const __m128i b2 = _mm_shuffle_epi8(a2, kCstAlpha2);
- const __m128i b3 = _mm_shuffle_epi8(a3, kCstAlpha3);
- const __m128i c0 = _mm_or_si128(b0, b1);
- const __m128i c1 = _mm_or_si128(b2, b3);
- const __m128i d0 = _mm_or_si128(c0, c1);
- // store
- _mm_storeu_si128((__m128i*)&alpha[i], d0);
- // accumulate sixteen alpha 'and' in parallel
- all_alphas = _mm_and_si128(all_alphas, d0);
- src += 4;
- }
- for (; i < width; ++i) {
- const uint32_t alpha_value = argb[4 * i];
- alpha[i] = alpha_value;
- alpha_and &= alpha_value;
- }
- argb += argb_stride;
- alpha += alpha_stride;
- }
- // Combine the sixteen alpha 'and' into an 8-bit mask.
- alpha_and |= 0xff00u; // pretend the upper bits [8..15] were tested ok.
- alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff));
- return (alpha_and == 0xffffu);
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPInitAlphaProcessingSSE41(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE41(void) {
- WebPExtractAlpha = ExtractAlpha;
-}
-
-#else // !WEBP_USE_SSE41
-
-WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingSSE41)
-
-#endif // WEBP_USE_SSE41
diff --git a/drivers/webp/dsp/argb.c b/drivers/webp/dsp/argb.c
deleted file mode 100644
index cc1f9a96c3..0000000000
--- a/drivers/webp/dsp/argb.c
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// ARGB making functions.
-//
-// Author: Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
- return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
-}
-
-static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g,
- const uint8_t* b, int len, uint32_t* out) {
- int i;
- for (i = 0; i < len; ++i) {
- out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
- }
-}
-
-static void PackRGB(const uint8_t* r, const uint8_t* g, const uint8_t* b,
- int len, int step, uint32_t* out) {
- int i, offset = 0;
- for (i = 0; i < len; ++i) {
- out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
- offset += step;
- }
-}
-
-void (*VP8PackARGB)(const uint8_t*, const uint8_t*, const uint8_t*,
- const uint8_t*, int, uint32_t*);
-void (*VP8PackRGB)(const uint8_t*, const uint8_t*, const uint8_t*,
- int, int, uint32_t*);
-
-extern void VP8EncDspARGBInitMIPSdspR2(void);
-extern void VP8EncDspARGBInitSSE2(void);
-
-static volatile VP8CPUInfo argb_last_cpuinfo_used =
- (VP8CPUInfo)&argb_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInit(void) {
- if (argb_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- VP8PackARGB = PackARGB;
- VP8PackRGB = PackRGB;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- VP8EncDspARGBInitSSE2();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- VP8EncDspARGBInitMIPSdspR2();
- }
-#endif
- }
- argb_last_cpuinfo_used = VP8GetCPUInfo;
-}
diff --git a/drivers/webp/dsp/argb_mips_dsp_r2.c b/drivers/webp/dsp/argb_mips_dsp_r2.c
deleted file mode 100644
index af65acb8ff..0000000000
--- a/drivers/webp/dsp/argb_mips_dsp_r2.c
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// ARGB making functions (mips version).
-//
-// Author: Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g,
- const uint8_t* b, int len, uint32_t* out) {
- int temp0, temp1, temp2, temp3, offset;
- const int rest = len & 1;
- const uint32_t* const loop_end = out + len - rest;
- const int step = 4;
- __asm__ volatile (
- "xor %[offset], %[offset], %[offset] \n\t"
- "beq %[loop_end], %[out], 0f \n\t"
- "2: \n\t"
- "lbux %[temp0], %[offset](%[a]) \n\t"
- "lbux %[temp1], %[offset](%[r]) \n\t"
- "lbux %[temp2], %[offset](%[g]) \n\t"
- "lbux %[temp3], %[offset](%[b]) \n\t"
- "ins %[temp1], %[temp0], 16, 16 \n\t"
- "ins %[temp3], %[temp2], 16, 16 \n\t"
- "addiu %[out], %[out], 4 \n\t"
- "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t"
- "sw %[temp0], -4(%[out]) \n\t"
- "addu %[offset], %[offset], %[step] \n\t"
- "bne %[loop_end], %[out], 2b \n\t"
- "0: \n\t"
- "beq %[rest], $zero, 1f \n\t"
- "lbux %[temp0], %[offset](%[a]) \n\t"
- "lbux %[temp1], %[offset](%[r]) \n\t"
- "lbux %[temp2], %[offset](%[g]) \n\t"
- "lbux %[temp3], %[offset](%[b]) \n\t"
- "ins %[temp1], %[temp0], 16, 16 \n\t"
- "ins %[temp3], %[temp2], 16, 16 \n\t"
- "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t"
- "sw %[temp0], 0(%[out]) \n\t"
- "1: \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [offset]"=&r"(offset), [out]"+&r"(out)
- : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step),
- [loop_end]"r"(loop_end), [rest]"r"(rest)
- : "memory"
- );
-}
-
-static void PackRGB(const uint8_t* r, const uint8_t* g, const uint8_t* b,
- int len, int step, uint32_t* out) {
- int temp0, temp1, temp2, offset;
- const int rest = len & 1;
- const int a = 0xff;
- const uint32_t* const loop_end = out + len - rest;
- __asm__ volatile (
- "xor %[offset], %[offset], %[offset] \n\t"
- "beq %[loop_end], %[out], 0f \n\t"
- "2: \n\t"
- "lbux %[temp0], %[offset](%[r]) \n\t"
- "lbux %[temp1], %[offset](%[g]) \n\t"
- "lbux %[temp2], %[offset](%[b]) \n\t"
- "ins %[temp0], %[a], 16, 16 \n\t"
- "ins %[temp2], %[temp1], 16, 16 \n\t"
- "addiu %[out], %[out], 4 \n\t"
- "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t"
- "sw %[temp0], -4(%[out]) \n\t"
- "addu %[offset], %[offset], %[step] \n\t"
- "bne %[loop_end], %[out], 2b \n\t"
- "0: \n\t"
- "beq %[rest], $zero, 1f \n\t"
- "lbux %[temp0], %[offset](%[r]) \n\t"
- "lbux %[temp1], %[offset](%[g]) \n\t"
- "lbux %[temp2], %[offset](%[b]) \n\t"
- "ins %[temp0], %[a], 16, 16 \n\t"
- "ins %[temp2], %[temp1], 16, 16 \n\t"
- "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t"
- "sw %[temp0], 0(%[out]) \n\t"
- "1: \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [offset]"=&r"(offset), [out]"+&r"(out)
- : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step),
- [loop_end]"r"(loop_end), [rest]"r"(rest)
- : "memory"
- );
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspARGBInitMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitMIPSdspR2(void) {
- VP8PackARGB = PackARGB;
- VP8PackRGB = PackRGB;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(VP8EncDspARGBInitMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/argb_sse2.c b/drivers/webp/dsp/argb_sse2.c
deleted file mode 100644
index afcb1957e7..0000000000
--- a/drivers/webp/dsp/argb_sse2.c
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// ARGB making functions (SSE2 version).
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-
-#include <assert.h>
-#include <emmintrin.h>
-#include <string.h>
-
-static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
- return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
-}
-
-static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g,
- const uint8_t* b, int len, uint32_t* out) {
- if (g == r + 1) { // RGBA input order. Need to swap R and B.
- int i = 0;
- const int len_max = len & ~3; // max length processed in main loop
- const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu);
- assert(b == r + 2);
- assert(a == r + 3);
- for (; i < len_max; i += 4) {
- const __m128i A = _mm_loadu_si128((const __m128i*)(r + 4 * i));
- const __m128i B = _mm_and_si128(A, red_blue_mask); // R 0 B 0
- const __m128i C = _mm_andnot_si128(red_blue_mask, A); // 0 G 0 A
- const __m128i D = _mm_shufflelo_epi16(B, _MM_SHUFFLE(2, 3, 0, 1));
- const __m128i E = _mm_shufflehi_epi16(D, _MM_SHUFFLE(2, 3, 0, 1));
- const __m128i F = _mm_or_si128(E, C);
- _mm_storeu_si128((__m128i*)(out + i), F);
- }
- for (; i < len; ++i) {
- out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
- }
- } else {
- assert(g == b + 1);
- assert(r == b + 2);
- assert(a == b + 3);
- memcpy(out, b, len * 4);
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspARGBInitSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitSSE2(void) {
- VP8PackARGB = PackARGB;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(VP8EncDspARGBInitSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/common_sse2.h b/drivers/webp/dsp/common_sse2.h
deleted file mode 100644
index 7cea13fb3c..0000000000
--- a/drivers/webp/dsp/common_sse2.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 code common to several files.
-//
-// Author: Vincent Rabaud (vrabaud@google.com)
-
-#ifndef WEBP_DSP_COMMON_SSE2_H_
-#define WEBP_DSP_COMMON_SSE2_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(WEBP_USE_SSE2)
-
-#include <emmintrin.h>
-
-//------------------------------------------------------------------------------
-// Quite useful macro for debugging. Left here for convenience.
-
-#if 0
-#include <stdio.h>
-static WEBP_INLINE void PrintReg(const __m128i r, const char* const name,
- int size) {
- int n;
- union {
- __m128i r;
- uint8_t i8[16];
- uint16_t i16[8];
- uint32_t i32[4];
- uint64_t i64[2];
- } tmp;
- tmp.r = r;
- fprintf(stderr, "%s\t: ", name);
- if (size == 8) {
- for (n = 0; n < 16; ++n) fprintf(stderr, "%.2x ", tmp.i8[n]);
- } else if (size == 16) {
- for (n = 0; n < 8; ++n) fprintf(stderr, "%.4x ", tmp.i16[n]);
- } else if (size == 32) {
- for (n = 0; n < 4; ++n) fprintf(stderr, "%.8x ", tmp.i32[n]);
- } else {
- for (n = 0; n < 2; ++n) fprintf(stderr, "%.16lx ", tmp.i64[n]);
- }
- fprintf(stderr, "\n");
-}
-#endif
-
-//------------------------------------------------------------------------------
-// Math functions.
-
-// Return the sum of all the 8b in the register.
-static WEBP_INLINE int VP8HorizontalAdd8b(const __m128i* const a) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i sad8x2 = _mm_sad_epu8(*a, zero);
- // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
- const __m128i sum = _mm_add_epi32(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
- return _mm_cvtsi128_si32(sum);
-}
-
-// Transpose two 4x4 16b matrices horizontally stored in registers.
-static WEBP_INLINE void VP8Transpose_2_4x4_16b(
- const __m128i* const in0, const __m128i* const in1,
- const __m128i* const in2, const __m128i* const in3, __m128i* const out0,
- __m128i* const out1, __m128i* const out2, __m128i* const out3) {
- // Transpose the two 4x4.
- // a00 a01 a02 a03 b00 b01 b02 b03
- // a10 a11 a12 a13 b10 b11 b12 b13
- // a20 a21 a22 a23 b20 b21 b22 b23
- // a30 a31 a32 a33 b30 b31 b32 b33
- const __m128i transpose0_0 = _mm_unpacklo_epi16(*in0, *in1);
- const __m128i transpose0_1 = _mm_unpacklo_epi16(*in2, *in3);
- const __m128i transpose0_2 = _mm_unpackhi_epi16(*in0, *in1);
- const __m128i transpose0_3 = _mm_unpackhi_epi16(*in2, *in3);
- // a00 a10 a01 a11 a02 a12 a03 a13
- // a20 a30 a21 a31 a22 a32 a23 a33
- // b00 b10 b01 b11 b02 b12 b03 b13
- // b20 b30 b21 b31 b22 b32 b23 b33
- const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
- const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
- const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
- const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
- // a00 a10 a20 a30 a01 a11 a21 a31
- // b00 b10 b20 b30 b01 b11 b21 b31
- // a02 a12 a22 a32 a03 a13 a23 a33
- // b02 b12 a22 b32 b03 b13 b23 b33
- *out0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
- *out1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
- *out2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
- *out3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
- // a00 a10 a20 a30 b00 b10 b20 b30
- // a01 a11 a21 a31 b01 b11 b21 b31
- // a02 a12 a22 a32 b02 b12 b22 b32
- // a03 a13 a23 a33 b03 b13 b23 b33
-}
-
-#endif // WEBP_USE_SSE2
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // WEBP_DSP_COMMON_SSE2_H_
diff --git a/drivers/webp/dsp/cost.c b/drivers/webp/dsp/cost.c
deleted file mode 100644
index fe72d26e79..0000000000
--- a/drivers/webp/dsp/cost.c
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-#include "../enc/cost.h"
-
-//------------------------------------------------------------------------------
-// Boolean-cost cost table
-
-const uint16_t VP8EntropyCost[256] = {
- 1792, 1792, 1792, 1536, 1536, 1408, 1366, 1280, 1280, 1216,
- 1178, 1152, 1110, 1076, 1061, 1024, 1024, 992, 968, 951,
- 939, 911, 896, 878, 871, 854, 838, 820, 811, 794,
- 786, 768, 768, 752, 740, 732, 720, 709, 704, 690,
- 683, 672, 666, 655, 647, 640, 631, 622, 615, 607,
- 598, 592, 586, 576, 572, 564, 559, 555, 547, 541,
- 534, 528, 522, 512, 512, 504, 500, 494, 488, 483,
- 477, 473, 467, 461, 458, 452, 448, 443, 438, 434,
- 427, 424, 419, 415, 410, 406, 403, 399, 394, 390,
- 384, 384, 377, 374, 370, 366, 362, 359, 355, 351,
- 347, 342, 342, 336, 333, 330, 326, 323, 320, 316,
- 312, 308, 305, 302, 299, 296, 293, 288, 287, 283,
- 280, 277, 274, 272, 268, 266, 262, 256, 256, 256,
- 251, 248, 245, 242, 240, 237, 234, 232, 228, 226,
- 223, 221, 218, 216, 214, 211, 208, 205, 203, 201,
- 198, 196, 192, 191, 188, 187, 183, 181, 179, 176,
- 175, 171, 171, 168, 165, 163, 160, 159, 156, 154,
- 152, 150, 148, 146, 144, 142, 139, 138, 135, 133,
- 131, 128, 128, 125, 123, 121, 119, 117, 115, 113,
- 111, 110, 107, 105, 103, 102, 100, 98, 96, 94,
- 92, 91, 89, 86, 86, 83, 82, 80, 77, 76,
- 74, 73, 71, 69, 67, 66, 64, 63, 61, 59,
- 57, 55, 54, 52, 51, 49, 47, 46, 44, 43,
- 41, 40, 38, 36, 35, 33, 32, 30, 29, 27,
- 25, 24, 22, 21, 19, 18, 16, 15, 13, 12,
- 10, 9, 7, 6, 4, 3
-};
-
-//------------------------------------------------------------------------------
-// Level cost tables
-
-// fixed costs for coding levels, deduce from the coding tree.
-// This is only the part that doesn't depend on the probability state.
-const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = {
- 0, 256, 256, 256, 256, 432, 618, 630,
- 731, 640, 640, 828, 901, 948, 1021, 1101,
- 1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
- 1245, 1275, 1318, 1337, 1380, 1410, 1453, 1497,
- 1540, 1570, 1613, 1280, 1295, 1317, 1332, 1358,
- 1373, 1395, 1410, 1454, 1469, 1491, 1506, 1532,
- 1547, 1569, 1584, 1601, 1616, 1638, 1653, 1679,
- 1694, 1716, 1731, 1775, 1790, 1812, 1827, 1853,
- 1868, 1890, 1905, 1727, 1733, 1742, 1748, 1759,
- 1765, 1774, 1780, 1800, 1806, 1815, 1821, 1832,
- 1838, 1847, 1853, 1878, 1884, 1893, 1899, 1910,
- 1916, 1925, 1931, 1951, 1957, 1966, 1972, 1983,
- 1989, 1998, 2004, 2027, 2033, 2042, 2048, 2059,
- 2065, 2074, 2080, 2100, 2106, 2115, 2121, 2132,
- 2138, 2147, 2153, 2178, 2184, 2193, 2199, 2210,
- 2216, 2225, 2231, 2251, 2257, 2266, 2272, 2283,
- 2289, 2298, 2304, 2168, 2174, 2183, 2189, 2200,
- 2206, 2215, 2221, 2241, 2247, 2256, 2262, 2273,
- 2279, 2288, 2294, 2319, 2325, 2334, 2340, 2351,
- 2357, 2366, 2372, 2392, 2398, 2407, 2413, 2424,
- 2430, 2439, 2445, 2468, 2474, 2483, 2489, 2500,
- 2506, 2515, 2521, 2541, 2547, 2556, 2562, 2573,
- 2579, 2588, 2594, 2619, 2625, 2634, 2640, 2651,
- 2657, 2666, 2672, 2692, 2698, 2707, 2713, 2724,
- 2730, 2739, 2745, 2540, 2546, 2555, 2561, 2572,
- 2578, 2587, 2593, 2613, 2619, 2628, 2634, 2645,
- 2651, 2660, 2666, 2691, 2697, 2706, 2712, 2723,
- 2729, 2738, 2744, 2764, 2770, 2779, 2785, 2796,
- 2802, 2811, 2817, 2840, 2846, 2855, 2861, 2872,
- 2878, 2887, 2893, 2913, 2919, 2928, 2934, 2945,
- 2951, 2960, 2966, 2991, 2997, 3006, 3012, 3023,
- 3029, 3038, 3044, 3064, 3070, 3079, 3085, 3096,
- 3102, 3111, 3117, 2981, 2987, 2996, 3002, 3013,
- 3019, 3028, 3034, 3054, 3060, 3069, 3075, 3086,
- 3092, 3101, 3107, 3132, 3138, 3147, 3153, 3164,
- 3170, 3179, 3185, 3205, 3211, 3220, 3226, 3237,
- 3243, 3252, 3258, 3281, 3287, 3296, 3302, 3313,
- 3319, 3328, 3334, 3354, 3360, 3369, 3375, 3386,
- 3392, 3401, 3407, 3432, 3438, 3447, 3453, 3464,
- 3470, 3479, 3485, 3505, 3511, 3520, 3526, 3537,
- 3543, 3552, 3558, 2816, 2822, 2831, 2837, 2848,
- 2854, 2863, 2869, 2889, 2895, 2904, 2910, 2921,
- 2927, 2936, 2942, 2967, 2973, 2982, 2988, 2999,
- 3005, 3014, 3020, 3040, 3046, 3055, 3061, 3072,
- 3078, 3087, 3093, 3116, 3122, 3131, 3137, 3148,
- 3154, 3163, 3169, 3189, 3195, 3204, 3210, 3221,
- 3227, 3236, 3242, 3267, 3273, 3282, 3288, 3299,
- 3305, 3314, 3320, 3340, 3346, 3355, 3361, 3372,
- 3378, 3387, 3393, 3257, 3263, 3272, 3278, 3289,
- 3295, 3304, 3310, 3330, 3336, 3345, 3351, 3362,
- 3368, 3377, 3383, 3408, 3414, 3423, 3429, 3440,
- 3446, 3455, 3461, 3481, 3487, 3496, 3502, 3513,
- 3519, 3528, 3534, 3557, 3563, 3572, 3578, 3589,
- 3595, 3604, 3610, 3630, 3636, 3645, 3651, 3662,
- 3668, 3677, 3683, 3708, 3714, 3723, 3729, 3740,
- 3746, 3755, 3761, 3781, 3787, 3796, 3802, 3813,
- 3819, 3828, 3834, 3629, 3635, 3644, 3650, 3661,
- 3667, 3676, 3682, 3702, 3708, 3717, 3723, 3734,
- 3740, 3749, 3755, 3780, 3786, 3795, 3801, 3812,
- 3818, 3827, 3833, 3853, 3859, 3868, 3874, 3885,
- 3891, 3900, 3906, 3929, 3935, 3944, 3950, 3961,
- 3967, 3976, 3982, 4002, 4008, 4017, 4023, 4034,
- 4040, 4049, 4055, 4080, 4086, 4095, 4101, 4112,
- 4118, 4127, 4133, 4153, 4159, 4168, 4174, 4185,
- 4191, 4200, 4206, 4070, 4076, 4085, 4091, 4102,
- 4108, 4117, 4123, 4143, 4149, 4158, 4164, 4175,
- 4181, 4190, 4196, 4221, 4227, 4236, 4242, 4253,
- 4259, 4268, 4274, 4294, 4300, 4309, 4315, 4326,
- 4332, 4341, 4347, 4370, 4376, 4385, 4391, 4402,
- 4408, 4417, 4423, 4443, 4449, 4458, 4464, 4475,
- 4481, 4490, 4496, 4521, 4527, 4536, 4542, 4553,
- 4559, 4568, 4574, 4594, 4600, 4609, 4615, 4626,
- 4632, 4641, 4647, 3515, 3521, 3530, 3536, 3547,
- 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
- 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
- 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
- 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
- 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
- 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
- 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
- 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
- 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
- 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
- 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
- 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
- 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
- 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
- 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
- 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
- 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
- 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
- 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
- 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
- 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
- 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
- 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
- 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
- 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
- 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
- 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
- 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
- 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
- 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
- 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
- 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
- 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
- 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
- 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
- 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
- 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
- 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
- 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
- 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
- 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
- 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
- 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
- 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
- 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
- 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
- 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
- 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
- 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
- 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
- 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
- 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
- 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
- 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
- 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
- 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
- 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
- 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
- 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
- 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
- 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
- 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
- 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
- 6420, 6429, 6435, 3515, 3521, 3530, 3536, 3547,
- 3553, 3562, 3568, 3588, 3594, 3603, 3609, 3620,
- 3626, 3635, 3641, 3666, 3672, 3681, 3687, 3698,
- 3704, 3713, 3719, 3739, 3745, 3754, 3760, 3771,
- 3777, 3786, 3792, 3815, 3821, 3830, 3836, 3847,
- 3853, 3862, 3868, 3888, 3894, 3903, 3909, 3920,
- 3926, 3935, 3941, 3966, 3972, 3981, 3987, 3998,
- 4004, 4013, 4019, 4039, 4045, 4054, 4060, 4071,
- 4077, 4086, 4092, 3956, 3962, 3971, 3977, 3988,
- 3994, 4003, 4009, 4029, 4035, 4044, 4050, 4061,
- 4067, 4076, 4082, 4107, 4113, 4122, 4128, 4139,
- 4145, 4154, 4160, 4180, 4186, 4195, 4201, 4212,
- 4218, 4227, 4233, 4256, 4262, 4271, 4277, 4288,
- 4294, 4303, 4309, 4329, 4335, 4344, 4350, 4361,
- 4367, 4376, 4382, 4407, 4413, 4422, 4428, 4439,
- 4445, 4454, 4460, 4480, 4486, 4495, 4501, 4512,
- 4518, 4527, 4533, 4328, 4334, 4343, 4349, 4360,
- 4366, 4375, 4381, 4401, 4407, 4416, 4422, 4433,
- 4439, 4448, 4454, 4479, 4485, 4494, 4500, 4511,
- 4517, 4526, 4532, 4552, 4558, 4567, 4573, 4584,
- 4590, 4599, 4605, 4628, 4634, 4643, 4649, 4660,
- 4666, 4675, 4681, 4701, 4707, 4716, 4722, 4733,
- 4739, 4748, 4754, 4779, 4785, 4794, 4800, 4811,
- 4817, 4826, 4832, 4852, 4858, 4867, 4873, 4884,
- 4890, 4899, 4905, 4769, 4775, 4784, 4790, 4801,
- 4807, 4816, 4822, 4842, 4848, 4857, 4863, 4874,
- 4880, 4889, 4895, 4920, 4926, 4935, 4941, 4952,
- 4958, 4967, 4973, 4993, 4999, 5008, 5014, 5025,
- 5031, 5040, 5046, 5069, 5075, 5084, 5090, 5101,
- 5107, 5116, 5122, 5142, 5148, 5157, 5163, 5174,
- 5180, 5189, 5195, 5220, 5226, 5235, 5241, 5252,
- 5258, 5267, 5273, 5293, 5299, 5308, 5314, 5325,
- 5331, 5340, 5346, 4604, 4610, 4619, 4625, 4636,
- 4642, 4651, 4657, 4677, 4683, 4692, 4698, 4709,
- 4715, 4724, 4730, 4755, 4761, 4770, 4776, 4787,
- 4793, 4802, 4808, 4828, 4834, 4843, 4849, 4860,
- 4866, 4875, 4881, 4904, 4910, 4919, 4925, 4936,
- 4942, 4951, 4957, 4977, 4983, 4992, 4998, 5009,
- 5015, 5024, 5030, 5055, 5061, 5070, 5076, 5087,
- 5093, 5102, 5108, 5128, 5134, 5143, 5149, 5160,
- 5166, 5175, 5181, 5045, 5051, 5060, 5066, 5077,
- 5083, 5092, 5098, 5118, 5124, 5133, 5139, 5150,
- 5156, 5165, 5171, 5196, 5202, 5211, 5217, 5228,
- 5234, 5243, 5249, 5269, 5275, 5284, 5290, 5301,
- 5307, 5316, 5322, 5345, 5351, 5360, 5366, 5377,
- 5383, 5392, 5398, 5418, 5424, 5433, 5439, 5450,
- 5456, 5465, 5471, 5496, 5502, 5511, 5517, 5528,
- 5534, 5543, 5549, 5569, 5575, 5584, 5590, 5601,
- 5607, 5616, 5622, 5417, 5423, 5432, 5438, 5449,
- 5455, 5464, 5470, 5490, 5496, 5505, 5511, 5522,
- 5528, 5537, 5543, 5568, 5574, 5583, 5589, 5600,
- 5606, 5615, 5621, 5641, 5647, 5656, 5662, 5673,
- 5679, 5688, 5694, 5717, 5723, 5732, 5738, 5749,
- 5755, 5764, 5770, 5790, 5796, 5805, 5811, 5822,
- 5828, 5837, 5843, 5868, 5874, 5883, 5889, 5900,
- 5906, 5915, 5921, 5941, 5947, 5956, 5962, 5973,
- 5979, 5988, 5994, 5858, 5864, 5873, 5879, 5890,
- 5896, 5905, 5911, 5931, 5937, 5946, 5952, 5963,
- 5969, 5978, 5984, 6009, 6015, 6024, 6030, 6041,
- 6047, 6056, 6062, 6082, 6088, 6097, 6103, 6114,
- 6120, 6129, 6135, 6158, 6164, 6173, 6179, 6190,
- 6196, 6205, 6211, 6231, 6237, 6246, 6252, 6263,
- 6269, 6278, 6284, 6309, 6315, 6324, 6330, 6341,
- 6347, 6356, 6362, 6382, 6388, 6397, 6403, 6414,
- 6420, 6429, 6435, 5303, 5309, 5318, 5324, 5335,
- 5341, 5350, 5356, 5376, 5382, 5391, 5397, 5408,
- 5414, 5423, 5429, 5454, 5460, 5469, 5475, 5486,
- 5492, 5501, 5507, 5527, 5533, 5542, 5548, 5559,
- 5565, 5574, 5580, 5603, 5609, 5618, 5624, 5635,
- 5641, 5650, 5656, 5676, 5682, 5691, 5697, 5708,
- 5714, 5723, 5729, 5754, 5760, 5769, 5775, 5786,
- 5792, 5801, 5807, 5827, 5833, 5842, 5848, 5859,
- 5865, 5874, 5880, 5744, 5750, 5759, 5765, 5776,
- 5782, 5791, 5797, 5817, 5823, 5832, 5838, 5849,
- 5855, 5864, 5870, 5895, 5901, 5910, 5916, 5927,
- 5933, 5942, 5948, 5968, 5974, 5983, 5989, 6000,
- 6006, 6015, 6021, 6044, 6050, 6059, 6065, 6076,
- 6082, 6091, 6097, 6117, 6123, 6132, 6138, 6149,
- 6155, 6164, 6170, 6195, 6201, 6210, 6216, 6227,
- 6233, 6242, 6248, 6268, 6274, 6283, 6289, 6300,
- 6306, 6315, 6321, 6116, 6122, 6131, 6137, 6148,
- 6154, 6163, 6169, 6189, 6195, 6204, 6210, 6221,
- 6227, 6236, 6242, 6267, 6273, 6282, 6288, 6299,
- 6305, 6314, 6320, 6340, 6346, 6355, 6361, 6372,
- 6378, 6387, 6393, 6416, 6422, 6431, 6437, 6448,
- 6454, 6463, 6469, 6489, 6495, 6504, 6510, 6521,
- 6527, 6536, 6542, 6567, 6573, 6582, 6588, 6599,
- 6605, 6614, 6620, 6640, 6646, 6655, 6661, 6672,
- 6678, 6687, 6693, 6557, 6563, 6572, 6578, 6589,
- 6595, 6604, 6610, 6630, 6636, 6645, 6651, 6662,
- 6668, 6677, 6683, 6708, 6714, 6723, 6729, 6740,
- 6746, 6755, 6761, 6781, 6787, 6796, 6802, 6813,
- 6819, 6828, 6834, 6857, 6863, 6872, 6878, 6889,
- 6895, 6904, 6910, 6930, 6936, 6945, 6951, 6962,
- 6968, 6977, 6983, 7008, 7014, 7023, 7029, 7040,
- 7046, 7055, 7061, 7081, 7087, 7096, 7102, 7113,
- 7119, 7128, 7134, 6392, 6398, 6407, 6413, 6424,
- 6430, 6439, 6445, 6465, 6471, 6480, 6486, 6497,
- 6503, 6512, 6518, 6543, 6549, 6558, 6564, 6575,
- 6581, 6590, 6596, 6616, 6622, 6631, 6637, 6648,
- 6654, 6663, 6669, 6692, 6698, 6707, 6713, 6724,
- 6730, 6739, 6745, 6765, 6771, 6780, 6786, 6797,
- 6803, 6812, 6818, 6843, 6849, 6858, 6864, 6875,
- 6881, 6890, 6896, 6916, 6922, 6931, 6937, 6948,
- 6954, 6963, 6969, 6833, 6839, 6848, 6854, 6865,
- 6871, 6880, 6886, 6906, 6912, 6921, 6927, 6938,
- 6944, 6953, 6959, 6984, 6990, 6999, 7005, 7016,
- 7022, 7031, 7037, 7057, 7063, 7072, 7078, 7089,
- 7095, 7104, 7110, 7133, 7139, 7148, 7154, 7165,
- 7171, 7180, 7186, 7206, 7212, 7221, 7227, 7238,
- 7244, 7253, 7259, 7284, 7290, 7299, 7305, 7316,
- 7322, 7331, 7337, 7357, 7363, 7372, 7378, 7389,
- 7395, 7404, 7410, 7205, 7211, 7220, 7226, 7237,
- 7243, 7252, 7258, 7278, 7284, 7293, 7299, 7310,
- 7316, 7325, 7331, 7356, 7362, 7371, 7377, 7388,
- 7394, 7403, 7409, 7429, 7435, 7444, 7450, 7461,
- 7467, 7476, 7482, 7505, 7511, 7520, 7526, 7537,
- 7543, 7552, 7558, 7578, 7584, 7593, 7599, 7610,
- 7616, 7625, 7631, 7656, 7662, 7671, 7677, 7688,
- 7694, 7703, 7709, 7729, 7735, 7744, 7750, 7761
-};
-
-//------------------------------------------------------------------------------
-// Tables for level coding
-
-const uint8_t VP8EncBands[16 + 1] = {
- 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
- 0 // sentinel
-};
-
-//------------------------------------------------------------------------------
-// Mode costs
-
-static int GetResidualCost(int ctx0, const VP8Residual* const res) {
- int n = res->first;
- // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
- const int p0 = res->prob[n][ctx0][0];
- CostArrayPtr const costs = res->costs;
- const uint16_t* t = costs[n][ctx0];
- // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
- // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
- // be missing during the loop.
- int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
-
- if (res->last < 0) {
- return VP8BitCost(0, p0);
- }
- for (; n < res->last; ++n) {
- const int v = abs(res->coeffs[n]);
- const int ctx = (v >= 2) ? 2 : v;
- cost += VP8LevelCost(t, v);
- t = costs[n + 1][ctx];
- }
- // Last coefficient is always non-zero
- {
- const int v = abs(res->coeffs[n]);
- assert(v != 0);
- cost += VP8LevelCost(t, v);
- if (n < 15) {
- const int b = VP8EncBands[n + 1];
- const int ctx = (v == 1) ? 1 : 2;
- const int last_p0 = res->prob[b][ctx][0];
- cost += VP8BitCost(0, last_p0);
- }
- }
- return cost;
-}
-
-static void SetResidualCoeffs(const int16_t* const coeffs,
- VP8Residual* const res) {
- int n;
- res->last = -1;
- assert(res->first == 0 || coeffs[0] == 0);
- for (n = 15; n >= 0; --n) {
- if (coeffs[n]) {
- res->last = n;
- break;
- }
- }
- res->coeffs = coeffs;
-}
-
-//------------------------------------------------------------------------------
-// init function
-
-VP8GetResidualCostFunc VP8GetResidualCost;
-VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
-
-extern void VP8EncDspCostInitMIPS32(void);
-extern void VP8EncDspCostInitMIPSdspR2(void);
-extern void VP8EncDspCostInitSSE2(void);
-
-static volatile VP8CPUInfo cost_last_cpuinfo_used =
- (VP8CPUInfo)&cost_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) {
- if (cost_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- VP8GetResidualCost = GetResidualCost;
- VP8SetResidualCoeffs = SetResidualCoeffs;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_MIPS32)
- if (VP8GetCPUInfo(kMIPS32)) {
- VP8EncDspCostInitMIPS32();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- VP8EncDspCostInitMIPSdspR2();
- }
-#endif
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- VP8EncDspCostInitSSE2();
- }
-#endif
- }
-
- cost_last_cpuinfo_used = VP8GetCPUInfo;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dsp/cost_mips32.c b/drivers/webp/dsp/cost_mips32.c
deleted file mode 100644
index d1e240e191..0000000000
--- a/drivers/webp/dsp/cost_mips32.c
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS32)
-
-#include "../enc/cost.h"
-
-static int GetResidualCost(int ctx0, const VP8Residual* const res) {
- int temp0, temp1;
- int v_reg, ctx_reg;
- int n = res->first;
- // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
- int p0 = res->prob[n][ctx0][0];
- CostArrayPtr const costs = res->costs;
- const uint16_t* t = costs[n][ctx0];
- // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
- // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
- // be missing during the loop.
- int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
- const int16_t* res_coeffs = res->coeffs;
- const int res_last = res->last;
- const int const_max_level = MAX_VARIABLE_LEVEL;
- const int const_2 = 2;
- const uint16_t** p_costs = &costs[n][0];
- const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs);
-
- if (res->last < 0) {
- return VP8BitCost(0, p0);
- }
-
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "subu %[temp1], %[res_last], %[n] \n\t"
- "sll %[temp0], %[n], 1 \n\t"
- "blez %[temp1], 2f \n\t"
- " addu %[res_coeffs], %[res_coeffs], %[temp0] \n\t"
- "1: \n\t"
- "lh %[v_reg], 0(%[res_coeffs]) \n\t"
- "addiu %[n], %[n], 1 \n\t"
- "negu %[temp0], %[v_reg] \n\t"
- "slti %[temp1], %[v_reg], 0 \n\t"
- "movn %[v_reg], %[temp0], %[temp1] \n\t"
- "sltiu %[temp0], %[v_reg], 2 \n\t"
- "move %[ctx_reg], %[v_reg] \n\t"
- "movz %[ctx_reg], %[const_2], %[temp0] \n\t"
- "sll %[temp1], %[v_reg], 1 \n\t"
- "addu %[temp1], %[temp1], %[VP8LevelFixedCosts] \n\t"
- "lhu %[temp1], 0(%[temp1]) \n\t"
- "slt %[temp0], %[v_reg], %[const_max_level] \n\t"
- "movz %[v_reg], %[const_max_level], %[temp0] \n\t"
- "addu %[cost], %[cost], %[temp1] \n\t"
- "sll %[v_reg], %[v_reg], 1 \n\t"
- "sll %[ctx_reg], %[ctx_reg], 2 \n\t"
- "addu %[v_reg], %[v_reg], %[t] \n\t"
- "lhu %[temp0], 0(%[v_reg]) \n\t"
- "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t"
- "addu %[t], %[p_costs], %[ctx_reg] \n\t"
- "addu %[cost], %[cost], %[temp0] \n\t"
- "addiu %[res_coeffs], %[res_coeffs], 2 \n\t"
- "bne %[n], %[res_last], 1b \n\t"
- " lw %[t], 0(%[t]) \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg),
- [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0),
- [temp1]"=&r"(temp1), [res_coeffs]"+&r"(res_coeffs)
- : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level),
- [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last),
- [inc_p_costs]"r"(inc_p_costs)
- : "memory"
- );
-
- // Last coefficient is always non-zero
- {
- const int v = abs(res->coeffs[n]);
- assert(v != 0);
- cost += VP8LevelCost(t, v);
- if (n < 15) {
- const int b = VP8EncBands[n + 1];
- const int ctx = (v == 1) ? 1 : 2;
- const int last_p0 = res->prob[b][ctx][0];
- cost += VP8BitCost(0, last_p0);
- }
- }
- return cost;
-}
-
-static void SetResidualCoeffs(const int16_t* const coeffs,
- VP8Residual* const res) {
- const int16_t* p_coeffs = (int16_t*)coeffs;
- int temp0, temp1, temp2, n, n1;
- assert(res->first == 0 || coeffs[0] == 0);
-
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "addiu %[p_coeffs], %[p_coeffs], 28 \n\t"
- "li %[n], 15 \n\t"
- "li %[temp2], -1 \n\t"
- "0: \n\t"
- "ulw %[temp0], 0(%[p_coeffs]) \n\t"
- "beqz %[temp0], 1f \n\t"
-#if defined(WORDS_BIGENDIAN)
- " sll %[temp1], %[temp0], 16 \n\t"
-#else
- " srl %[temp1], %[temp0], 16 \n\t"
-#endif
- "addiu %[n1], %[n], -1 \n\t"
- "movz %[temp0], %[n1], %[temp1] \n\t"
- "movn %[temp0], %[n], %[temp1] \n\t"
- "j 2f \n\t"
- " addiu %[temp2], %[temp0], 0 \n\t"
- "1: \n\t"
- "addiu %[n], %[n], -2 \n\t"
- "bgtz %[n], 0b \n\t"
- " addiu %[p_coeffs], %[p_coeffs], -4 \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [p_coeffs]"+&r"(p_coeffs), [temp0]"=&r"(temp0),
- [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [n]"=&r"(n), [n1]"=&r"(n1)
- :
- : "memory"
- );
- res->last = temp2;
- res->coeffs = coeffs;
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspCostInitMIPS32(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPS32(void) {
- VP8GetResidualCost = GetResidualCost;
- VP8SetResidualCoeffs = SetResidualCoeffs;
-}
-
-#else // !WEBP_USE_MIPS32
-
-WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPS32)
-
-#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/cost_mips_dsp_r2.c b/drivers/webp/dsp/cost_mips_dsp_r2.c
deleted file mode 100644
index ce64067756..0000000000
--- a/drivers/webp/dsp/cost_mips_dsp_r2.c
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include "../enc/cost.h"
-
-static int GetResidualCost(int ctx0, const VP8Residual* const res) {
- int temp0, temp1;
- int v_reg, ctx_reg;
- int n = res->first;
- // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
- int p0 = res->prob[n][ctx0][0];
- CostArrayPtr const costs = res->costs;
- const uint16_t* t = costs[n][ctx0];
- // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
- // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
- // be missing during the loop.
- int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
- const int16_t* res_coeffs = res->coeffs;
- const int res_last = res->last;
- const int const_max_level = MAX_VARIABLE_LEVEL;
- const int const_2 = 2;
- const uint16_t** p_costs = &costs[n][0];
- const size_t inc_p_costs = NUM_CTX * sizeof(*p_costs);
-
- if (res->last < 0) {
- return VP8BitCost(0, p0);
- }
-
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "subu %[temp1], %[res_last], %[n] \n\t"
- "blez %[temp1], 2f \n\t"
- " nop \n\t"
- "1: \n\t"
- "sll %[temp0], %[n], 1 \n\t"
- "lhx %[v_reg], %[temp0](%[res_coeffs]) \n\t"
- "addiu %[n], %[n], 1 \n\t"
- "absq_s.w %[v_reg], %[v_reg] \n\t"
- "sltiu %[temp0], %[v_reg], 2 \n\t"
- "move %[ctx_reg], %[v_reg] \n\t"
- "movz %[ctx_reg], %[const_2], %[temp0] \n\t"
- "sll %[temp1], %[v_reg], 1 \n\t"
- "lhx %[temp1], %[temp1](%[VP8LevelFixedCosts]) \n\t"
- "slt %[temp0], %[v_reg], %[const_max_level] \n\t"
- "movz %[v_reg], %[const_max_level], %[temp0] \n\t"
- "addu %[cost], %[cost], %[temp1] \n\t"
- "sll %[v_reg], %[v_reg], 1 \n\t"
- "sll %[ctx_reg], %[ctx_reg], 2 \n\t"
- "lhx %[temp0], %[v_reg](%[t]) \n\t"
- "addu %[p_costs], %[p_costs], %[inc_p_costs] \n\t"
- "addu %[t], %[p_costs], %[ctx_reg] \n\t"
- "addu %[cost], %[cost], %[temp0] \n\t"
- "bne %[n], %[res_last], 1b \n\t"
- " lw %[t], 0(%[t]) \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [cost]"+&r"(cost), [t]"+&r"(t), [n]"+&r"(n), [v_reg]"=&r"(v_reg),
- [ctx_reg]"=&r"(ctx_reg), [p_costs]"+&r"(p_costs), [temp0]"=&r"(temp0),
- [temp1]"=&r"(temp1)
- : [const_2]"r"(const_2), [const_max_level]"r"(const_max_level),
- [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_last]"r"(res_last),
- [res_coeffs]"r"(res_coeffs), [inc_p_costs]"r"(inc_p_costs)
- : "memory"
- );
-
- // Last coefficient is always non-zero
- {
- const int v = abs(res->coeffs[n]);
- assert(v != 0);
- cost += VP8LevelCost(t, v);
- if (n < 15) {
- const int b = VP8EncBands[n + 1];
- const int ctx = (v == 1) ? 1 : 2;
- const int last_p0 = res->prob[b][ctx][0];
- cost += VP8BitCost(0, last_p0);
- }
- }
- return cost;
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspCostInitMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPSdspR2(void) {
- VP8GetResidualCost = GetResidualCost;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(VP8EncDspCostInitMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/cost_sse2.c b/drivers/webp/dsp/cost_sse2.c
deleted file mode 100644
index 0cb1c1fa04..0000000000
--- a/drivers/webp/dsp/cost_sse2.c
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 version of cost functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-#include <emmintrin.h>
-
-#include "../enc/cost.h"
-#include "../enc/vp8enci.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-
-static void SetResidualCoeffsSSE2(const int16_t* const coeffs,
- VP8Residual* const res) {
- const __m128i c0 = _mm_loadu_si128((const __m128i*)(coeffs + 0));
- const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8));
- // Use SSE2 to compare 16 values with a single instruction.
- const __m128i zero = _mm_setzero_si128();
- const __m128i m0 = _mm_packs_epi16(c0, c1);
- const __m128i m1 = _mm_cmpeq_epi8(m0, zero);
- // Get the comparison results as a bitmask into 16bits. Negate the mask to get
- // the position of entries that are not equal to zero. We don't need to mask
- // out least significant bits according to res->first, since coeffs[0] is 0
- // if res->first > 0.
- const uint32_t mask = 0x0000ffffu ^ (uint32_t)_mm_movemask_epi8(m1);
- // The position of the most significant non-zero bit indicates the position of
- // the last non-zero value.
- assert(res->first == 0 || coeffs[0] == 0);
- res->last = mask ? BitsLog2Floor(mask) : -1;
- res->coeffs = coeffs;
-}
-
-static int GetResidualCostSSE2(int ctx0, const VP8Residual* const res) {
- uint8_t levels[16], ctxs[16];
- uint16_t abs_levels[16];
- int n = res->first;
- // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
- const int p0 = res->prob[n][ctx0][0];
- CostArrayPtr const costs = res->costs;
- const uint16_t* t = costs[n][ctx0];
- // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
- // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
- // be missing during the loop.
- int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
-
- if (res->last < 0) {
- return VP8BitCost(0, p0);
- }
-
- { // precompute clamped levels and contexts, packed to 8b.
- const __m128i zero = _mm_setzero_si128();
- const __m128i kCst2 = _mm_set1_epi8(2);
- const __m128i kCst67 = _mm_set1_epi8(MAX_VARIABLE_LEVEL);
- const __m128i c0 = _mm_loadu_si128((const __m128i*)&res->coeffs[0]);
- const __m128i c1 = _mm_loadu_si128((const __m128i*)&res->coeffs[8]);
- const __m128i D0 = _mm_sub_epi16(zero, c0);
- const __m128i D1 = _mm_sub_epi16(zero, c1);
- const __m128i E0 = _mm_max_epi16(c0, D0); // abs(v), 16b
- const __m128i E1 = _mm_max_epi16(c1, D1);
- const __m128i F = _mm_packs_epi16(E0, E1);
- const __m128i G = _mm_min_epu8(F, kCst2); // context = 0,1,2
- const __m128i H = _mm_min_epu8(F, kCst67); // clamp_level in [0..67]
-
- _mm_storeu_si128((__m128i*)&ctxs[0], G);
- _mm_storeu_si128((__m128i*)&levels[0], H);
-
- _mm_storeu_si128((__m128i*)&abs_levels[0], E0);
- _mm_storeu_si128((__m128i*)&abs_levels[8], E1);
- }
- for (; n < res->last; ++n) {
- const int ctx = ctxs[n];
- const int level = levels[n];
- const int flevel = abs_levels[n]; // full level
- cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost()
- t = costs[n + 1][ctx];
- }
- // Last coefficient is always non-zero
- {
- const int level = levels[n];
- const int flevel = abs_levels[n];
- assert(flevel != 0);
- cost += VP8LevelFixedCosts[flevel] + t[level];
- if (n < 15) {
- const int b = VP8EncBands[n + 1];
- const int ctx = ctxs[n];
- const int last_p0 = res->prob[b][ctx][0];
- cost += VP8BitCost(0, last_p0);
- }
- }
- return cost;
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspCostInitSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitSSE2(void) {
- VP8SetResidualCoeffs = SetResidualCoeffsSSE2;
- VP8GetResidualCost = GetResidualCostSSE2;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(VP8EncDspCostInitSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/cpu.c b/drivers/webp/dsp/cpu.c
deleted file mode 100644
index cbb08db90a..0000000000
--- a/drivers/webp/dsp/cpu.c
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// CPU detection
-//
-// Author: Christian Duvivier (cduvivier@google.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_HAVE_NEON_RTCD)
-#include <stdio.h>
-#include <string.h>
-#endif
-
-#if defined(WEBP_ANDROID_NEON)
-#include <cpu-features.h>
-#endif
-
-//------------------------------------------------------------------------------
-// SSE2 detection.
-//
-
-// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC.
-#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__)
-static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
- __asm__ volatile (
- "mov %%ebx, %%edi\n"
- "cpuid\n"
- "xchg %%edi, %%ebx\n"
- : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
- : "a"(info_type), "c"(0));
-}
-#elif defined(__x86_64__) && \
- (defined(__code_model_medium__) || defined(__code_model_large__)) && \
- defined(__PIC__)
-static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
- __asm__ volatile (
- "xchg{q}\t{%%rbx}, %q1\n"
- "cpuid\n"
- "xchg{q}\t{%%rbx}, %q1\n"
- : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]),
- "=d"(cpu_info[3])
- : "a"(info_type), "c"(0));
-}
-#elif defined(__i386__) || defined(__x86_64__)
-static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
- __asm__ volatile (
- "cpuid\n"
- : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
- : "a"(info_type), "c"(0));
-}
-#elif (defined(_M_X64) || defined(_M_IX86)) && \
- defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1
-#include <intrin.h>
-#define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0
-#elif defined(WEBP_MSC_SSE2)
-#define GetCPUInfo __cpuid
-#endif
-
-// NaCl has no support for xgetbv or the raw opcode.
-#if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__))
-static WEBP_INLINE uint64_t xgetbv(void) {
- const uint32_t ecx = 0;
- uint32_t eax, edx;
- // Use the raw opcode for xgetbv for compatibility with older toolchains.
- __asm__ volatile (
- ".byte 0x0f, 0x01, 0xd0\n"
- : "=a"(eax), "=d"(edx) : "c" (ecx));
- return ((uint64_t)edx << 32) | eax;
-}
-#elif (defined(_M_X64) || defined(_M_IX86)) && \
- defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
-#include <immintrin.h>
-#define xgetbv() _xgetbv(0)
-#elif defined(_MSC_VER) && defined(_M_IX86)
-static WEBP_INLINE uint64_t xgetbv(void) {
- uint32_t eax_, edx_;
- __asm {
- xor ecx, ecx // ecx = 0
- // Use the raw opcode for xgetbv for compatibility with older toolchains.
- __asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0
- mov eax_, eax
- mov edx_, edx
- }
- return ((uint64_t)edx_ << 32) | eax_;
-}
-#else
-#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains.
-#endif
-
-#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2)
-static int x86CPUInfo(CPUFeature feature) {
- int max_cpuid_value;
- int cpu_info[4];
-
- // get the highest feature value cpuid supports
- GetCPUInfo(cpu_info, 0);
- max_cpuid_value = cpu_info[0];
- if (max_cpuid_value < 1) {
- return 0;
- }
-
- GetCPUInfo(cpu_info, 1);
- if (feature == kSSE2) {
- return 0 != (cpu_info[3] & 0x04000000);
- }
- if (feature == kSSE3) {
- return 0 != (cpu_info[2] & 0x00000001);
- }
- if (feature == kSSE4_1) {
- return 0 != (cpu_info[2] & 0x00080000);
- }
- if (feature == kAVX) {
- // bits 27 (OSXSAVE) & 28 (256-bit AVX)
- if ((cpu_info[2] & 0x18000000) == 0x18000000) {
- // XMM state and YMM state enabled by the OS.
- return (xgetbv() & 0x6) == 0x6;
- }
- }
- if (feature == kAVX2) {
- if (x86CPUInfo(kAVX) && max_cpuid_value >= 7) {
- GetCPUInfo(cpu_info, 7);
- return ((cpu_info[1] & 0x00000020) == 0x00000020);
- }
- }
- return 0;
-}
-VP8CPUInfo VP8GetCPUInfo = x86CPUInfo;
-#elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test.
-static int AndroidCPUInfo(CPUFeature feature) {
- const AndroidCpuFamily cpu_family = android_getCpuFamily();
- const uint64_t cpu_features = android_getCpuFeatures();
- if (feature == kNEON) {
- return (cpu_family == ANDROID_CPU_FAMILY_ARM &&
- 0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON));
- }
- return 0;
-}
-VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo;
-#elif defined(WEBP_USE_NEON)
-// define a dummy function to enable turning off NEON at runtime by setting
-// VP8DecGetCPUInfo = NULL
-static int armCPUInfo(CPUFeature feature) {
- if (feature != kNEON) return 0;
-#if defined(__linux__) && defined(WEBP_HAVE_NEON_RTCD)
- {
- int has_neon = 0;
- char line[200];
- FILE* const cpuinfo = fopen("/proc/cpuinfo", "r");
- if (cpuinfo == NULL) return 0;
- while (fgets(line, sizeof(line), cpuinfo)) {
- if (!strncmp(line, "Features", 8)) {
- if (strstr(line, " neon ") != NULL) {
- has_neon = 1;
- break;
- }
- }
- }
- fclose(cpuinfo);
- return has_neon;
- }
-#else
- return 1;
-#endif
-}
-VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
-#elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2) || \
- defined(WEBP_USE_MSA)
-static int mipsCPUInfo(CPUFeature feature) {
- if ((feature == kMIPS32) || (feature == kMIPSdspR2) || (feature == kMSA)) {
- return 1;
- } else {
- return 0;
- }
-
-}
-VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo;
-#else
-VP8CPUInfo VP8GetCPUInfo = NULL;
-#endif
-
diff --git a/drivers/webp/dsp/dec.c b/drivers/webp/dsp/dec.c
deleted file mode 100644
index e92d693362..0000000000
--- a/drivers/webp/dsp/dec.c
+++ /dev/null
@@ -1,795 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Speed-critical decoding functions, default plain-C implementations.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-#include "../dec/vp8i.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE uint8_t clip_8b(int v) {
- return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
-}
-
-//------------------------------------------------------------------------------
-// Transforms (Paragraph 14.4)
-
-#define STORE(x, y, v) \
- dst[x + y * BPS] = clip_8b(dst[x + y * BPS] + ((v) >> 3))
-
-#define STORE2(y, dc, d, c) do { \
- const int DC = (dc); \
- STORE(0, y, DC + (d)); \
- STORE(1, y, DC + (c)); \
- STORE(2, y, DC - (c)); \
- STORE(3, y, DC - (d)); \
-} while (0)
-
-#define MUL1(a) ((((a) * 20091) >> 16) + (a))
-#define MUL2(a) (((a) * 35468) >> 16)
-
-static void TransformOne(const int16_t* in, uint8_t* dst) {
- int C[4 * 4], *tmp;
- int i;
- tmp = C;
- for (i = 0; i < 4; ++i) { // vertical pass
- const int a = in[0] + in[8]; // [-4096, 4094]
- const int b = in[0] - in[8]; // [-4095, 4095]
- const int c = MUL2(in[4]) - MUL1(in[12]); // [-3783, 3783]
- const int d = MUL1(in[4]) + MUL2(in[12]); // [-3785, 3781]
- tmp[0] = a + d; // [-7881, 7875]
- tmp[1] = b + c; // [-7878, 7878]
- tmp[2] = b - c; // [-7878, 7878]
- tmp[3] = a - d; // [-7877, 7879]
- tmp += 4;
- in++;
- }
- // Each pass is expanding the dynamic range by ~3.85 (upper bound).
- // The exact value is (2. + (20091 + 35468) / 65536).
- // After the second pass, maximum interval is [-3794, 3794], assuming
- // an input in [-2048, 2047] interval. We then need to add a dst value
- // in the [0, 255] range.
- // In the worst case scenario, the input to clip_8b() can be as large as
- // [-60713, 60968].
- tmp = C;
- for (i = 0; i < 4; ++i) { // horizontal pass
- const int dc = tmp[0] + 4;
- const int a = dc + tmp[8];
- const int b = dc - tmp[8];
- const int c = MUL2(tmp[4]) - MUL1(tmp[12]);
- const int d = MUL1(tmp[4]) + MUL2(tmp[12]);
- STORE(0, 0, a + d);
- STORE(1, 0, b + c);
- STORE(2, 0, b - c);
- STORE(3, 0, a - d);
- tmp++;
- dst += BPS;
- }
-}
-
-// Simplified transform when only in[0], in[1] and in[4] are non-zero
-static void TransformAC3(const int16_t* in, uint8_t* dst) {
- const int a = in[0] + 4;
- const int c4 = MUL2(in[4]);
- const int d4 = MUL1(in[4]);
- const int c1 = MUL2(in[1]);
- const int d1 = MUL1(in[1]);
- STORE2(0, a + d4, d1, c1);
- STORE2(1, a + c4, d1, c1);
- STORE2(2, a - c4, d1, c1);
- STORE2(3, a - d4, d1, c1);
-}
-#undef MUL1
-#undef MUL2
-#undef STORE2
-
-static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
- TransformOne(in, dst);
- if (do_two) {
- TransformOne(in + 16, dst + 4);
- }
-}
-
-static void TransformUV(const int16_t* in, uint8_t* dst) {
- VP8Transform(in + 0 * 16, dst, 1);
- VP8Transform(in + 2 * 16, dst + 4 * BPS, 1);
-}
-
-static void TransformDC(const int16_t* in, uint8_t* dst) {
- const int DC = in[0] + 4;
- int i, j;
- for (j = 0; j < 4; ++j) {
- for (i = 0; i < 4; ++i) {
- STORE(i, j, DC);
- }
- }
-}
-
-static void TransformDCUV(const int16_t* in, uint8_t* dst) {
- if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst);
- if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4);
- if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS);
- if (in[3 * 16]) VP8TransformDC(in + 3 * 16, dst + 4 * BPS + 4);
-}
-
-#undef STORE
-
-//------------------------------------------------------------------------------
-// Paragraph 14.3
-
-static void TransformWHT(const int16_t* in, int16_t* out) {
- int tmp[16];
- int i;
- for (i = 0; i < 4; ++i) {
- const int a0 = in[0 + i] + in[12 + i];
- const int a1 = in[4 + i] + in[ 8 + i];
- const int a2 = in[4 + i] - in[ 8 + i];
- const int a3 = in[0 + i] - in[12 + i];
- tmp[0 + i] = a0 + a1;
- tmp[8 + i] = a0 - a1;
- tmp[4 + i] = a3 + a2;
- tmp[12 + i] = a3 - a2;
- }
- for (i = 0; i < 4; ++i) {
- const int dc = tmp[0 + i * 4] + 3; // w/ rounder
- const int a0 = dc + tmp[3 + i * 4];
- const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4];
- const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4];
- const int a3 = dc - tmp[3 + i * 4];
- out[ 0] = (a0 + a1) >> 3;
- out[16] = (a3 + a2) >> 3;
- out[32] = (a0 - a1) >> 3;
- out[48] = (a3 - a2) >> 3;
- out += 64;
- }
-}
-
-void (*VP8TransformWHT)(const int16_t* in, int16_t* out);
-
-//------------------------------------------------------------------------------
-// Intra predictions
-
-#define DST(x, y) dst[(x) + (y) * BPS]
-
-static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) {
- const uint8_t* top = dst - BPS;
- const uint8_t* const clip0 = VP8kclip1 - top[-1];
- int y;
- for (y = 0; y < size; ++y) {
- const uint8_t* const clip = clip0 + dst[-1];
- int x;
- for (x = 0; x < size; ++x) {
- dst[x] = clip[top[x]];
- }
- dst += BPS;
- }
-}
-static void TM4(uint8_t* dst) { TrueMotion(dst, 4); }
-static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); }
-static void TM16(uint8_t* dst) { TrueMotion(dst, 16); }
-
-//------------------------------------------------------------------------------
-// 16x16
-
-static void VE16(uint8_t* dst) { // vertical
- int j;
- for (j = 0; j < 16; ++j) {
- memcpy(dst + j * BPS, dst - BPS, 16);
- }
-}
-
-static void HE16(uint8_t* dst) { // horizontal
- int j;
- for (j = 16; j > 0; --j) {
- memset(dst, dst[-1], 16);
- dst += BPS;
- }
-}
-
-static WEBP_INLINE void Put16(int v, uint8_t* dst) {
- int j;
- for (j = 0; j < 16; ++j) {
- memset(dst + j * BPS, v, 16);
- }
-}
-
-static void DC16(uint8_t* dst) { // DC
- int DC = 16;
- int j;
- for (j = 0; j < 16; ++j) {
- DC += dst[-1 + j * BPS] + dst[j - BPS];
- }
- Put16(DC >> 5, dst);
-}
-
-static void DC16NoTop(uint8_t* dst) { // DC with top samples not available
- int DC = 8;
- int j;
- for (j = 0; j < 16; ++j) {
- DC += dst[-1 + j * BPS];
- }
- Put16(DC >> 4, dst);
-}
-
-static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available
- int DC = 8;
- int i;
- for (i = 0; i < 16; ++i) {
- DC += dst[i - BPS];
- }
- Put16(DC >> 4, dst);
-}
-
-static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples
- Put16(0x80, dst);
-}
-
-VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES];
-
-//------------------------------------------------------------------------------
-// 4x4
-
-#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
-#define AVG2(a, b) (((a) + (b) + 1) >> 1)
-
-static void VE4(uint8_t* dst) { // vertical
- const uint8_t* top = dst - BPS;
- const uint8_t vals[4] = {
- AVG3(top[-1], top[0], top[1]),
- AVG3(top[ 0], top[1], top[2]),
- AVG3(top[ 1], top[2], top[3]),
- AVG3(top[ 2], top[3], top[4])
- };
- int i;
- for (i = 0; i < 4; ++i) {
- memcpy(dst + i * BPS, vals, sizeof(vals));
- }
-}
-
-static void HE4(uint8_t* dst) { // horizontal
- const int A = dst[-1 - BPS];
- const int B = dst[-1];
- const int C = dst[-1 + BPS];
- const int D = dst[-1 + 2 * BPS];
- const int E = dst[-1 + 3 * BPS];
- WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(A, B, C));
- WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(B, C, D));
- WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(C, D, E));
- WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(D, E, E));
-}
-
-static void DC4(uint8_t* dst) { // DC
- uint32_t dc = 4;
- int i;
- for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS];
- dc >>= 3;
- for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4);
-}
-
-static void RD4(uint8_t* dst) { // Down-right
- const int I = dst[-1 + 0 * BPS];
- const int J = dst[-1 + 1 * BPS];
- const int K = dst[-1 + 2 * BPS];
- const int L = dst[-1 + 3 * BPS];
- const int X = dst[-1 - BPS];
- const int A = dst[0 - BPS];
- const int B = dst[1 - BPS];
- const int C = dst[2 - BPS];
- const int D = dst[3 - BPS];
- DST(0, 3) = AVG3(J, K, L);
- DST(1, 3) = DST(0, 2) = AVG3(I, J, K);
- DST(2, 3) = DST(1, 2) = DST(0, 1) = AVG3(X, I, J);
- DST(3, 3) = DST(2, 2) = DST(1, 1) = DST(0, 0) = AVG3(A, X, I);
- DST(3, 2) = DST(2, 1) = DST(1, 0) = AVG3(B, A, X);
- DST(3, 1) = DST(2, 0) = AVG3(C, B, A);
- DST(3, 0) = AVG3(D, C, B);
-}
-
-static void LD4(uint8_t* dst) { // Down-Left
- const int A = dst[0 - BPS];
- const int B = dst[1 - BPS];
- const int C = dst[2 - BPS];
- const int D = dst[3 - BPS];
- const int E = dst[4 - BPS];
- const int F = dst[5 - BPS];
- const int G = dst[6 - BPS];
- const int H = dst[7 - BPS];
- DST(0, 0) = AVG3(A, B, C);
- DST(1, 0) = DST(0, 1) = AVG3(B, C, D);
- DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E);
- DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F);
- DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G);
- DST(3, 2) = DST(2, 3) = AVG3(F, G, H);
- DST(3, 3) = AVG3(G, H, H);
-}
-
-static void VR4(uint8_t* dst) { // Vertical-Right
- const int I = dst[-1 + 0 * BPS];
- const int J = dst[-1 + 1 * BPS];
- const int K = dst[-1 + 2 * BPS];
- const int X = dst[-1 - BPS];
- const int A = dst[0 - BPS];
- const int B = dst[1 - BPS];
- const int C = dst[2 - BPS];
- const int D = dst[3 - BPS];
- DST(0, 0) = DST(1, 2) = AVG2(X, A);
- DST(1, 0) = DST(2, 2) = AVG2(A, B);
- DST(2, 0) = DST(3, 2) = AVG2(B, C);
- DST(3, 0) = AVG2(C, D);
-
- DST(0, 3) = AVG3(K, J, I);
- DST(0, 2) = AVG3(J, I, X);
- DST(0, 1) = DST(1, 3) = AVG3(I, X, A);
- DST(1, 1) = DST(2, 3) = AVG3(X, A, B);
- DST(2, 1) = DST(3, 3) = AVG3(A, B, C);
- DST(3, 1) = AVG3(B, C, D);
-}
-
-static void VL4(uint8_t* dst) { // Vertical-Left
- const int A = dst[0 - BPS];
- const int B = dst[1 - BPS];
- const int C = dst[2 - BPS];
- const int D = dst[3 - BPS];
- const int E = dst[4 - BPS];
- const int F = dst[5 - BPS];
- const int G = dst[6 - BPS];
- const int H = dst[7 - BPS];
- DST(0, 0) = AVG2(A, B);
- DST(1, 0) = DST(0, 2) = AVG2(B, C);
- DST(2, 0) = DST(1, 2) = AVG2(C, D);
- DST(3, 0) = DST(2, 2) = AVG2(D, E);
-
- DST(0, 1) = AVG3(A, B, C);
- DST(1, 1) = DST(0, 3) = AVG3(B, C, D);
- DST(2, 1) = DST(1, 3) = AVG3(C, D, E);
- DST(3, 1) = DST(2, 3) = AVG3(D, E, F);
- DST(3, 2) = AVG3(E, F, G);
- DST(3, 3) = AVG3(F, G, H);
-}
-
-static void HU4(uint8_t* dst) { // Horizontal-Up
- const int I = dst[-1 + 0 * BPS];
- const int J = dst[-1 + 1 * BPS];
- const int K = dst[-1 + 2 * BPS];
- const int L = dst[-1 + 3 * BPS];
- DST(0, 0) = AVG2(I, J);
- DST(2, 0) = DST(0, 1) = AVG2(J, K);
- DST(2, 1) = DST(0, 2) = AVG2(K, L);
- DST(1, 0) = AVG3(I, J, K);
- DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
- DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
- DST(3, 2) = DST(2, 2) =
- DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
-}
-
-static void HD4(uint8_t* dst) { // Horizontal-Down
- const int I = dst[-1 + 0 * BPS];
- const int J = dst[-1 + 1 * BPS];
- const int K = dst[-1 + 2 * BPS];
- const int L = dst[-1 + 3 * BPS];
- const int X = dst[-1 - BPS];
- const int A = dst[0 - BPS];
- const int B = dst[1 - BPS];
- const int C = dst[2 - BPS];
-
- DST(0, 0) = DST(2, 1) = AVG2(I, X);
- DST(0, 1) = DST(2, 2) = AVG2(J, I);
- DST(0, 2) = DST(2, 3) = AVG2(K, J);
- DST(0, 3) = AVG2(L, K);
-
- DST(3, 0) = AVG3(A, B, C);
- DST(2, 0) = AVG3(X, A, B);
- DST(1, 0) = DST(3, 1) = AVG3(I, X, A);
- DST(1, 1) = DST(3, 2) = AVG3(J, I, X);
- DST(1, 2) = DST(3, 3) = AVG3(K, J, I);
- DST(1, 3) = AVG3(L, K, J);
-}
-
-#undef DST
-#undef AVG3
-#undef AVG2
-
-VP8PredFunc VP8PredLuma4[NUM_BMODES];
-
-//------------------------------------------------------------------------------
-// Chroma
-
-static void VE8uv(uint8_t* dst) { // vertical
- int j;
- for (j = 0; j < 8; ++j) {
- memcpy(dst + j * BPS, dst - BPS, 8);
- }
-}
-
-static void HE8uv(uint8_t* dst) { // horizontal
- int j;
- for (j = 0; j < 8; ++j) {
- memset(dst, dst[-1], 8);
- dst += BPS;
- }
-}
-
-// helper for chroma-DC predictions
-static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) {
- int j;
- for (j = 0; j < 8; ++j) {
- memset(dst + j * BPS, value, 8);
- }
-}
-
-static void DC8uv(uint8_t* dst) { // DC
- int dc0 = 8;
- int i;
- for (i = 0; i < 8; ++i) {
- dc0 += dst[i - BPS] + dst[-1 + i * BPS];
- }
- Put8x8uv(dc0 >> 4, dst);
-}
-
-static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
- int dc0 = 4;
- int i;
- for (i = 0; i < 8; ++i) {
- dc0 += dst[i - BPS];
- }
- Put8x8uv(dc0 >> 3, dst);
-}
-
-static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
- int dc0 = 4;
- int i;
- for (i = 0; i < 8; ++i) {
- dc0 += dst[-1 + i * BPS];
- }
- Put8x8uv(dc0 >> 3, dst);
-}
-
-static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing
- Put8x8uv(0x80, dst);
-}
-
-VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES];
-
-//------------------------------------------------------------------------------
-// Edge filtering functions
-
-// 4 pixels in, 2 pixels out
-static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
- const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892]
- const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15]
- const int a2 = VP8ksclip2[(a + 3) >> 3];
- p[-step] = VP8kclip1[p0 + a2];
- p[ 0] = VP8kclip1[q0 - a1];
-}
-
-// 4 pixels in, 4 pixels out
-static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
- const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- const int a = 3 * (q0 - p0);
- const int a1 = VP8ksclip2[(a + 4) >> 3];
- const int a2 = VP8ksclip2[(a + 3) >> 3];
- const int a3 = (a1 + 1) >> 1;
- p[-2*step] = VP8kclip1[p1 + a3];
- p[- step] = VP8kclip1[p0 + a2];
- p[ 0] = VP8kclip1[q0 - a1];
- p[ step] = VP8kclip1[q1 - a3];
-}
-
-// 6 pixels in, 6 pixels out
-static WEBP_INLINE void do_filter6(uint8_t* p, int step) {
- const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
- const int q0 = p[0], q1 = p[step], q2 = p[2*step];
- const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]];
- // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9]
- const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7
- const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7
- const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7
- p[-3*step] = VP8kclip1[p2 + a3];
- p[-2*step] = VP8kclip1[p1 + a2];
- p[- step] = VP8kclip1[p0 + a1];
- p[ 0] = VP8kclip1[q0 - a1];
- p[ step] = VP8kclip1[q1 - a2];
- p[ 2*step] = VP8kclip1[q2 - a3];
-}
-
-static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
- const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
- return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh);
-}
-
-static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) {
- const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
- return ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) <= t);
-}
-
-static WEBP_INLINE int needs_filter2(const uint8_t* p,
- int step, int t, int it) {
- const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step];
- const int p0 = p[-step], q0 = p[0];
- const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
- if ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) > t) return 0;
- return VP8kabs0[p3 - p2] <= it && VP8kabs0[p2 - p1] <= it &&
- VP8kabs0[p1 - p0] <= it && VP8kabs0[q3 - q2] <= it &&
- VP8kabs0[q2 - q1] <= it && VP8kabs0[q1 - q0] <= it;
-}
-
-//------------------------------------------------------------------------------
-// Simple In-loop filtering (Paragraph 15.2)
-
-static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
- int i;
- const int thresh2 = 2 * thresh + 1;
- for (i = 0; i < 16; ++i) {
- if (needs_filter(p + i, stride, thresh2)) {
- do_filter2(p + i, stride);
- }
- }
-}
-
-static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
- int i;
- const int thresh2 = 2 * thresh + 1;
- for (i = 0; i < 16; ++i) {
- if (needs_filter(p + i * stride, 1, thresh2)) {
- do_filter2(p + i * stride, 1);
- }
- }
-}
-
-static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- SimpleVFilter16(p, stride, thresh);
- }
-}
-
-static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- SimpleHFilter16(p, stride, thresh);
- }
-}
-
-//------------------------------------------------------------------------------
-// Complex In-loop filtering (Paragraph 15.3)
-
-static WEBP_INLINE void FilterLoop26(uint8_t* p,
- int hstride, int vstride, int size,
- int thresh, int ithresh, int hev_thresh) {
- const int thresh2 = 2 * thresh + 1;
- while (size-- > 0) {
- if (needs_filter2(p, hstride, thresh2, ithresh)) {
- if (hev(p, hstride, hev_thresh)) {
- do_filter2(p, hstride);
- } else {
- do_filter6(p, hstride);
- }
- }
- p += vstride;
- }
-}
-
-static WEBP_INLINE void FilterLoop24(uint8_t* p,
- int hstride, int vstride, int size,
- int thresh, int ithresh, int hev_thresh) {
- const int thresh2 = 2 * thresh + 1;
- while (size-- > 0) {
- if (needs_filter2(p, hstride, thresh2, ithresh)) {
- if (hev(p, hstride, hev_thresh)) {
- do_filter2(p, hstride);
- } else {
- do_filter4(p, hstride);
- }
- }
- p += vstride;
- }
-}
-
-// on macroblock edges
-static void VFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
-}
-
-// on three inner edges
-static void VFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
- }
-}
-
-static void HFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
- }
-}
-
-// 8-pixels wide variant, for chroma filtering
-static void VFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
- FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
- FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
-}
-
-static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
- FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
- FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
-}
-
-//------------------------------------------------------------------------------
-
-static void DitherCombine8x8(const uint8_t* dither, uint8_t* dst,
- int dst_stride) {
- int i, j;
- for (j = 0; j < 8; ++j) {
- for (i = 0; i < 8; ++i) {
- const int delta0 = dither[i] - VP8_DITHER_AMP_CENTER;
- const int delta1 =
- (delta0 + VP8_DITHER_DESCALE_ROUNDER) >> VP8_DITHER_DESCALE;
- dst[i] = clip_8b((int)dst[i] + delta1);
- }
- dst += dst_stride;
- dither += 8;
- }
-}
-
-//------------------------------------------------------------------------------
-
-VP8DecIdct2 VP8Transform;
-VP8DecIdct VP8TransformAC3;
-VP8DecIdct VP8TransformUV;
-VP8DecIdct VP8TransformDC;
-VP8DecIdct VP8TransformDCUV;
-
-VP8LumaFilterFunc VP8VFilter16;
-VP8LumaFilterFunc VP8HFilter16;
-VP8ChromaFilterFunc VP8VFilter8;
-VP8ChromaFilterFunc VP8HFilter8;
-VP8LumaFilterFunc VP8VFilter16i;
-VP8LumaFilterFunc VP8HFilter16i;
-VP8ChromaFilterFunc VP8VFilter8i;
-VP8ChromaFilterFunc VP8HFilter8i;
-VP8SimpleFilterFunc VP8SimpleVFilter16;
-VP8SimpleFilterFunc VP8SimpleHFilter16;
-VP8SimpleFilterFunc VP8SimpleVFilter16i;
-VP8SimpleFilterFunc VP8SimpleHFilter16i;
-
-void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst,
- int dst_stride);
-
-extern void VP8DspInitSSE2(void);
-extern void VP8DspInitSSE41(void);
-extern void VP8DspInitNEON(void);
-extern void VP8DspInitMIPS32(void);
-extern void VP8DspInitMIPSdspR2(void);
-extern void VP8DspInitMSA(void);
-
-static volatile VP8CPUInfo dec_last_cpuinfo_used =
- (VP8CPUInfo)&dec_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) {
- if (dec_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- VP8InitClipTables();
-
- VP8TransformWHT = TransformWHT;
- VP8Transform = TransformTwo;
- VP8TransformUV = TransformUV;
- VP8TransformDC = TransformDC;
- VP8TransformDCUV = TransformDCUV;
- VP8TransformAC3 = TransformAC3;
-
- VP8VFilter16 = VFilter16;
- VP8HFilter16 = HFilter16;
- VP8VFilter8 = VFilter8;
- VP8HFilter8 = HFilter8;
- VP8VFilter16i = VFilter16i;
- VP8HFilter16i = HFilter16i;
- VP8VFilter8i = VFilter8i;
- VP8HFilter8i = HFilter8i;
- VP8SimpleVFilter16 = SimpleVFilter16;
- VP8SimpleHFilter16 = SimpleHFilter16;
- VP8SimpleVFilter16i = SimpleVFilter16i;
- VP8SimpleHFilter16i = SimpleHFilter16i;
-
- VP8PredLuma4[0] = DC4;
- VP8PredLuma4[1] = TM4;
- VP8PredLuma4[2] = VE4;
- VP8PredLuma4[3] = HE4;
- VP8PredLuma4[4] = RD4;
- VP8PredLuma4[5] = VR4;
- VP8PredLuma4[6] = LD4;
- VP8PredLuma4[7] = VL4;
- VP8PredLuma4[8] = HD4;
- VP8PredLuma4[9] = HU4;
-
- VP8PredLuma16[0] = DC16;
- VP8PredLuma16[1] = TM16;
- VP8PredLuma16[2] = VE16;
- VP8PredLuma16[3] = HE16;
- VP8PredLuma16[4] = DC16NoTop;
- VP8PredLuma16[5] = DC16NoLeft;
- VP8PredLuma16[6] = DC16NoTopLeft;
-
- VP8PredChroma8[0] = DC8uv;
- VP8PredChroma8[1] = TM8uv;
- VP8PredChroma8[2] = VE8uv;
- VP8PredChroma8[3] = HE8uv;
- VP8PredChroma8[4] = DC8uvNoTop;
- VP8PredChroma8[5] = DC8uvNoLeft;
- VP8PredChroma8[6] = DC8uvNoTopLeft;
-
- VP8DitherCombine8x8 = DitherCombine8x8;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- VP8DspInitSSE2();
-#if defined(WEBP_USE_SSE41)
- if (VP8GetCPUInfo(kSSE4_1)) {
- VP8DspInitSSE41();
- }
-#endif
- }
-#endif
-#if defined(WEBP_USE_NEON)
- if (VP8GetCPUInfo(kNEON)) {
- VP8DspInitNEON();
- }
-#endif
-#if defined(WEBP_USE_MIPS32)
- if (VP8GetCPUInfo(kMIPS32)) {
- VP8DspInitMIPS32();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- VP8DspInitMIPSdspR2();
- }
-#endif
-#if defined(WEBP_USE_MSA)
- if (VP8GetCPUInfo(kMSA)) {
- VP8DspInitMSA();
- }
-#endif
- }
- dec_last_cpuinfo_used = VP8GetCPUInfo;
-}
diff --git a/drivers/webp/dsp/dec_clip_tables.c b/drivers/webp/dsp/dec_clip_tables.c
deleted file mode 100644
index 3b6dde86ba..0000000000
--- a/drivers/webp/dsp/dec_clip_tables.c
+++ /dev/null
@@ -1,366 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Clipping tables for filtering
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#define USE_STATIC_TABLES // undefine to have run-time table initialization
-
-#ifdef USE_STATIC_TABLES
-
-static const uint8_t abs0[255 + 255 + 1] = {
- 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4,
- 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
- 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc,
- 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0,
- 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4,
- 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
- 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac,
- 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
- 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94,
- 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88,
- 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c,
- 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
- 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64,
- 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58,
- 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c,
- 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
- 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34,
- 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
- 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c,
- 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
- 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
- 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
- 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44,
- 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c,
- 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
- 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
- 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
- 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c,
- 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
- 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
- 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
- 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
- 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
- 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec,
- 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
-};
-
-static const int8_t sclip1[1020 + 1020 + 1] = {
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
- 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
- 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,
- 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
- 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
- 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
- 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
- 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
- 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
- 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
-};
-
-static const int8_t sclip2[112 + 112 + 1] = {
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
- 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f
-};
-
-static const uint8_t clip1[255 + 511 + 1] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
- 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
- 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44,
- 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c,
- 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
- 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
- 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
- 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c,
- 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
- 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
- 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
- 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
- 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
- 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec,
- 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-#else
-
-// uninitialized tables
-static uint8_t abs0[255 + 255 + 1];
-static int8_t sclip1[1020 + 1020 + 1];
-static int8_t sclip2[112 + 112 + 1];
-static uint8_t clip1[255 + 511 + 1];
-
-// We declare this variable 'volatile' to prevent instruction reordering
-// and make sure it's set to true _last_ (so as to be thread-safe)
-static volatile int tables_ok = 0;
-
-#endif
-
-const int8_t* const VP8ksclip1 = &sclip1[1020];
-const int8_t* const VP8ksclip2 = &sclip2[112];
-const uint8_t* const VP8kclip1 = &clip1[255];
-const uint8_t* const VP8kabs0 = &abs0[255];
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8InitClipTables(void) {
-#if !defined(USE_STATIC_TABLES)
- int i;
- if (!tables_ok) {
- for (i = -255; i <= 255; ++i) {
- abs0[255 + i] = (i < 0) ? -i : i;
- }
- for (i = -1020; i <= 1020; ++i) {
- sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
- }
- for (i = -112; i <= 112; ++i) {
- sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
- }
- for (i = -255; i <= 255 + 255; ++i) {
- clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
- }
- tables_ok = 1;
- }
-#endif // USE_STATIC_TABLES
-}
diff --git a/drivers/webp/dsp/dec_mips32.c b/drivers/webp/dsp/dec_mips32.c
deleted file mode 100644
index 4e9ef42605..0000000000
--- a/drivers/webp/dsp/dec_mips32.c
+++ /dev/null
@@ -1,587 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS version of dsp functions
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS32)
-
-#include "./mips_macro.h"
-
-static const int kC1 = 20091 + (1 << 16);
-static const int kC2 = 35468;
-
-static WEBP_INLINE int abs_mips32(int x) {
- const int sign = x >> 31;
- return (x ^ sign) - sign;
-}
-
-// 4 pixels in, 2 pixels out
-static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
- const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
- const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1];
- const int a1 = VP8ksclip2[(a + 4) >> 3];
- const int a2 = VP8ksclip2[(a + 3) >> 3];
- p[-step] = VP8kclip1[p0 + a2];
- p[ 0] = VP8kclip1[q0 - a1];
-}
-
-// 4 pixels in, 4 pixels out
-static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
- const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
- const int a = 3 * (q0 - p0);
- const int a1 = VP8ksclip2[(a + 4) >> 3];
- const int a2 = VP8ksclip2[(a + 3) >> 3];
- const int a3 = (a1 + 1) >> 1;
- p[-2 * step] = VP8kclip1[p1 + a3];
- p[- step] = VP8kclip1[p0 + a2];
- p[ 0] = VP8kclip1[q0 - a1];
- p[ step] = VP8kclip1[q1 - a3];
-}
-
-// 6 pixels in, 6 pixels out
-static WEBP_INLINE void do_filter6(uint8_t* p, int step) {
- const int p2 = p[-3 * step], p1 = p[-2 * step], p0 = p[-step];
- const int q0 = p[0], q1 = p[step], q2 = p[2 * step];
- const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]];
- // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9]
- const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7
- const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7
- const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7
- p[-3 * step] = VP8kclip1[p2 + a3];
- p[-2 * step] = VP8kclip1[p1 + a2];
- p[- step] = VP8kclip1[p0 + a1];
- p[ 0] = VP8kclip1[q0 - a1];
- p[ step] = VP8kclip1[q1 - a2];
- p[ 2 * step] = VP8kclip1[q2 - a3];
-}
-
-static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
- const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
- return (abs_mips32(p1 - p0) > thresh) || (abs_mips32(q1 - q0) > thresh);
-}
-
-static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) {
- const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
- return ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) <= t);
-}
-
-static WEBP_INLINE int needs_filter2(const uint8_t* p,
- int step, int t, int it) {
- const int p3 = p[-4 * step], p2 = p[-3 * step];
- const int p1 = p[-2 * step], p0 = p[-step];
- const int q0 = p[0], q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
- if ((4 * abs_mips32(p0 - q0) + abs_mips32(p1 - q1)) > t) {
- return 0;
- }
- return abs_mips32(p3 - p2) <= it && abs_mips32(p2 - p1) <= it &&
- abs_mips32(p1 - p0) <= it && abs_mips32(q3 - q2) <= it &&
- abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it;
-}
-
-static WEBP_INLINE void FilterLoop26(uint8_t* p,
- int hstride, int vstride, int size,
- int thresh, int ithresh, int hev_thresh) {
- const int thresh2 = 2 * thresh + 1;
- while (size-- > 0) {
- if (needs_filter2(p, hstride, thresh2, ithresh)) {
- if (hev(p, hstride, hev_thresh)) {
- do_filter2(p, hstride);
- } else {
- do_filter6(p, hstride);
- }
- }
- p += vstride;
- }
-}
-
-static WEBP_INLINE void FilterLoop24(uint8_t* p,
- int hstride, int vstride, int size,
- int thresh, int ithresh, int hev_thresh) {
- const int thresh2 = 2 * thresh + 1;
- while (size-- > 0) {
- if (needs_filter2(p, hstride, thresh2, ithresh)) {
- if (hev(p, hstride, hev_thresh)) {
- do_filter2(p, hstride);
- } else {
- do_filter4(p, hstride);
- }
- }
- p += vstride;
- }
-}
-
-// on macroblock edges
-static void VFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
-}
-
-// 8-pixels wide variant, for chroma filtering
-static void VFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
- FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
- FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
-}
-
-static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
- FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
- FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
-}
-
-// on three inner edges
-static void VFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
- }
-}
-
-static void HFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
- }
-}
-
-//------------------------------------------------------------------------------
-// Simple In-loop filtering (Paragraph 15.2)
-
-static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
- int i;
- const int thresh2 = 2 * thresh + 1;
- for (i = 0; i < 16; ++i) {
- if (needs_filter(p + i, stride, thresh2)) {
- do_filter2(p + i, stride);
- }
- }
-}
-
-static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
- int i;
- const int thresh2 = 2 * thresh + 1;
- for (i = 0; i < 16; ++i) {
- if (needs_filter(p + i * stride, 1, thresh2)) {
- do_filter2(p + i * stride, 1);
- }
- }
-}
-
-static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- SimpleVFilter16(p, stride, thresh);
- }
-}
-
-static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- SimpleHFilter16(p, stride, thresh);
- }
-}
-
-static void TransformOne(const int16_t* in, uint8_t* dst) {
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8, temp9;
- int temp10, temp11, temp12, temp13, temp14;
- int temp15, temp16, temp17, temp18;
- int16_t* p_in = (int16_t*)in;
-
- // loops unrolled and merged to avoid usage of tmp buffer
- // and to reduce number of stalls. MUL macro is written
- // in assembler and inlined
- __asm__ volatile(
- "lh %[temp0], 0(%[in]) \n\t"
- "lh %[temp8], 16(%[in]) \n\t"
- "lh %[temp4], 8(%[in]) \n\t"
- "lh %[temp12], 24(%[in]) \n\t"
- "addu %[temp16], %[temp0], %[temp8] \n\t"
- "subu %[temp0], %[temp0], %[temp8] \n\t"
- "mul %[temp8], %[temp4], %[kC2] \n\t"
- "mul %[temp17], %[temp12], %[kC1] \n\t"
- "mul %[temp4], %[temp4], %[kC1] \n\t"
- "mul %[temp12], %[temp12], %[kC2] \n\t"
- "lh %[temp1], 2(%[in]) \n\t"
- "lh %[temp5], 10(%[in]) \n\t"
- "lh %[temp9], 18(%[in]) \n\t"
- "lh %[temp13], 26(%[in]) \n\t"
- "sra %[temp8], %[temp8], 16 \n\t"
- "sra %[temp17], %[temp17], 16 \n\t"
- "sra %[temp4], %[temp4], 16 \n\t"
- "sra %[temp12], %[temp12], 16 \n\t"
- "lh %[temp2], 4(%[in]) \n\t"
- "lh %[temp6], 12(%[in]) \n\t"
- "lh %[temp10], 20(%[in]) \n\t"
- "lh %[temp14], 28(%[in]) \n\t"
- "subu %[temp17], %[temp8], %[temp17] \n\t"
- "addu %[temp4], %[temp4], %[temp12] \n\t"
- "addu %[temp8], %[temp16], %[temp4] \n\t"
- "subu %[temp4], %[temp16], %[temp4] \n\t"
- "addu %[temp16], %[temp1], %[temp9] \n\t"
- "subu %[temp1], %[temp1], %[temp9] \n\t"
- "lh %[temp3], 6(%[in]) \n\t"
- "lh %[temp7], 14(%[in]) \n\t"
- "lh %[temp11], 22(%[in]) \n\t"
- "lh %[temp15], 30(%[in]) \n\t"
- "addu %[temp12], %[temp0], %[temp17] \n\t"
- "subu %[temp0], %[temp0], %[temp17] \n\t"
- "mul %[temp9], %[temp5], %[kC2] \n\t"
- "mul %[temp17], %[temp13], %[kC1] \n\t"
- "mul %[temp5], %[temp5], %[kC1] \n\t"
- "mul %[temp13], %[temp13], %[kC2] \n\t"
- "sra %[temp9], %[temp9], 16 \n\t"
- "sra %[temp17], %[temp17], 16 \n\t"
- "subu %[temp17], %[temp9], %[temp17] \n\t"
- "sra %[temp5], %[temp5], 16 \n\t"
- "sra %[temp13], %[temp13], 16 \n\t"
- "addu %[temp5], %[temp5], %[temp13] \n\t"
- "addu %[temp13], %[temp1], %[temp17] \n\t"
- "subu %[temp1], %[temp1], %[temp17] \n\t"
- "mul %[temp17], %[temp14], %[kC1] \n\t"
- "mul %[temp14], %[temp14], %[kC2] \n\t"
- "addu %[temp9], %[temp16], %[temp5] \n\t"
- "subu %[temp5], %[temp16], %[temp5] \n\t"
- "addu %[temp16], %[temp2], %[temp10] \n\t"
- "subu %[temp2], %[temp2], %[temp10] \n\t"
- "mul %[temp10], %[temp6], %[kC2] \n\t"
- "mul %[temp6], %[temp6], %[kC1] \n\t"
- "sra %[temp17], %[temp17], 16 \n\t"
- "sra %[temp14], %[temp14], 16 \n\t"
- "sra %[temp10], %[temp10], 16 \n\t"
- "sra %[temp6], %[temp6], 16 \n\t"
- "subu %[temp17], %[temp10], %[temp17] \n\t"
- "addu %[temp6], %[temp6], %[temp14] \n\t"
- "addu %[temp10], %[temp16], %[temp6] \n\t"
- "subu %[temp6], %[temp16], %[temp6] \n\t"
- "addu %[temp14], %[temp2], %[temp17] \n\t"
- "subu %[temp2], %[temp2], %[temp17] \n\t"
- "mul %[temp17], %[temp15], %[kC1] \n\t"
- "mul %[temp15], %[temp15], %[kC2] \n\t"
- "addu %[temp16], %[temp3], %[temp11] \n\t"
- "subu %[temp3], %[temp3], %[temp11] \n\t"
- "mul %[temp11], %[temp7], %[kC2] \n\t"
- "mul %[temp7], %[temp7], %[kC1] \n\t"
- "addiu %[temp8], %[temp8], 4 \n\t"
- "addiu %[temp12], %[temp12], 4 \n\t"
- "addiu %[temp0], %[temp0], 4 \n\t"
- "addiu %[temp4], %[temp4], 4 \n\t"
- "sra %[temp17], %[temp17], 16 \n\t"
- "sra %[temp15], %[temp15], 16 \n\t"
- "sra %[temp11], %[temp11], 16 \n\t"
- "sra %[temp7], %[temp7], 16 \n\t"
- "subu %[temp17], %[temp11], %[temp17] \n\t"
- "addu %[temp7], %[temp7], %[temp15] \n\t"
- "addu %[temp15], %[temp3], %[temp17] \n\t"
- "subu %[temp3], %[temp3], %[temp17] \n\t"
- "addu %[temp11], %[temp16], %[temp7] \n\t"
- "subu %[temp7], %[temp16], %[temp7] \n\t"
- "addu %[temp16], %[temp8], %[temp10] \n\t"
- "subu %[temp8], %[temp8], %[temp10] \n\t"
- "mul %[temp10], %[temp9], %[kC2] \n\t"
- "mul %[temp17], %[temp11], %[kC1] \n\t"
- "mul %[temp9], %[temp9], %[kC1] \n\t"
- "mul %[temp11], %[temp11], %[kC2] \n\t"
- "sra %[temp10], %[temp10], 16 \n\t"
- "sra %[temp17], %[temp17], 16 \n\t"
- "sra %[temp9], %[temp9], 16 \n\t"
- "sra %[temp11], %[temp11], 16 \n\t"
- "subu %[temp17], %[temp10], %[temp17] \n\t"
- "addu %[temp11], %[temp9], %[temp11] \n\t"
- "addu %[temp10], %[temp12], %[temp14] \n\t"
- "subu %[temp12], %[temp12], %[temp14] \n\t"
- "mul %[temp14], %[temp13], %[kC2] \n\t"
- "mul %[temp9], %[temp15], %[kC1] \n\t"
- "mul %[temp13], %[temp13], %[kC1] \n\t"
- "mul %[temp15], %[temp15], %[kC2] \n\t"
- "sra %[temp14], %[temp14], 16 \n\t"
- "sra %[temp9], %[temp9], 16 \n\t"
- "sra %[temp13], %[temp13], 16 \n\t"
- "sra %[temp15], %[temp15], 16 \n\t"
- "subu %[temp9], %[temp14], %[temp9] \n\t"
- "addu %[temp15], %[temp13], %[temp15] \n\t"
- "addu %[temp14], %[temp0], %[temp2] \n\t"
- "subu %[temp0], %[temp0], %[temp2] \n\t"
- "mul %[temp2], %[temp1], %[kC2] \n\t"
- "mul %[temp13], %[temp3], %[kC1] \n\t"
- "mul %[temp1], %[temp1], %[kC1] \n\t"
- "mul %[temp3], %[temp3], %[kC2] \n\t"
- "sra %[temp2], %[temp2], 16 \n\t"
- "sra %[temp13], %[temp13], 16 \n\t"
- "sra %[temp1], %[temp1], 16 \n\t"
- "sra %[temp3], %[temp3], 16 \n\t"
- "subu %[temp13], %[temp2], %[temp13] \n\t"
- "addu %[temp3], %[temp1], %[temp3] \n\t"
- "addu %[temp2], %[temp4], %[temp6] \n\t"
- "subu %[temp4], %[temp4], %[temp6] \n\t"
- "mul %[temp6], %[temp5], %[kC2] \n\t"
- "mul %[temp1], %[temp7], %[kC1] \n\t"
- "mul %[temp5], %[temp5], %[kC1] \n\t"
- "mul %[temp7], %[temp7], %[kC2] \n\t"
- "sra %[temp6], %[temp6], 16 \n\t"
- "sra %[temp1], %[temp1], 16 \n\t"
- "sra %[temp5], %[temp5], 16 \n\t"
- "sra %[temp7], %[temp7], 16 \n\t"
- "subu %[temp1], %[temp6], %[temp1] \n\t"
- "addu %[temp7], %[temp5], %[temp7] \n\t"
- "addu %[temp5], %[temp16], %[temp11] \n\t"
- "subu %[temp16], %[temp16], %[temp11] \n\t"
- "addu %[temp11], %[temp8], %[temp17] \n\t"
- "subu %[temp8], %[temp8], %[temp17] \n\t"
- "sra %[temp5], %[temp5], 3 \n\t"
- "sra %[temp16], %[temp16], 3 \n\t"
- "sra %[temp11], %[temp11], 3 \n\t"
- "sra %[temp8], %[temp8], 3 \n\t"
- "addu %[temp17], %[temp10], %[temp15] \n\t"
- "subu %[temp10], %[temp10], %[temp15] \n\t"
- "addu %[temp15], %[temp12], %[temp9] \n\t"
- "subu %[temp12], %[temp12], %[temp9] \n\t"
- "sra %[temp17], %[temp17], 3 \n\t"
- "sra %[temp10], %[temp10], 3 \n\t"
- "sra %[temp15], %[temp15], 3 \n\t"
- "sra %[temp12], %[temp12], 3 \n\t"
- "addu %[temp9], %[temp14], %[temp3] \n\t"
- "subu %[temp14], %[temp14], %[temp3] \n\t"
- "addu %[temp3], %[temp0], %[temp13] \n\t"
- "subu %[temp0], %[temp0], %[temp13] \n\t"
- "sra %[temp9], %[temp9], 3 \n\t"
- "sra %[temp14], %[temp14], 3 \n\t"
- "sra %[temp3], %[temp3], 3 \n\t"
- "sra %[temp0], %[temp0], 3 \n\t"
- "addu %[temp13], %[temp2], %[temp7] \n\t"
- "subu %[temp2], %[temp2], %[temp7] \n\t"
- "addu %[temp7], %[temp4], %[temp1] \n\t"
- "subu %[temp4], %[temp4], %[temp1] \n\t"
- "sra %[temp13], %[temp13], 3 \n\t"
- "sra %[temp2], %[temp2], 3 \n\t"
- "sra %[temp7], %[temp7], 3 \n\t"
- "sra %[temp4], %[temp4], 3 \n\t"
- "addiu %[temp6], $zero, 255 \n\t"
- "lbu %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t"
- "addu %[temp1], %[temp1], %[temp5] \n\t"
- "sra %[temp5], %[temp1], 8 \n\t"
- "sra %[temp18], %[temp1], 31 \n\t"
- "beqz %[temp5], 1f \n\t"
- "xor %[temp1], %[temp1], %[temp1] \n\t"
- "movz %[temp1], %[temp6], %[temp18] \n\t"
- "1: \n\t"
- "lbu %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp1], 0+0*" XSTR(BPS) "(%[dst]) \n\t"
- "addu %[temp18], %[temp18], %[temp11] \n\t"
- "sra %[temp11], %[temp18], 8 \n\t"
- "sra %[temp1], %[temp18], 31 \n\t"
- "beqz %[temp11], 2f \n\t"
- "xor %[temp18], %[temp18], %[temp18] \n\t"
- "movz %[temp18], %[temp6], %[temp1] \n\t"
- "2: \n\t"
- "lbu %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp18], 1+0*" XSTR(BPS) "(%[dst]) \n\t"
- "addu %[temp1], %[temp1], %[temp8] \n\t"
- "sra %[temp8], %[temp1], 8 \n\t"
- "sra %[temp18], %[temp1], 31 \n\t"
- "beqz %[temp8], 3f \n\t"
- "xor %[temp1], %[temp1], %[temp1] \n\t"
- "movz %[temp1], %[temp6], %[temp18] \n\t"
- "3: \n\t"
- "lbu %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp1], 2+0*" XSTR(BPS) "(%[dst]) \n\t"
- "addu %[temp18], %[temp18], %[temp16] \n\t"
- "sra %[temp16], %[temp18], 8 \n\t"
- "sra %[temp1], %[temp18], 31 \n\t"
- "beqz %[temp16], 4f \n\t"
- "xor %[temp18], %[temp18], %[temp18] \n\t"
- "movz %[temp18], %[temp6], %[temp1] \n\t"
- "4: \n\t"
- "sb %[temp18], 3+0*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t"
- "addu %[temp5], %[temp5], %[temp17] \n\t"
- "addu %[temp8], %[temp8], %[temp15] \n\t"
- "addu %[temp11], %[temp11], %[temp12] \n\t"
- "addu %[temp16], %[temp16], %[temp10] \n\t"
- "sra %[temp18], %[temp5], 8 \n\t"
- "sra %[temp1], %[temp5], 31 \n\t"
- "beqz %[temp18], 5f \n\t"
- "xor %[temp5], %[temp5], %[temp5] \n\t"
- "movz %[temp5], %[temp6], %[temp1] \n\t"
- "5: \n\t"
- "sra %[temp18], %[temp8], 8 \n\t"
- "sra %[temp1], %[temp8], 31 \n\t"
- "beqz %[temp18], 6f \n\t"
- "xor %[temp8], %[temp8], %[temp8] \n\t"
- "movz %[temp8], %[temp6], %[temp1] \n\t"
- "6: \n\t"
- "sra %[temp18], %[temp11], 8 \n\t"
- "sra %[temp1], %[temp11], 31 \n\t"
- "sra %[temp17], %[temp16], 8 \n\t"
- "sra %[temp15], %[temp16], 31 \n\t"
- "beqz %[temp18], 7f \n\t"
- "xor %[temp11], %[temp11], %[temp11] \n\t"
- "movz %[temp11], %[temp6], %[temp1] \n\t"
- "7: \n\t"
- "beqz %[temp17], 8f \n\t"
- "xor %[temp16], %[temp16], %[temp16] \n\t"
- "movz %[temp16], %[temp6], %[temp15] \n\t"
- "8: \n\t"
- "sb %[temp5], 0+1*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp8], 1+1*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp11], 2+1*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp16], 3+1*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t"
- "addu %[temp5], %[temp5], %[temp9] \n\t"
- "addu %[temp8], %[temp8], %[temp3] \n\t"
- "addu %[temp11], %[temp11], %[temp0] \n\t"
- "addu %[temp16], %[temp16], %[temp14] \n\t"
- "sra %[temp18], %[temp5], 8 \n\t"
- "sra %[temp1], %[temp5], 31 \n\t"
- "sra %[temp17], %[temp8], 8 \n\t"
- "sra %[temp15], %[temp8], 31 \n\t"
- "sra %[temp12], %[temp11], 8 \n\t"
- "sra %[temp10], %[temp11], 31 \n\t"
- "sra %[temp9], %[temp16], 8 \n\t"
- "sra %[temp3], %[temp16], 31 \n\t"
- "beqz %[temp18], 9f \n\t"
- "xor %[temp5], %[temp5], %[temp5] \n\t"
- "movz %[temp5], %[temp6], %[temp1] \n\t"
- "9: \n\t"
- "beqz %[temp17], 10f \n\t"
- "xor %[temp8], %[temp8], %[temp8] \n\t"
- "movz %[temp8], %[temp6], %[temp15] \n\t"
- "10: \n\t"
- "beqz %[temp12], 11f \n\t"
- "xor %[temp11], %[temp11], %[temp11] \n\t"
- "movz %[temp11], %[temp6], %[temp10] \n\t"
- "11: \n\t"
- "beqz %[temp9], 12f \n\t"
- "xor %[temp16], %[temp16], %[temp16] \n\t"
- "movz %[temp16], %[temp6], %[temp3] \n\t"
- "12: \n\t"
- "sb %[temp5], 0+2*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp8], 1+2*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp11], 2+2*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp16], 3+2*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t"
- "lbu %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t"
- "addu %[temp5], %[temp5], %[temp13] \n\t"
- "addu %[temp8], %[temp8], %[temp7] \n\t"
- "addu %[temp11], %[temp11], %[temp4] \n\t"
- "addu %[temp16], %[temp16], %[temp2] \n\t"
- "sra %[temp18], %[temp5], 8 \n\t"
- "sra %[temp1], %[temp5], 31 \n\t"
- "sra %[temp17], %[temp8], 8 \n\t"
- "sra %[temp15], %[temp8], 31 \n\t"
- "sra %[temp12], %[temp11], 8 \n\t"
- "sra %[temp10], %[temp11], 31 \n\t"
- "sra %[temp9], %[temp16], 8 \n\t"
- "sra %[temp3], %[temp16], 31 \n\t"
- "beqz %[temp18], 13f \n\t"
- "xor %[temp5], %[temp5], %[temp5] \n\t"
- "movz %[temp5], %[temp6], %[temp1] \n\t"
- "13: \n\t"
- "beqz %[temp17], 14f \n\t"
- "xor %[temp8], %[temp8], %[temp8] \n\t"
- "movz %[temp8], %[temp6], %[temp15] \n\t"
- "14: \n\t"
- "beqz %[temp12], 15f \n\t"
- "xor %[temp11], %[temp11], %[temp11] \n\t"
- "movz %[temp11], %[temp6], %[temp10] \n\t"
- "15: \n\t"
- "beqz %[temp9], 16f \n\t"
- "xor %[temp16], %[temp16], %[temp16] \n\t"
- "movz %[temp16], %[temp6], %[temp3] \n\t"
- "16: \n\t"
- "sb %[temp5], 0+3*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp8], 1+3*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp11], 2+3*" XSTR(BPS) "(%[dst]) \n\t"
- "sb %[temp16], 3+3*" XSTR(BPS) "(%[dst]) \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
- [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
- [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
- [temp18]"=&r"(temp18)
- : [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst)
- : "memory", "hi", "lo"
- );
-}
-
-static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
- TransformOne(in, dst);
- if (do_two) {
- TransformOne(in + 16, dst + 4);
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8DspInitMIPS32(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPS32(void) {
- VP8InitClipTables();
-
- VP8Transform = TransformTwo;
-
- VP8VFilter16 = VFilter16;
- VP8HFilter16 = HFilter16;
- VP8VFilter8 = VFilter8;
- VP8HFilter8 = HFilter8;
- VP8VFilter16i = VFilter16i;
- VP8HFilter16i = HFilter16i;
- VP8VFilter8i = VFilter8i;
- VP8HFilter8i = HFilter8i;
-
- VP8SimpleVFilter16 = SimpleVFilter16;
- VP8SimpleHFilter16 = SimpleHFilter16;
- VP8SimpleVFilter16i = SimpleVFilter16i;
- VP8SimpleHFilter16i = SimpleHFilter16i;
-}
-
-#else // !WEBP_USE_MIPS32
-
-WEBP_DSP_INIT_STUB(VP8DspInitMIPS32)
-
-#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/dec_mips_dsp_r2.c b/drivers/webp/dsp/dec_mips_dsp_r2.c
deleted file mode 100644
index db5c657228..0000000000
--- a/drivers/webp/dsp/dec_mips_dsp_r2.c
+++ /dev/null
@@ -1,994 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS version of dsp functions
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include "./mips_macro.h"
-
-static const int kC1 = 20091 + (1 << 16);
-static const int kC2 = 35468;
-
-#define MUL(a, b) (((a) * (b)) >> 16)
-
-static void TransformDC(const int16_t* in, uint8_t* dst) {
- int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10;
-
- __asm__ volatile (
- LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, dst,
- 0, 0, 0, 0,
- 0, 1, 2, 3,
- BPS)
- "lh %[temp5], 0(%[in]) \n\t"
- "addiu %[temp5], %[temp5], 4 \n\t"
- "ins %[temp5], %[temp5], 16, 16 \n\t"
- "shra.ph %[temp5], %[temp5], 3 \n\t"
- CONVERT_2_BYTES_TO_HALF(temp6, temp7, temp8, temp9, temp10, temp1, temp2,
- temp3, temp1, temp2, temp3, temp4)
- STORE_SAT_SUM_X2(temp6, temp7, temp8, temp9, temp10, temp1, temp2, temp3,
- temp5, temp5, temp5, temp5, temp5, temp5, temp5, temp5,
- dst, 0, 1, 2, 3, BPS)
-
- OUTPUT_EARLY_CLOBBER_REGS_10()
- : [in]"r"(in), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void TransformAC3(const int16_t* in, uint8_t* dst) {
- const int a = in[0] + 4;
- int c4 = MUL(in[4], kC2);
- const int d4 = MUL(in[4], kC1);
- const int c1 = MUL(in[1], kC2);
- const int d1 = MUL(in[1], kC1);
- int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
- int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
-
- __asm__ volatile (
- "ins %[c4], %[d4], 16, 16 \n\t"
- "replv.ph %[temp1], %[a] \n\t"
- "replv.ph %[temp4], %[d1] \n\t"
- ADD_SUB_HALVES(temp2, temp3, temp1, c4)
- "replv.ph %[temp5], %[c1] \n\t"
- SHIFT_R_SUM_X2(temp1, temp6, temp7, temp8, temp2, temp9, temp10, temp4,
- temp2, temp2, temp3, temp3, temp4, temp5, temp4, temp5)
- LOAD_WITH_OFFSET_X4(temp3, temp5, temp11, temp12, dst,
- 0, 0, 0, 0,
- 0, 1, 2, 3,
- BPS)
- CONVERT_2_BYTES_TO_HALF(temp13, temp14, temp3, temp15, temp5, temp16,
- temp11, temp17, temp3, temp5, temp11, temp12)
- PACK_2_HALVES_TO_WORD(temp12, temp18, temp7, temp6, temp1, temp8, temp2,
- temp4, temp7, temp6, temp10, temp9)
- STORE_SAT_SUM_X2(temp13, temp14, temp3, temp15, temp5, temp16, temp11,
- temp17, temp12, temp18, temp1, temp8, temp2, temp4,
- temp7, temp6, dst, 0, 1, 2, 3, BPS)
-
- OUTPUT_EARLY_CLOBBER_REGS_18(),
- [c4]"+&r"(c4)
- : [dst]"r"(dst), [a]"r"(a), [d1]"r"(d1), [d4]"r"(d4), [c1]"r"(c1)
- : "memory"
- );
-}
-
-static void TransformOne(const int16_t* in, uint8_t* dst) {
- int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
- int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
-
- __asm__ volatile (
- "ulw %[temp1], 0(%[in]) \n\t"
- "ulw %[temp2], 16(%[in]) \n\t"
- LOAD_IN_X2(temp5, temp6, 24, 26)
- ADD_SUB_HALVES(temp3, temp4, temp1, temp2)
- LOAD_IN_X2(temp1, temp2, 8, 10)
- MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14,
- temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6,
- temp13, temp11, temp14, temp12)
- INSERT_HALF_X2(temp8, temp7, temp10, temp9)
- "ulw %[temp17], 4(%[in]) \n\t"
- "ulw %[temp18], 20(%[in]) \n\t"
- ADD_SUB_HALVES(temp1, temp2, temp3, temp8)
- ADD_SUB_HALVES(temp5, temp6, temp4, temp7)
- ADD_SUB_HALVES(temp7, temp8, temp17, temp18)
- LOAD_IN_X2(temp17, temp18, 12, 14)
- LOAD_IN_X2(temp9, temp10, 28, 30)
- MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17,
- temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10,
- temp15, temp4, temp16, temp17)
- INSERT_HALF_X2(temp11, temp12, temp13, temp14)
- ADD_SUB_HALVES(temp17, temp8, temp8, temp11)
- ADD_SUB_HALVES(temp3, temp4, temp7, temp12)
-
- // horizontal
- SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6)
- INSERT_HALF_X2(temp1, temp6, temp5, temp2)
- SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8)
- "repl.ph %[temp2], 0x4 \n\t"
- INSERT_HALF_X2(temp3, temp8, temp17, temp4)
- "addq.ph %[temp1], %[temp1], %[temp2] \n\t"
- "addq.ph %[temp6], %[temp6], %[temp2] \n\t"
- ADD_SUB_HALVES(temp2, temp4, temp1, temp3)
- ADD_SUB_HALVES(temp5, temp7, temp6, temp8)
- MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18,
- temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15,
- temp6, temp17, temp8, temp18)
- MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16,
- temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14,
- temp18, temp12, temp17, temp16)
- INSERT_HALF_X2(temp1, temp3, temp9, temp13)
- INSERT_HALF_X2(temp6, temp8, temp11, temp15)
- SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15,
- temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8,
- temp6)
- PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13,
- temp16, temp11, temp10, temp15, temp14)
- LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, dst,
- 0, 0, 0, 0,
- 0, 1, 2, 3,
- BPS)
- CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10,
- temp11, temp10, temp11, temp14, temp15)
- STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11,
- temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4,
- dst, 0, 1, 2, 3, BPS)
-
- OUTPUT_EARLY_CLOBBER_REGS_18()
- : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2)
- : "memory", "hi", "lo"
- );
-}
-
-static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
- TransformOne(in, dst);
- if (do_two) {
- TransformOne(in + 16, dst + 4);
- }
-}
-
-static WEBP_INLINE void FilterLoop26(uint8_t* p,
- int hstride, int vstride, int size,
- int thresh, int ithresh, int hev_thresh) {
- const int thresh2 = 2 * thresh + 1;
- int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
- int temp10, temp11, temp12, temp13, temp14, temp15;
-
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "1: \n\t"
- "negu %[temp1], %[hstride] \n\t"
- "addiu %[size], %[size], -1 \n\t"
- "sll %[temp2], %[hstride], 1 \n\t"
- "sll %[temp3], %[temp1], 1 \n\t"
- "addu %[temp4], %[temp2], %[hstride] \n\t"
- "addu %[temp5], %[temp3], %[temp1] \n\t"
- "lbu %[temp7], 0(%[p]) \n\t"
- "sll %[temp6], %[temp3], 1 \n\t"
- "lbux %[temp8], %[temp5](%[p]) \n\t"
- "lbux %[temp9], %[temp3](%[p]) \n\t"
- "lbux %[temp10], %[temp1](%[p]) \n\t"
- "lbux %[temp11], %[temp6](%[p]) \n\t"
- "lbux %[temp12], %[hstride](%[p]) \n\t"
- "lbux %[temp13], %[temp2](%[p]) \n\t"
- "lbux %[temp14], %[temp4](%[p]) \n\t"
- "subu %[temp1], %[temp10], %[temp7] \n\t"
- "subu %[temp2], %[temp9], %[temp12] \n\t"
- "absq_s.w %[temp3], %[temp1] \n\t"
- "absq_s.w %[temp4], %[temp2] \n\t"
- "negu %[temp1], %[temp1] \n\t"
- "sll %[temp3], %[temp3], 2 \n\t"
- "addu %[temp15], %[temp3], %[temp4] \n\t"
- "subu %[temp3], %[temp15], %[thresh2] \n\t"
- "sll %[temp6], %[temp1], 1 \n\t"
- "bgtz %[temp3], 3f \n\t"
- " subu %[temp4], %[temp11], %[temp8] \n\t"
- "absq_s.w %[temp4], %[temp4] \n\t"
- "shll_s.w %[temp2], %[temp2], 24 \n\t"
- "subu %[temp4], %[temp4], %[ithresh] \n\t"
- "bgtz %[temp4], 3f \n\t"
- " subu %[temp3], %[temp8], %[temp9] \n\t"
- "absq_s.w %[temp3], %[temp3] \n\t"
- "subu %[temp3], %[temp3], %[ithresh] \n\t"
- "bgtz %[temp3], 3f \n\t"
- " subu %[temp5], %[temp9], %[temp10] \n\t"
- "absq_s.w %[temp3], %[temp5] \n\t"
- "absq_s.w %[temp5], %[temp5] \n\t"
- "subu %[temp3], %[temp3], %[ithresh] \n\t"
- "bgtz %[temp3], 3f \n\t"
- " subu %[temp3], %[temp14], %[temp13] \n\t"
- "absq_s.w %[temp3], %[temp3] \n\t"
- "slt %[temp5], %[hev_thresh], %[temp5] \n\t"
- "subu %[temp3], %[temp3], %[ithresh] \n\t"
- "bgtz %[temp3], 3f \n\t"
- " subu %[temp3], %[temp13], %[temp12] \n\t"
- "absq_s.w %[temp3], %[temp3] \n\t"
- "sra %[temp4], %[temp2], 24 \n\t"
- "subu %[temp3], %[temp3], %[ithresh] \n\t"
- "bgtz %[temp3], 3f \n\t"
- " subu %[temp15], %[temp12], %[temp7] \n\t"
- "absq_s.w %[temp3], %[temp15] \n\t"
- "absq_s.w %[temp15], %[temp15] \n\t"
- "subu %[temp3], %[temp3], %[ithresh] \n\t"
- "bgtz %[temp3], 3f \n\t"
- " slt %[temp15], %[hev_thresh], %[temp15] \n\t"
- "addu %[temp3], %[temp6], %[temp1] \n\t"
- "or %[temp2], %[temp5], %[temp15] \n\t"
- "addu %[temp5], %[temp4], %[temp3] \n\t"
- "beqz %[temp2], 4f \n\t"
- " shra_r.w %[temp1], %[temp5], 3 \n\t"
- "addiu %[temp2], %[temp5], 3 \n\t"
- "sra %[temp2], %[temp2], 3 \n\t"
- "shll_s.w %[temp1], %[temp1], 27 \n\t"
- "shll_s.w %[temp2], %[temp2], 27 \n\t"
- "subu %[temp3], %[p], %[hstride] \n\t"
- "sra %[temp1], %[temp1], 27 \n\t"
- "sra %[temp2], %[temp2], 27 \n\t"
- "subu %[temp1], %[temp7], %[temp1] \n\t"
- "addu %[temp2], %[temp10], %[temp2] \n\t"
- "lbux %[temp2], %[temp2](%[VP8kclip1]) \n\t"
- "lbux %[temp1], %[temp1](%[VP8kclip1]) \n\t"
- "sb %[temp2], 0(%[temp3]) \n\t"
- "j 3f \n\t"
- " sb %[temp1], 0(%[p]) \n\t"
- "4: \n\t"
- "shll_s.w %[temp5], %[temp5], 24 \n\t"
- "subu %[temp14], %[p], %[hstride] \n\t"
- "subu %[temp11], %[temp14], %[hstride] \n\t"
- "sra %[temp6], %[temp5], 24 \n\t"
- "sll %[temp1], %[temp6], 3 \n\t"
- "subu %[temp15], %[temp11], %[hstride] \n\t"
- "addu %[temp2], %[temp6], %[temp1] \n\t"
- "sll %[temp3], %[temp2], 1 \n\t"
- "addu %[temp4], %[temp3], %[temp2] \n\t"
- "addiu %[temp2], %[temp2], 63 \n\t"
- "addiu %[temp3], %[temp3], 63 \n\t"
- "addiu %[temp4], %[temp4], 63 \n\t"
- "sra %[temp2], %[temp2], 7 \n\t"
- "sra %[temp3], %[temp3], 7 \n\t"
- "sra %[temp4], %[temp4], 7 \n\t"
- "addu %[temp1], %[temp8], %[temp2] \n\t"
- "addu %[temp5], %[temp9], %[temp3] \n\t"
- "addu %[temp6], %[temp10], %[temp4] \n\t"
- "subu %[temp8], %[temp7], %[temp4] \n\t"
- "subu %[temp7], %[temp12], %[temp3] \n\t"
- "addu %[temp10], %[p], %[hstride] \n\t"
- "subu %[temp9], %[temp13], %[temp2] \n\t"
- "addu %[temp12], %[temp10], %[hstride] \n\t"
- "lbux %[temp2], %[temp1](%[VP8kclip1]) \n\t"
- "lbux %[temp3], %[temp5](%[VP8kclip1]) \n\t"
- "lbux %[temp4], %[temp6](%[VP8kclip1]) \n\t"
- "lbux %[temp5], %[temp8](%[VP8kclip1]) \n\t"
- "lbux %[temp6], %[temp7](%[VP8kclip1]) \n\t"
- "lbux %[temp8], %[temp9](%[VP8kclip1]) \n\t"
- "sb %[temp2], 0(%[temp15]) \n\t"
- "sb %[temp3], 0(%[temp11]) \n\t"
- "sb %[temp4], 0(%[temp14]) \n\t"
- "sb %[temp5], 0(%[p]) \n\t"
- "sb %[temp6], 0(%[temp10]) \n\t"
- "sb %[temp8], 0(%[temp12]) \n\t"
- "3: \n\t"
- "bgtz %[size], 1b \n\t"
- " addu %[p], %[p], %[vstride] \n\t"
- ".set pop \n\t"
- : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),[temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6),
- [temp7]"=&r"(temp7),[temp8]"=&r"(temp8),[temp9]"=&r"(temp9),
- [temp10]"=&r"(temp10),[temp11]"=&r"(temp11),[temp12]"=&r"(temp12),
- [temp13]"=&r"(temp13),[temp14]"=&r"(temp14),[temp15]"=&r"(temp15),
- [size]"+&r"(size), [p]"+&r"(p)
- : [hstride]"r"(hstride), [thresh2]"r"(thresh2),
- [ithresh]"r"(ithresh),[vstride]"r"(vstride), [hev_thresh]"r"(hev_thresh),
- [VP8kclip1]"r"(VP8kclip1)
- : "memory"
- );
-}
-
-static WEBP_INLINE void FilterLoop24(uint8_t* p,
- int hstride, int vstride, int size,
- int thresh, int ithresh, int hev_thresh) {
- int p0, q0, p1, q1, p2, q2, p3, q3;
- int step1, step2, temp1, temp2, temp3, temp4;
- uint8_t* pTemp0;
- uint8_t* pTemp1;
- const int thresh2 = 2 * thresh + 1;
-
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "bltz %[size], 3f \n\t"
- " nop \n\t"
- "2: \n\t"
- "negu %[step1], %[hstride] \n\t"
- "lbu %[q0], 0(%[p]) \n\t"
- "lbux %[p0], %[step1](%[p]) \n\t"
- "subu %[step1], %[step1], %[hstride] \n\t"
- "lbux %[q1], %[hstride](%[p]) \n\t"
- "subu %[temp1], %[p0], %[q0] \n\t"
- "lbux %[p1], %[step1](%[p]) \n\t"
- "addu %[step2], %[hstride], %[hstride] \n\t"
- "absq_s.w %[temp2], %[temp1] \n\t"
- "subu %[temp3], %[p1], %[q1] \n\t"
- "absq_s.w %[temp4], %[temp3] \n\t"
- "sll %[temp2], %[temp2], 2 \n\t"
- "addu %[temp2], %[temp2], %[temp4] \n\t"
- "subu %[temp4], %[temp2], %[thresh2] \n\t"
- "subu %[step1], %[step1], %[hstride] \n\t"
- "bgtz %[temp4], 0f \n\t"
- " lbux %[p2], %[step1](%[p]) \n\t"
- "subu %[step1], %[step1], %[hstride] \n\t"
- "lbux %[q2], %[step2](%[p]) \n\t"
- "lbux %[p3], %[step1](%[p]) \n\t"
- "subu %[temp4], %[p2], %[p1] \n\t"
- "addu %[step2], %[step2], %[hstride] \n\t"
- "subu %[temp2], %[p3], %[p2] \n\t"
- "absq_s.w %[temp4], %[temp4] \n\t"
- "absq_s.w %[temp2], %[temp2] \n\t"
- "lbux %[q3], %[step2](%[p]) \n\t"
- "subu %[temp4], %[temp4], %[ithresh] \n\t"
- "negu %[temp1], %[temp1] \n\t"
- "bgtz %[temp4], 0f \n\t"
- " subu %[temp2], %[temp2], %[ithresh] \n\t"
- "subu %[p3], %[p1], %[p0] \n\t"
- "bgtz %[temp2], 0f \n\t"
- " absq_s.w %[p3], %[p3] \n\t"
- "subu %[temp4], %[q3], %[q2] \n\t"
- "subu %[pTemp0], %[p], %[hstride] \n\t"
- "absq_s.w %[temp4], %[temp4] \n\t"
- "subu %[temp2], %[p3], %[ithresh] \n\t"
- "sll %[step1], %[temp1], 1 \n\t"
- "bgtz %[temp2], 0f \n\t"
- " subu %[temp4], %[temp4], %[ithresh] \n\t"
- "subu %[temp2], %[q2], %[q1] \n\t"
- "bgtz %[temp4], 0f \n\t"
- " absq_s.w %[temp2], %[temp2] \n\t"
- "subu %[q3], %[q1], %[q0] \n\t"
- "absq_s.w %[q3], %[q3] \n\t"
- "subu %[temp2], %[temp2], %[ithresh] \n\t"
- "addu %[temp1], %[temp1], %[step1] \n\t"
- "bgtz %[temp2], 0f \n\t"
- " subu %[temp4], %[q3], %[ithresh] \n\t"
- "slt %[p3], %[hev_thresh], %[p3] \n\t"
- "bgtz %[temp4], 0f \n\t"
- " slt %[q3], %[hev_thresh], %[q3] \n\t"
- "or %[q3], %[q3], %[p3] \n\t"
- "bgtz %[q3], 1f \n\t"
- " shra_r.w %[temp2], %[temp1], 3 \n\t"
- "addiu %[temp1], %[temp1], 3 \n\t"
- "sra %[temp1], %[temp1], 3 \n\t"
- "shll_s.w %[temp2], %[temp2], 27 \n\t"
- "shll_s.w %[temp1], %[temp1], 27 \n\t"
- "addu %[pTemp1], %[p], %[hstride] \n\t"
- "sra %[temp2], %[temp2], 27 \n\t"
- "sra %[temp1], %[temp1], 27 \n\t"
- "addiu %[step1], %[temp2], 1 \n\t"
- "sra %[step1], %[step1], 1 \n\t"
- "addu %[p0], %[p0], %[temp1] \n\t"
- "addu %[p1], %[p1], %[step1] \n\t"
- "subu %[q0], %[q0], %[temp2] \n\t"
- "subu %[q1], %[q1], %[step1] \n\t"
- "lbux %[temp2], %[p0](%[VP8kclip1]) \n\t"
- "lbux %[temp3], %[q0](%[VP8kclip1]) \n\t"
- "lbux %[temp4], %[q1](%[VP8kclip1]) \n\t"
- "sb %[temp2], 0(%[pTemp0]) \n\t"
- "lbux %[temp1], %[p1](%[VP8kclip1]) \n\t"
- "subu %[pTemp0], %[pTemp0], %[hstride] \n\t"
- "sb %[temp3], 0(%[p]) \n\t"
- "sb %[temp4], 0(%[pTemp1]) \n\t"
- "j 0f \n\t"
- " sb %[temp1], 0(%[pTemp0]) \n\t"
- "1: \n\t"
- "shll_s.w %[temp3], %[temp3], 24 \n\t"
- "sra %[temp3], %[temp3], 24 \n\t"
- "addu %[temp1], %[temp1], %[temp3] \n\t"
- "shra_r.w %[temp2], %[temp1], 3 \n\t"
- "addiu %[temp1], %[temp1], 3 \n\t"
- "shll_s.w %[temp2], %[temp2], 27 \n\t"
- "sra %[temp1], %[temp1], 3 \n\t"
- "shll_s.w %[temp1], %[temp1], 27 \n\t"
- "sra %[temp2], %[temp2], 27 \n\t"
- "sra %[temp1], %[temp1], 27 \n\t"
- "addu %[p0], %[p0], %[temp1] \n\t"
- "subu %[q0], %[q0], %[temp2] \n\t"
- "lbux %[temp1], %[p0](%[VP8kclip1]) \n\t"
- "lbux %[temp2], %[q0](%[VP8kclip1]) \n\t"
- "sb %[temp2], 0(%[p]) \n\t"
- "sb %[temp1], 0(%[pTemp0]) \n\t"
- "0: \n\t"
- "subu %[size], %[size], 1 \n\t"
- "bgtz %[size], 2b \n\t"
- " addu %[p], %[p], %[vstride] \n\t"
- "3: \n\t"
- ".set pop \n\t"
- : [p0]"=&r"(p0), [q0]"=&r"(q0), [p1]"=&r"(p1), [q1]"=&r"(q1),
- [p2]"=&r"(p2), [q2]"=&r"(q2), [p3]"=&r"(p3), [q3]"=&r"(q3),
- [step2]"=&r"(step2), [step1]"=&r"(step1), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
- [pTemp0]"=&r"(pTemp0), [pTemp1]"=&r"(pTemp1), [p]"+&r"(p),
- [size]"+&r"(size)
- : [vstride]"r"(vstride), [ithresh]"r"(ithresh),
- [hev_thresh]"r"(hev_thresh), [hstride]"r"(hstride),
- [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2)
- : "memory"
- );
-}
-
-// on macroblock edges
-static void VFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
-}
-
-// 8-pixels wide variant, for chroma filtering
-static void VFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
- FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
- FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
-}
-
-// on three inner edges
-static void VFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
- }
-}
-
-static void HFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
- }
-}
-
-static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
- FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
-}
-
-static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
- FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
-}
-
-#undef MUL
-
-//------------------------------------------------------------------------------
-// Simple In-loop filtering (Paragraph 15.2)
-
-static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
- int i;
- const int thresh2 = 2 * thresh + 1;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
- uint8_t* p1 = p - stride;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "li %[i], 16 \n\t"
- "0: \n\t"
- "negu %[temp4], %[stride] \n\t"
- "sll %[temp5], %[temp4], 1 \n\t"
- "lbu %[temp2], 0(%[p]) \n\t"
- "lbux %[temp3], %[stride](%[p]) \n\t"
- "lbux %[temp1], %[temp4](%[p]) \n\t"
- "lbux %[temp0], %[temp5](%[p]) \n\t"
- "subu %[temp7], %[temp1], %[temp2] \n\t"
- "subu %[temp6], %[temp0], %[temp3] \n\t"
- "absq_s.w %[temp4], %[temp7] \n\t"
- "absq_s.w %[temp5], %[temp6] \n\t"
- "sll %[temp4], %[temp4], 2 \n\t"
- "subu %[temp5], %[temp5], %[thresh2] \n\t"
- "addu %[temp5], %[temp4], %[temp5] \n\t"
- "negu %[temp8], %[temp7] \n\t"
- "bgtz %[temp5], 1f \n\t"
- " addiu %[i], %[i], -1 \n\t"
- "sll %[temp4], %[temp8], 1 \n\t"
- "shll_s.w %[temp5], %[temp6], 24 \n\t"
- "addu %[temp3], %[temp4], %[temp8] \n\t"
- "sra %[temp5], %[temp5], 24 \n\t"
- "addu %[temp3], %[temp3], %[temp5] \n\t"
- "addiu %[temp7], %[temp3], 3 \n\t"
- "sra %[temp7], %[temp7], 3 \n\t"
- "shra_r.w %[temp8], %[temp3], 3 \n\t"
- "shll_s.w %[temp0], %[temp7], 27 \n\t"
- "shll_s.w %[temp4], %[temp8], 27 \n\t"
- "sra %[temp0], %[temp0], 27 \n\t"
- "sra %[temp4], %[temp4], 27 \n\t"
- "addu %[temp7], %[temp1], %[temp0] \n\t"
- "subu %[temp2], %[temp2], %[temp4] \n\t"
- "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t"
- "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t"
- "sb %[temp3], 0(%[p1]) \n\t"
- "sb %[temp4], 0(%[p]) \n\t"
- "1: \n\t"
- "addiu %[p1], %[p1], 1 \n\t"
- "bgtz %[i], 0b \n\t"
- " addiu %[p], %[p], 1 \n\t"
- " .set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [p]"+&r"(p), [i]"=&r"(i), [p1]"+&r"(p1)
- : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2)
- : "memory"
- );
-}
-
-// TEMP0 = SRC[A + A1 * BPS]
-// TEMP1 = SRC[B + B1 * BPS]
-// TEMP2 = SRC[C + C1 * BPS]
-// TEMP3 = SRC[D + D1 * BPS]
-#define LOAD_4_BYTES(TEMP0, TEMP1, TEMP2, TEMP3, \
- A, A1, B, B1, C, C1, D, D1, SRC) \
- "lbu %[" #TEMP0 "], " #A "+" #A1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
- "lbu %[" #TEMP1 "], " #B "+" #B1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
- "lbu %[" #TEMP2 "], " #C "+" #C1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
- "lbu %[" #TEMP3 "], " #D "+" #D1 "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
-
-static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
- int i;
- const int thresh2 = 2 * thresh + 1;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "li %[i], 16 \n\t"
- "0: \n\t"
- LOAD_4_BYTES(temp0, temp1, temp2, temp3, -2, 0, -1, 0, 0, 0, 1, 0, p)
- "subu %[temp7], %[temp1], %[temp2] \n\t"
- "subu %[temp6], %[temp0], %[temp3] \n\t"
- "absq_s.w %[temp4], %[temp7] \n\t"
- "absq_s.w %[temp5], %[temp6] \n\t"
- "sll %[temp4], %[temp4], 2 \n\t"
- "addu %[temp5], %[temp4], %[temp5] \n\t"
- "subu %[temp5], %[temp5], %[thresh2] \n\t"
- "negu %[temp8], %[temp7] \n\t"
- "bgtz %[temp5], 1f \n\t"
- " addiu %[i], %[i], -1 \n\t"
- "sll %[temp4], %[temp8], 1 \n\t"
- "shll_s.w %[temp5], %[temp6], 24 \n\t"
- "addu %[temp3], %[temp4], %[temp8] \n\t"
- "sra %[temp5], %[temp5], 24 \n\t"
- "addu %[temp3], %[temp3], %[temp5] \n\t"
- "addiu %[temp7], %[temp3], 3 \n\t"
- "sra %[temp7], %[temp7], 3 \n\t"
- "shra_r.w %[temp8], %[temp3], 3 \n\t"
- "shll_s.w %[temp0], %[temp7], 27 \n\t"
- "shll_s.w %[temp4], %[temp8], 27 \n\t"
- "sra %[temp0], %[temp0], 27 \n\t"
- "sra %[temp4], %[temp4], 27 \n\t"
- "addu %[temp7], %[temp1], %[temp0] \n\t"
- "subu %[temp2], %[temp2], %[temp4] \n\t"
- "lbux %[temp3], %[temp7](%[VP8kclip1]) \n\t"
- "lbux %[temp4], %[temp2](%[VP8kclip1]) \n\t"
- "sb %[temp3], -1(%[p]) \n\t"
- "sb %[temp4], 0(%[p]) \n\t"
- "1: \n\t"
- "bgtz %[i], 0b \n\t"
- " addu %[p], %[p], %[stride] \n\t"
- ".set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [p]"+&r"(p), [i]"=&r"(i)
- : [stride]"r"(stride), [VP8kclip1]"r"(VP8kclip1), [thresh2]"r"(thresh2)
- : "memory"
- );
-}
-
-static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- SimpleVFilter16(p, stride, thresh);
- }
-}
-
-static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- SimpleHFilter16(p, stride, thresh);
- }
-}
-
-// DST[A * BPS] = TEMP0
-// DST[B + C * BPS] = TEMP1
-#define STORE_8_BYTES(TEMP0, TEMP1, A, B, C, DST) \
- "usw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #DST "]) \n\t" \
- "usw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #DST "]) \n\t"
-
-static void VE4(uint8_t* dst) { // vertical
- const uint8_t* top = dst - BPS;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
- __asm__ volatile (
- "ulw %[temp0], -1(%[top]) \n\t"
- "ulh %[temp1], 3(%[top]) \n\t"
- "preceu.ph.qbr %[temp2], %[temp0] \n\t"
- "preceu.ph.qbl %[temp3], %[temp0] \n\t"
- "preceu.ph.qbr %[temp4], %[temp1] \n\t"
- "packrl.ph %[temp5], %[temp3], %[temp2] \n\t"
- "packrl.ph %[temp6], %[temp4], %[temp3] \n\t"
- "shll.ph %[temp5], %[temp5], 1 \n\t"
- "shll.ph %[temp6], %[temp6], 1 \n\t"
- "addq.ph %[temp2], %[temp5], %[temp2] \n\t"
- "addq.ph %[temp6], %[temp6], %[temp4] \n\t"
- "addq.ph %[temp2], %[temp2], %[temp3] \n\t"
- "addq.ph %[temp6], %[temp6], %[temp3] \n\t"
- "shra_r.ph %[temp2], %[temp2], 2 \n\t"
- "shra_r.ph %[temp6], %[temp6], 2 \n\t"
- "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t"
- STORE_8_BYTES(temp4, temp4, 0, 0, 1, dst)
- STORE_8_BYTES(temp4, temp4, 2, 0, 3, dst)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void DC4(uint8_t* dst) { // DC
- int temp0, temp1, temp2, temp3, temp4;
- __asm__ volatile (
- "ulw %[temp0], -1*" XSTR(BPS) "(%[dst]) \n\t"
- LOAD_4_BYTES(temp1, temp2, temp3, temp4, -1, 0, -1, 1, -1, 2, -1, 3, dst)
- "ins %[temp1], %[temp2], 8, 8 \n\t"
- "ins %[temp1], %[temp3], 16, 8 \n\t"
- "ins %[temp1], %[temp4], 24, 8 \n\t"
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "raddu.w.qb %[temp1], %[temp1] \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "shra_r.w %[temp0], %[temp0], 3 \n\t"
- "replv.qb %[temp0], %[temp0] \n\t"
- STORE_8_BYTES(temp0, temp0, 0, 0, 1, dst)
- STORE_8_BYTES(temp0, temp0, 2, 0, 3, dst)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4)
- : [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void RD4(uint8_t* dst) { // Down-right
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8;
- __asm__ volatile (
- LOAD_4_BYTES(temp0, temp1, temp2, temp3, -1, 0, -1, 1, -1, 2, -1, 3, dst)
- "ulw %[temp7], -1-" XSTR(BPS) "(%[dst]) \n\t"
- "ins %[temp1], %[temp0], 16, 16 \n\t"
- "preceu.ph.qbr %[temp5], %[temp7] \n\t"
- "ins %[temp2], %[temp1], 16, 16 \n\t"
- "preceu.ph.qbl %[temp4], %[temp7] \n\t"
- "ins %[temp3], %[temp2], 16, 16 \n\t"
- "shll.ph %[temp2], %[temp2], 1 \n\t"
- "addq.ph %[temp3], %[temp3], %[temp1] \n\t"
- "packrl.ph %[temp6], %[temp5], %[temp1] \n\t"
- "addq.ph %[temp3], %[temp3], %[temp2] \n\t"
- "addq.ph %[temp1], %[temp1], %[temp5] \n\t"
- "shll.ph %[temp6], %[temp6], 1 \n\t"
- "addq.ph %[temp1], %[temp1], %[temp6] \n\t"
- "packrl.ph %[temp0], %[temp4], %[temp5] \n\t"
- "addq.ph %[temp8], %[temp5], %[temp4] \n\t"
- "shra_r.ph %[temp3], %[temp3], 2 \n\t"
- "shll.ph %[temp0], %[temp0], 1 \n\t"
- "shra_r.ph %[temp1], %[temp1], 2 \n\t"
- "addq.ph %[temp8], %[temp0], %[temp8] \n\t"
- "lbu %[temp5], 3-" XSTR(BPS) "(%[dst]) \n\t"
- "precrq.ph.w %[temp7], %[temp7], %[temp7] \n\t"
- "shra_r.ph %[temp8], %[temp8], 2 \n\t"
- "ins %[temp7], %[temp5], 0, 8 \n\t"
- "precr.qb.ph %[temp2], %[temp1], %[temp3] \n\t"
- "raddu.w.qb %[temp4], %[temp7] \n\t"
- "precr.qb.ph %[temp6], %[temp8], %[temp1] \n\t"
- "shra_r.w %[temp4], %[temp4], 2 \n\t"
- STORE_8_BYTES(temp2, temp6, 3, 0, 1, dst)
- "prepend %[temp2], %[temp8], 8 \n\t"
- "prepend %[temp6], %[temp4], 8 \n\t"
- STORE_8_BYTES(temp2, temp6, 2, 0, 0, dst)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
- : [dst]"r"(dst)
- : "memory"
- );
-}
-
-// TEMP0 = SRC[A * BPS]
-// TEMP1 = SRC[B + C * BPS]
-#define LOAD_8_BYTES(TEMP0, TEMP1, A, B, C, SRC) \
- "ulw %[" #TEMP0 "], " #A "*" XSTR(BPS) "(%[" #SRC "]) \n\t" \
- "ulw %[" #TEMP1 "], " #B "+" #C "*" XSTR(BPS) "(%[" #SRC "]) \n\t"
-
-static void LD4(uint8_t* dst) { // Down-Left
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8, temp9;
- __asm__ volatile (
- LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
- "preceu.ph.qbl %[temp2], %[temp0] \n\t"
- "preceu.ph.qbr %[temp3], %[temp0] \n\t"
- "preceu.ph.qbr %[temp4], %[temp1] \n\t"
- "preceu.ph.qbl %[temp5], %[temp1] \n\t"
- "packrl.ph %[temp6], %[temp2], %[temp3] \n\t"
- "packrl.ph %[temp7], %[temp4], %[temp2] \n\t"
- "packrl.ph %[temp8], %[temp5], %[temp4] \n\t"
- "shll.ph %[temp6], %[temp6], 1 \n\t"
- "addq.ph %[temp9], %[temp2], %[temp6] \n\t"
- "shll.ph %[temp7], %[temp7], 1 \n\t"
- "addq.ph %[temp9], %[temp9], %[temp3] \n\t"
- "shll.ph %[temp8], %[temp8], 1 \n\t"
- "shra_r.ph %[temp9], %[temp9], 2 \n\t"
- "addq.ph %[temp3], %[temp4], %[temp7] \n\t"
- "addq.ph %[temp0], %[temp5], %[temp8] \n\t"
- "addq.ph %[temp3], %[temp3], %[temp2] \n\t"
- "addq.ph %[temp0], %[temp0], %[temp4] \n\t"
- "shra_r.ph %[temp3], %[temp3], 2 \n\t"
- "shra_r.ph %[temp0], %[temp0], 2 \n\t"
- "srl %[temp1], %[temp1], 24 \n\t"
- "sll %[temp1], %[temp1], 1 \n\t"
- "raddu.w.qb %[temp5], %[temp5] \n\t"
- "precr.qb.ph %[temp9], %[temp3], %[temp9] \n\t"
- "precr.qb.ph %[temp3], %[temp0], %[temp3] \n\t"
- "addu %[temp1], %[temp1], %[temp5] \n\t"
- "shra_r.w %[temp1], %[temp1], 2 \n\t"
- STORE_8_BYTES(temp9, temp3, 0, 0, 2, dst)
- "prepend %[temp9], %[temp0], 8 \n\t"
- "prepend %[temp3], %[temp1], 8 \n\t"
- STORE_8_BYTES(temp9, temp3, 1, 0, 3, dst)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9)
- : [dst]"r"(dst)
- : "memory"
- );
-}
-
-//------------------------------------------------------------------------------
-// Chroma
-
-static void DC8uv(uint8_t* dst) { // DC
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8, temp9;
- __asm__ volatile (
- LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
- LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst)
- LOAD_4_BYTES(temp6, temp7, temp8, temp9, -1, 4, -1, 5, -1, 6, -1, 7, dst)
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "raddu.w.qb %[temp1], %[temp1] \n\t"
- "addu %[temp2], %[temp2], %[temp3] \n\t"
- "addu %[temp4], %[temp4], %[temp5] \n\t"
- "addu %[temp6], %[temp6], %[temp7] \n\t"
- "addu %[temp8], %[temp8], %[temp9] \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "addu %[temp2], %[temp2], %[temp4] \n\t"
- "addu %[temp6], %[temp6], %[temp8] \n\t"
- "addu %[temp0], %[temp0], %[temp2] \n\t"
- "addu %[temp0], %[temp0], %[temp6] \n\t"
- "shra_r.w %[temp0], %[temp0], 4 \n\t"
- "replv.qb %[temp0], %[temp0] \n\t"
- STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst)
- STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst)
- STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst)
- STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst)
- STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst)
- STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst)
- STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst)
- STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9)
- : [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
- int temp0, temp1;
- __asm__ volatile (
- LOAD_8_BYTES(temp0, temp1, -1, 4, -1, dst)
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "raddu.w.qb %[temp1], %[temp1] \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "shra_r.w %[temp0], %[temp0], 3 \n\t"
- "replv.qb %[temp0], %[temp0] \n\t"
- STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst)
- STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst)
- STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst)
- STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst)
- STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst)
- STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst)
- STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst)
- STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1)
- : [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8;
- __asm__ volatile (
- LOAD_4_BYTES(temp2, temp3, temp4, temp5, -1, 0, -1, 1, -1, 2, -1, 3, dst)
- LOAD_4_BYTES(temp6, temp7, temp8, temp1, -1, 4, -1, 5, -1, 6, -1, 7, dst)
- "addu %[temp2], %[temp2], %[temp3] \n\t"
- "addu %[temp4], %[temp4], %[temp5] \n\t"
- "addu %[temp6], %[temp6], %[temp7] \n\t"
- "addu %[temp8], %[temp8], %[temp1] \n\t"
- "addu %[temp2], %[temp2], %[temp4] \n\t"
- "addu %[temp6], %[temp6], %[temp8] \n\t"
- "addu %[temp0], %[temp6], %[temp2] \n\t"
- "shra_r.w %[temp0], %[temp0], 3 \n\t"
- "replv.qb %[temp0], %[temp0] \n\t"
- STORE_8_BYTES(temp0, temp0, 0, 4, 0, dst)
- STORE_8_BYTES(temp0, temp0, 1, 4, 1, dst)
- STORE_8_BYTES(temp0, temp0, 2, 4, 2, dst)
- STORE_8_BYTES(temp0, temp0, 3, 4, 3, dst)
- STORE_8_BYTES(temp0, temp0, 4, 4, 4, dst)
- STORE_8_BYTES(temp0, temp0, 5, 4, 5, dst)
- STORE_8_BYTES(temp0, temp0, 6, 4, 6, dst)
- STORE_8_BYTES(temp0, temp0, 7, 4, 7, dst)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
- : [dst]"r"(dst)
- : "memory"
- );
-}
-
-#undef LOAD_8_BYTES
-#undef STORE_8_BYTES
-#undef LOAD_4_BYTES
-
-#define CLIPPING(SIZE) \
- "preceu.ph.qbl %[temp2], %[temp0] \n\t" \
- "preceu.ph.qbr %[temp0], %[temp0] \n\t" \
-".if " #SIZE " == 8 \n\t" \
- "preceu.ph.qbl %[temp3], %[temp1] \n\t" \
- "preceu.ph.qbr %[temp1], %[temp1] \n\t" \
-".endif \n\t" \
- "addu.ph %[temp2], %[temp2], %[dst_1] \n\t" \
- "addu.ph %[temp0], %[temp0], %[dst_1] \n\t" \
-".if " #SIZE " == 8 \n\t" \
- "addu.ph %[temp3], %[temp3], %[dst_1] \n\t" \
- "addu.ph %[temp1], %[temp1], %[dst_1] \n\t" \
-".endif \n\t" \
- "shll_s.ph %[temp2], %[temp2], 7 \n\t" \
- "shll_s.ph %[temp0], %[temp0], 7 \n\t" \
-".if " #SIZE " == 8 \n\t" \
- "shll_s.ph %[temp3], %[temp3], 7 \n\t" \
- "shll_s.ph %[temp1], %[temp1], 7 \n\t" \
-".endif \n\t" \
- "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \
-".if " #SIZE " == 8 \n\t" \
- "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t" \
-".endif \n\t"
-
-
-#define CLIP_8B_TO_DST(DST, TOP, SIZE) do { \
- int dst_1 = ((int)(DST)[-1] << 16) + (DST)[-1]; \
- int temp0, temp1, temp2, temp3; \
- __asm__ volatile ( \
- ".if " #SIZE " < 8 \n\t" \
- "ulw %[temp0], 0(%[top]) \n\t" \
- "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \
- CLIPPING(4) \
- "usw %[temp0], 0(%[dst]) \n\t" \
- ".else \n\t" \
- "ulw %[temp0], 0(%[top]) \n\t" \
- "ulw %[temp1], 4(%[top]) \n\t" \
- "subu.ph %[dst_1], %[dst_1], %[top_1] \n\t" \
- CLIPPING(8) \
- "usw %[temp0], 0(%[dst]) \n\t" \
- "usw %[temp1], 4(%[dst]) \n\t" \
- ".if " #SIZE " == 16 \n\t" \
- "ulw %[temp0], 8(%[top]) \n\t" \
- "ulw %[temp1], 12(%[top]) \n\t" \
- CLIPPING(8) \
- "usw %[temp0], 8(%[dst]) \n\t" \
- "usw %[temp1], 12(%[dst]) \n\t" \
- ".endif \n\t" \
- ".endif \n\t" \
- : [dst_1]"+&r"(dst_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \
- : [top_1]"r"(top_1), [top]"r"((TOP)), [dst]"r"((DST)) \
- : "memory" \
- ); \
-} while (0)
-
-#define CLIP_TO_DST(DST, SIZE) do { \
- int y; \
- const uint8_t* top = (DST) - BPS; \
- const int top_1 = ((int)top[-1] << 16) + top[-1]; \
- for (y = 0; y < (SIZE); ++y) { \
- CLIP_8B_TO_DST((DST), top, (SIZE)); \
- (DST) += BPS; \
- } \
-} while (0)
-
-#define TRUE_MOTION(DST, SIZE) \
-static void TrueMotion##SIZE(uint8_t* (DST)) { \
- CLIP_TO_DST((DST), (SIZE)); \
-}
-
-TRUE_MOTION(dst, 4)
-TRUE_MOTION(dst, 8)
-TRUE_MOTION(dst, 16)
-
-#undef TRUE_MOTION
-#undef CLIP_TO_DST
-#undef CLIP_8B_TO_DST
-#undef CLIPPING
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8DspInitMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMIPSdspR2(void) {
- VP8TransformDC = TransformDC;
- VP8TransformAC3 = TransformAC3;
- VP8Transform = TransformTwo;
-
- VP8VFilter16 = VFilter16;
- VP8HFilter16 = HFilter16;
- VP8VFilter8 = VFilter8;
- VP8HFilter8 = HFilter8;
- VP8VFilter16i = VFilter16i;
- VP8HFilter16i = HFilter16i;
- VP8VFilter8i = VFilter8i;
- VP8HFilter8i = HFilter8i;
- VP8SimpleVFilter16 = SimpleVFilter16;
- VP8SimpleHFilter16 = SimpleHFilter16;
- VP8SimpleVFilter16i = SimpleVFilter16i;
- VP8SimpleHFilter16i = SimpleHFilter16i;
-
- VP8PredLuma4[0] = DC4;
- VP8PredLuma4[1] = TrueMotion4;
- VP8PredLuma4[2] = VE4;
- VP8PredLuma4[4] = RD4;
- VP8PredLuma4[6] = LD4;
-
- VP8PredChroma8[0] = DC8uv;
- VP8PredChroma8[1] = TrueMotion8;
- VP8PredChroma8[4] = DC8uvNoTop;
- VP8PredChroma8[5] = DC8uvNoLeft;
-
- VP8PredLuma16[1] = TrueMotion16;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(VP8DspInitMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/dec_msa.c b/drivers/webp/dsp/dec_msa.c
deleted file mode 100644
index f76055cab0..0000000000
--- a/drivers/webp/dsp/dec_msa.c
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MSA version of dsp functions
-//
-// Author(s): Prashant Patil (prashant.patil@imgtec.com)
-
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MSA)
-
-#include "./msa_macro.h"
-
-//------------------------------------------------------------------------------
-// Transforms
-
-#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) { \
- v4i32 a1_m, b1_m, c1_m, d1_m; \
- v4i32 c_tmp1_m, c_tmp2_m, d_tmp1_m, d_tmp2_m; \
- const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \
- const v4i32 sinpi8sqrt2 = __msa_fill_w(35468); \
- \
- a1_m = in0 + in2; \
- b1_m = in0 - in2; \
- c_tmp1_m = (in1 * sinpi8sqrt2) >> 16; \
- c_tmp2_m = in3 + ((in3 * cospi8sqrt2minus1) >> 16); \
- c1_m = c_tmp1_m - c_tmp2_m; \
- d_tmp1_m = in1 + ((in1 * cospi8sqrt2minus1) >> 16); \
- d_tmp2_m = (in3 * sinpi8sqrt2) >> 16; \
- d1_m = d_tmp1_m + d_tmp2_m; \
- BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \
-}
-#define MULT1(a) ((((a) * 20091) >> 16) + (a))
-#define MULT2(a) (((a) * 35468) >> 16)
-
-static void TransformOne(const int16_t* in, uint8_t* dst) {
- v8i16 input0, input1;
- v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3;
- v4i32 res0, res1, res2, res3;
- const v16i8 zero = { 0 };
- v16i8 dest0, dest1, dest2, dest3;
-
- LD_SH2(in, 8, input0, input1);
- UNPCK_SH_SW(input0, in0, in1);
- UNPCK_SH_SW(input1, in2, in3);
- IDCT_1D_W(in0, in1, in2, in3, hz0, hz1, hz2, hz3);
- TRANSPOSE4x4_SW_SW(hz0, hz1, hz2, hz3, hz0, hz1, hz2, hz3);
- IDCT_1D_W(hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3);
- SRARI_W4_SW(vt0, vt1, vt2, vt3, 3);
- TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3);
- LD_SB4(dst, BPS, dest0, dest1, dest2, dest3);
- ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3,
- res0, res1, res2, res3);
- ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3,
- res0, res1, res2, res3);
- ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3);
- CLIP_SW4_0_255(res0, res1, res2, res3);
- PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1);
- res0 = (v4i32)__msa_pckev_b((v16i8)vt0, (v16i8)vt1);
- ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS);
-}
-
-static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
- TransformOne(in, dst);
- if (do_two) {
- TransformOne(in + 16, dst + 4);
- }
-}
-
-static void TransformWHT(const int16_t* in, int16_t* out) {
- v8i16 input0, input1;
- const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 };
- const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 };
- const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 };
- const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 };
- v8i16 tmp0, tmp1, tmp2, tmp3;
- v8i16 out0, out1;
-
- LD_SH2(in, 8, input0, input1);
- input1 = SLDI_SH(input1, input1, 8);
- tmp0 = input0 + input1;
- tmp1 = input0 - input1;
- VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3);
- out0 = tmp2 + tmp3;
- out1 = tmp2 - tmp3;
- VSHF_H2_SH(out0, out1, out0, out1, mask2, mask3, input0, input1);
- tmp0 = input0 + input1;
- tmp1 = input0 - input1;
- VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3);
- tmp0 = tmp2 + tmp3;
- tmp1 = tmp2 - tmp3;
- ADDVI_H2_SH(tmp0, 3, tmp1, 3, out0, out1);
- SRAI_H2_SH(out0, out1, 3);
- out[0] = __msa_copy_s_h(out0, 0);
- out[16] = __msa_copy_s_h(out0, 4);
- out[32] = __msa_copy_s_h(out1, 0);
- out[48] = __msa_copy_s_h(out1, 4);
- out[64] = __msa_copy_s_h(out0, 1);
- out[80] = __msa_copy_s_h(out0, 5);
- out[96] = __msa_copy_s_h(out1, 1);
- out[112] = __msa_copy_s_h(out1, 5);
- out[128] = __msa_copy_s_h(out0, 2);
- out[144] = __msa_copy_s_h(out0, 6);
- out[160] = __msa_copy_s_h(out1, 2);
- out[176] = __msa_copy_s_h(out1, 6);
- out[192] = __msa_copy_s_h(out0, 3);
- out[208] = __msa_copy_s_h(out0, 7);
- out[224] = __msa_copy_s_h(out1, 3);
- out[240] = __msa_copy_s_h(out1, 7);
-}
-
-static void TransformDC(const int16_t* in, uint8_t* dst) {
- const int DC = (in[0] + 4) >> 3;
- const v8i16 tmp0 = __msa_fill_h(DC);
- ADDBLK_ST4x4_UB(tmp0, tmp0, tmp0, tmp0, dst, BPS);
-}
-
-static void TransformAC3(const int16_t* in, uint8_t* dst) {
- const int a = in[0] + 4;
- const int c4 = MULT2(in[4]);
- const int d4 = MULT1(in[4]);
- const int in2 = MULT2(in[1]);
- const int in3 = MULT1(in[1]);
- v4i32 tmp0 = { 0 };
- v4i32 out0 = __msa_fill_w(a + d4);
- v4i32 out1 = __msa_fill_w(a + c4);
- v4i32 out2 = __msa_fill_w(a - c4);
- v4i32 out3 = __msa_fill_w(a - d4);
- v4i32 res0, res1, res2, res3;
- const v4i32 zero = { 0 };
- v16u8 dest0, dest1, dest2, dest3;
-
- INSERT_W4_SW(in3, in2, -in2, -in3, tmp0);
- ADD4(out0, tmp0, out1, tmp0, out2, tmp0, out3, tmp0,
- out0, out1, out2, out3);
- SRAI_W4_SW(out0, out1, out2, out3, 3);
- LD_UB4(dst, BPS, dest0, dest1, dest2, dest3);
- ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3,
- res0, res1, res2, res3);
- ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3,
- res0, res1, res2, res3);
- ADD4(res0, out0, res1, out1, res2, out2, res3, out3, res0, res1, res2, res3);
- CLIP_SW4_0_255(res0, res1, res2, res3);
- PCKEV_B2_SW(res0, res1, res2, res3, out0, out1);
- res0 = (v4i32)__msa_pckev_b((v16i8)out0, (v16i8)out1);
- ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS);
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8DspInitMSA(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMSA(void) {
- VP8TransformWHT = TransformWHT;
- VP8Transform = TransformTwo;
- VP8TransformDC = TransformDC;
- VP8TransformAC3 = TransformAC3;
-}
-
-#else // !WEBP_USE_MSA
-
-WEBP_DSP_INIT_STUB(VP8DspInitMSA)
-
-#endif // WEBP_USE_MSA
diff --git a/drivers/webp/dsp/dec_neon.c b/drivers/webp/dsp/dec_neon.c
deleted file mode 100644
index a63f43fe17..0000000000
--- a/drivers/webp/dsp/dec_neon.c
+++ /dev/null
@@ -1,1639 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// ARM NEON version of dsp functions and loop filtering.
-//
-// Authors: Somnath Banerjee (somnath@google.com)
-// Johann Koenig (johannkoenig@google.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_NEON)
-
-#include "./neon.h"
-#include "../dec/vp8i.h"
-
-//------------------------------------------------------------------------------
-// NxM Loading functions
-
-// Load/Store vertical edge
-#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \
- "vld4.8 {" #c1 "[0]," #c2 "[0]," #c3 "[0]," #c4 "[0]}," #b1 "," #stride "\n" \
- "vld4.8 {" #c1 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \
- "vld4.8 {" #c1 "[2]," #c2 "[2]," #c3 "[2]," #c4 "[2]}," #b1 "," #stride "\n" \
- "vld4.8 {" #c1 "[3]," #c2 "[3]," #c3 "[3]," #c4 "[3]}," #b2 "," #stride "\n" \
- "vld4.8 {" #c1 "[4]," #c2 "[4]," #c3 "[4]," #c4 "[4]}," #b1 "," #stride "\n" \
- "vld4.8 {" #c1 "[5]," #c2 "[5]," #c3 "[5]," #c4 "[5]}," #b2 "," #stride "\n" \
- "vld4.8 {" #c1 "[6]," #c2 "[6]," #c3 "[6]," #c4 "[6]}," #b1 "," #stride "\n" \
- "vld4.8 {" #c1 "[7]," #c2 "[7]," #c3 "[7]," #c4 "[7]}," #b2 "," #stride "\n"
-
-#define STORE8x2(c1, c2, p, stride) \
- "vst2.8 {" #c1 "[0], " #c2 "[0]}," #p "," #stride " \n" \
- "vst2.8 {" #c1 "[1], " #c2 "[1]}," #p "," #stride " \n" \
- "vst2.8 {" #c1 "[2], " #c2 "[2]}," #p "," #stride " \n" \
- "vst2.8 {" #c1 "[3], " #c2 "[3]}," #p "," #stride " \n" \
- "vst2.8 {" #c1 "[4], " #c2 "[4]}," #p "," #stride " \n" \
- "vst2.8 {" #c1 "[5], " #c2 "[5]}," #p "," #stride " \n" \
- "vst2.8 {" #c1 "[6], " #c2 "[6]}," #p "," #stride " \n" \
- "vst2.8 {" #c1 "[7], " #c2 "[7]}," #p "," #stride " \n"
-
-#if !defined(WORK_AROUND_GCC)
-
-// This intrinsics version makes gcc-4.6.3 crash during Load4x??() compilation
-// (register alloc, probably). The variants somewhat mitigate the problem, but
-// not quite. HFilter16i() remains problematic.
-static WEBP_INLINE uint8x8x4_t Load4x8(const uint8_t* const src, int stride) {
- const uint8x8_t zero = vdup_n_u8(0);
- uint8x8x4_t out;
- INIT_VECTOR4(out, zero, zero, zero, zero);
- out = vld4_lane_u8(src + 0 * stride, out, 0);
- out = vld4_lane_u8(src + 1 * stride, out, 1);
- out = vld4_lane_u8(src + 2 * stride, out, 2);
- out = vld4_lane_u8(src + 3 * stride, out, 3);
- out = vld4_lane_u8(src + 4 * stride, out, 4);
- out = vld4_lane_u8(src + 5 * stride, out, 5);
- out = vld4_lane_u8(src + 6 * stride, out, 6);
- out = vld4_lane_u8(src + 7 * stride, out, 7);
- return out;
-}
-
-static WEBP_INLINE void Load4x16(const uint8_t* const src, int stride,
- uint8x16_t* const p1, uint8x16_t* const p0,
- uint8x16_t* const q0, uint8x16_t* const q1) {
- // row0 = p1[0..7]|p0[0..7]|q0[0..7]|q1[0..7]
- // row8 = p1[8..15]|p0[8..15]|q0[8..15]|q1[8..15]
- const uint8x8x4_t row0 = Load4x8(src - 2 + 0 * stride, stride);
- const uint8x8x4_t row8 = Load4x8(src - 2 + 8 * stride, stride);
- *p1 = vcombine_u8(row0.val[0], row8.val[0]);
- *p0 = vcombine_u8(row0.val[1], row8.val[1]);
- *q0 = vcombine_u8(row0.val[2], row8.val[2]);
- *q1 = vcombine_u8(row0.val[3], row8.val[3]);
-}
-
-#else // WORK_AROUND_GCC
-
-#define LOADQ_LANE_32b(VALUE, LANE) do { \
- (VALUE) = vld1q_lane_u32((const uint32_t*)src, (VALUE), (LANE)); \
- src += stride; \
-} while (0)
-
-static WEBP_INLINE void Load4x16(const uint8_t* src, int stride,
- uint8x16_t* const p1, uint8x16_t* const p0,
- uint8x16_t* const q0, uint8x16_t* const q1) {
- const uint32x4_t zero = vdupq_n_u32(0);
- uint32x4x4_t in;
- INIT_VECTOR4(in, zero, zero, zero, zero);
- src -= 2;
- LOADQ_LANE_32b(in.val[0], 0);
- LOADQ_LANE_32b(in.val[1], 0);
- LOADQ_LANE_32b(in.val[2], 0);
- LOADQ_LANE_32b(in.val[3], 0);
- LOADQ_LANE_32b(in.val[0], 1);
- LOADQ_LANE_32b(in.val[1], 1);
- LOADQ_LANE_32b(in.val[2], 1);
- LOADQ_LANE_32b(in.val[3], 1);
- LOADQ_LANE_32b(in.val[0], 2);
- LOADQ_LANE_32b(in.val[1], 2);
- LOADQ_LANE_32b(in.val[2], 2);
- LOADQ_LANE_32b(in.val[3], 2);
- LOADQ_LANE_32b(in.val[0], 3);
- LOADQ_LANE_32b(in.val[1], 3);
- LOADQ_LANE_32b(in.val[2], 3);
- LOADQ_LANE_32b(in.val[3], 3);
- // Transpose four 4x4 parts:
- {
- const uint8x16x2_t row01 = vtrnq_u8(vreinterpretq_u8_u32(in.val[0]),
- vreinterpretq_u8_u32(in.val[1]));
- const uint8x16x2_t row23 = vtrnq_u8(vreinterpretq_u8_u32(in.val[2]),
- vreinterpretq_u8_u32(in.val[3]));
- const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]),
- vreinterpretq_u16_u8(row23.val[0]));
- const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]),
- vreinterpretq_u16_u8(row23.val[1]));
- *p1 = vreinterpretq_u8_u16(row02.val[0]);
- *p0 = vreinterpretq_u8_u16(row13.val[0]);
- *q0 = vreinterpretq_u8_u16(row02.val[1]);
- *q1 = vreinterpretq_u8_u16(row13.val[1]);
- }
-}
-#undef LOADQ_LANE_32b
-
-#endif // !WORK_AROUND_GCC
-
-static WEBP_INLINE void Load8x16(const uint8_t* const src, int stride,
- uint8x16_t* const p3, uint8x16_t* const p2,
- uint8x16_t* const p1, uint8x16_t* const p0,
- uint8x16_t* const q0, uint8x16_t* const q1,
- uint8x16_t* const q2, uint8x16_t* const q3) {
- Load4x16(src - 2, stride, p3, p2, p1, p0);
- Load4x16(src + 2, stride, q0, q1, q2, q3);
-}
-
-static WEBP_INLINE void Load16x4(const uint8_t* const src, int stride,
- uint8x16_t* const p1, uint8x16_t* const p0,
- uint8x16_t* const q0, uint8x16_t* const q1) {
- *p1 = vld1q_u8(src - 2 * stride);
- *p0 = vld1q_u8(src - 1 * stride);
- *q0 = vld1q_u8(src + 0 * stride);
- *q1 = vld1q_u8(src + 1 * stride);
-}
-
-static WEBP_INLINE void Load16x8(const uint8_t* const src, int stride,
- uint8x16_t* const p3, uint8x16_t* const p2,
- uint8x16_t* const p1, uint8x16_t* const p0,
- uint8x16_t* const q0, uint8x16_t* const q1,
- uint8x16_t* const q2, uint8x16_t* const q3) {
- Load16x4(src - 2 * stride, stride, p3, p2, p1, p0);
- Load16x4(src + 2 * stride, stride, q0, q1, q2, q3);
-}
-
-static WEBP_INLINE void Load8x8x2(const uint8_t* const u,
- const uint8_t* const v,
- int stride,
- uint8x16_t* const p3, uint8x16_t* const p2,
- uint8x16_t* const p1, uint8x16_t* const p0,
- uint8x16_t* const q0, uint8x16_t* const q1,
- uint8x16_t* const q2, uint8x16_t* const q3) {
- // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination
- // and the v-samples on the higher half.
- *p3 = vcombine_u8(vld1_u8(u - 4 * stride), vld1_u8(v - 4 * stride));
- *p2 = vcombine_u8(vld1_u8(u - 3 * stride), vld1_u8(v - 3 * stride));
- *p1 = vcombine_u8(vld1_u8(u - 2 * stride), vld1_u8(v - 2 * stride));
- *p0 = vcombine_u8(vld1_u8(u - 1 * stride), vld1_u8(v - 1 * stride));
- *q0 = vcombine_u8(vld1_u8(u + 0 * stride), vld1_u8(v + 0 * stride));
- *q1 = vcombine_u8(vld1_u8(u + 1 * stride), vld1_u8(v + 1 * stride));
- *q2 = vcombine_u8(vld1_u8(u + 2 * stride), vld1_u8(v + 2 * stride));
- *q3 = vcombine_u8(vld1_u8(u + 3 * stride), vld1_u8(v + 3 * stride));
-}
-
-#if !defined(WORK_AROUND_GCC)
-
-#define LOAD_UV_8(ROW) \
- vcombine_u8(vld1_u8(u - 4 + (ROW) * stride), vld1_u8(v - 4 + (ROW) * stride))
-
-static WEBP_INLINE void Load8x8x2T(const uint8_t* const u,
- const uint8_t* const v,
- int stride,
- uint8x16_t* const p3, uint8x16_t* const p2,
- uint8x16_t* const p1, uint8x16_t* const p0,
- uint8x16_t* const q0, uint8x16_t* const q1,
- uint8x16_t* const q2, uint8x16_t* const q3) {
- // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination
- // and the v-samples on the higher half.
- const uint8x16_t row0 = LOAD_UV_8(0);
- const uint8x16_t row1 = LOAD_UV_8(1);
- const uint8x16_t row2 = LOAD_UV_8(2);
- const uint8x16_t row3 = LOAD_UV_8(3);
- const uint8x16_t row4 = LOAD_UV_8(4);
- const uint8x16_t row5 = LOAD_UV_8(5);
- const uint8x16_t row6 = LOAD_UV_8(6);
- const uint8x16_t row7 = LOAD_UV_8(7);
- // Perform two side-by-side 8x8 transposes
- // u00 u01 u02 u03 u04 u05 u06 u07 | v00 v01 v02 v03 v04 v05 v06 v07
- // u10 u11 u12 u13 u14 u15 u16 u17 | v10 v11 v12 ...
- // u20 u21 u22 u23 u24 u25 u26 u27 | v20 v21 ...
- // u30 u31 u32 u33 u34 u35 u36 u37 | ...
- // u40 u41 u42 u43 u44 u45 u46 u47 | ...
- // u50 u51 u52 u53 u54 u55 u56 u57 | ...
- // u60 u61 u62 u63 u64 u65 u66 u67 | v60 ...
- // u70 u71 u72 u73 u74 u75 u76 u77 | v70 v71 v72 ...
- const uint8x16x2_t row01 = vtrnq_u8(row0, row1); // u00 u10 u02 u12 ...
- // u01 u11 u03 u13 ...
- const uint8x16x2_t row23 = vtrnq_u8(row2, row3); // u20 u30 u22 u32 ...
- // u21 u31 u23 u33 ...
- const uint8x16x2_t row45 = vtrnq_u8(row4, row5); // ...
- const uint8x16x2_t row67 = vtrnq_u8(row6, row7); // ...
- const uint16x8x2_t row02 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[0]),
- vreinterpretq_u16_u8(row23.val[0]));
- const uint16x8x2_t row13 = vtrnq_u16(vreinterpretq_u16_u8(row01.val[1]),
- vreinterpretq_u16_u8(row23.val[1]));
- const uint16x8x2_t row46 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[0]),
- vreinterpretq_u16_u8(row67.val[0]));
- const uint16x8x2_t row57 = vtrnq_u16(vreinterpretq_u16_u8(row45.val[1]),
- vreinterpretq_u16_u8(row67.val[1]));
- const uint32x4x2_t row04 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[0]),
- vreinterpretq_u32_u16(row46.val[0]));
- const uint32x4x2_t row26 = vtrnq_u32(vreinterpretq_u32_u16(row02.val[1]),
- vreinterpretq_u32_u16(row46.val[1]));
- const uint32x4x2_t row15 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[0]),
- vreinterpretq_u32_u16(row57.val[0]));
- const uint32x4x2_t row37 = vtrnq_u32(vreinterpretq_u32_u16(row13.val[1]),
- vreinterpretq_u32_u16(row57.val[1]));
- *p3 = vreinterpretq_u8_u32(row04.val[0]);
- *p2 = vreinterpretq_u8_u32(row15.val[0]);
- *p1 = vreinterpretq_u8_u32(row26.val[0]);
- *p0 = vreinterpretq_u8_u32(row37.val[0]);
- *q0 = vreinterpretq_u8_u32(row04.val[1]);
- *q1 = vreinterpretq_u8_u32(row15.val[1]);
- *q2 = vreinterpretq_u8_u32(row26.val[1]);
- *q3 = vreinterpretq_u8_u32(row37.val[1]);
-}
-#undef LOAD_UV_8
-
-#endif // !WORK_AROUND_GCC
-
-static WEBP_INLINE void Store2x8(const uint8x8x2_t v,
- uint8_t* const dst, int stride) {
- vst2_lane_u8(dst + 0 * stride, v, 0);
- vst2_lane_u8(dst + 1 * stride, v, 1);
- vst2_lane_u8(dst + 2 * stride, v, 2);
- vst2_lane_u8(dst + 3 * stride, v, 3);
- vst2_lane_u8(dst + 4 * stride, v, 4);
- vst2_lane_u8(dst + 5 * stride, v, 5);
- vst2_lane_u8(dst + 6 * stride, v, 6);
- vst2_lane_u8(dst + 7 * stride, v, 7);
-}
-
-static WEBP_INLINE void Store2x16(const uint8x16_t p0, const uint8x16_t q0,
- uint8_t* const dst, int stride) {
- uint8x8x2_t lo, hi;
- lo.val[0] = vget_low_u8(p0);
- lo.val[1] = vget_low_u8(q0);
- hi.val[0] = vget_high_u8(p0);
- hi.val[1] = vget_high_u8(q0);
- Store2x8(lo, dst - 1 + 0 * stride, stride);
- Store2x8(hi, dst - 1 + 8 * stride, stride);
-}
-
-#if !defined(WORK_AROUND_GCC)
-static WEBP_INLINE void Store4x8(const uint8x8x4_t v,
- uint8_t* const dst, int stride) {
- vst4_lane_u8(dst + 0 * stride, v, 0);
- vst4_lane_u8(dst + 1 * stride, v, 1);
- vst4_lane_u8(dst + 2 * stride, v, 2);
- vst4_lane_u8(dst + 3 * stride, v, 3);
- vst4_lane_u8(dst + 4 * stride, v, 4);
- vst4_lane_u8(dst + 5 * stride, v, 5);
- vst4_lane_u8(dst + 6 * stride, v, 6);
- vst4_lane_u8(dst + 7 * stride, v, 7);
-}
-
-static WEBP_INLINE void Store4x16(const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- uint8_t* const dst, int stride) {
- uint8x8x4_t lo, hi;
- INIT_VECTOR4(lo,
- vget_low_u8(p1), vget_low_u8(p0),
- vget_low_u8(q0), vget_low_u8(q1));
- INIT_VECTOR4(hi,
- vget_high_u8(p1), vget_high_u8(p0),
- vget_high_u8(q0), vget_high_u8(q1));
- Store4x8(lo, dst - 2 + 0 * stride, stride);
- Store4x8(hi, dst - 2 + 8 * stride, stride);
-}
-#endif // !WORK_AROUND_GCC
-
-static WEBP_INLINE void Store16x2(const uint8x16_t p0, const uint8x16_t q0,
- uint8_t* const dst, int stride) {
- vst1q_u8(dst - stride, p0);
- vst1q_u8(dst, q0);
-}
-
-static WEBP_INLINE void Store16x4(const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- uint8_t* const dst, int stride) {
- Store16x2(p1, p0, dst - stride, stride);
- Store16x2(q0, q1, dst + stride, stride);
-}
-
-static WEBP_INLINE void Store8x2x2(const uint8x16_t p0, const uint8x16_t q0,
- uint8_t* const u, uint8_t* const v,
- int stride) {
- // p0 and q0 contain the u+v samples packed in low/high halves.
- vst1_u8(u - stride, vget_low_u8(p0));
- vst1_u8(u, vget_low_u8(q0));
- vst1_u8(v - stride, vget_high_u8(p0));
- vst1_u8(v, vget_high_u8(q0));
-}
-
-static WEBP_INLINE void Store8x4x2(const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- uint8_t* const u, uint8_t* const v,
- int stride) {
- // The p1...q1 registers contain the u+v samples packed in low/high halves.
- Store8x2x2(p1, p0, u - stride, v - stride, stride);
- Store8x2x2(q0, q1, u + stride, v + stride, stride);
-}
-
-#if !defined(WORK_AROUND_GCC)
-
-#define STORE6_LANE(DST, VAL0, VAL1, LANE) do { \
- vst3_lane_u8((DST) - 3, (VAL0), (LANE)); \
- vst3_lane_u8((DST) + 0, (VAL1), (LANE)); \
- (DST) += stride; \
-} while (0)
-
-static WEBP_INLINE void Store6x8x2(const uint8x16_t p2, const uint8x16_t p1,
- const uint8x16_t p0, const uint8x16_t q0,
- const uint8x16_t q1, const uint8x16_t q2,
- uint8_t* u, uint8_t* v,
- int stride) {
- uint8x8x3_t u0, u1, v0, v1;
- INIT_VECTOR3(u0, vget_low_u8(p2), vget_low_u8(p1), vget_low_u8(p0));
- INIT_VECTOR3(u1, vget_low_u8(q0), vget_low_u8(q1), vget_low_u8(q2));
- INIT_VECTOR3(v0, vget_high_u8(p2), vget_high_u8(p1), vget_high_u8(p0));
- INIT_VECTOR3(v1, vget_high_u8(q0), vget_high_u8(q1), vget_high_u8(q2));
- STORE6_LANE(u, u0, u1, 0);
- STORE6_LANE(u, u0, u1, 1);
- STORE6_LANE(u, u0, u1, 2);
- STORE6_LANE(u, u0, u1, 3);
- STORE6_LANE(u, u0, u1, 4);
- STORE6_LANE(u, u0, u1, 5);
- STORE6_LANE(u, u0, u1, 6);
- STORE6_LANE(u, u0, u1, 7);
- STORE6_LANE(v, v0, v1, 0);
- STORE6_LANE(v, v0, v1, 1);
- STORE6_LANE(v, v0, v1, 2);
- STORE6_LANE(v, v0, v1, 3);
- STORE6_LANE(v, v0, v1, 4);
- STORE6_LANE(v, v0, v1, 5);
- STORE6_LANE(v, v0, v1, 6);
- STORE6_LANE(v, v0, v1, 7);
-}
-#undef STORE6_LANE
-
-static WEBP_INLINE void Store4x8x2(const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- uint8_t* const u, uint8_t* const v,
- int stride) {
- uint8x8x4_t u0, v0;
- INIT_VECTOR4(u0,
- vget_low_u8(p1), vget_low_u8(p0),
- vget_low_u8(q0), vget_low_u8(q1));
- INIT_VECTOR4(v0,
- vget_high_u8(p1), vget_high_u8(p0),
- vget_high_u8(q0), vget_high_u8(q1));
- vst4_lane_u8(u - 2 + 0 * stride, u0, 0);
- vst4_lane_u8(u - 2 + 1 * stride, u0, 1);
- vst4_lane_u8(u - 2 + 2 * stride, u0, 2);
- vst4_lane_u8(u - 2 + 3 * stride, u0, 3);
- vst4_lane_u8(u - 2 + 4 * stride, u0, 4);
- vst4_lane_u8(u - 2 + 5 * stride, u0, 5);
- vst4_lane_u8(u - 2 + 6 * stride, u0, 6);
- vst4_lane_u8(u - 2 + 7 * stride, u0, 7);
- vst4_lane_u8(v - 2 + 0 * stride, v0, 0);
- vst4_lane_u8(v - 2 + 1 * stride, v0, 1);
- vst4_lane_u8(v - 2 + 2 * stride, v0, 2);
- vst4_lane_u8(v - 2 + 3 * stride, v0, 3);
- vst4_lane_u8(v - 2 + 4 * stride, v0, 4);
- vst4_lane_u8(v - 2 + 5 * stride, v0, 5);
- vst4_lane_u8(v - 2 + 6 * stride, v0, 6);
- vst4_lane_u8(v - 2 + 7 * stride, v0, 7);
-}
-
-#endif // !WORK_AROUND_GCC
-
-// Zero extend 'v' to an int16x8_t.
-static WEBP_INLINE int16x8_t ConvertU8ToS16(uint8x8_t v) {
- return vreinterpretq_s16_u16(vmovl_u8(v));
-}
-
-// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result
-// to the corresponding rows of 'dst'.
-static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst,
- const int16x8_t dst01,
- const int16x8_t dst23) {
- // Unsigned saturate to 8b.
- const uint8x8_t dst01_u8 = vqmovun_s16(dst01);
- const uint8x8_t dst23_u8 = vqmovun_s16(dst23);
-
- // Store the results.
- vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0);
- vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1);
- vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0);
- vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1);
-}
-
-static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23,
- uint8_t* const dst) {
- uint32x2_t dst01 = vdup_n_u32(0);
- uint32x2_t dst23 = vdup_n_u32(0);
-
- // Load the source pixels.
- dst01 = vld1_lane_u32((uint32_t*)(dst + 0 * BPS), dst01, 0);
- dst23 = vld1_lane_u32((uint32_t*)(dst + 2 * BPS), dst23, 0);
- dst01 = vld1_lane_u32((uint32_t*)(dst + 1 * BPS), dst01, 1);
- dst23 = vld1_lane_u32((uint32_t*)(dst + 3 * BPS), dst23, 1);
-
- {
- // Convert to 16b.
- const int16x8_t dst01_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst01));
- const int16x8_t dst23_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst23));
-
- // Descale with rounding.
- const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3);
- const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3);
- // Add the inverse transform.
- SaturateAndStore4x4(dst, out01, out23);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Simple In-loop filtering (Paragraph 15.2)
-
-static uint8x16_t NeedsFilter(const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- int thresh) {
- const uint8x16_t thresh_v = vdupq_n_u8((uint8_t)thresh);
- const uint8x16_t a_p0_q0 = vabdq_u8(p0, q0); // abs(p0-q0)
- const uint8x16_t a_p1_q1 = vabdq_u8(p1, q1); // abs(p1-q1)
- const uint8x16_t a_p0_q0_2 = vqaddq_u8(a_p0_q0, a_p0_q0); // 2 * abs(p0-q0)
- const uint8x16_t a_p1_q1_2 = vshrq_n_u8(a_p1_q1, 1); // abs(p1-q1) / 2
- const uint8x16_t sum = vqaddq_u8(a_p0_q0_2, a_p1_q1_2);
- const uint8x16_t mask = vcgeq_u8(thresh_v, sum);
- return mask;
-}
-
-static int8x16_t FlipSign(const uint8x16_t v) {
- const uint8x16_t sign_bit = vdupq_n_u8(0x80);
- return vreinterpretq_s8_u8(veorq_u8(v, sign_bit));
-}
-
-static uint8x16_t FlipSignBack(const int8x16_t v) {
- const int8x16_t sign_bit = vdupq_n_s8(0x80);
- return vreinterpretq_u8_s8(veorq_s8(v, sign_bit));
-}
-
-static int8x16_t GetBaseDelta(const int8x16_t p1, const int8x16_t p0,
- const int8x16_t q0, const int8x16_t q1) {
- const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0)
- const int8x16_t p1_q1 = vqsubq_s8(p1, q1); // (p1-q1)
- const int8x16_t s1 = vqaddq_s8(p1_q1, q0_p0); // (p1-q1) + 1 * (q0 - p0)
- const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // (p1-q1) + 2 * (q0 - p0)
- const int8x16_t s3 = vqaddq_s8(q0_p0, s2); // (p1-q1) + 3 * (q0 - p0)
- return s3;
-}
-
-static int8x16_t GetBaseDelta0(const int8x16_t p0, const int8x16_t q0) {
- const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0)
- const int8x16_t s1 = vqaddq_s8(q0_p0, q0_p0); // 2 * (q0 - p0)
- const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // 3 * (q0 - p0)
- return s2;
-}
-
-//------------------------------------------------------------------------------
-
-static void ApplyFilter2NoFlip(const int8x16_t p0s, const int8x16_t q0s,
- const int8x16_t delta,
- int8x16_t* const op0, int8x16_t* const oq0) {
- const int8x16_t kCst3 = vdupq_n_s8(0x03);
- const int8x16_t kCst4 = vdupq_n_s8(0x04);
- const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3);
- const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4);
- const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3);
- const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3);
- *op0 = vqaddq_s8(p0s, delta3);
- *oq0 = vqsubq_s8(q0s, delta4);
-}
-
-#if defined(WEBP_USE_INTRINSICS)
-
-static void ApplyFilter2(const int8x16_t p0s, const int8x16_t q0s,
- const int8x16_t delta,
- uint8x16_t* const op0, uint8x16_t* const oq0) {
- const int8x16_t kCst3 = vdupq_n_s8(0x03);
- const int8x16_t kCst4 = vdupq_n_s8(0x04);
- const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3);
- const int8x16_t delta_p4 = vqaddq_s8(delta, kCst4);
- const int8x16_t delta3 = vshrq_n_s8(delta_p3, 3);
- const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3);
- const int8x16_t sp0 = vqaddq_s8(p0s, delta3);
- const int8x16_t sq0 = vqsubq_s8(q0s, delta4);
- *op0 = FlipSignBack(sp0);
- *oq0 = FlipSignBack(sq0);
-}
-
-static void DoFilter2(const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- const uint8x16_t mask,
- uint8x16_t* const op0, uint8x16_t* const oq0) {
- const int8x16_t p1s = FlipSign(p1);
- const int8x16_t p0s = FlipSign(p0);
- const int8x16_t q0s = FlipSign(q0);
- const int8x16_t q1s = FlipSign(q1);
- const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s);
- const int8x16_t delta1 = vandq_s8(delta0, vreinterpretq_s8_u8(mask));
- ApplyFilter2(p0s, q0s, delta1, op0, oq0);
-}
-
-static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
- uint8x16_t p1, p0, q0, q1, op0, oq0;
- Load16x4(p, stride, &p1, &p0, &q0, &q1);
- {
- const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh);
- DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0);
- }
- Store16x2(op0, oq0, p, stride);
-}
-
-static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
- uint8x16_t p1, p0, q0, q1, oq0, op0;
- Load4x16(p, stride, &p1, &p0, &q0, &q1);
- {
- const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh);
- DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0);
- }
- Store2x16(op0, oq0, p, stride);
-}
-
-#else
-
-#define QRegs "q0", "q1", "q2", "q3", \
- "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
-
-#define FLIP_SIGN_BIT2(a, b, s) \
- "veor " #a "," #a "," #s " \n" \
- "veor " #b "," #b "," #s " \n" \
-
-#define FLIP_SIGN_BIT4(a, b, c, d, s) \
- FLIP_SIGN_BIT2(a, b, s) \
- FLIP_SIGN_BIT2(c, d, s) \
-
-#define NEEDS_FILTER(p1, p0, q0, q1, thresh, mask) \
- "vabd.u8 q15," #p0 "," #q0 " \n" /* abs(p0 - q0) */ \
- "vabd.u8 q14," #p1 "," #q1 " \n" /* abs(p1 - q1) */ \
- "vqadd.u8 q15, q15, q15 \n" /* abs(p0 - q0) * 2 */ \
- "vshr.u8 q14, q14, #1 \n" /* abs(p1 - q1) / 2 */ \
- "vqadd.u8 q15, q15, q14 \n" /* abs(p0 - q0) * 2 + abs(p1 - q1) / 2 */ \
- "vdup.8 q14, " #thresh " \n" \
- "vcge.u8 " #mask ", q14, q15 \n" /* mask <= thresh */
-
-#define GET_BASE_DELTA(p1, p0, q0, q1, o) \
- "vqsub.s8 q15," #q0 "," #p0 " \n" /* (q0 - p0) */ \
- "vqsub.s8 " #o "," #p1 "," #q1 " \n" /* (p1 - q1) */ \
- "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 1 * (p0 - q0) */ \
- "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 2 * (p0 - q0) */ \
- "vqadd.s8 " #o "," #o ", q15 \n" /* (p1 - q1) + 3 * (p0 - q0) */
-
-#define DO_SIMPLE_FILTER(p0, q0, fl) \
- "vmov.i8 q15, #0x03 \n" \
- "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 3 */ \
- "vshr.s8 q15, q15, #3 \n" /* filter1 >> 3 */ \
- "vqadd.s8 " #p0 "," #p0 ", q15 \n" /* p0 += filter1 */ \
- \
- "vmov.i8 q15, #0x04 \n" \
- "vqadd.s8 q15, q15, " #fl " \n" /* filter1 = filter + 4 */ \
- "vshr.s8 q15, q15, #3 \n" /* filter2 >> 3 */ \
- "vqsub.s8 " #q0 "," #q0 ", q15 \n" /* q0 -= filter2 */
-
-// Applies filter on 2 pixels (p0 and q0)
-#define DO_FILTER2(p1, p0, q0, q1, thresh) \
- NEEDS_FILTER(p1, p0, q0, q1, thresh, q9) /* filter mask in q9 */ \
- "vmov.i8 q10, #0x80 \n" /* sign bit */ \
- FLIP_SIGN_BIT4(p1, p0, q0, q1, q10) /* convert to signed value */ \
- GET_BASE_DELTA(p1, p0, q0, q1, q11) /* get filter level */ \
- "vand q9, q9, q11 \n" /* apply filter mask */ \
- DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \
- FLIP_SIGN_BIT2(p0, q0, q10)
-
-static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
- __asm__ volatile (
- "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
-
- "vld1.u8 {q1}, [%[p]], %[stride] \n" // p1
- "vld1.u8 {q2}, [%[p]], %[stride] \n" // p0
- "vld1.u8 {q3}, [%[p]], %[stride] \n" // q0
- "vld1.u8 {q12}, [%[p]] \n" // q1
-
- DO_FILTER2(q1, q2, q3, q12, %[thresh])
-
- "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride
-
- "vst1.u8 {q2}, [%[p]], %[stride] \n" // store op0
- "vst1.u8 {q3}, [%[p]] \n" // store oq0
- : [p] "+r"(p)
- : [stride] "r"(stride), [thresh] "r"(thresh)
- : "memory", QRegs
- );
-}
-
-static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
- __asm__ volatile (
- "sub r4, %[p], #2 \n" // base1 = p - 2
- "lsl r6, %[stride], #1 \n" // r6 = 2 * stride
- "add r5, r4, %[stride] \n" // base2 = base1 + stride
-
- LOAD8x4(d2, d3, d4, d5, [r4], [r5], r6)
- LOAD8x4(d24, d25, d26, d27, [r4], [r5], r6)
- "vswp d3, d24 \n" // p1:q1 p0:q3
- "vswp d5, d26 \n" // q0:q2 q1:q4
- "vswp q2, q12 \n" // p1:q1 p0:q2 q0:q3 q1:q4
-
- DO_FILTER2(q1, q2, q12, q13, %[thresh])
-
- "sub %[p], %[p], #1 \n" // p - 1
-
- "vswp d5, d24 \n"
- STORE8x2(d4, d5, [%[p]], %[stride])
- STORE8x2(d24, d25, [%[p]], %[stride])
-
- : [p] "+r"(p)
- : [stride] "r"(stride), [thresh] "r"(thresh)
- : "memory", "r4", "r5", "r6", QRegs
- );
-}
-
-#endif // WEBP_USE_INTRINSICS
-
-static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
- uint32_t k;
- for (k = 3; k != 0; --k) {
- p += 4 * stride;
- SimpleVFilter16(p, stride, thresh);
- }
-}
-
-static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
- uint32_t k;
- for (k = 3; k != 0; --k) {
- p += 4;
- SimpleHFilter16(p, stride, thresh);
- }
-}
-
-//------------------------------------------------------------------------------
-// Complex In-loop filtering (Paragraph 15.3)
-
-static uint8x16_t NeedsHev(const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- int hev_thresh) {
- const uint8x16_t hev_thresh_v = vdupq_n_u8((uint8_t)hev_thresh);
- const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0)
- const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0)
- const uint8x16_t mask1 = vcgtq_u8(a_p1_p0, hev_thresh_v);
- const uint8x16_t mask2 = vcgtq_u8(a_q1_q0, hev_thresh_v);
- const uint8x16_t mask = vorrq_u8(mask1, mask2);
- return mask;
-}
-
-static uint8x16_t NeedsFilter2(const uint8x16_t p3, const uint8x16_t p2,
- const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- const uint8x16_t q2, const uint8x16_t q3,
- int ithresh, int thresh) {
- const uint8x16_t ithresh_v = vdupq_n_u8((uint8_t)ithresh);
- const uint8x16_t a_p3_p2 = vabdq_u8(p3, p2); // abs(p3 - p2)
- const uint8x16_t a_p2_p1 = vabdq_u8(p2, p1); // abs(p2 - p1)
- const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0)
- const uint8x16_t a_q3_q2 = vabdq_u8(q3, q2); // abs(q3 - q2)
- const uint8x16_t a_q2_q1 = vabdq_u8(q2, q1); // abs(q2 - q1)
- const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0)
- const uint8x16_t max1 = vmaxq_u8(a_p3_p2, a_p2_p1);
- const uint8x16_t max2 = vmaxq_u8(a_p1_p0, a_q3_q2);
- const uint8x16_t max3 = vmaxq_u8(a_q2_q1, a_q1_q0);
- const uint8x16_t max12 = vmaxq_u8(max1, max2);
- const uint8x16_t max123 = vmaxq_u8(max12, max3);
- const uint8x16_t mask2 = vcgeq_u8(ithresh_v, max123);
- const uint8x16_t mask1 = NeedsFilter(p1, p0, q0, q1, thresh);
- const uint8x16_t mask = vandq_u8(mask1, mask2);
- return mask;
-}
-
-// 4-points filter
-
-static void ApplyFilter4(
- const int8x16_t p1, const int8x16_t p0,
- const int8x16_t q0, const int8x16_t q1,
- const int8x16_t delta0,
- uint8x16_t* const op1, uint8x16_t* const op0,
- uint8x16_t* const oq0, uint8x16_t* const oq1) {
- const int8x16_t kCst3 = vdupq_n_s8(0x03);
- const int8x16_t kCst4 = vdupq_n_s8(0x04);
- const int8x16_t delta1 = vqaddq_s8(delta0, kCst4);
- const int8x16_t delta2 = vqaddq_s8(delta0, kCst3);
- const int8x16_t a1 = vshrq_n_s8(delta1, 3);
- const int8x16_t a2 = vshrq_n_s8(delta2, 3);
- const int8x16_t a3 = vrshrq_n_s8(a1, 1); // a3 = (a1 + 1) >> 1
- *op0 = FlipSignBack(vqaddq_s8(p0, a2)); // clip(p0 + a2)
- *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - a1)
- *op1 = FlipSignBack(vqaddq_s8(p1, a3)); // clip(p1 + a3)
- *oq1 = FlipSignBack(vqsubq_s8(q1, a3)); // clip(q1 - a3)
-}
-
-static void DoFilter4(
- const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1,
- const uint8x16_t mask, const uint8x16_t hev_mask,
- uint8x16_t* const op1, uint8x16_t* const op0,
- uint8x16_t* const oq0, uint8x16_t* const oq1) {
- // This is a fused version of DoFilter2() calling ApplyFilter2 directly
- const int8x16_t p1s = FlipSign(p1);
- int8x16_t p0s = FlipSign(p0);
- int8x16_t q0s = FlipSign(q0);
- const int8x16_t q1s = FlipSign(q1);
- const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask);
-
- // do_filter2 part (simple loopfilter on pixels with hev)
- {
- const int8x16_t delta = GetBaseDelta(p1s, p0s, q0s, q1s);
- const int8x16_t simple_lf_delta =
- vandq_s8(delta, vreinterpretq_s8_u8(simple_lf_mask));
- ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s);
- }
-
- // do_filter4 part (complex loopfilter on pixels without hev)
- {
- const int8x16_t delta0 = GetBaseDelta0(p0s, q0s);
- // we use: (mask & hev_mask) ^ mask = mask & !hev_mask
- const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask);
- const int8x16_t complex_lf_delta =
- vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask));
- ApplyFilter4(p1s, p0s, q0s, q1s, complex_lf_delta, op1, op0, oq0, oq1);
- }
-}
-
-// 6-points filter
-
-static void ApplyFilter6(
- const int8x16_t p2, const int8x16_t p1, const int8x16_t p0,
- const int8x16_t q0, const int8x16_t q1, const int8x16_t q2,
- const int8x16_t delta,
- uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0,
- uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) {
- const int16x8_t kCst63 = vdupq_n_s16(63);
- const int8x8_t kCst27 = vdup_n_s8(27);
- const int8x8_t kCst18 = vdup_n_s8(18);
- const int8x8_t kCst9 = vdup_n_s8(9);
- const int8x8_t delta_lo = vget_low_s8(delta);
- const int8x8_t delta_hi = vget_high_s8(delta);
- const int16x8_t s1_lo = vmlal_s8(kCst63, kCst27, delta_lo); // 63 + 27 * a
- const int16x8_t s1_hi = vmlal_s8(kCst63, kCst27, delta_hi); // 63 + 27 * a
- const int16x8_t s2_lo = vmlal_s8(kCst63, kCst18, delta_lo); // 63 + 18 * a
- const int16x8_t s2_hi = vmlal_s8(kCst63, kCst18, delta_hi); // 63 + 18 * a
- const int16x8_t s3_lo = vmlal_s8(kCst63, kCst9, delta_lo); // 63 + 9 * a
- const int16x8_t s3_hi = vmlal_s8(kCst63, kCst9, delta_hi); // 63 + 9 * a
- const int8x8_t a1_lo = vqshrn_n_s16(s1_lo, 7);
- const int8x8_t a1_hi = vqshrn_n_s16(s1_hi, 7);
- const int8x8_t a2_lo = vqshrn_n_s16(s2_lo, 7);
- const int8x8_t a2_hi = vqshrn_n_s16(s2_hi, 7);
- const int8x8_t a3_lo = vqshrn_n_s16(s3_lo, 7);
- const int8x8_t a3_hi = vqshrn_n_s16(s3_hi, 7);
- const int8x16_t a1 = vcombine_s8(a1_lo, a1_hi);
- const int8x16_t a2 = vcombine_s8(a2_lo, a2_hi);
- const int8x16_t a3 = vcombine_s8(a3_lo, a3_hi);
-
- *op0 = FlipSignBack(vqaddq_s8(p0, a1)); // clip(p0 + a1)
- *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - q1)
- *oq1 = FlipSignBack(vqsubq_s8(q1, a2)); // clip(q1 - a2)
- *op1 = FlipSignBack(vqaddq_s8(p1, a2)); // clip(p1 + a2)
- *oq2 = FlipSignBack(vqsubq_s8(q2, a3)); // clip(q2 - a3)
- *op2 = FlipSignBack(vqaddq_s8(p2, a3)); // clip(p2 + a3)
-}
-
-static void DoFilter6(
- const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0,
- const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2,
- const uint8x16_t mask, const uint8x16_t hev_mask,
- uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0,
- uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) {
- // This is a fused version of DoFilter2() calling ApplyFilter2 directly
- const int8x16_t p2s = FlipSign(p2);
- const int8x16_t p1s = FlipSign(p1);
- int8x16_t p0s = FlipSign(p0);
- int8x16_t q0s = FlipSign(q0);
- const int8x16_t q1s = FlipSign(q1);
- const int8x16_t q2s = FlipSign(q2);
- const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask);
- const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s);
-
- // do_filter2 part (simple loopfilter on pixels with hev)
- {
- const int8x16_t simple_lf_delta =
- vandq_s8(delta0, vreinterpretq_s8_u8(simple_lf_mask));
- ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s);
- }
-
- // do_filter6 part (complex loopfilter on pixels without hev)
- {
- // we use: (mask & hev_mask) ^ mask = mask & !hev_mask
- const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask);
- const int8x16_t complex_lf_delta =
- vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask));
- ApplyFilter6(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta,
- op2, op1, op0, oq0, oq1, oq2);
- }
-}
-
-// on macroblock edges
-
-static void VFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
- Load16x8(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
- {
- const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
- ithresh, thresh);
- const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
- uint8x16_t op2, op1, op0, oq0, oq1, oq2;
- DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask,
- &op2, &op1, &op0, &oq0, &oq1, &oq2);
- Store16x2(op2, op1, p - 2 * stride, stride);
- Store16x2(op0, oq0, p + 0 * stride, stride);
- Store16x2(oq1, oq2, p + 2 * stride, stride);
- }
-}
-
-static void HFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
- Load8x16(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
- {
- const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
- ithresh, thresh);
- const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
- uint8x16_t op2, op1, op0, oq0, oq1, oq2;
- DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask,
- &op2, &op1, &op0, &oq0, &oq1, &oq2);
- Store2x16(op2, op1, p - 2, stride);
- Store2x16(op0, oq0, p + 0, stride);
- Store2x16(oq1, oq2, p + 2, stride);
- }
-}
-
-// on three inner edges
-static void VFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- uint32_t k;
- uint8x16_t p3, p2, p1, p0;
- Load16x4(p + 2 * stride, stride, &p3, &p2, &p1, &p0);
- for (k = 3; k != 0; --k) {
- uint8x16_t q0, q1, q2, q3;
- p += 4 * stride;
- Load16x4(p + 2 * stride, stride, &q0, &q1, &q2, &q3);
- {
- const uint8x16_t mask =
- NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
- const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
- // p3 and p2 are not just temporary variables here: they will be
- // re-used for next span. And q2/q3 will become p1/p0 accordingly.
- DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2);
- Store16x4(p1, p0, p3, p2, p, stride);
- p1 = q2;
- p0 = q3;
- }
- }
-}
-
-#if !defined(WORK_AROUND_GCC)
-static void HFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- uint32_t k;
- uint8x16_t p3, p2, p1, p0;
- Load4x16(p + 2, stride, &p3, &p2, &p1, &p0);
- for (k = 3; k != 0; --k) {
- uint8x16_t q0, q1, q2, q3;
- p += 4;
- Load4x16(p + 2, stride, &q0, &q1, &q2, &q3);
- {
- const uint8x16_t mask =
- NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh);
- const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
- DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2);
- Store4x16(p1, p0, p3, p2, p, stride);
- p1 = q2;
- p0 = q3;
- }
- }
-}
-#endif // !WORK_AROUND_GCC
-
-// 8-pixels wide variant, for chroma filtering
-static void VFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
- Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
- {
- const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
- ithresh, thresh);
- const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
- uint8x16_t op2, op1, op0, oq0, oq1, oq2;
- DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask,
- &op2, &op1, &op0, &oq0, &oq1, &oq2);
- Store8x2x2(op2, op1, u - 2 * stride, v - 2 * stride, stride);
- Store8x2x2(op0, oq0, u + 0 * stride, v + 0 * stride, stride);
- Store8x2x2(oq1, oq2, u + 2 * stride, v + 2 * stride, stride);
- }
-}
-static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
- u += 4 * stride;
- v += 4 * stride;
- Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
- {
- const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
- ithresh, thresh);
- const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
- uint8x16_t op1, op0, oq0, oq1;
- DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1);
- Store8x4x2(op1, op0, oq0, oq1, u, v, stride);
- }
-}
-
-#if !defined(WORK_AROUND_GCC)
-static void HFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
- Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
- {
- const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
- ithresh, thresh);
- const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
- uint8x16_t op2, op1, op0, oq0, oq1, oq2;
- DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask,
- &op2, &op1, &op0, &oq0, &oq1, &oq2);
- Store6x8x2(op2, op1, op0, oq0, oq1, oq2, u, v, stride);
- }
-}
-
-static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
- u += 4;
- v += 4;
- Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
- {
- const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3,
- ithresh, thresh);
- const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh);
- uint8x16_t op1, op0, oq0, oq1;
- DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1);
- Store4x8x2(op1, op0, oq0, oq1, u, v, stride);
- }
-}
-#endif // !WORK_AROUND_GCC
-
-//-----------------------------------------------------------------------------
-// Inverse transforms (Paragraph 14.4)
-
-// Technically these are unsigned but vqdmulh is only available in signed.
-// vqdmulh returns high half (effectively >> 16) but also doubles the value,
-// changing the >> 16 to >> 15 and requiring an additional >> 1.
-// We use this to our advantage with kC2. The canonical value is 35468.
-// However, the high bit is set so treating it as signed will give incorrect
-// results. We avoid this by down shifting by 1 here to clear the highest bit.
-// Combined with the doubling effect of vqdmulh we get >> 16.
-// This can not be applied to kC1 because the lowest bit is set. Down shifting
-// the constant would reduce precision.
-
-// libwebp uses a trick to avoid some extra addition that libvpx does.
-// Instead of:
-// temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
-// libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the
-// same issue with kC1 and vqdmulh that we work around by down shifting kC2
-
-static const int16_t kC1 = 20091;
-static const int16_t kC2 = 17734; // half of kC2, actually. See comment above.
-
-#if defined(WEBP_USE_INTRINSICS)
-static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1,
- int16x8x2_t* const out) {
- // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1
- // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3
- const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ...
- // b0 d0 b1 d1 b2 d2 ...
- *out = vzipq_s16(tmp0.val[0], tmp0.val[1]);
-}
-
-static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) {
- // {rows} = in0 | in4
- // in8 | in12
- // B1 = in4 | in12
- const int16x8_t B1 =
- vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1]));
- // C0 = kC1 * in4 | kC1 * in12
- // C1 = kC2 * in4 | kC2 * in12
- const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1);
- const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2);
- const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]),
- vget_low_s16(rows->val[1])); // in0 + in8
- const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]),
- vget_low_s16(rows->val[1])); // in0 - in8
- // c = kC2 * in4 - kC1 * in12
- // d = kC1 * in4 + kC2 * in12
- const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0));
- const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1));
- const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b
- const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c
- const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c
- const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c
- const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp));
- Transpose8x2(E0, E1, rows);
-}
-
-static void TransformOne(const int16_t* in, uint8_t* dst) {
- int16x8x2_t rows;
- INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8));
- TransformPass(&rows);
- TransformPass(&rows);
- Add4x4(rows.val[0], rows.val[1], dst);
-}
-
-#else
-
-static void TransformOne(const int16_t* in, uint8_t* dst) {
- const int kBPS = BPS;
- // kC1, kC2. Padded because vld1.16 loads 8 bytes
- const int16_t constants[4] = { kC1, kC2, 0, 0 };
- /* Adapted from libvpx: vp8/common/arm/neon/shortidct4x4llm_neon.asm */
- __asm__ volatile (
- "vld1.16 {q1, q2}, [%[in]] \n"
- "vld1.16 {d0}, [%[constants]] \n"
-
- /* d2: in[0]
- * d3: in[8]
- * d4: in[4]
- * d5: in[12]
- */
- "vswp d3, d4 \n"
-
- /* q8 = {in[4], in[12]} * kC1 * 2 >> 16
- * q9 = {in[4], in[12]} * kC2 >> 16
- */
- "vqdmulh.s16 q8, q2, d0[0] \n"
- "vqdmulh.s16 q9, q2, d0[1] \n"
-
- /* d22 = a = in[0] + in[8]
- * d23 = b = in[0] - in[8]
- */
- "vqadd.s16 d22, d2, d3 \n"
- "vqsub.s16 d23, d2, d3 \n"
-
- /* The multiplication should be x * kC1 >> 16
- * However, with vqdmulh we get x * kC1 * 2 >> 16
- * (multiply, double, return high half)
- * We avoided this in kC2 by pre-shifting the constant.
- * q8 = in[4]/[12] * kC1 >> 16
- */
- "vshr.s16 q8, q8, #1 \n"
-
- /* Add {in[4], in[12]} back after the multiplication. This is handled by
- * adding 1 << 16 to kC1 in the libwebp C code.
- */
- "vqadd.s16 q8, q2, q8 \n"
-
- /* d20 = c = in[4]*kC2 - in[12]*kC1
- * d21 = d = in[4]*kC1 + in[12]*kC2
- */
- "vqsub.s16 d20, d18, d17 \n"
- "vqadd.s16 d21, d19, d16 \n"
-
- /* d2 = tmp[0] = a + d
- * d3 = tmp[1] = b + c
- * d4 = tmp[2] = b - c
- * d5 = tmp[3] = a - d
- */
- "vqadd.s16 d2, d22, d21 \n"
- "vqadd.s16 d3, d23, d20 \n"
- "vqsub.s16 d4, d23, d20 \n"
- "vqsub.s16 d5, d22, d21 \n"
-
- "vzip.16 q1, q2 \n"
- "vzip.16 q1, q2 \n"
-
- "vswp d3, d4 \n"
-
- /* q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16
- * q9 = {tmp[4], tmp[12]} * kC2 >> 16
- */
- "vqdmulh.s16 q8, q2, d0[0] \n"
- "vqdmulh.s16 q9, q2, d0[1] \n"
-
- /* d22 = a = tmp[0] + tmp[8]
- * d23 = b = tmp[0] - tmp[8]
- */
- "vqadd.s16 d22, d2, d3 \n"
- "vqsub.s16 d23, d2, d3 \n"
-
- /* See long winded explanations prior */
- "vshr.s16 q8, q8, #1 \n"
- "vqadd.s16 q8, q2, q8 \n"
-
- /* d20 = c = in[4]*kC2 - in[12]*kC1
- * d21 = d = in[4]*kC1 + in[12]*kC2
- */
- "vqsub.s16 d20, d18, d17 \n"
- "vqadd.s16 d21, d19, d16 \n"
-
- /* d2 = tmp[0] = a + d
- * d3 = tmp[1] = b + c
- * d4 = tmp[2] = b - c
- * d5 = tmp[3] = a - d
- */
- "vqadd.s16 d2, d22, d21 \n"
- "vqadd.s16 d3, d23, d20 \n"
- "vqsub.s16 d4, d23, d20 \n"
- "vqsub.s16 d5, d22, d21 \n"
-
- "vld1.32 d6[0], [%[dst]], %[kBPS] \n"
- "vld1.32 d6[1], [%[dst]], %[kBPS] \n"
- "vld1.32 d7[0], [%[dst]], %[kBPS] \n"
- "vld1.32 d7[1], [%[dst]], %[kBPS] \n"
-
- "sub %[dst], %[dst], %[kBPS], lsl #2 \n"
-
- /* (val) + 4 >> 3 */
- "vrshr.s16 d2, d2, #3 \n"
- "vrshr.s16 d3, d3, #3 \n"
- "vrshr.s16 d4, d4, #3 \n"
- "vrshr.s16 d5, d5, #3 \n"
-
- "vzip.16 q1, q2 \n"
- "vzip.16 q1, q2 \n"
-
- /* Must accumulate before saturating */
- "vmovl.u8 q8, d6 \n"
- "vmovl.u8 q9, d7 \n"
-
- "vqadd.s16 q1, q1, q8 \n"
- "vqadd.s16 q2, q2, q9 \n"
-
- "vqmovun.s16 d0, q1 \n"
- "vqmovun.s16 d1, q2 \n"
-
- "vst1.32 d0[0], [%[dst]], %[kBPS] \n"
- "vst1.32 d0[1], [%[dst]], %[kBPS] \n"
- "vst1.32 d1[0], [%[dst]], %[kBPS] \n"
- "vst1.32 d1[1], [%[dst]] \n"
-
- : [in] "+r"(in), [dst] "+r"(dst) /* modified registers */
- : [kBPS] "r"(kBPS), [constants] "r"(constants) /* constants */
- : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" /* clobbered */
- );
-}
-
-#endif // WEBP_USE_INTRINSICS
-
-static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
- TransformOne(in, dst);
- if (do_two) {
- TransformOne(in + 16, dst + 4);
- }
-}
-
-static void TransformDC(const int16_t* in, uint8_t* dst) {
- const int16x8_t DC = vdupq_n_s16(in[0]);
- Add4x4(DC, DC, dst);
-}
-
-//------------------------------------------------------------------------------
-
-#define STORE_WHT(dst, col, rows) do { \
- *dst = vgetq_lane_s32(rows.val[0], col); (dst) += 16; \
- *dst = vgetq_lane_s32(rows.val[1], col); (dst) += 16; \
- *dst = vgetq_lane_s32(rows.val[2], col); (dst) += 16; \
- *dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \
-} while (0)
-
-static void TransformWHT(const int16_t* in, int16_t* out) {
- int32x4x4_t tmp;
-
- {
- // Load the source.
- const int16x4_t in00_03 = vld1_s16(in + 0);
- const int16x4_t in04_07 = vld1_s16(in + 4);
- const int16x4_t in08_11 = vld1_s16(in + 8);
- const int16x4_t in12_15 = vld1_s16(in + 12);
- const int32x4_t a0 = vaddl_s16(in00_03, in12_15); // in[0..3] + in[12..15]
- const int32x4_t a1 = vaddl_s16(in04_07, in08_11); // in[4..7] + in[8..11]
- const int32x4_t a2 = vsubl_s16(in04_07, in08_11); // in[4..7] - in[8..11]
- const int32x4_t a3 = vsubl_s16(in00_03, in12_15); // in[0..3] - in[12..15]
- tmp.val[0] = vaddq_s32(a0, a1);
- tmp.val[1] = vaddq_s32(a3, a2);
- tmp.val[2] = vsubq_s32(a0, a1);
- tmp.val[3] = vsubq_s32(a3, a2);
- // Arrange the temporary results column-wise.
- tmp = Transpose4x4(tmp);
- }
-
- {
- const int32x4_t kCst3 = vdupq_n_s32(3);
- const int32x4_t dc = vaddq_s32(tmp.val[0], kCst3); // add rounder
- const int32x4_t a0 = vaddq_s32(dc, tmp.val[3]);
- const int32x4_t a1 = vaddq_s32(tmp.val[1], tmp.val[2]);
- const int32x4_t a2 = vsubq_s32(tmp.val[1], tmp.val[2]);
- const int32x4_t a3 = vsubq_s32(dc, tmp.val[3]);
-
- tmp.val[0] = vaddq_s32(a0, a1);
- tmp.val[1] = vaddq_s32(a3, a2);
- tmp.val[2] = vsubq_s32(a0, a1);
- tmp.val[3] = vsubq_s32(a3, a2);
-
- // right shift the results by 3.
- tmp.val[0] = vshrq_n_s32(tmp.val[0], 3);
- tmp.val[1] = vshrq_n_s32(tmp.val[1], 3);
- tmp.val[2] = vshrq_n_s32(tmp.val[2], 3);
- tmp.val[3] = vshrq_n_s32(tmp.val[3], 3);
-
- STORE_WHT(out, 0, tmp);
- STORE_WHT(out, 1, tmp);
- STORE_WHT(out, 2, tmp);
- STORE_WHT(out, 3, tmp);
- }
-}
-
-#undef STORE_WHT
-
-//------------------------------------------------------------------------------
-
-#define MUL(a, b) (((a) * (b)) >> 16)
-static void TransformAC3(const int16_t* in, uint8_t* dst) {
- static const int kC1_full = 20091 + (1 << 16);
- static const int kC2_full = 35468;
- const int16x4_t A = vld1_dup_s16(in);
- const int16x4_t c4 = vdup_n_s16(MUL(in[4], kC2_full));
- const int16x4_t d4 = vdup_n_s16(MUL(in[4], kC1_full));
- const int c1 = MUL(in[1], kC2_full);
- const int d1 = MUL(in[1], kC1_full);
- const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 |
- (uint64_t)( c1 & 0xffff) << 16 |
- (uint64_t)(-c1 & 0xffff) << 32 |
- (uint64_t)(-d1 & 0xffff) << 48;
- const int16x4_t CD = vcreate_s16(cd);
- const int16x4_t B = vqadd_s16(A, CD);
- const int16x8_t m0_m1 = vcombine_s16(vqadd_s16(B, d4), vqadd_s16(B, c4));
- const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4));
- Add4x4(m0_m1, m2_m3, dst);
-}
-#undef MUL
-
-//------------------------------------------------------------------------------
-// 4x4
-
-static void DC4(uint8_t* dst) { // DC
- const uint8x8_t A = vld1_u8(dst - BPS); // top row
- const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
- const uint16x4_t p1 = vpadd_u16(p0, p0);
- const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1));
- const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1));
- const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1));
- const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1));
- const uint16x8_t s0 = vaddq_u16(L0, L1);
- const uint16x8_t s1 = vaddq_u16(L2, L3);
- const uint16x8_t s01 = vaddq_u16(s0, s1);
- const uint16x8_t sum = vaddq_u16(s01, vcombine_u16(p1, p1));
- const uint8x8_t dc0 = vrshrn_n_u16(sum, 3); // (sum + 4) >> 3
- const uint8x8_t dc = vdup_lane_u8(dc0, 0);
- int i;
- for (i = 0; i < 4; ++i) {
- vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc), 0);
- }
-}
-
-// TrueMotion (4x4 + 8x8)
-static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) {
- const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]'
- const uint8x8_t T = vld1_u8(dst - BPS); // top row 'A[0..3]'
- const int16x8_t d = vreinterpretq_s16_u16(vsubl_u8(T, TL)); // A[c] - A[-1]
- int y;
- for (y = 0; y < size; y += 4) {
- // left edge
- const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1));
- const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1));
- const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1));
- const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1));
- const int16x8_t r0 = vaddq_s16(L0, d); // L[r] + A[c] - A[-1]
- const int16x8_t r1 = vaddq_s16(L1, d);
- const int16x8_t r2 = vaddq_s16(L2, d);
- const int16x8_t r3 = vaddq_s16(L3, d);
- // Saturate and store the result.
- const uint32x2_t r0_u32 = vreinterpret_u32_u8(vqmovun_s16(r0));
- const uint32x2_t r1_u32 = vreinterpret_u32_u8(vqmovun_s16(r1));
- const uint32x2_t r2_u32 = vreinterpret_u32_u8(vqmovun_s16(r2));
- const uint32x2_t r3_u32 = vreinterpret_u32_u8(vqmovun_s16(r3));
- if (size == 4) {
- vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0_u32, 0);
- vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1_u32, 0);
- vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2_u32, 0);
- vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3_u32, 0);
- } else {
- vst1_u32((uint32_t*)(dst + 0 * BPS), r0_u32);
- vst1_u32((uint32_t*)(dst + 1 * BPS), r1_u32);
- vst1_u32((uint32_t*)(dst + 2 * BPS), r2_u32);
- vst1_u32((uint32_t*)(dst + 3 * BPS), r3_u32);
- }
- dst += 4 * BPS;
- }
-}
-
-static void TM4(uint8_t* dst) { TrueMotion(dst, 4); }
-
-static void VE4(uint8_t* dst) { // vertical
- // NB: avoid vld1_u64 here as an alignment hint may be added -> SIGBUS.
- const uint64x1_t A0 = vreinterpret_u64_u8(vld1_u8(dst - BPS - 1)); // top row
- const uint64x1_t A1 = vshr_n_u64(A0, 8);
- const uint64x1_t A2 = vshr_n_u64(A0, 16);
- const uint8x8_t ABCDEFGH = vreinterpret_u8_u64(A0);
- const uint8x8_t BCDEFGH0 = vreinterpret_u8_u64(A1);
- const uint8x8_t CDEFGH00 = vreinterpret_u8_u64(A2);
- const uint8x8_t b = vhadd_u8(ABCDEFGH, CDEFGH00);
- const uint8x8_t avg = vrhadd_u8(b, BCDEFGH0);
- int i;
- for (i = 0; i < 4; ++i) {
- vst1_lane_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(avg), 0);
- }
-}
-
-static void RD4(uint8_t* dst) { // Down-right
- const uint8x8_t XABCD_u8 = vld1_u8(dst - BPS - 1);
- const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8);
- const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32);
- const uint32_t I = dst[-1 + 0 * BPS];
- const uint32_t J = dst[-1 + 1 * BPS];
- const uint32_t K = dst[-1 + 2 * BPS];
- const uint32_t L = dst[-1 + 3 * BPS];
- const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24));
- const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC);
- const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8));
- const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16));
- const uint8_t D = vget_lane_u8(XABCD_u8, 4);
- const uint8x8_t JIXABCD_ = vset_lane_u8(D, JIXABC__, 6);
- const uint8x8_t LKJIXABC_u8 = vreinterpret_u8_u64(LKJIXABC);
- const uint8x8_t avg1 = vhadd_u8(JIXABCD_, LKJIXABC_u8);
- const uint8x8_t avg2 = vrhadd_u8(avg1, KJIXABC_);
- const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2);
- const uint32x2_t r3 = vreinterpret_u32_u8(avg2);
- const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8));
- const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16));
- const uint32x2_t r0 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24));
- vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0);
- vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0);
- vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0);
- vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0);
-}
-
-static void LD4(uint8_t* dst) { // Down-left
- // Note using the same shift trick as VE4() is slower here.
- const uint8x8_t ABCDEFGH = vld1_u8(dst - BPS + 0);
- const uint8x8_t BCDEFGH0 = vld1_u8(dst - BPS + 1);
- const uint8x8_t CDEFGH00 = vld1_u8(dst - BPS + 2);
- const uint8x8_t CDEFGHH0 = vset_lane_u8(dst[-BPS + 7], CDEFGH00, 6);
- const uint8x8_t avg1 = vhadd_u8(ABCDEFGH, CDEFGHH0);
- const uint8x8_t avg2 = vrhadd_u8(avg1, BCDEFGH0);
- const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2);
- const uint32x2_t r0 = vreinterpret_u32_u8(avg2);
- const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8));
- const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16));
- const uint32x2_t r3 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24));
- vst1_lane_u32((uint32_t*)(dst + 0 * BPS), r0, 0);
- vst1_lane_u32((uint32_t*)(dst + 1 * BPS), r1, 0);
- vst1_lane_u32((uint32_t*)(dst + 2 * BPS), r2, 0);
- vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0);
-}
-
-//------------------------------------------------------------------------------
-// Chroma
-
-static void VE8uv(uint8_t* dst) { // vertical
- const uint8x8_t top = vld1_u8(dst - BPS);
- int j;
- for (j = 0; j < 8; ++j) {
- vst1_u8(dst + j * BPS, top);
- }
-}
-
-static void HE8uv(uint8_t* dst) { // horizontal
- int j;
- for (j = 0; j < 8; ++j) {
- const uint8x8_t left = vld1_dup_u8(dst - 1);
- vst1_u8(dst, left);
- dst += BPS;
- }
-}
-
-static WEBP_INLINE void DC8(uint8_t* dst, int do_top, int do_left) {
- uint16x8_t sum_top;
- uint16x8_t sum_left;
- uint8x8_t dc0;
-
- if (do_top) {
- const uint8x8_t A = vld1_u8(dst - BPS); // top row
- const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
- const uint16x4_t p1 = vpadd_u16(p0, p0);
- const uint16x4_t p2 = vpadd_u16(p1, p1);
- sum_top = vcombine_u16(p2, p2);
- }
-
- if (do_left) {
- const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1));
- const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1));
- const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1));
- const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1));
- const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + 4 * BPS - 1));
- const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + 5 * BPS - 1));
- const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + 6 * BPS - 1));
- const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + 7 * BPS - 1));
- const uint16x8_t s0 = vaddq_u16(L0, L1);
- const uint16x8_t s1 = vaddq_u16(L2, L3);
- const uint16x8_t s2 = vaddq_u16(L4, L5);
- const uint16x8_t s3 = vaddq_u16(L6, L7);
- const uint16x8_t s01 = vaddq_u16(s0, s1);
- const uint16x8_t s23 = vaddq_u16(s2, s3);
- sum_left = vaddq_u16(s01, s23);
- }
-
- if (do_top && do_left) {
- const uint16x8_t sum = vaddq_u16(sum_left, sum_top);
- dc0 = vrshrn_n_u16(sum, 4);
- } else if (do_top) {
- dc0 = vrshrn_n_u16(sum_top, 3);
- } else if (do_left) {
- dc0 = vrshrn_n_u16(sum_left, 3);
- } else {
- dc0 = vdup_n_u8(0x80);
- }
-
- {
- const uint8x8_t dc = vdup_lane_u8(dc0, 0);
- int i;
- for (i = 0; i < 8; ++i) {
- vst1_u32((uint32_t*)(dst + i * BPS), vreinterpret_u32_u8(dc));
- }
- }
-}
-
-static void DC8uv(uint8_t* dst) { DC8(dst, 1, 1); }
-static void DC8uvNoTop(uint8_t* dst) { DC8(dst, 0, 1); }
-static void DC8uvNoLeft(uint8_t* dst) { DC8(dst, 1, 0); }
-static void DC8uvNoTopLeft(uint8_t* dst) { DC8(dst, 0, 0); }
-
-static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); }
-
-//------------------------------------------------------------------------------
-// 16x16
-
-static void VE16(uint8_t* dst) { // vertical
- const uint8x16_t top = vld1q_u8(dst - BPS);
- int j;
- for (j = 0; j < 16; ++j) {
- vst1q_u8(dst + j * BPS, top);
- }
-}
-
-static void HE16(uint8_t* dst) { // horizontal
- int j;
- for (j = 0; j < 16; ++j) {
- const uint8x16_t left = vld1q_dup_u8(dst - 1);
- vst1q_u8(dst, left);
- dst += BPS;
- }
-}
-
-static WEBP_INLINE void DC16(uint8_t* dst, int do_top, int do_left) {
- uint16x8_t sum_top;
- uint16x8_t sum_left;
- uint8x8_t dc0;
-
- if (do_top) {
- const uint8x16_t A = vld1q_u8(dst - BPS); // top row
- const uint16x8_t p0 = vpaddlq_u8(A); // cascading summation of the top
- const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0));
- const uint16x4_t p2 = vpadd_u16(p1, p1);
- const uint16x4_t p3 = vpadd_u16(p2, p2);
- sum_top = vcombine_u16(p3, p3);
- }
-
- if (do_left) {
- int i;
- sum_left = vdupq_n_u16(0);
- for (i = 0; i < 16; i += 8) {
- const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + (i + 0) * BPS - 1));
- const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + (i + 1) * BPS - 1));
- const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + (i + 2) * BPS - 1));
- const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + (i + 3) * BPS - 1));
- const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + (i + 4) * BPS - 1));
- const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + (i + 5) * BPS - 1));
- const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + (i + 6) * BPS - 1));
- const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + (i + 7) * BPS - 1));
- const uint16x8_t s0 = vaddq_u16(L0, L1);
- const uint16x8_t s1 = vaddq_u16(L2, L3);
- const uint16x8_t s2 = vaddq_u16(L4, L5);
- const uint16x8_t s3 = vaddq_u16(L6, L7);
- const uint16x8_t s01 = vaddq_u16(s0, s1);
- const uint16x8_t s23 = vaddq_u16(s2, s3);
- const uint16x8_t sum = vaddq_u16(s01, s23);
- sum_left = vaddq_u16(sum_left, sum);
- }
- }
-
- if (do_top && do_left) {
- const uint16x8_t sum = vaddq_u16(sum_left, sum_top);
- dc0 = vrshrn_n_u16(sum, 5);
- } else if (do_top) {
- dc0 = vrshrn_n_u16(sum_top, 4);
- } else if (do_left) {
- dc0 = vrshrn_n_u16(sum_left, 4);
- } else {
- dc0 = vdup_n_u8(0x80);
- }
-
- {
- const uint8x16_t dc = vdupq_lane_u8(dc0, 0);
- int i;
- for (i = 0; i < 16; ++i) {
- vst1q_u8(dst + i * BPS, dc);
- }
- }
-}
-
-static void DC16TopLeft(uint8_t* dst) { DC16(dst, 1, 1); }
-static void DC16NoTop(uint8_t* dst) { DC16(dst, 0, 1); }
-static void DC16NoLeft(uint8_t* dst) { DC16(dst, 1, 0); }
-static void DC16NoTopLeft(uint8_t* dst) { DC16(dst, 0, 0); }
-
-static void TM16(uint8_t* dst) {
- const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]'
- const uint8x16_t T = vld1q_u8(dst - BPS); // top row 'A[0..15]'
- // A[c] - A[-1]
- const int16x8_t d_lo = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), TL));
- const int16x8_t d_hi = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), TL));
- int y;
- for (y = 0; y < 16; y += 4) {
- // left edge
- const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1));
- const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1));
- const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1));
- const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1));
- const int16x8_t r0_lo = vaddq_s16(L0, d_lo); // L[r] + A[c] - A[-1]
- const int16x8_t r1_lo = vaddq_s16(L1, d_lo);
- const int16x8_t r2_lo = vaddq_s16(L2, d_lo);
- const int16x8_t r3_lo = vaddq_s16(L3, d_lo);
- const int16x8_t r0_hi = vaddq_s16(L0, d_hi);
- const int16x8_t r1_hi = vaddq_s16(L1, d_hi);
- const int16x8_t r2_hi = vaddq_s16(L2, d_hi);
- const int16x8_t r3_hi = vaddq_s16(L3, d_hi);
- // Saturate and store the result.
- const uint8x16_t row0 = vcombine_u8(vqmovun_s16(r0_lo), vqmovun_s16(r0_hi));
- const uint8x16_t row1 = vcombine_u8(vqmovun_s16(r1_lo), vqmovun_s16(r1_hi));
- const uint8x16_t row2 = vcombine_u8(vqmovun_s16(r2_lo), vqmovun_s16(r2_hi));
- const uint8x16_t row3 = vcombine_u8(vqmovun_s16(r3_lo), vqmovun_s16(r3_hi));
- vst1q_u8(dst + 0 * BPS, row0);
- vst1q_u8(dst + 1 * BPS, row1);
- vst1q_u8(dst + 2 * BPS, row2);
- vst1q_u8(dst + 3 * BPS, row3);
- dst += 4 * BPS;
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8DspInitNEON(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitNEON(void) {
- VP8Transform = TransformTwo;
- VP8TransformAC3 = TransformAC3;
- VP8TransformDC = TransformDC;
- VP8TransformWHT = TransformWHT;
-
- VP8VFilter16 = VFilter16;
- VP8VFilter16i = VFilter16i;
- VP8HFilter16 = HFilter16;
-#if !defined(WORK_AROUND_GCC)
- VP8HFilter16i = HFilter16i;
-#endif
- VP8VFilter8 = VFilter8;
- VP8VFilter8i = VFilter8i;
-#if !defined(WORK_AROUND_GCC)
- VP8HFilter8 = HFilter8;
- VP8HFilter8i = HFilter8i;
-#endif
- VP8SimpleVFilter16 = SimpleVFilter16;
- VP8SimpleHFilter16 = SimpleHFilter16;
- VP8SimpleVFilter16i = SimpleVFilter16i;
- VP8SimpleHFilter16i = SimpleHFilter16i;
-
- VP8PredLuma4[0] = DC4;
- VP8PredLuma4[1] = TM4;
- VP8PredLuma4[2] = VE4;
- VP8PredLuma4[4] = RD4;
- VP8PredLuma4[6] = LD4;
-
- VP8PredLuma16[0] = DC16TopLeft;
- VP8PredLuma16[1] = TM16;
- VP8PredLuma16[2] = VE16;
- VP8PredLuma16[3] = HE16;
- VP8PredLuma16[4] = DC16NoTop;
- VP8PredLuma16[5] = DC16NoLeft;
- VP8PredLuma16[6] = DC16NoTopLeft;
-
- VP8PredChroma8[0] = DC8uv;
- VP8PredChroma8[1] = TM8uv;
- VP8PredChroma8[2] = VE8uv;
- VP8PredChroma8[3] = HE8uv;
- VP8PredChroma8[4] = DC8uvNoTop;
- VP8PredChroma8[5] = DC8uvNoLeft;
- VP8PredChroma8[6] = DC8uvNoTopLeft;
-}
-
-#else // !WEBP_USE_NEON
-
-WEBP_DSP_INIT_STUB(VP8DspInitNEON)
-
-#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/dec_sse2.c b/drivers/webp/dsp/dec_sse2.c
deleted file mode 100644
index f0a8ddcaf3..0000000000
--- a/drivers/webp/dsp/dec_sse2.c
+++ /dev/null
@@ -1,1231 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 version of some decoding functions (idct, loop filtering).
-//
-// Author: somnath@google.com (Somnath Banerjee)
-// cduvivier@google.com (Christian Duvivier)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-
-// The 3-coeff sparse transform in SSE2 is not really faster than the plain-C
-// one it seems => disable it by default. Uncomment the following to enable:
-// #define USE_TRANSFORM_AC3
-
-#include <emmintrin.h>
-#include "./common_sse2.h"
-#include "../dec/vp8i.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// Transforms (Paragraph 14.4)
-
-static void Transform(const int16_t* in, uint8_t* dst, int do_two) {
- // This implementation makes use of 16-bit fixed point versions of two
- // multiply constants:
- // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
- // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16
- //
- // To be able to use signed 16-bit integers, we use the following trick to
- // have constants within range:
- // - Associated constants are obtained by subtracting the 16-bit fixed point
- // version of one:
- // k = K - (1 << 16) => K = k + (1 << 16)
- // K1 = 85267 => k1 = 20091
- // K2 = 35468 => k2 = -30068
- // - The multiplication of a variable by a constant become the sum of the
- // variable and the multiplication of that variable by the associated
- // constant:
- // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
- const __m128i k1 = _mm_set1_epi16(20091);
- const __m128i k2 = _mm_set1_epi16(-30068);
- __m128i T0, T1, T2, T3;
-
- // Load and concatenate the transform coefficients (we'll do two transforms
- // in parallel). In the case of only one transform, the second half of the
- // vectors will just contain random value we'll never use nor store.
- __m128i in0, in1, in2, in3;
- {
- in0 = _mm_loadl_epi64((const __m128i*)&in[0]);
- in1 = _mm_loadl_epi64((const __m128i*)&in[4]);
- in2 = _mm_loadl_epi64((const __m128i*)&in[8]);
- in3 = _mm_loadl_epi64((const __m128i*)&in[12]);
- // a00 a10 a20 a30 x x x x
- // a01 a11 a21 a31 x x x x
- // a02 a12 a22 a32 x x x x
- // a03 a13 a23 a33 x x x x
- if (do_two) {
- const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]);
- const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]);
- const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]);
- const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]);
- in0 = _mm_unpacklo_epi64(in0, inB0);
- in1 = _mm_unpacklo_epi64(in1, inB1);
- in2 = _mm_unpacklo_epi64(in2, inB2);
- in3 = _mm_unpacklo_epi64(in3, inB3);
- // a00 a10 a20 a30 b00 b10 b20 b30
- // a01 a11 a21 a31 b01 b11 b21 b31
- // a02 a12 a22 a32 b02 b12 b22 b32
- // a03 a13 a23 a33 b03 b13 b23 b33
- }
- }
-
- // Vertical pass and subsequent transpose.
- {
- // First pass, c and d calculations are longer because of the "trick"
- // multiplications.
- const __m128i a = _mm_add_epi16(in0, in2);
- const __m128i b = _mm_sub_epi16(in0, in2);
- // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3
- const __m128i c1 = _mm_mulhi_epi16(in1, k2);
- const __m128i c2 = _mm_mulhi_epi16(in3, k1);
- const __m128i c3 = _mm_sub_epi16(in1, in3);
- const __m128i c4 = _mm_sub_epi16(c1, c2);
- const __m128i c = _mm_add_epi16(c3, c4);
- // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3
- const __m128i d1 = _mm_mulhi_epi16(in1, k1);
- const __m128i d2 = _mm_mulhi_epi16(in3, k2);
- const __m128i d3 = _mm_add_epi16(in1, in3);
- const __m128i d4 = _mm_add_epi16(d1, d2);
- const __m128i d = _mm_add_epi16(d3, d4);
-
- // Second pass.
- const __m128i tmp0 = _mm_add_epi16(a, d);
- const __m128i tmp1 = _mm_add_epi16(b, c);
- const __m128i tmp2 = _mm_sub_epi16(b, c);
- const __m128i tmp3 = _mm_sub_epi16(a, d);
-
- // Transpose the two 4x4.
- VP8Transpose_2_4x4_16b(&tmp0, &tmp1, &tmp2, &tmp3, &T0, &T1, &T2, &T3);
- }
-
- // Horizontal pass and subsequent transpose.
- {
- // First pass, c and d calculations are longer because of the "trick"
- // multiplications.
- const __m128i four = _mm_set1_epi16(4);
- const __m128i dc = _mm_add_epi16(T0, four);
- const __m128i a = _mm_add_epi16(dc, T2);
- const __m128i b = _mm_sub_epi16(dc, T2);
- // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3
- const __m128i c1 = _mm_mulhi_epi16(T1, k2);
- const __m128i c2 = _mm_mulhi_epi16(T3, k1);
- const __m128i c3 = _mm_sub_epi16(T1, T3);
- const __m128i c4 = _mm_sub_epi16(c1, c2);
- const __m128i c = _mm_add_epi16(c3, c4);
- // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3
- const __m128i d1 = _mm_mulhi_epi16(T1, k1);
- const __m128i d2 = _mm_mulhi_epi16(T3, k2);
- const __m128i d3 = _mm_add_epi16(T1, T3);
- const __m128i d4 = _mm_add_epi16(d1, d2);
- const __m128i d = _mm_add_epi16(d3, d4);
-
- // Second pass.
- const __m128i tmp0 = _mm_add_epi16(a, d);
- const __m128i tmp1 = _mm_add_epi16(b, c);
- const __m128i tmp2 = _mm_sub_epi16(b, c);
- const __m128i tmp3 = _mm_sub_epi16(a, d);
- const __m128i shifted0 = _mm_srai_epi16(tmp0, 3);
- const __m128i shifted1 = _mm_srai_epi16(tmp1, 3);
- const __m128i shifted2 = _mm_srai_epi16(tmp2, 3);
- const __m128i shifted3 = _mm_srai_epi16(tmp3, 3);
-
- // Transpose the two 4x4.
- VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1,
- &T2, &T3);
- }
-
- // Add inverse transform to 'dst' and store.
- {
- const __m128i zero = _mm_setzero_si128();
- // Load the reference(s).
- __m128i dst0, dst1, dst2, dst3;
- if (do_two) {
- // Load eight bytes/pixels per line.
- dst0 = _mm_loadl_epi64((__m128i*)(dst + 0 * BPS));
- dst1 = _mm_loadl_epi64((__m128i*)(dst + 1 * BPS));
- dst2 = _mm_loadl_epi64((__m128i*)(dst + 2 * BPS));
- dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS));
- } else {
- // Load four bytes/pixels per line.
- dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS));
- dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS));
- dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS));
- dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS));
- }
- // Convert to 16b.
- dst0 = _mm_unpacklo_epi8(dst0, zero);
- dst1 = _mm_unpacklo_epi8(dst1, zero);
- dst2 = _mm_unpacklo_epi8(dst2, zero);
- dst3 = _mm_unpacklo_epi8(dst3, zero);
- // Add the inverse transform(s).
- dst0 = _mm_add_epi16(dst0, T0);
- dst1 = _mm_add_epi16(dst1, T1);
- dst2 = _mm_add_epi16(dst2, T2);
- dst3 = _mm_add_epi16(dst3, T3);
- // Unsigned saturate to 8b.
- dst0 = _mm_packus_epi16(dst0, dst0);
- dst1 = _mm_packus_epi16(dst1, dst1);
- dst2 = _mm_packus_epi16(dst2, dst2);
- dst3 = _mm_packus_epi16(dst3, dst3);
- // Store the results.
- if (do_two) {
- // Store eight bytes/pixels per line.
- _mm_storel_epi64((__m128i*)(dst + 0 * BPS), dst0);
- _mm_storel_epi64((__m128i*)(dst + 1 * BPS), dst1);
- _mm_storel_epi64((__m128i*)(dst + 2 * BPS), dst2);
- _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3);
- } else {
- // Store four bytes/pixels per line.
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2));
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3));
- }
- }
-}
-
-#if defined(USE_TRANSFORM_AC3)
-#define MUL(a, b) (((a) * (b)) >> 16)
-static void TransformAC3(const int16_t* in, uint8_t* dst) {
- static const int kC1 = 20091 + (1 << 16);
- static const int kC2 = 35468;
- const __m128i A = _mm_set1_epi16(in[0] + 4);
- const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2));
- const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1));
- const int c1 = MUL(in[1], kC2);
- const int d1 = MUL(in[1], kC1);
- const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1);
- const __m128i B = _mm_adds_epi16(A, CD);
- const __m128i m0 = _mm_adds_epi16(B, d4);
- const __m128i m1 = _mm_adds_epi16(B, c4);
- const __m128i m2 = _mm_subs_epi16(B, c4);
- const __m128i m3 = _mm_subs_epi16(B, d4);
- const __m128i zero = _mm_setzero_si128();
- // Load the source pixels.
- __m128i dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS));
- __m128i dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS));
- __m128i dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS));
- __m128i dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS));
- // Convert to 16b.
- dst0 = _mm_unpacklo_epi8(dst0, zero);
- dst1 = _mm_unpacklo_epi8(dst1, zero);
- dst2 = _mm_unpacklo_epi8(dst2, zero);
- dst3 = _mm_unpacklo_epi8(dst3, zero);
- // Add the inverse transform.
- dst0 = _mm_adds_epi16(dst0, _mm_srai_epi16(m0, 3));
- dst1 = _mm_adds_epi16(dst1, _mm_srai_epi16(m1, 3));
- dst2 = _mm_adds_epi16(dst2, _mm_srai_epi16(m2, 3));
- dst3 = _mm_adds_epi16(dst3, _mm_srai_epi16(m3, 3));
- // Unsigned saturate to 8b.
- dst0 = _mm_packus_epi16(dst0, dst0);
- dst1 = _mm_packus_epi16(dst1, dst1);
- dst2 = _mm_packus_epi16(dst2, dst2);
- dst3 = _mm_packus_epi16(dst3, dst3);
- // Store the results.
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2));
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3));
-}
-#undef MUL
-#endif // USE_TRANSFORM_AC3
-
-//------------------------------------------------------------------------------
-// Loop Filter (Paragraph 15)
-
-// Compute abs(p - q) = subs(p - q) OR subs(q - p)
-#define MM_ABS(p, q) _mm_or_si128( \
- _mm_subs_epu8((q), (p)), \
- _mm_subs_epu8((p), (q)))
-
-// Shift each byte of "x" by 3 bits while preserving by the sign bit.
-static WEBP_INLINE void SignedShift8b(__m128i* const x) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i lo_0 = _mm_unpacklo_epi8(zero, *x);
- const __m128i hi_0 = _mm_unpackhi_epi8(zero, *x);
- const __m128i lo_1 = _mm_srai_epi16(lo_0, 3 + 8);
- const __m128i hi_1 = _mm_srai_epi16(hi_0, 3 + 8);
- *x = _mm_packs_epi16(lo_1, hi_1);
-}
-
-#define FLIP_SIGN_BIT2(a, b) { \
- a = _mm_xor_si128(a, sign_bit); \
- b = _mm_xor_si128(b, sign_bit); \
-}
-
-#define FLIP_SIGN_BIT4(a, b, c, d) { \
- FLIP_SIGN_BIT2(a, b); \
- FLIP_SIGN_BIT2(c, d); \
-}
-
-// input/output is uint8_t
-static WEBP_INLINE void GetNotHEV(const __m128i* const p1,
- const __m128i* const p0,
- const __m128i* const q0,
- const __m128i* const q1,
- int hev_thresh, __m128i* const not_hev) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i t_1 = MM_ABS(*p1, *p0);
- const __m128i t_2 = MM_ABS(*q1, *q0);
-
- const __m128i h = _mm_set1_epi8(hev_thresh);
- const __m128i t_max = _mm_max_epu8(t_1, t_2);
-
- const __m128i t_max_h = _mm_subs_epu8(t_max, h);
- *not_hev = _mm_cmpeq_epi8(t_max_h, zero); // not_hev <= t1 && not_hev <= t2
-}
-
-// input pixels are int8_t
-static WEBP_INLINE void GetBaseDelta(const __m128i* const p1,
- const __m128i* const p0,
- const __m128i* const q0,
- const __m128i* const q1,
- __m128i* const delta) {
- // beware of addition order, for saturation!
- const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1
- const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0
- const __m128i s1 = _mm_adds_epi8(p1_q1, q0_p0); // p1 - q1 + 1 * (q0 - p0)
- const __m128i s2 = _mm_adds_epi8(q0_p0, s1); // p1 - q1 + 2 * (q0 - p0)
- const __m128i s3 = _mm_adds_epi8(q0_p0, s2); // p1 - q1 + 3 * (q0 - p0)
- *delta = s3;
-}
-
-// input and output are int8_t
-static WEBP_INLINE void DoSimpleFilter(__m128i* const p0, __m128i* const q0,
- const __m128i* const fl) {
- const __m128i k3 = _mm_set1_epi8(3);
- const __m128i k4 = _mm_set1_epi8(4);
- __m128i v3 = _mm_adds_epi8(*fl, k3);
- __m128i v4 = _mm_adds_epi8(*fl, k4);
-
- SignedShift8b(&v4); // v4 >> 3
- SignedShift8b(&v3); // v3 >> 3
- *q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4
- *p0 = _mm_adds_epi8(*p0, v3); // p0 += v3
-}
-
-// Updates values of 2 pixels at MB edge during complex filtering.
-// Update operations:
-// q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)]
-// Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip).
-static WEBP_INLINE void Update2Pixels(__m128i* const pi, __m128i* const qi,
- const __m128i* const a0_lo,
- const __m128i* const a0_hi) {
- const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7);
- const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7);
- const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi);
- const __m128i sign_bit = _mm_set1_epi8(0x80);
- *pi = _mm_adds_epi8(*pi, delta);
- *qi = _mm_subs_epi8(*qi, delta);
- FLIP_SIGN_BIT2(*pi, *qi);
-}
-
-// input pixels are uint8_t
-static WEBP_INLINE void NeedsFilter(const __m128i* const p1,
- const __m128i* const p0,
- const __m128i* const q0,
- const __m128i* const q1,
- int thresh, __m128i* const mask) {
- const __m128i m_thresh = _mm_set1_epi8(thresh);
- const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
- const __m128i kFE = _mm_set1_epi8(0xFE);
- const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero
- const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2
-
- const __m128i t4 = MM_ABS(*p0, *q0); // abs(p0 - q0)
- const __m128i t5 = _mm_adds_epu8(t4, t4); // abs(p0 - q0) * 2
- const __m128i t6 = _mm_adds_epu8(t5, t3); // abs(p0-q0)*2 + abs(p1-q1)/2
-
- const __m128i t7 = _mm_subs_epu8(t6, m_thresh); // mask <= m_thresh
- *mask = _mm_cmpeq_epi8(t7, _mm_setzero_si128());
-}
-
-//------------------------------------------------------------------------------
-// Edge filtering functions
-
-// Applies filter on 2 pixels (p0 and q0)
-static WEBP_INLINE void DoFilter2(__m128i* const p1, __m128i* const p0,
- __m128i* const q0, __m128i* const q1,
- int thresh) {
- __m128i a, mask;
- const __m128i sign_bit = _mm_set1_epi8(0x80);
- // convert p1/q1 to int8_t (for GetBaseDelta)
- const __m128i p1s = _mm_xor_si128(*p1, sign_bit);
- const __m128i q1s = _mm_xor_si128(*q1, sign_bit);
-
- NeedsFilter(p1, p0, q0, q1, thresh, &mask);
-
- FLIP_SIGN_BIT2(*p0, *q0);
- GetBaseDelta(&p1s, p0, q0, &q1s, &a);
- a = _mm_and_si128(a, mask); // mask filter values we don't care about
- DoSimpleFilter(p0, q0, &a);
- FLIP_SIGN_BIT2(*p0, *q0);
-}
-
-// Applies filter on 4 pixels (p1, p0, q0 and q1)
-static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0,
- __m128i* const q0, __m128i* const q1,
- const __m128i* const mask, int hev_thresh) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i sign_bit = _mm_set1_epi8(0x80);
- const __m128i k64 = _mm_set1_epi8(64);
- const __m128i k3 = _mm_set1_epi8(3);
- const __m128i k4 = _mm_set1_epi8(4);
- __m128i not_hev;
- __m128i t1, t2, t3;
-
- // compute hev mask
- GetNotHEV(p1, p0, q0, q1, hev_thresh, &not_hev);
-
- // convert to signed values
- FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
-
- t1 = _mm_subs_epi8(*p1, *q1); // p1 - q1
- t1 = _mm_andnot_si128(not_hev, t1); // hev(p1 - q1)
- t2 = _mm_subs_epi8(*q0, *p0); // q0 - p0
- t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 1 * (q0 - p0)
- t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 2 * (q0 - p0)
- t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0)
- t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about
-
- t2 = _mm_adds_epi8(t1, k3); // 3 * (q0 - p0) + hev(p1 - q1) + 3
- t3 = _mm_adds_epi8(t1, k4); // 3 * (q0 - p0) + hev(p1 - q1) + 4
- SignedShift8b(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3
- SignedShift8b(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3
- *p0 = _mm_adds_epi8(*p0, t2); // p0 += t2
- *q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3
- FLIP_SIGN_BIT2(*p0, *q0);
-
- // this is equivalent to signed (a + 1) >> 1 calculation
- t2 = _mm_add_epi8(t3, sign_bit);
- t3 = _mm_avg_epu8(t2, zero);
- t3 = _mm_sub_epi8(t3, k64);
-
- t3 = _mm_and_si128(not_hev, t3); // if !hev
- *q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3
- *p1 = _mm_adds_epi8(*p1, t3); // p1 += t3
- FLIP_SIGN_BIT2(*p1, *q1);
-}
-
-// Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2)
-static WEBP_INLINE void DoFilter6(__m128i* const p2, __m128i* const p1,
- __m128i* const p0, __m128i* const q0,
- __m128i* const q1, __m128i* const q2,
- const __m128i* const mask, int hev_thresh) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i sign_bit = _mm_set1_epi8(0x80);
- __m128i a, not_hev;
-
- // compute hev mask
- GetNotHEV(p1, p0, q0, q1, hev_thresh, &not_hev);
-
- FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
- FLIP_SIGN_BIT2(*p2, *q2);
- GetBaseDelta(p1, p0, q0, q1, &a);
-
- { // do simple filter on pixels with hev
- const __m128i m = _mm_andnot_si128(not_hev, *mask);
- const __m128i f = _mm_and_si128(a, m);
- DoSimpleFilter(p0, q0, &f);
- }
-
- { // do strong filter on pixels with not hev
- const __m128i k9 = _mm_set1_epi16(0x0900);
- const __m128i k63 = _mm_set1_epi16(63);
-
- const __m128i m = _mm_and_si128(not_hev, *mask);
- const __m128i f = _mm_and_si128(a, m);
-
- const __m128i f_lo = _mm_unpacklo_epi8(zero, f);
- const __m128i f_hi = _mm_unpackhi_epi8(zero, f);
-
- const __m128i f9_lo = _mm_mulhi_epi16(f_lo, k9); // Filter (lo) * 9
- const __m128i f9_hi = _mm_mulhi_epi16(f_hi, k9); // Filter (hi) * 9
-
- const __m128i a2_lo = _mm_add_epi16(f9_lo, k63); // Filter * 9 + 63
- const __m128i a2_hi = _mm_add_epi16(f9_hi, k63); // Filter * 9 + 63
-
- const __m128i a1_lo = _mm_add_epi16(a2_lo, f9_lo); // Filter * 18 + 63
- const __m128i a1_hi = _mm_add_epi16(a2_hi, f9_hi); // Filter * 18 + 63
-
- const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63
- const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63
-
- Update2Pixels(p2, q2, &a2_lo, &a2_hi);
- Update2Pixels(p1, q1, &a1_lo, &a1_hi);
- Update2Pixels(p0, q0, &a0_lo, &a0_hi);
- }
-}
-
-// reads 8 rows across a vertical edge.
-static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride,
- __m128i* const p, __m128i* const q) {
- // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00
- // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10
- const __m128i A0 = _mm_set_epi32(
- WebPMemToUint32(&b[6 * stride]), WebPMemToUint32(&b[2 * stride]),
- WebPMemToUint32(&b[4 * stride]), WebPMemToUint32(&b[0 * stride]));
- const __m128i A1 = _mm_set_epi32(
- WebPMemToUint32(&b[7 * stride]), WebPMemToUint32(&b[3 * stride]),
- WebPMemToUint32(&b[5 * stride]), WebPMemToUint32(&b[1 * stride]));
-
- // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
- // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
- const __m128i B0 = _mm_unpacklo_epi8(A0, A1);
- const __m128i B1 = _mm_unpackhi_epi8(A0, A1);
-
- // C0 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
- // C1 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
- const __m128i C0 = _mm_unpacklo_epi16(B0, B1);
- const __m128i C1 = _mm_unpackhi_epi16(B0, B1);
-
- // *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
- // *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
- *p = _mm_unpacklo_epi32(C0, C1);
- *q = _mm_unpackhi_epi32(C0, C1);
-}
-
-static WEBP_INLINE void Load16x4(const uint8_t* const r0,
- const uint8_t* const r8,
- int stride,
- __m128i* const p1, __m128i* const p0,
- __m128i* const q0, __m128i* const q1) {
- // Assume the pixels around the edge (|) are numbered as follows
- // 00 01 | 02 03
- // 10 11 | 12 13
- // ... | ...
- // e0 e1 | e2 e3
- // f0 f1 | f2 f3
- //
- // r0 is pointing to the 0th row (00)
- // r8 is pointing to the 8th row (80)
-
- // Load
- // p1 = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
- // q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
- // p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
- // q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
- Load8x4(r0, stride, p1, q0);
- Load8x4(r8, stride, p0, q1);
-
- {
- // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
- // p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
- // q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
- // q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
- const __m128i t1 = *p1;
- const __m128i t2 = *q0;
- *p1 = _mm_unpacklo_epi64(t1, *p0);
- *p0 = _mm_unpackhi_epi64(t1, *p0);
- *q0 = _mm_unpacklo_epi64(t2, *q1);
- *q1 = _mm_unpackhi_epi64(t2, *q1);
- }
-}
-
-static WEBP_INLINE void Store4x4(__m128i* const x, uint8_t* dst, int stride) {
- int i;
- for (i = 0; i < 4; ++i, dst += stride) {
- WebPUint32ToMem(dst, _mm_cvtsi128_si32(*x));
- *x = _mm_srli_si128(*x, 4);
- }
-}
-
-// Transpose back and store
-static WEBP_INLINE void Store16x4(const __m128i* const p1,
- const __m128i* const p0,
- const __m128i* const q0,
- const __m128i* const q1,
- uint8_t* r0, uint8_t* r8,
- int stride) {
- __m128i t1, p1_s, p0_s, q0_s, q1_s;
-
- // p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
- // p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
- t1 = *p0;
- p0_s = _mm_unpacklo_epi8(*p1, t1);
- p1_s = _mm_unpackhi_epi8(*p1, t1);
-
- // q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
- // q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
- t1 = *q0;
- q0_s = _mm_unpacklo_epi8(t1, *q1);
- q1_s = _mm_unpackhi_epi8(t1, *q1);
-
- // p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
- // q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
- t1 = p0_s;
- p0_s = _mm_unpacklo_epi16(t1, q0_s);
- q0_s = _mm_unpackhi_epi16(t1, q0_s);
-
- // p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
- // q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
- t1 = p1_s;
- p1_s = _mm_unpacklo_epi16(t1, q1_s);
- q1_s = _mm_unpackhi_epi16(t1, q1_s);
-
- Store4x4(&p0_s, r0, stride);
- r0 += 4 * stride;
- Store4x4(&q0_s, r0, stride);
-
- Store4x4(&p1_s, r8, stride);
- r8 += 4 * stride;
- Store4x4(&q1_s, r8, stride);
-}
-
-//------------------------------------------------------------------------------
-// Simple In-loop filtering (Paragraph 15.2)
-
-static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
- // Load
- __m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]);
- __m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]);
- __m128i q0 = _mm_loadu_si128((__m128i*)&p[0]);
- __m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]);
-
- DoFilter2(&p1, &p0, &q0, &q1, thresh);
-
- // Store
- _mm_storeu_si128((__m128i*)&p[-stride], p0);
- _mm_storeu_si128((__m128i*)&p[0], q0);
-}
-
-static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
- __m128i p1, p0, q0, q1;
-
- p -= 2; // beginning of p1
-
- Load16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1);
- DoFilter2(&p1, &p0, &q0, &q1, thresh);
- Store16x4(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride);
-}
-
-static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4 * stride;
- SimpleVFilter16(p, stride, thresh);
- }
-}
-
-static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
- int k;
- for (k = 3; k > 0; --k) {
- p += 4;
- SimpleHFilter16(p, stride, thresh);
- }
-}
-
-//------------------------------------------------------------------------------
-// Complex In-loop filtering (Paragraph 15.3)
-
-#define MAX_DIFF1(p3, p2, p1, p0, m) do { \
- m = MM_ABS(p1, p0); \
- m = _mm_max_epu8(m, MM_ABS(p3, p2)); \
- m = _mm_max_epu8(m, MM_ABS(p2, p1)); \
-} while (0)
-
-#define MAX_DIFF2(p3, p2, p1, p0, m) do { \
- m = _mm_max_epu8(m, MM_ABS(p1, p0)); \
- m = _mm_max_epu8(m, MM_ABS(p3, p2)); \
- m = _mm_max_epu8(m, MM_ABS(p2, p1)); \
-} while (0)
-
-#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \
- e1 = _mm_loadu_si128((__m128i*)&(p)[0 * stride]); \
- e2 = _mm_loadu_si128((__m128i*)&(p)[1 * stride]); \
- e3 = _mm_loadu_si128((__m128i*)&(p)[2 * stride]); \
- e4 = _mm_loadu_si128((__m128i*)&(p)[3 * stride]); \
-}
-
-#define LOADUV_H_EDGE(p, u, v, stride) do { \
- const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \
- const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \
- p = _mm_unpacklo_epi64(U, V); \
-} while (0)
-
-#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \
- LOADUV_H_EDGE(e1, u, v, 0 * stride); \
- LOADUV_H_EDGE(e2, u, v, 1 * stride); \
- LOADUV_H_EDGE(e3, u, v, 2 * stride); \
- LOADUV_H_EDGE(e4, u, v, 3 * stride); \
-}
-
-#define STOREUV(p, u, v, stride) { \
- _mm_storel_epi64((__m128i*)&u[(stride)], p); \
- p = _mm_srli_si128(p, 8); \
- _mm_storel_epi64((__m128i*)&v[(stride)], p); \
-}
-
-static WEBP_INLINE void ComplexMask(const __m128i* const p1,
- const __m128i* const p0,
- const __m128i* const q0,
- const __m128i* const q1,
- int thresh, int ithresh,
- __m128i* const mask) {
- const __m128i it = _mm_set1_epi8(ithresh);
- const __m128i diff = _mm_subs_epu8(*mask, it);
- const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128());
- __m128i filter_mask;
- NeedsFilter(p1, p0, q0, q1, thresh, &filter_mask);
- *mask = _mm_and_si128(thresh_mask, filter_mask);
-}
-
-// on macroblock edges
-static void VFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- __m128i t1;
- __m128i mask;
- __m128i p2, p1, p0, q0, q1, q2;
-
- // Load p3, p2, p1, p0
- LOAD_H_EDGES4(p - 4 * stride, stride, t1, p2, p1, p0);
- MAX_DIFF1(t1, p2, p1, p0, mask);
-
- // Load q0, q1, q2, q3
- LOAD_H_EDGES4(p, stride, q0, q1, q2, t1);
- MAX_DIFF2(t1, q2, q1, q0, mask);
-
- ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
- DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
-
- // Store
- _mm_storeu_si128((__m128i*)&p[-3 * stride], p2);
- _mm_storeu_si128((__m128i*)&p[-2 * stride], p1);
- _mm_storeu_si128((__m128i*)&p[-1 * stride], p0);
- _mm_storeu_si128((__m128i*)&p[+0 * stride], q0);
- _mm_storeu_si128((__m128i*)&p[+1 * stride], q1);
- _mm_storeu_si128((__m128i*)&p[+2 * stride], q2);
-}
-
-static void HFilter16(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- __m128i mask;
- __m128i p3, p2, p1, p0, q0, q1, q2, q3;
-
- uint8_t* const b = p - 4;
- Load16x4(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0
- MAX_DIFF1(p3, p2, p1, p0, mask);
-
- Load16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3
- MAX_DIFF2(q3, q2, q1, q0, mask);
-
- ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
- DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
-
- Store16x4(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride);
- Store16x4(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride);
-}
-
-// on three inner edges
-static void VFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- __m128i p3, p2, p1, p0; // loop invariants
-
- LOAD_H_EDGES4(p, stride, p3, p2, p1, p0); // prologue
-
- for (k = 3; k > 0; --k) {
- __m128i mask, tmp1, tmp2;
- uint8_t* const b = p + 2 * stride; // beginning of p1
- p += 4 * stride;
-
- MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask
- LOAD_H_EDGES4(p, stride, p3, p2, tmp1, tmp2);
- MAX_DIFF2(p3, p2, tmp1, tmp2, mask);
-
- // p3 and p2 are not just temporary variables here: they will be
- // re-used for next span. And q2/q3 will become p1/p0 accordingly.
- ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask);
- DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh);
-
- // Store
- _mm_storeu_si128((__m128i*)&b[0 * stride], p1);
- _mm_storeu_si128((__m128i*)&b[1 * stride], p0);
- _mm_storeu_si128((__m128i*)&b[2 * stride], p3);
- _mm_storeu_si128((__m128i*)&b[3 * stride], p2);
-
- // rotate samples
- p1 = tmp1;
- p0 = tmp2;
- }
-}
-
-static void HFilter16i(uint8_t* p, int stride,
- int thresh, int ithresh, int hev_thresh) {
- int k;
- __m128i p3, p2, p1, p0; // loop invariants
-
- Load16x4(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue
-
- for (k = 3; k > 0; --k) {
- __m128i mask, tmp1, tmp2;
- uint8_t* const b = p + 2; // beginning of p1
-
- p += 4; // beginning of q0 (and next span)
-
- MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask
- Load16x4(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2);
- MAX_DIFF2(p3, p2, tmp1, tmp2, mask);
-
- ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask);
- DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh);
-
- Store16x4(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride);
-
- // rotate samples
- p1 = tmp1;
- p0 = tmp2;
- }
-}
-
-// 8-pixels wide variant, for chroma filtering
-static void VFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- __m128i mask;
- __m128i t1, p2, p1, p0, q0, q1, q2;
-
- // Load p3, p2, p1, p0
- LOADUV_H_EDGES4(u - 4 * stride, v - 4 * stride, stride, t1, p2, p1, p0);
- MAX_DIFF1(t1, p2, p1, p0, mask);
-
- // Load q0, q1, q2, q3
- LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1);
- MAX_DIFF2(t1, q2, q1, q0, mask);
-
- ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
- DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
-
- // Store
- STOREUV(p2, u, v, -3 * stride);
- STOREUV(p1, u, v, -2 * stride);
- STOREUV(p0, u, v, -1 * stride);
- STOREUV(q0, u, v, 0 * stride);
- STOREUV(q1, u, v, 1 * stride);
- STOREUV(q2, u, v, 2 * stride);
-}
-
-static void HFilter8(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- __m128i mask;
- __m128i p3, p2, p1, p0, q0, q1, q2, q3;
-
- uint8_t* const tu = u - 4;
- uint8_t* const tv = v - 4;
- Load16x4(tu, tv, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0
- MAX_DIFF1(p3, p2, p1, p0, mask);
-
- Load16x4(u, v, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3
- MAX_DIFF2(q3, q2, q1, q0, mask);
-
- ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
- DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
-
- Store16x4(&p3, &p2, &p1, &p0, tu, tv, stride);
- Store16x4(&q0, &q1, &q2, &q3, u, v, stride);
-}
-
-static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- __m128i mask;
- __m128i t1, t2, p1, p0, q0, q1;
-
- // Load p3, p2, p1, p0
- LOADUV_H_EDGES4(u, v, stride, t2, t1, p1, p0);
- MAX_DIFF1(t2, t1, p1, p0, mask);
-
- u += 4 * stride;
- v += 4 * stride;
-
- // Load q0, q1, q2, q3
- LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2);
- MAX_DIFF2(t2, t1, q1, q0, mask);
-
- ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
- DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
-
- // Store
- STOREUV(p1, u, v, -2 * stride);
- STOREUV(p0, u, v, -1 * stride);
- STOREUV(q0, u, v, 0 * stride);
- STOREUV(q1, u, v, 1 * stride);
-}
-
-static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_thresh) {
- __m128i mask;
- __m128i t1, t2, p1, p0, q0, q1;
- Load16x4(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
- MAX_DIFF1(t2, t1, p1, p0, mask);
-
- u += 4; // beginning of q0
- v += 4;
- Load16x4(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3
- MAX_DIFF2(t2, t1, q1, q0, mask);
-
- ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
- DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
-
- u -= 2; // beginning of p1
- v -= 2;
- Store16x4(&p1, &p0, &q0, &q1, u, v, stride);
-}
-
-//------------------------------------------------------------------------------
-// 4x4 predictions
-
-#define DST(x, y) dst[(x) + (y) * BPS]
-#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
-
-// We use the following 8b-arithmetic tricks:
-// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1
-// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1]
-// and:
-// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb
-// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1
-// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1
-
-static void VE4(uint8_t* dst) { // vertical
- const __m128i one = _mm_set1_epi8(1);
- const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
- const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
- const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
- const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00);
- const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one);
- const __m128i b = _mm_subs_epu8(a, lsb);
- const __m128i avg = _mm_avg_epu8(b, BCDEFGH0);
- const uint32_t vals = _mm_cvtsi128_si32(avg);
- int i;
- for (i = 0; i < 4; ++i) {
- WebPUint32ToMem(dst + i * BPS, vals);
- }
-}
-
-static void LD4(uint8_t* dst) { // Down-Left
- const __m128i one = _mm_set1_epi8(1);
- const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS));
- const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
- const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
- const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, dst[-BPS + 7], 3);
- const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0);
- const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
- const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
- const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg ));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
-}
-
-static void VR4(uint8_t* dst) { // Vertical-Right
- const __m128i one = _mm_set1_epi8(1);
- const int I = dst[-1 + 0 * BPS];
- const int J = dst[-1 + 1 * BPS];
- const int K = dst[-1 + 2 * BPS];
- const int X = dst[-1 - BPS];
- const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
- const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
- const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
- const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
- const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0);
- const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
- const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
- const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
- const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd ));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh ));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
-
- // these two are hard to implement in SSE2, so we keep the C-version:
- DST(0, 2) = AVG3(J, I, X);
- DST(0, 3) = AVG3(K, J, I);
-}
-
-static void VL4(uint8_t* dst) { // Vertical-Left
- const __m128i one = _mm_set1_epi8(1);
- const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS));
- const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1);
- const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2);
- const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_);
- const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_);
- const __m128i avg3 = _mm_avg_epu8(avg1, avg2);
- const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one);
- const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_);
- const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_);
- const __m128i abbc = _mm_or_si128(ab, bc);
- const __m128i lsb2 = _mm_and_si128(abbc, lsb1);
- const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
- const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 ));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 ));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
-
- // these two are hard to get and irregular
- DST(3, 2) = (extra_out >> 0) & 0xff;
- DST(3, 3) = (extra_out >> 8) & 0xff;
-}
-
-static void RD4(uint8_t* dst) { // Down-right
- const __m128i one = _mm_set1_epi8(1);
- const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1));
- const __m128i ____XABCD = _mm_slli_si128(XABCD, 4);
- const uint32_t I = dst[-1 + 0 * BPS];
- const uint32_t J = dst[-1 + 1 * BPS];
- const uint32_t K = dst[-1 + 2 * BPS];
- const uint32_t L = dst[-1 + 3 * BPS];
- const __m128i LKJI_____ =
- _mm_cvtsi32_si128(L | (K << 8) | (J << 16) | (I << 24));
- const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD);
- const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1);
- const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2);
- const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD);
- const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
- const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
- const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg ));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
-}
-
-#undef DST
-#undef AVG3
-
-//------------------------------------------------------------------------------
-// Luma 16x16
-
-static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) {
- const uint8_t* top = dst - BPS;
- const __m128i zero = _mm_setzero_si128();
- int y;
- if (size == 4) {
- const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top));
- const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
- for (y = 0; y < 4; ++y, dst += BPS) {
- const int val = dst[-1] - top[-1];
- const __m128i base = _mm_set1_epi16(val);
- const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
- WebPUint32ToMem(dst, _mm_cvtsi128_si32(out));
- }
- } else if (size == 8) {
- const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
- const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
- for (y = 0; y < 8; ++y, dst += BPS) {
- const int val = dst[-1] - top[-1];
- const __m128i base = _mm_set1_epi16(val);
- const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
- _mm_storel_epi64((__m128i*)dst, out);
- }
- } else {
- const __m128i top_values = _mm_loadu_si128((const __m128i*)top);
- const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero);
- const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero);
- for (y = 0; y < 16; ++y, dst += BPS) {
- const int val = dst[-1] - top[-1];
- const __m128i base = _mm_set1_epi16(val);
- const __m128i out_0 = _mm_add_epi16(base, top_base_0);
- const __m128i out_1 = _mm_add_epi16(base, top_base_1);
- const __m128i out = _mm_packus_epi16(out_0, out_1);
- _mm_storeu_si128((__m128i*)dst, out);
- }
- }
-}
-
-static void TM4(uint8_t* dst) { TrueMotion(dst, 4); }
-static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); }
-static void TM16(uint8_t* dst) { TrueMotion(dst, 16); }
-
-static void VE16(uint8_t* dst) {
- const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
- int j;
- for (j = 0; j < 16; ++j) {
- _mm_storeu_si128((__m128i*)(dst + j * BPS), top);
- }
-}
-
-static void HE16(uint8_t* dst) { // horizontal
- int j;
- for (j = 16; j > 0; --j) {
- const __m128i values = _mm_set1_epi8(dst[-1]);
- _mm_storeu_si128((__m128i*)dst, values);
- dst += BPS;
- }
-}
-
-static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) {
- int j;
- const __m128i values = _mm_set1_epi8(v);
- for (j = 0; j < 16; ++j) {
- _mm_storeu_si128((__m128i*)(dst + j * BPS), values);
- }
-}
-
-static void DC16(uint8_t* dst) { // DC
- const __m128i zero = _mm_setzero_si128();
- const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
- const __m128i sad8x2 = _mm_sad_epu8(top, zero);
- // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
- const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
- int left = 0;
- int j;
- for (j = 0; j < 16; ++j) {
- left += dst[-1 + j * BPS];
- }
- {
- const int DC = _mm_cvtsi128_si32(sum) + left + 16;
- Put16(DC >> 5, dst);
- }
-}
-
-static void DC16NoTop(uint8_t* dst) { // DC with top samples not available
- int DC = 8;
- int j;
- for (j = 0; j < 16; ++j) {
- DC += dst[-1 + j * BPS];
- }
- Put16(DC >> 4, dst);
-}
-
-static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available
- const __m128i zero = _mm_setzero_si128();
- const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS));
- const __m128i sad8x2 = _mm_sad_epu8(top, zero);
- // sum the two sads: sad8x2[0:1] + sad8x2[8:9]
- const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2));
- const int DC = _mm_cvtsi128_si32(sum) + 8;
- Put16(DC >> 4, dst);
-}
-
-static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples
- Put16(0x80, dst);
-}
-
-//------------------------------------------------------------------------------
-// Chroma
-
-static void VE8uv(uint8_t* dst) { // vertical
- int j;
- const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
- for (j = 0; j < 8; ++j) {
- _mm_storel_epi64((__m128i*)(dst + j * BPS), top);
- }
-}
-
-static void HE8uv(uint8_t* dst) { // horizontal
- int j;
- for (j = 0; j < 8; ++j) {
- const __m128i values = _mm_set1_epi8(dst[-1]);
- _mm_storel_epi64((__m128i*)dst, values);
- dst += BPS;
- }
-}
-
-// helper for chroma-DC predictions
-static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) {
- int j;
- const __m128i values = _mm_set1_epi8(v);
- for (j = 0; j < 8; ++j) {
- _mm_storel_epi64((__m128i*)(dst + j * BPS), values);
- }
-}
-
-static void DC8uv(uint8_t* dst) { // DC
- const __m128i zero = _mm_setzero_si128();
- const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
- const __m128i sum = _mm_sad_epu8(top, zero);
- int left = 0;
- int j;
- for (j = 0; j < 8; ++j) {
- left += dst[-1 + j * BPS];
- }
- {
- const int DC = _mm_cvtsi128_si32(sum) + left + 8;
- Put8x8uv(DC >> 4, dst);
- }
-}
-
-static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
- const __m128i zero = _mm_setzero_si128();
- const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS));
- const __m128i sum = _mm_sad_epu8(top, zero);
- const int DC = _mm_cvtsi128_si32(sum) + 4;
- Put8x8uv(DC >> 3, dst);
-}
-
-static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
- int dc0 = 4;
- int i;
- for (i = 0; i < 8; ++i) {
- dc0 += dst[-1 + i * BPS];
- }
- Put8x8uv(dc0 >> 3, dst);
-}
-
-static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing
- Put8x8uv(0x80, dst);
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8DspInitSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE2(void) {
- VP8Transform = Transform;
-#if defined(USE_TRANSFORM_AC3)
- VP8TransformAC3 = TransformAC3;
-#endif
-
- VP8VFilter16 = VFilter16;
- VP8HFilter16 = HFilter16;
- VP8VFilter8 = VFilter8;
- VP8HFilter8 = HFilter8;
- VP8VFilter16i = VFilter16i;
- VP8HFilter16i = HFilter16i;
- VP8VFilter8i = VFilter8i;
- VP8HFilter8i = HFilter8i;
-
- VP8SimpleVFilter16 = SimpleVFilter16;
- VP8SimpleHFilter16 = SimpleHFilter16;
- VP8SimpleVFilter16i = SimpleVFilter16i;
- VP8SimpleHFilter16i = SimpleHFilter16i;
-
- VP8PredLuma4[1] = TM4;
- VP8PredLuma4[2] = VE4;
- VP8PredLuma4[4] = RD4;
- VP8PredLuma4[5] = VR4;
- VP8PredLuma4[6] = LD4;
- VP8PredLuma4[7] = VL4;
-
- VP8PredLuma16[0] = DC16;
- VP8PredLuma16[1] = TM16;
- VP8PredLuma16[2] = VE16;
- VP8PredLuma16[3] = HE16;
- VP8PredLuma16[4] = DC16NoTop;
- VP8PredLuma16[5] = DC16NoLeft;
- VP8PredLuma16[6] = DC16NoTopLeft;
-
- VP8PredChroma8[0] = DC8uv;
- VP8PredChroma8[1] = TM8uv;
- VP8PredChroma8[2] = VE8uv;
- VP8PredChroma8[3] = HE8uv;
- VP8PredChroma8[4] = DC8uvNoTop;
- VP8PredChroma8[5] = DC8uvNoLeft;
- VP8PredChroma8[6] = DC8uvNoTopLeft;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(VP8DspInitSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/dec_sse41.c b/drivers/webp/dsp/dec_sse41.c
deleted file mode 100644
index 8d6aed13e6..0000000000
--- a/drivers/webp/dsp/dec_sse41.c
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE4 version of some decoding functions.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE41)
-
-#include <smmintrin.h>
-#include "../dec/vp8i.h"
-#include "../utils/utils.h"
-
-static void HE16(uint8_t* dst) { // horizontal
- int j;
- const __m128i kShuffle3 = _mm_set1_epi8(3);
- for (j = 16; j > 0; --j) {
- const __m128i in = _mm_cvtsi32_si128(WebPMemToUint32(dst - 4));
- const __m128i values = _mm_shuffle_epi8(in, kShuffle3);
- _mm_storeu_si128((__m128i*)dst, values);
- dst += BPS;
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8DspInitSSE41(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE41(void) {
- VP8PredLuma16[3] = HE16;
-}
-
-#else // !WEBP_USE_SSE41
-
-WEBP_DSP_INIT_STUB(VP8DspInitSSE41)
-
-#endif // WEBP_USE_SSE41
diff --git a/drivers/webp/dsp/dsp.h b/drivers/webp/dsp/dsp.h
deleted file mode 100644
index 2469f7d3ac..0000000000
--- a/drivers/webp/dsp/dsp.h
+++ /dev/null
@@ -1,569 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Speed-critical functions.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_DSP_DSP_H_
-#define WEBP_DSP_DSP_H_
-
-#ifdef HAVE_CONFIG_H
-#include "webp/config.h"
-#endif
-
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BPS 32 // this is the common stride for enc/dec
-
-//------------------------------------------------------------------------------
-// CPU detection
-
-#if defined(__GNUC__)
-# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
-# define LOCAL_GCC_PREREQ(maj, min) \
- (LOCAL_GCC_VERSION >= (((maj) << 8) | (min)))
-#else
-# define LOCAL_GCC_VERSION 0
-# define LOCAL_GCC_PREREQ(maj, min) 0
-#endif
-
-#ifndef __has_builtin
-# define __has_builtin(x) 0
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER > 1310 && \
- (defined(_M_X64) || defined(_M_IX86))
-#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER >= 1500 && \
- (defined(_M_X64) || defined(_M_IX86))
-#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets
-#endif
-
-// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp
-// files without intrinsics, allowing the corresponding Init() to be called.
-// Files containing intrinsics will need to be built targeting the instruction
-// set so should succeed on one of the earlier tests.
-#if defined(__SSE2__) || defined(WEBP_MSC_SSE2) || defined(WEBP_HAVE_SSE2)
-#define WEBP_USE_SSE2
-#endif
-
-#if defined(__SSE4_1__) || defined(WEBP_MSC_SSE41) || defined(WEBP_HAVE_SSE41)
-#define WEBP_USE_SSE41
-#endif
-
-#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2)
-#define WEBP_USE_AVX2
-#endif
-
-#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
-#define WEBP_ANDROID_NEON // Android targets that might support NEON
-#endif
-
-// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
-// inline assembly would need to be modified for use with Native Client.
-#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || \
- defined(__aarch64__) || defined(WEBP_HAVE_NEON)) && \
- !defined(__native_client__)
-#define WEBP_USE_NEON
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
-#define WEBP_USE_NEON
-#define WEBP_USE_INTRINSICS
-#endif
-
-#if defined(__mips__) && !defined(__mips64) && \
- defined(__mips_isa_rev) && (__mips_isa_rev >= 1) && (__mips_isa_rev < 6)
-#define WEBP_USE_MIPS32
-#if (__mips_isa_rev >= 2)
-#define WEBP_USE_MIPS32_R2
-#if defined(__mips_dspr2) || (__mips_dsp_rev >= 2)
-#define WEBP_USE_MIPS_DSP_R2
-#endif
-#endif
-#endif
-
-#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5)
-#define WEBP_USE_MSA
-#endif
-
-// This macro prevents thread_sanitizer from reporting known concurrent writes.
-#define WEBP_TSAN_IGNORE_FUNCTION
-#if defined(__has_feature)
-#if __has_feature(thread_sanitizer)
-#undef WEBP_TSAN_IGNORE_FUNCTION
-#define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread))
-#endif
-#endif
-
-#define WEBP_UBSAN_IGNORE_UNDEF
-#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
-#if !defined(WEBP_FORCE_ALIGNED) && defined(__clang__) && \
- defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-// This macro prevents the undefined behavior sanitizer from reporting
-// failures. This is only meant to silence unaligned loads on platforms that
-// are known to support them.
-#undef WEBP_UBSAN_IGNORE_UNDEF
-#define WEBP_UBSAN_IGNORE_UNDEF \
- __attribute__((no_sanitize("undefined")))
-
-// This macro prevents the undefined behavior sanitizer from reporting
-// failures related to unsigned integer overflows. This is only meant to
-// silence cases where this well defined behavior is expected.
-#undef WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
-#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW \
- __attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-
-typedef enum {
- kSSE2,
- kSSE3,
- kSSE4_1,
- kAVX,
- kAVX2,
- kNEON,
- kMIPS32,
- kMIPSdspR2,
- kMSA
-} CPUFeature;
-// returns true if the CPU supports the feature.
-typedef int (*VP8CPUInfo)(CPUFeature feature);
-WEBP_EXTERN(VP8CPUInfo) VP8GetCPUInfo;
-
-//------------------------------------------------------------------------------
-// Init stub generator
-
-// Defines an init function stub to ensure each module exposes a symbol,
-// avoiding a compiler warning.
-#define WEBP_DSP_INIT_STUB(func) \
- extern void func(void); \
- WEBP_TSAN_IGNORE_FUNCTION void func(void) {}
-
-//------------------------------------------------------------------------------
-// Encoding
-
-// Transforms
-// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms
-// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4).
-typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst,
- int do_two);
-typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out);
-typedef void (*VP8WHT)(const int16_t* in, int16_t* out);
-extern VP8Idct VP8ITransform;
-extern VP8Fdct VP8FTransform;
-extern VP8Fdct VP8FTransform2; // performs two transforms at a time
-extern VP8WHT VP8FTransformWHT;
-// Predictions
-// *dst is the destination block. *top and *left can be NULL.
-typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left,
- const uint8_t* top);
-typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top);
-extern VP8Intra4Preds VP8EncPredLuma4;
-extern VP8IntraPreds VP8EncPredLuma16;
-extern VP8IntraPreds VP8EncPredChroma8;
-
-typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref);
-extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4;
-typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref,
- const uint16_t* const weights);
-// The weights for VP8TDisto4x4 and VP8TDisto16x16 contain a row-major
-// 4 by 4 symmetric matrix.
-extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16;
-
-typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst);
-extern VP8BlockCopy VP8Copy4x4;
-extern VP8BlockCopy VP8Copy16x8;
-// Quantization
-struct VP8Matrix; // forward declaration
-typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16],
- const struct VP8Matrix* const mtx);
-// Same as VP8QuantizeBlock, but quantizes two consecutive blocks.
-typedef int (*VP8Quantize2Blocks)(int16_t in[32], int16_t out[32],
- const struct VP8Matrix* const mtx);
-
-extern VP8QuantizeBlock VP8EncQuantizeBlock;
-extern VP8Quantize2Blocks VP8EncQuantize2Blocks;
-
-// specific to 2nd transform:
-typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16],
- const struct VP8Matrix* const mtx);
-extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT;
-
-extern const int VP8DspScan[16 + 4 + 4];
-
-// Collect histogram for susceptibility calculation.
-#define MAX_COEFF_THRESH 31 // size of histogram used by CollectHistogram.
-typedef struct {
- // We only need to store max_value and last_non_zero, not the distribution.
- int max_value;
- int last_non_zero;
-} VP8Histogram;
-typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block,
- VP8Histogram* const histo);
-extern VP8CHisto VP8CollectHistogram;
-// General-purpose util function to help VP8CollectHistogram().
-void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1],
- VP8Histogram* const histo);
-
-// must be called before using any of the above
-void VP8EncDspInit(void);
-
-//------------------------------------------------------------------------------
-// cost functions (encoding)
-
-extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p)
-// approximate cost per level:
-extern const uint16_t VP8LevelFixedCosts[2047 /*MAX_LEVEL*/ + 1];
-extern const uint8_t VP8EncBands[16 + 1];
-
-struct VP8Residual;
-typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs,
- struct VP8Residual* const res);
-extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
-
-// Cost calculation function.
-typedef int (*VP8GetResidualCostFunc)(int ctx0,
- const struct VP8Residual* const res);
-extern VP8GetResidualCostFunc VP8GetResidualCost;
-
-// must be called before anything using the above
-void VP8EncDspCostInit(void);
-
-//------------------------------------------------------------------------------
-// SSIM utils
-
-// struct for accumulating statistical moments
-typedef struct {
- double w; // sum(w_i) : sum of weights
- double xm, ym; // sum(w_i * x_i), sum(w_i * y_i)
- double xxm, xym, yym; // sum(w_i * x_i * x_i), etc.
-} VP8DistoStats;
-
-#define VP8_SSIM_KERNEL 3 // total size of the kernel: 2 * VP8_SSIM_KERNEL + 1
-typedef void (*VP8SSIMAccumulateClippedFunc)(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int xo, int yo, // center position
- int W, int H, // plane dimension
- VP8DistoStats* const stats);
-
-// This version is called with the guarantee that you can load 8 bytes and
-// 8 rows at offset src1 and src2
-typedef void (*VP8SSIMAccumulateFunc)(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- VP8DistoStats* const stats);
-
-extern VP8SSIMAccumulateFunc VP8SSIMAccumulate; // unclipped / unchecked
-extern VP8SSIMAccumulateClippedFunc VP8SSIMAccumulateClipped; // with clipping
-
-// must be called before using any of the above directly
-void VP8SSIMDspInit(void);
-
-//------------------------------------------------------------------------------
-// Decoding
-
-typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst);
-// when doing two transforms, coeffs is actually int16_t[2][16].
-typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two);
-extern VP8DecIdct2 VP8Transform;
-extern VP8DecIdct VP8TransformAC3;
-extern VP8DecIdct VP8TransformUV;
-extern VP8DecIdct VP8TransformDC;
-extern VP8DecIdct VP8TransformDCUV;
-extern VP8WHT VP8TransformWHT;
-
-// *dst is the destination block, with stride BPS. Boundary samples are
-// assumed accessible when needed.
-typedef void (*VP8PredFunc)(uint8_t* dst);
-extern VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */];
-extern VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */];
-extern VP8PredFunc VP8PredLuma4[/* NUM_BMODES */];
-
-// clipping tables (for filtering)
-extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127]
-extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15]
-extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255]
-extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255]
-// must be called first
-void VP8InitClipTables(void);
-
-// simple filter (only for luma)
-typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh);
-extern VP8SimpleFilterFunc VP8SimpleVFilter16;
-extern VP8SimpleFilterFunc VP8SimpleHFilter16;
-extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges
-extern VP8SimpleFilterFunc VP8SimpleHFilter16i;
-
-// regular filter (on both macroblock edges and inner edges)
-typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride,
- int thresh, int ithresh, int hev_t);
-typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride,
- int thresh, int ithresh, int hev_t);
-// on outer edge
-extern VP8LumaFilterFunc VP8VFilter16;
-extern VP8LumaFilterFunc VP8HFilter16;
-extern VP8ChromaFilterFunc VP8VFilter8;
-extern VP8ChromaFilterFunc VP8HFilter8;
-
-// on inner edge
-extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether
-extern VP8LumaFilterFunc VP8HFilter16i;
-extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether
-extern VP8ChromaFilterFunc VP8HFilter8i;
-
-// Dithering. Combines dithering values (centered around 128) with dst[],
-// according to: dst[] = clip(dst[] + (((dither[]-128) + 8) >> 4)
-#define VP8_DITHER_DESCALE 4
-#define VP8_DITHER_DESCALE_ROUNDER (1 << (VP8_DITHER_DESCALE - 1))
-#define VP8_DITHER_AMP_BITS 7
-#define VP8_DITHER_AMP_CENTER (1 << VP8_DITHER_AMP_BITS)
-extern void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst,
- int dst_stride);
-
-// must be called before anything using the above
-void VP8DspInit(void);
-
-//------------------------------------------------------------------------------
-// WebP I/O
-
-#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support
-
-// Convert a pair of y/u/v lines together to the output rgb/a colorspace.
-// bottom_y can be NULL if only one line of output is needed (at top/bottom).
-typedef void (*WebPUpsampleLinePairFunc)(
- const uint8_t* top_y, const uint8_t* bottom_y,
- const uint8_t* top_u, const uint8_t* top_v,
- const uint8_t* cur_u, const uint8_t* cur_v,
- uint8_t* top_dst, uint8_t* bottom_dst, int len);
-
-#ifdef FANCY_UPSAMPLING
-
-// Fancy upsampling functions to convert YUV to RGB(A) modes
-extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
-
-#endif // FANCY_UPSAMPLING
-
-// Per-row point-sampling methods.
-typedef void (*WebPSamplerRowFunc)(const uint8_t* y,
- const uint8_t* u, const uint8_t* v,
- uint8_t* dst, int len);
-// Generic function to apply 'WebPSamplerRowFunc' to the whole plane:
-void WebPSamplerProcessPlane(const uint8_t* y, int y_stride,
- const uint8_t* u, const uint8_t* v, int uv_stride,
- uint8_t* dst, int dst_stride,
- int width, int height, WebPSamplerRowFunc func);
-
-// Sampling functions to convert rows of YUV to RGB(A)
-extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */];
-
-// General function for converting two lines of ARGB or RGBA.
-// 'alpha_is_last' should be true if 0xff000000 is stored in memory as
-// as 0x00, 0x00, 0x00, 0xff (little endian).
-WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last);
-
-// YUV444->RGB converters
-typedef void (*WebPYUV444Converter)(const uint8_t* y,
- const uint8_t* u, const uint8_t* v,
- uint8_t* dst, int len);
-
-extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
-
-// Must be called before using the WebPUpsamplers[] (and for premultiplied
-// colorspaces like rgbA, rgbA4444, etc)
-void WebPInitUpsamplers(void);
-// Must be called before using WebPSamplers[]
-void WebPInitSamplers(void);
-// Must be called before using WebPYUV444Converters[]
-void WebPInitYUV444Converters(void);
-
-//------------------------------------------------------------------------------
-// ARGB -> YUV converters
-
-// Convert ARGB samples to luma Y.
-extern void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width);
-// Convert ARGB samples to U/V with downsampling. do_store should be '1' for
-// even lines and '0' for odd ones. 'src_width' is the original width, not
-// the U/V one.
-extern void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v,
- int src_width, int do_store);
-
-// Convert a row of accumulated (four-values) of rgba32 toward U/V
-extern void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb,
- uint8_t* u, uint8_t* v, int width);
-
-// Convert RGB or BGR to Y
-extern void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width);
-extern void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width);
-
-// used for plain-C fallback.
-extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v,
- int src_width, int do_store);
-extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb,
- uint8_t* u, uint8_t* v, int width);
-
-// Must be called before using the above.
-void WebPInitConvertARGBToYUV(void);
-
-//------------------------------------------------------------------------------
-// Rescaler
-
-struct WebPRescaler;
-
-// Import a row of data and save its contribution in the rescaler.
-// 'channel' denotes the channel number to be imported. 'Expand' corresponds to
-// the wrk->x_expand case. Otherwise, 'Shrink' is to be used.
-typedef void (*WebPRescalerImportRowFunc)(struct WebPRescaler* const wrk,
- const uint8_t* src);
-
-extern WebPRescalerImportRowFunc WebPRescalerImportRowExpand;
-extern WebPRescalerImportRowFunc WebPRescalerImportRowShrink;
-
-// Export one row (starting at x_out position) from rescaler.
-// 'Expand' corresponds to the wrk->y_expand case.
-// Otherwise 'Shrink' is to be used
-typedef void (*WebPRescalerExportRowFunc)(struct WebPRescaler* const wrk);
-extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand;
-extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink;
-
-// Plain-C implementation, as fall-back.
-extern void WebPRescalerImportRowExpandC(struct WebPRescaler* const wrk,
- const uint8_t* src);
-extern void WebPRescalerImportRowShrinkC(struct WebPRescaler* const wrk,
- const uint8_t* src);
-extern void WebPRescalerExportRowExpandC(struct WebPRescaler* const wrk);
-extern void WebPRescalerExportRowShrinkC(struct WebPRescaler* const wrk);
-
-// Main entry calls:
-extern void WebPRescalerImportRow(struct WebPRescaler* const wrk,
- const uint8_t* src);
-// Export one row (starting at x_out position) from rescaler.
-extern void WebPRescalerExportRow(struct WebPRescaler* const wrk);
-
-// Must be called first before using the above.
-void WebPRescalerDspInit(void);
-
-//------------------------------------------------------------------------------
-// Utilities for processing transparent channel.
-
-// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h.
-// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last).
-extern void (*WebPApplyAlphaMultiply)(
- uint8_t* rgba, int alpha_first, int w, int h, int stride);
-
-// Same, buf specifically for RGBA4444 format
-extern void (*WebPApplyAlphaMultiply4444)(
- uint8_t* rgba4444, int w, int h, int stride);
-
-// Dispatch the values from alpha[] plane to the ARGB destination 'dst'.
-// Returns true if alpha[] plane has non-trivial values different from 0xff.
-extern int (*WebPDispatchAlpha)(const uint8_t* alpha, int alpha_stride,
- int width, int height,
- uint8_t* dst, int dst_stride);
-
-// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the
-// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units.
-extern void (*WebPDispatchAlphaToGreen)(const uint8_t* alpha, int alpha_stride,
- int width, int height,
- uint32_t* dst, int dst_stride);
-
-// Extract the alpha values from 32b values in argb[] and pack them into alpha[]
-// (this is the opposite of WebPDispatchAlpha).
-// Returns true if there's only trivial 0xff alpha values.
-extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride,
- int width, int height,
- uint8_t* alpha, int alpha_stride);
-
-// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B).
-// Un-Multiply operation transforms x into x * 255 / A.
-
-// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row.
-extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
-
-// Same a WebPMultARGBRow(), but for several rows.
-void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
- int inverse);
-
-// Same for a row of single values, with side alpha values.
-extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
- int width, int inverse);
-
-// Same a WebPMultRow(), but for several 'num_rows' rows.
-void WebPMultRows(uint8_t* ptr, int stride,
- const uint8_t* alpha, int alpha_stride,
- int width, int num_rows, int inverse);
-
-// Plain-C versions, used as fallback by some implementations.
-void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha,
- int width, int inverse);
-void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse);
-
-// To be called first before using the above.
-void WebPInitAlphaProcessing(void);
-
-// ARGB packing function: a/r/g/b input is rgba or bgra order.
-extern void (*VP8PackARGB)(const uint8_t* a, const uint8_t* r,
- const uint8_t* g, const uint8_t* b, int len,
- uint32_t* out);
-
-// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order.
-extern void (*VP8PackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
- int len, int step, uint32_t* out);
-
-// To be called first before using the above.
-void VP8EncDspARGBInit(void);
-
-//------------------------------------------------------------------------------
-// Filter functions
-
-typedef enum { // Filter types.
- WEBP_FILTER_NONE = 0,
- WEBP_FILTER_HORIZONTAL,
- WEBP_FILTER_VERTICAL,
- WEBP_FILTER_GRADIENT,
- WEBP_FILTER_LAST = WEBP_FILTER_GRADIENT + 1, // end marker
- WEBP_FILTER_BEST, // meta-types
- WEBP_FILTER_FAST
-} WEBP_FILTER_TYPE;
-
-typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height,
- int stride, uint8_t* out);
-// In-place un-filtering.
-// Warning! 'prev_line' pointer can be equal to 'cur_line' or 'preds'.
-typedef void (*WebPUnfilterFunc)(const uint8_t* prev_line, const uint8_t* preds,
- uint8_t* cur_line, int width);
-
-// Filter the given data using the given predictor.
-// 'in' corresponds to a 2-dimensional pixel array of size (stride * height)
-// in raster order.
-// 'stride' is number of bytes per scan line (with possible padding).
-// 'out' should be pre-allocated.
-extern WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
-
-// In-place reconstruct the original data from the given filtered data.
-// The reconstruction will be done for 'num_rows' rows starting from 'row'
-// (assuming rows upto 'row - 1' are already reconstructed).
-extern WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
-
-// To be called first before using the above.
-void VP8FiltersInit(void);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DSP_DSP_H_ */
diff --git a/drivers/webp/dsp/enc.c b/drivers/webp/dsp/enc.c
deleted file mode 100644
index f639f5570c..0000000000
--- a/drivers/webp/dsp/enc.c
+++ /dev/null
@@ -1,863 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Speed-critical encoding functions.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h> // for abs()
-
-#include "./dsp.h"
-#include "../enc/vp8enci.h"
-
-static WEBP_INLINE uint8_t clip_8b(int v) {
- return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
-}
-
-static WEBP_INLINE int clip_max(int v, int max) {
- return (v > max) ? max : v;
-}
-
-//------------------------------------------------------------------------------
-// Compute susceptibility based on DCT-coeff histograms:
-// the higher, the "easier" the macroblock is to compress.
-
-const int VP8DspScan[16 + 4 + 4] = {
- // Luma
- 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
- 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
- 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
- 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS,
-
- 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U
- 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V
-};
-
-// general-purpose util function
-void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1],
- VP8Histogram* const histo) {
- int max_value = 0, last_non_zero = 1;
- int k;
- for (k = 0; k <= MAX_COEFF_THRESH; ++k) {
- const int value = distribution[k];
- if (value > 0) {
- if (value > max_value) max_value = value;
- last_non_zero = k;
- }
- }
- histo->max_value = max_value;
- histo->last_non_zero = last_non_zero;
-}
-
-static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block,
- VP8Histogram* const histo) {
- int j;
- int distribution[MAX_COEFF_THRESH + 1] = { 0 };
- for (j = start_block; j < end_block; ++j) {
- int k;
- int16_t out[16];
-
- VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
-
- // Convert coefficients to bin.
- for (k = 0; k < 16; ++k) {
- const int v = abs(out[k]) >> 3;
- const int clipped_value = clip_max(v, MAX_COEFF_THRESH);
- ++distribution[clipped_value];
- }
- }
- VP8SetHistogramData(distribution, histo);
-}
-
-//------------------------------------------------------------------------------
-// run-time tables (~4k)
-
-static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
-
-// We declare this variable 'volatile' to prevent instruction reordering
-// and make sure it's set to true _last_ (so as to be thread-safe)
-static volatile int tables_ok = 0;
-
-static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) {
- if (!tables_ok) {
- int i;
- for (i = -255; i <= 255 + 255; ++i) {
- clip1[255 + i] = clip_8b(i);
- }
- tables_ok = 1;
- }
-}
-
-
-//------------------------------------------------------------------------------
-// Transforms (Paragraph 14.4)
-
-#define STORE(x, y, v) \
- dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3))
-
-static const int kC1 = 20091 + (1 << 16);
-static const int kC2 = 35468;
-#define MUL(a, b) (((a) * (b)) >> 16)
-
-static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
- uint8_t* dst) {
- int C[4 * 4], *tmp;
- int i;
- tmp = C;
- for (i = 0; i < 4; ++i) { // vertical pass
- const int a = in[0] + in[8];
- const int b = in[0] - in[8];
- const int c = MUL(in[4], kC2) - MUL(in[12], kC1);
- const int d = MUL(in[4], kC1) + MUL(in[12], kC2);
- tmp[0] = a + d;
- tmp[1] = b + c;
- tmp[2] = b - c;
- tmp[3] = a - d;
- tmp += 4;
- in++;
- }
-
- tmp = C;
- for (i = 0; i < 4; ++i) { // horizontal pass
- const int dc = tmp[0] + 4;
- const int a = dc + tmp[8];
- const int b = dc - tmp[8];
- const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1);
- const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2);
- STORE(0, i, a + d);
- STORE(1, i, b + c);
- STORE(2, i, b - c);
- STORE(3, i, a - d);
- tmp++;
- }
-}
-
-static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
- int do_two) {
- ITransformOne(ref, in, dst);
- if (do_two) {
- ITransformOne(ref + 4, in + 16, dst + 4);
- }
-}
-
-static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
- int i;
- int tmp[16];
- for (i = 0; i < 4; ++i, src += BPS, ref += BPS) {
- const int d0 = src[0] - ref[0]; // 9bit dynamic range ([-255,255])
- const int d1 = src[1] - ref[1];
- const int d2 = src[2] - ref[2];
- const int d3 = src[3] - ref[3];
- const int a0 = (d0 + d3); // 10b [-510,510]
- const int a1 = (d1 + d2);
- const int a2 = (d1 - d2);
- const int a3 = (d0 - d3);
- tmp[0 + i * 4] = (a0 + a1) * 8; // 14b [-8160,8160]
- tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 1812) >> 9; // [-7536,7542]
- tmp[2 + i * 4] = (a0 - a1) * 8;
- tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9;
- }
- for (i = 0; i < 4; ++i) {
- const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b
- const int a1 = (tmp[4 + i] + tmp[ 8 + i]);
- const int a2 = (tmp[4 + i] - tmp[ 8 + i]);
- const int a3 = (tmp[0 + i] - tmp[12 + i]);
- out[0 + i] = (a0 + a1 + 7) >> 4; // 12b
- out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0);
- out[8 + i] = (a0 - a1 + 7) >> 4;
- out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16);
- }
-}
-
-static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) {
- VP8FTransform(src, ref, out);
- VP8FTransform(src + 4, ref + 4, out + 16);
-}
-
-static void FTransformWHT(const int16_t* in, int16_t* out) {
- // input is 12b signed
- int32_t tmp[16];
- int i;
- for (i = 0; i < 4; ++i, in += 64) {
- const int a0 = (in[0 * 16] + in[2 * 16]); // 13b
- const int a1 = (in[1 * 16] + in[3 * 16]);
- const int a2 = (in[1 * 16] - in[3 * 16]);
- const int a3 = (in[0 * 16] - in[2 * 16]);
- tmp[0 + i * 4] = a0 + a1; // 14b
- tmp[1 + i * 4] = a3 + a2;
- tmp[2 + i * 4] = a3 - a2;
- tmp[3 + i * 4] = a0 - a1;
- }
- for (i = 0; i < 4; ++i) {
- const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b
- const int a1 = (tmp[4 + i] + tmp[12+ i]);
- const int a2 = (tmp[4 + i] - tmp[12+ i]);
- const int a3 = (tmp[0 + i] - tmp[8 + i]);
- const int b0 = a0 + a1; // 16b
- const int b1 = a3 + a2;
- const int b2 = a3 - a2;
- const int b3 = a0 - a1;
- out[ 0 + i] = b0 >> 1; // 15b
- out[ 4 + i] = b1 >> 1;
- out[ 8 + i] = b2 >> 1;
- out[12 + i] = b3 >> 1;
- }
-}
-
-#undef MUL
-#undef STORE
-
-//------------------------------------------------------------------------------
-// Intra predictions
-
-static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) {
- int j;
- for (j = 0; j < size; ++j) {
- memset(dst + j * BPS, value, size);
- }
-}
-
-static WEBP_INLINE void VerticalPred(uint8_t* dst,
- const uint8_t* top, int size) {
- int j;
- if (top != NULL) {
- for (j = 0; j < size; ++j) memcpy(dst + j * BPS, top, size);
- } else {
- Fill(dst, 127, size);
- }
-}
-
-static WEBP_INLINE void HorizontalPred(uint8_t* dst,
- const uint8_t* left, int size) {
- if (left != NULL) {
- int j;
- for (j = 0; j < size; ++j) {
- memset(dst + j * BPS, left[j], size);
- }
- } else {
- Fill(dst, 129, size);
- }
-}
-
-static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left,
- const uint8_t* top, int size) {
- int y;
- if (left != NULL) {
- if (top != NULL) {
- const uint8_t* const clip = clip1 + 255 - left[-1];
- for (y = 0; y < size; ++y) {
- const uint8_t* const clip_table = clip + left[y];
- int x;
- for (x = 0; x < size; ++x) {
- dst[x] = clip_table[top[x]];
- }
- dst += BPS;
- }
- } else {
- HorizontalPred(dst, left, size);
- }
- } else {
- // true motion without left samples (hence: with default 129 value)
- // is equivalent to VE prediction where you just copy the top samples.
- // Note that if top samples are not available, the default value is
- // then 129, and not 127 as in the VerticalPred case.
- if (top != NULL) {
- VerticalPred(dst, top, size);
- } else {
- Fill(dst, 129, size);
- }
- }
-}
-
-static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left,
- const uint8_t* top,
- int size, int round, int shift) {
- int DC = 0;
- int j;
- if (top != NULL) {
- for (j = 0; j < size; ++j) DC += top[j];
- if (left != NULL) { // top and left present
- for (j = 0; j < size; ++j) DC += left[j];
- } else { // top, but no left
- DC += DC;
- }
- DC = (DC + round) >> shift;
- } else if (left != NULL) { // left but no top
- for (j = 0; j < size; ++j) DC += left[j];
- DC += DC;
- DC = (DC + round) >> shift;
- } else { // no top, no left, nothing.
- DC = 0x80;
- }
- Fill(dst, DC, size);
-}
-
-//------------------------------------------------------------------------------
-// Chroma 8x8 prediction (paragraph 12.2)
-
-static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- // U block
- DCMode(C8DC8 + dst, left, top, 8, 8, 4);
- VerticalPred(C8VE8 + dst, top, 8);
- HorizontalPred(C8HE8 + dst, left, 8);
- TrueMotion(C8TM8 + dst, left, top, 8);
- // V block
- dst += 8;
- if (top != NULL) top += 8;
- if (left != NULL) left += 16;
- DCMode(C8DC8 + dst, left, top, 8, 8, 4);
- VerticalPred(C8VE8 + dst, top, 8);
- HorizontalPred(C8HE8 + dst, left, 8);
- TrueMotion(C8TM8 + dst, left, top, 8);
-}
-
-//------------------------------------------------------------------------------
-// luma 16x16 prediction (paragraph 12.3)
-
-static void Intra16Preds(uint8_t* dst,
- const uint8_t* left, const uint8_t* top) {
- DCMode(I16DC16 + dst, left, top, 16, 16, 5);
- VerticalPred(I16VE16 + dst, top, 16);
- HorizontalPred(I16HE16 + dst, left, 16);
- TrueMotion(I16TM16 + dst, left, top, 16);
-}
-
-//------------------------------------------------------------------------------
-// luma 4x4 prediction
-
-#define DST(x, y) dst[(x) + (y) * BPS]
-#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
-#define AVG2(a, b) (((a) + (b) + 1) >> 1)
-
-static void VE4(uint8_t* dst, const uint8_t* top) { // vertical
- const uint8_t vals[4] = {
- AVG3(top[-1], top[0], top[1]),
- AVG3(top[ 0], top[1], top[2]),
- AVG3(top[ 1], top[2], top[3]),
- AVG3(top[ 2], top[3], top[4])
- };
- int i;
- for (i = 0; i < 4; ++i) {
- memcpy(dst + i * BPS, vals, 4);
- }
-}
-
-static void HE4(uint8_t* dst, const uint8_t* top) { // horizontal
- const int X = top[-1];
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int L = top[-5];
- WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J));
- WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K));
- WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L));
- WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L));
-}
-
-static void DC4(uint8_t* dst, const uint8_t* top) {
- uint32_t dc = 4;
- int i;
- for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i];
- Fill(dst, dc >> 3, 4);
-}
-
-static void RD4(uint8_t* dst, const uint8_t* top) {
- const int X = top[-1];
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int L = top[-5];
- const int A = top[0];
- const int B = top[1];
- const int C = top[2];
- const int D = top[3];
- DST(0, 3) = AVG3(J, K, L);
- DST(0, 2) = DST(1, 3) = AVG3(I, J, K);
- DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J);
- DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I);
- DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X);
- DST(2, 0) = DST(3, 1) = AVG3(C, B, A);
- DST(3, 0) = AVG3(D, C, B);
-}
-
-static void LD4(uint8_t* dst, const uint8_t* top) {
- const int A = top[0];
- const int B = top[1];
- const int C = top[2];
- const int D = top[3];
- const int E = top[4];
- const int F = top[5];
- const int G = top[6];
- const int H = top[7];
- DST(0, 0) = AVG3(A, B, C);
- DST(1, 0) = DST(0, 1) = AVG3(B, C, D);
- DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E);
- DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F);
- DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G);
- DST(3, 2) = DST(2, 3) = AVG3(F, G, H);
- DST(3, 3) = AVG3(G, H, H);
-}
-
-static void VR4(uint8_t* dst, const uint8_t* top) {
- const int X = top[-1];
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int A = top[0];
- const int B = top[1];
- const int C = top[2];
- const int D = top[3];
- DST(0, 0) = DST(1, 2) = AVG2(X, A);
- DST(1, 0) = DST(2, 2) = AVG2(A, B);
- DST(2, 0) = DST(3, 2) = AVG2(B, C);
- DST(3, 0) = AVG2(C, D);
-
- DST(0, 3) = AVG3(K, J, I);
- DST(0, 2) = AVG3(J, I, X);
- DST(0, 1) = DST(1, 3) = AVG3(I, X, A);
- DST(1, 1) = DST(2, 3) = AVG3(X, A, B);
- DST(2, 1) = DST(3, 3) = AVG3(A, B, C);
- DST(3, 1) = AVG3(B, C, D);
-}
-
-static void VL4(uint8_t* dst, const uint8_t* top) {
- const int A = top[0];
- const int B = top[1];
- const int C = top[2];
- const int D = top[3];
- const int E = top[4];
- const int F = top[5];
- const int G = top[6];
- const int H = top[7];
- DST(0, 0) = AVG2(A, B);
- DST(1, 0) = DST(0, 2) = AVG2(B, C);
- DST(2, 0) = DST(1, 2) = AVG2(C, D);
- DST(3, 0) = DST(2, 2) = AVG2(D, E);
-
- DST(0, 1) = AVG3(A, B, C);
- DST(1, 1) = DST(0, 3) = AVG3(B, C, D);
- DST(2, 1) = DST(1, 3) = AVG3(C, D, E);
- DST(3, 1) = DST(2, 3) = AVG3(D, E, F);
- DST(3, 2) = AVG3(E, F, G);
- DST(3, 3) = AVG3(F, G, H);
-}
-
-static void HU4(uint8_t* dst, const uint8_t* top) {
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int L = top[-5];
- DST(0, 0) = AVG2(I, J);
- DST(2, 0) = DST(0, 1) = AVG2(J, K);
- DST(2, 1) = DST(0, 2) = AVG2(K, L);
- DST(1, 0) = AVG3(I, J, K);
- DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
- DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
- DST(3, 2) = DST(2, 2) =
- DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
-}
-
-static void HD4(uint8_t* dst, const uint8_t* top) {
- const int X = top[-1];
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int L = top[-5];
- const int A = top[0];
- const int B = top[1];
- const int C = top[2];
-
- DST(0, 0) = DST(2, 1) = AVG2(I, X);
- DST(0, 1) = DST(2, 2) = AVG2(J, I);
- DST(0, 2) = DST(2, 3) = AVG2(K, J);
- DST(0, 3) = AVG2(L, K);
-
- DST(3, 0) = AVG3(A, B, C);
- DST(2, 0) = AVG3(X, A, B);
- DST(1, 0) = DST(3, 1) = AVG3(I, X, A);
- DST(1, 1) = DST(3, 2) = AVG3(J, I, X);
- DST(1, 2) = DST(3, 3) = AVG3(K, J, I);
- DST(1, 3) = AVG3(L, K, J);
-}
-
-static void TM4(uint8_t* dst, const uint8_t* top) {
- int x, y;
- const uint8_t* const clip = clip1 + 255 - top[-1];
- for (y = 0; y < 4; ++y) {
- const uint8_t* const clip_table = clip + top[-2 - y];
- for (x = 0; x < 4; ++x) {
- dst[x] = clip_table[top[x]];
- }
- dst += BPS;
- }
-}
-
-#undef DST
-#undef AVG3
-#undef AVG2
-
-// Left samples are top[-5 .. -2], top_left is top[-1], top are
-// located at top[0..3], and top right is top[4..7]
-static void Intra4Preds(uint8_t* dst, const uint8_t* top) {
- DC4(I4DC4 + dst, top);
- TM4(I4TM4 + dst, top);
- VE4(I4VE4 + dst, top);
- HE4(I4HE4 + dst, top);
- RD4(I4RD4 + dst, top);
- VR4(I4VR4 + dst, top);
- LD4(I4LD4 + dst, top);
- VL4(I4VL4 + dst, top);
- HD4(I4HD4 + dst, top);
- HU4(I4HU4 + dst, top);
-}
-
-//------------------------------------------------------------------------------
-// Metric
-
-static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b,
- int w, int h) {
- int count = 0;
- int y, x;
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- const int diff = (int)a[x] - b[x];
- count += diff * diff;
- }
- a += BPS;
- b += BPS;
- }
- return count;
-}
-
-static int SSE16x16(const uint8_t* a, const uint8_t* b) {
- return GetSSE(a, b, 16, 16);
-}
-static int SSE16x8(const uint8_t* a, const uint8_t* b) {
- return GetSSE(a, b, 16, 8);
-}
-static int SSE8x8(const uint8_t* a, const uint8_t* b) {
- return GetSSE(a, b, 8, 8);
-}
-static int SSE4x4(const uint8_t* a, const uint8_t* b) {
- return GetSSE(a, b, 4, 4);
-}
-
-//------------------------------------------------------------------------------
-// Texture distortion
-//
-// We try to match the spectral content (weighted) between source and
-// reconstructed samples.
-
-// Hadamard transform
-// Returns the weighted sum of the absolute value of transformed coefficients.
-// w[] contains a row-major 4 by 4 symmetric matrix.
-static int TTransform(const uint8_t* in, const uint16_t* w) {
- int sum = 0;
- int tmp[16];
- int i;
- // horizontal pass
- for (i = 0; i < 4; ++i, in += BPS) {
- const int a0 = in[0] + in[2];
- const int a1 = in[1] + in[3];
- const int a2 = in[1] - in[3];
- const int a3 = in[0] - in[2];
- tmp[0 + i * 4] = a0 + a1;
- tmp[1 + i * 4] = a3 + a2;
- tmp[2 + i * 4] = a3 - a2;
- tmp[3 + i * 4] = a0 - a1;
- }
- // vertical pass
- for (i = 0; i < 4; ++i, ++w) {
- const int a0 = tmp[0 + i] + tmp[8 + i];
- const int a1 = tmp[4 + i] + tmp[12+ i];
- const int a2 = tmp[4 + i] - tmp[12+ i];
- const int a3 = tmp[0 + i] - tmp[8 + i];
- const int b0 = a0 + a1;
- const int b1 = a3 + a2;
- const int b2 = a3 - a2;
- const int b3 = a0 - a1;
-
- sum += w[ 0] * abs(b0);
- sum += w[ 4] * abs(b1);
- sum += w[ 8] * abs(b2);
- sum += w[12] * abs(b3);
- }
- return sum;
-}
-
-static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- const int sum1 = TTransform(a, w);
- const int sum2 = TTransform(b, w);
- return abs(sum2 - sum1) >> 5;
-}
-
-static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- int D = 0;
- int x, y;
- for (y = 0; y < 16 * BPS; y += 4 * BPS) {
- for (x = 0; x < 16; x += 4) {
- D += Disto4x4(a + x + y, b + x + y, w);
- }
- }
- return D;
-}
-
-//------------------------------------------------------------------------------
-// Quantization
-//
-
-static const uint8_t kZigzag[16] = {
- 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
-};
-
-// Simple quantization
-static int QuantizeBlock(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- int last = -1;
- int n;
- for (n = 0; n < 16; ++n) {
- const int j = kZigzag[n];
- const int sign = (in[j] < 0);
- const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
- if (coeff > mtx->zthresh_[j]) {
- const uint32_t Q = mtx->q_[j];
- const uint32_t iQ = mtx->iq_[j];
- const uint32_t B = mtx->bias_[j];
- int level = QUANTDIV(coeff, iQ, B);
- if (level > MAX_LEVEL) level = MAX_LEVEL;
- if (sign) level = -level;
- in[j] = level * (int)Q;
- out[n] = level;
- if (level) last = n;
- } else {
- out[n] = 0;
- in[j] = 0;
- }
- }
- return (last >= 0);
-}
-
-static int Quantize2Blocks(int16_t in[32], int16_t out[32],
- const VP8Matrix* const mtx) {
- int nz;
- nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0;
- nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1;
- return nz;
-}
-
-static int QuantizeBlockWHT(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- int n, last = -1;
- for (n = 0; n < 16; ++n) {
- const int j = kZigzag[n];
- const int sign = (in[j] < 0);
- const uint32_t coeff = sign ? -in[j] : in[j];
- assert(mtx->sharpen_[j] == 0);
- if (coeff > mtx->zthresh_[j]) {
- const uint32_t Q = mtx->q_[j];
- const uint32_t iQ = mtx->iq_[j];
- const uint32_t B = mtx->bias_[j];
- int level = QUANTDIV(coeff, iQ, B);
- if (level > MAX_LEVEL) level = MAX_LEVEL;
- if (sign) level = -level;
- in[j] = level * (int)Q;
- out[n] = level;
- if (level) last = n;
- } else {
- out[n] = 0;
- in[j] = 0;
- }
- }
- return (last >= 0);
-}
-
-//------------------------------------------------------------------------------
-// Block copy
-
-static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int w, int h) {
- int y;
- for (y = 0; y < h; ++y) {
- memcpy(dst, src, w);
- src += BPS;
- dst += BPS;
- }
-}
-
-static void Copy4x4(const uint8_t* src, uint8_t* dst) {
- Copy(src, dst, 4, 4);
-}
-
-static void Copy16x8(const uint8_t* src, uint8_t* dst) {
- Copy(src, dst, 16, 8);
-}
-
-//------------------------------------------------------------------------------
-
-static void SSIMAccumulateClipped(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int xo, int yo, int W, int H,
- VP8DistoStats* const stats) {
- const int ymin = (yo - VP8_SSIM_KERNEL < 0) ? 0 : yo - VP8_SSIM_KERNEL;
- const int ymax = (yo + VP8_SSIM_KERNEL > H - 1) ? H - 1
- : yo + VP8_SSIM_KERNEL;
- const int xmin = (xo - VP8_SSIM_KERNEL < 0) ? 0 : xo - VP8_SSIM_KERNEL;
- const int xmax = (xo + VP8_SSIM_KERNEL > W - 1) ? W - 1
- : xo + VP8_SSIM_KERNEL;
- int x, y;
- src1 += ymin * stride1;
- src2 += ymin * stride2;
- for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) {
- for (x = xmin; x <= xmax; ++x) {
- const int s1 = src1[x];
- const int s2 = src2[x];
- stats->w += 1;
- stats->xm += s1;
- stats->ym += s2;
- stats->xxm += s1 * s1;
- stats->xym += s1 * s2;
- stats->yym += s2 * s2;
- }
- }
-}
-
-static void SSIMAccumulate(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- VP8DistoStats* const stats) {
- int x, y;
- for (y = 0; y <= 2 * VP8_SSIM_KERNEL; ++y, src1 += stride1, src2 += stride2) {
- for (x = 0; x <= 2 * VP8_SSIM_KERNEL; ++x) {
- const int s1 = src1[x];
- const int s2 = src2[x];
- stats->w += 1;
- stats->xm += s1;
- stats->ym += s2;
- stats->xxm += s1 * s1;
- stats->xym += s1 * s2;
- stats->yym += s2 * s2;
- }
- }
-}
-
-VP8SSIMAccumulateFunc VP8SSIMAccumulate;
-VP8SSIMAccumulateClippedFunc VP8SSIMAccumulateClipped;
-
-static volatile VP8CPUInfo ssim_last_cpuinfo_used =
- (VP8CPUInfo)&ssim_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) {
- if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- VP8SSIMAccumulate = SSIMAccumulate;
- VP8SSIMAccumulateClipped = SSIMAccumulateClipped;
-
- ssim_last_cpuinfo_used = VP8GetCPUInfo;
-}
-
-//------------------------------------------------------------------------------
-// Initialization
-
-// Speed-critical function pointers. We have to initialize them to the default
-// implementations within VP8EncDspInit().
-VP8CHisto VP8CollectHistogram;
-VP8Idct VP8ITransform;
-VP8Fdct VP8FTransform;
-VP8Fdct VP8FTransform2;
-VP8WHT VP8FTransformWHT;
-VP8Intra4Preds VP8EncPredLuma4;
-VP8IntraPreds VP8EncPredLuma16;
-VP8IntraPreds VP8EncPredChroma8;
-VP8Metric VP8SSE16x16;
-VP8Metric VP8SSE8x8;
-VP8Metric VP8SSE16x8;
-VP8Metric VP8SSE4x4;
-VP8WMetric VP8TDisto4x4;
-VP8WMetric VP8TDisto16x16;
-VP8QuantizeBlock VP8EncQuantizeBlock;
-VP8Quantize2Blocks VP8EncQuantize2Blocks;
-VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT;
-VP8BlockCopy VP8Copy4x4;
-VP8BlockCopy VP8Copy16x8;
-
-extern void VP8EncDspInitSSE2(void);
-extern void VP8EncDspInitSSE41(void);
-extern void VP8EncDspInitAVX2(void);
-extern void VP8EncDspInitNEON(void);
-extern void VP8EncDspInitMIPS32(void);
-extern void VP8EncDspInitMIPSdspR2(void);
-
-static volatile VP8CPUInfo enc_last_cpuinfo_used =
- (VP8CPUInfo)&enc_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
- if (enc_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- VP8DspInit(); // common inverse transforms
- InitTables();
-
- // default C implementations
- VP8CollectHistogram = CollectHistogram;
- VP8ITransform = ITransform;
- VP8FTransform = FTransform;
- VP8FTransform2 = FTransform2;
- VP8FTransformWHT = FTransformWHT;
- VP8EncPredLuma4 = Intra4Preds;
- VP8EncPredLuma16 = Intra16Preds;
- VP8EncPredChroma8 = IntraChromaPreds;
- VP8SSE16x16 = SSE16x16;
- VP8SSE8x8 = SSE8x8;
- VP8SSE16x8 = SSE16x8;
- VP8SSE4x4 = SSE4x4;
- VP8TDisto4x4 = Disto4x4;
- VP8TDisto16x16 = Disto16x16;
- VP8EncQuantizeBlock = QuantizeBlock;
- VP8EncQuantize2Blocks = Quantize2Blocks;
- VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
- VP8Copy4x4 = Copy4x4;
- VP8Copy16x8 = Copy16x8;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- VP8EncDspInitSSE2();
-#if defined(WEBP_USE_SSE41)
- if (VP8GetCPUInfo(kSSE4_1)) {
- VP8EncDspInitSSE41();
- }
-#endif
- }
-#endif
-#if defined(WEBP_USE_AVX2)
- if (VP8GetCPUInfo(kAVX2)) {
- VP8EncDspInitAVX2();
- }
-#endif
-#if defined(WEBP_USE_NEON)
- if (VP8GetCPUInfo(kNEON)) {
- VP8EncDspInitNEON();
- }
-#endif
-#if defined(WEBP_USE_MIPS32)
- if (VP8GetCPUInfo(kMIPS32)) {
- VP8EncDspInitMIPS32();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- VP8EncDspInitMIPSdspR2();
- }
-#endif
- }
- enc_last_cpuinfo_used = VP8GetCPUInfo;
-}
diff --git a/drivers/webp/dsp/enc_avx2.c b/drivers/webp/dsp/enc_avx2.c
deleted file mode 100644
index 93efb30b10..0000000000
--- a/drivers/webp/dsp/enc_avx2.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// AVX2 version of speed-critical encoding functions.
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_AVX2)
-
-#endif // WEBP_USE_AVX2
-
-//------------------------------------------------------------------------------
-// Entry point
-
-WEBP_DSP_INIT_STUB(VP8EncDspInitAVX2)
diff --git a/drivers/webp/dsp/enc_mips32.c b/drivers/webp/dsp/enc_mips32.c
deleted file mode 100644
index fd10143de9..0000000000
--- a/drivers/webp/dsp/enc_mips32.c
+++ /dev/null
@@ -1,672 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS version of speed-critical encoding functions.
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
-// Slobodan Prijic (slobodan.prijic@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS32)
-
-#include "./mips_macro.h"
-#include "../enc/vp8enci.h"
-#include "../enc/cost.h"
-
-static const int kC1 = 20091 + (1 << 16);
-static const int kC2 = 35468;
-
-// macro for one vertical pass in ITransformOne
-// MUL macro inlined
-// temp0..temp15 holds tmp[0]..tmp[15]
-// A..D - offsets in bytes to load from in buffer
-// TEMP0..TEMP3 - registers for corresponding tmp elements
-// TEMP4..TEMP5 - temporary registers
-#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \
- "lh %[temp16], " #A "(%[temp20]) \n\t" \
- "lh %[temp18], " #B "(%[temp20]) \n\t" \
- "lh %[temp17], " #C "(%[temp20]) \n\t" \
- "lh %[temp19], " #D "(%[temp20]) \n\t" \
- "addu %[" #TEMP4 "], %[temp16], %[temp18] \n\t" \
- "subu %[temp16], %[temp16], %[temp18] \n\t" \
- "mul %[" #TEMP0 "], %[temp17], %[kC2] \n\t" \
- "mul %[temp18], %[temp19], %[kC1] \n\t" \
- "mul %[temp17], %[temp17], %[kC1] \n\t" \
- "mul %[temp19], %[temp19], %[kC2] \n\t" \
- "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\n" \
- "sra %[temp18], %[temp18], 16 \n\n" \
- "sra %[temp17], %[temp17], 16 \n\n" \
- "sra %[temp19], %[temp19], 16 \n\n" \
- "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp18] \n\t" \
- "addu %[" #TEMP3 "], %[temp17], %[temp19] \n\t" \
- "addu %[" #TEMP0 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t" \
- "addu %[" #TEMP1 "], %[temp16], %[" #TEMP2 "] \n\t" \
- "subu %[" #TEMP2 "], %[temp16], %[" #TEMP2 "] \n\t" \
- "subu %[" #TEMP3 "], %[" #TEMP4 "], %[" #TEMP3 "] \n\t"
-
-// macro for one horizontal pass in ITransformOne
-// MUL and STORE macros inlined
-// a = clip_8b(a) is replaced with: a = max(a, 0); a = min(a, 255)
-// temp0..temp15 holds tmp[0]..tmp[15]
-// A - offset in bytes to load from ref and store to dst buffer
-// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements
-#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \
- "addiu %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \
- "addu %[temp16], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \
- "subu %[temp17], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \
- "mul %[" #TEMP0 "], %[" #TEMP4 "], %[kC2] \n\t" \
- "mul %[" #TEMP8 "], %[" #TEMP12 "], %[kC1] \n\t" \
- "mul %[" #TEMP4 "], %[" #TEMP4 "], %[kC1] \n\t" \
- "mul %[" #TEMP12 "], %[" #TEMP12 "], %[kC2] \n\t" \
- "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \
- "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \
- "sra %[" #TEMP4 "], %[" #TEMP4 "], 16 \n\t" \
- "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \
- "subu %[temp18], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \
- "addu %[temp19], %[" #TEMP4 "], %[" #TEMP12 "] \n\t" \
- "addu %[" #TEMP0 "], %[temp16], %[temp19] \n\t" \
- "addu %[" #TEMP4 "], %[temp17], %[temp18] \n\t" \
- "subu %[" #TEMP8 "], %[temp17], %[temp18] \n\t" \
- "subu %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \
- "lw %[temp20], 0(%[args]) \n\t" \
- "sra %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \
- "sra %[" #TEMP4 "], %[" #TEMP4 "], 3 \n\t" \
- "sra %[" #TEMP8 "], %[" #TEMP8 "], 3 \n\t" \
- "sra %[" #TEMP12 "], %[" #TEMP12 "], 3 \n\t" \
- "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \
- "lbu %[temp17], 1+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \
- "lbu %[temp18], 2+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \
- "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[temp20]) \n\t" \
- "addu %[" #TEMP0 "], %[temp16], %[" #TEMP0 "] \n\t" \
- "addu %[" #TEMP4 "], %[temp17], %[" #TEMP4 "] \n\t" \
- "addu %[" #TEMP8 "], %[temp18], %[" #TEMP8 "] \n\t" \
- "addu %[" #TEMP12 "], %[temp19], %[" #TEMP12 "] \n\t" \
- "slt %[temp16], %[" #TEMP0 "], $zero \n\t" \
- "slt %[temp17], %[" #TEMP4 "], $zero \n\t" \
- "slt %[temp18], %[" #TEMP8 "], $zero \n\t" \
- "slt %[temp19], %[" #TEMP12 "], $zero \n\t" \
- "movn %[" #TEMP0 "], $zero, %[temp16] \n\t" \
- "movn %[" #TEMP4 "], $zero, %[temp17] \n\t" \
- "movn %[" #TEMP8 "], $zero, %[temp18] \n\t" \
- "movn %[" #TEMP12 "], $zero, %[temp19] \n\t" \
- "addiu %[temp20], $zero, 255 \n\t" \
- "slt %[temp16], %[" #TEMP0 "], %[temp20] \n\t" \
- "slt %[temp17], %[" #TEMP4 "], %[temp20] \n\t" \
- "slt %[temp18], %[" #TEMP8 "], %[temp20] \n\t" \
- "slt %[temp19], %[" #TEMP12 "], %[temp20] \n\t" \
- "movz %[" #TEMP0 "], %[temp20], %[temp16] \n\t" \
- "movz %[" #TEMP4 "], %[temp20], %[temp17] \n\t" \
- "lw %[temp16], 8(%[args]) \n\t" \
- "movz %[" #TEMP8 "], %[temp20], %[temp18] \n\t" \
- "movz %[" #TEMP12 "], %[temp20], %[temp19] \n\t" \
- "sb %[" #TEMP0 "], 0+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
- "sb %[" #TEMP4 "], 1+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
- "sb %[" #TEMP8 "], 2+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" \
- "sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t"
-
-// Does one or two inverse transforms.
-static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
- uint8_t* dst) {
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
- int temp7, temp8, temp9, temp10, temp11, temp12, temp13;
- int temp14, temp15, temp16, temp17, temp18, temp19, temp20;
- const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst};
-
- __asm__ volatile(
- "lw %[temp20], 4(%[args]) \n\t"
- VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3)
- VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7)
- VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11)
- VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15)
-
- HORIZONTAL_PASS(0, temp0, temp4, temp8, temp12)
- HORIZONTAL_PASS(1, temp1, temp5, temp9, temp13)
- HORIZONTAL_PASS(2, temp2, temp6, temp10, temp14)
- HORIZONTAL_PASS(3, temp3, temp7, temp11, temp15)
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
- [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
- [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
- [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
- : [args]"r"(args), [kC1]"r"(kC1), [kC2]"r"(kC2)
- : "memory", "hi", "lo"
- );
-}
-
-static void ITransform(const uint8_t* ref, const int16_t* in,
- uint8_t* dst, int do_two) {
- ITransformOne(ref, in, dst);
- if (do_two) {
- ITransformOne(ref + 4, in + 16, dst + 4);
- }
-}
-
-#undef VERTICAL_PASS
-#undef HORIZONTAL_PASS
-
-// macro for one pass through for loop in QuantizeBlock
-// QUANTDIV macro inlined
-// J - offset in bytes (kZigzag[n] * 2)
-// K - offset in bytes (kZigzag[n] * 4)
-// N - offset in bytes (n * 2)
-#define QUANTIZE_ONE(J, K, N) \
- "lh %[temp0], " #J "(%[ppin]) \n\t" \
- "lhu %[temp1], " #J "(%[ppsharpen]) \n\t" \
- "lw %[temp2], " #K "(%[ppzthresh]) \n\t" \
- "sra %[sign], %[temp0], 15 \n\t" \
- "xor %[coeff], %[temp0], %[sign] \n\t" \
- "subu %[coeff], %[coeff], %[sign] \n\t" \
- "addu %[coeff], %[coeff], %[temp1] \n\t" \
- "slt %[temp4], %[temp2], %[coeff] \n\t" \
- "addiu %[temp5], $zero, 0 \n\t" \
- "addiu %[level], $zero, 0 \n\t" \
- "beqz %[temp4], 2f \n\t" \
- "lhu %[temp1], " #J "(%[ppiq]) \n\t" \
- "lw %[temp2], " #K "(%[ppbias]) \n\t" \
- "lhu %[temp3], " #J "(%[ppq]) \n\t" \
- "mul %[level], %[coeff], %[temp1] \n\t" \
- "addu %[level], %[level], %[temp2] \n\t" \
- "sra %[level], %[level], 17 \n\t" \
- "slt %[temp4], %[max_level], %[level] \n\t" \
- "movn %[level], %[max_level], %[temp4] \n\t" \
- "xor %[level], %[level], %[sign] \n\t" \
- "subu %[level], %[level], %[sign] \n\t" \
- "mul %[temp5], %[level], %[temp3] \n\t" \
-"2: \n\t" \
- "sh %[temp5], " #J "(%[ppin]) \n\t" \
- "sh %[level], " #N "(%[pout]) \n\t"
-
-static int QuantizeBlock(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- int sign, coeff, level, i;
- int max_level = MAX_LEVEL;
-
- int16_t* ppin = &in[0];
- int16_t* pout = &out[0];
- const uint16_t* ppsharpen = &mtx->sharpen_[0];
- const uint32_t* ppzthresh = &mtx->zthresh_[0];
- const uint16_t* ppq = &mtx->q_[0];
- const uint16_t* ppiq = &mtx->iq_[0];
- const uint32_t* ppbias = &mtx->bias_[0];
-
- __asm__ volatile(
- QUANTIZE_ONE( 0, 0, 0)
- QUANTIZE_ONE( 2, 4, 2)
- QUANTIZE_ONE( 8, 16, 4)
- QUANTIZE_ONE(16, 32, 6)
- QUANTIZE_ONE(10, 20, 8)
- QUANTIZE_ONE( 4, 8, 10)
- QUANTIZE_ONE( 6, 12, 12)
- QUANTIZE_ONE(12, 24, 14)
- QUANTIZE_ONE(18, 36, 16)
- QUANTIZE_ONE(24, 48, 18)
- QUANTIZE_ONE(26, 52, 20)
- QUANTIZE_ONE(20, 40, 22)
- QUANTIZE_ONE(14, 28, 24)
- QUANTIZE_ONE(22, 44, 26)
- QUANTIZE_ONE(28, 56, 28)
- QUANTIZE_ONE(30, 60, 30)
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [sign]"=&r"(sign), [coeff]"=&r"(coeff),
- [level]"=&r"(level)
- : [pout]"r"(pout), [ppin]"r"(ppin),
- [ppiq]"r"(ppiq), [max_level]"r"(max_level),
- [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh),
- [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq)
- : "memory", "hi", "lo"
- );
-
- // moved out from macro to increase possibility for earlier breaking
- for (i = 15; i >= 0; i--) {
- if (out[i]) return 1;
- }
- return 0;
-}
-
-static int Quantize2Blocks(int16_t in[32], int16_t out[32],
- const VP8Matrix* const mtx) {
- int nz;
- nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0;
- nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1;
- return nz;
-}
-
-#undef QUANTIZE_ONE
-
-// macro for one horizontal pass in Disto4x4 (TTransform)
-// two calls of function TTransform are merged into single one
-// A - offset in bytes to load from a and b buffers
-// E..H - offsets in bytes to store first results to tmp buffer
-// E1..H1 - offsets in bytes to store second results to tmp buffer
-#define HORIZONTAL_PASS(A, E, F, G, H, E1, F1, G1, H1) \
- "lbu %[temp0], 0+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
- "lbu %[temp1], 1+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
- "lbu %[temp2], 2+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
- "lbu %[temp3], 3+" XSTR(BPS) "*" #A "(%[a]) \n\t" \
- "lbu %[temp4], 0+" XSTR(BPS) "*" #A "(%[b]) \n\t" \
- "lbu %[temp5], 1+" XSTR(BPS) "*" #A "(%[b]) \n\t" \
- "lbu %[temp6], 2+" XSTR(BPS) "*" #A "(%[b]) \n\t" \
- "lbu %[temp7], 3+" XSTR(BPS) "*" #A "(%[b]) \n\t" \
- "addu %[temp8], %[temp0], %[temp2] \n\t" \
- "subu %[temp0], %[temp0], %[temp2] \n\t" \
- "addu %[temp2], %[temp1], %[temp3] \n\t" \
- "subu %[temp1], %[temp1], %[temp3] \n\t" \
- "addu %[temp3], %[temp4], %[temp6] \n\t" \
- "subu %[temp4], %[temp4], %[temp6] \n\t" \
- "addu %[temp6], %[temp5], %[temp7] \n\t" \
- "subu %[temp5], %[temp5], %[temp7] \n\t" \
- "addu %[temp7], %[temp8], %[temp2] \n\t" \
- "subu %[temp2], %[temp8], %[temp2] \n\t" \
- "addu %[temp8], %[temp0], %[temp1] \n\t" \
- "subu %[temp0], %[temp0], %[temp1] \n\t" \
- "addu %[temp1], %[temp3], %[temp6] \n\t" \
- "subu %[temp3], %[temp3], %[temp6] \n\t" \
- "addu %[temp6], %[temp4], %[temp5] \n\t" \
- "subu %[temp4], %[temp4], %[temp5] \n\t" \
- "sw %[temp7], " #E "(%[tmp]) \n\t" \
- "sw %[temp2], " #H "(%[tmp]) \n\t" \
- "sw %[temp8], " #F "(%[tmp]) \n\t" \
- "sw %[temp0], " #G "(%[tmp]) \n\t" \
- "sw %[temp1], " #E1 "(%[tmp]) \n\t" \
- "sw %[temp3], " #H1 "(%[tmp]) \n\t" \
- "sw %[temp6], " #F1 "(%[tmp]) \n\t" \
- "sw %[temp4], " #G1 "(%[tmp]) \n\t"
-
-// macro for one vertical pass in Disto4x4 (TTransform)
-// two calls of function TTransform are merged into single one
-// since only one accu is available in mips32r1 instruction set
-// first is done second call of function TTransform and after
-// that first one.
-// const int sum1 = TTransform(a, w);
-// const int sum2 = TTransform(b, w);
-// return abs(sum2 - sum1) >> 5;
-// (sum2 - sum1) is calculated with madds (sub2) and msubs (sub1)
-// A..D - offsets in bytes to load first results from tmp buffer
-// A1..D1 - offsets in bytes to load second results from tmp buffer
-// E..H - offsets in bytes to load from w buffer
-#define VERTICAL_PASS(A, B, C, D, A1, B1, C1, D1, E, F, G, H) \
- "lw %[temp0], " #A1 "(%[tmp]) \n\t" \
- "lw %[temp1], " #C1 "(%[tmp]) \n\t" \
- "lw %[temp2], " #B1 "(%[tmp]) \n\t" \
- "lw %[temp3], " #D1 "(%[tmp]) \n\t" \
- "addu %[temp8], %[temp0], %[temp1] \n\t" \
- "subu %[temp0], %[temp0], %[temp1] \n\t" \
- "addu %[temp1], %[temp2], %[temp3] \n\t" \
- "subu %[temp2], %[temp2], %[temp3] \n\t" \
- "addu %[temp3], %[temp8], %[temp1] \n\t" \
- "subu %[temp8], %[temp8], %[temp1] \n\t" \
- "addu %[temp1], %[temp0], %[temp2] \n\t" \
- "subu %[temp0], %[temp0], %[temp2] \n\t" \
- "sra %[temp4], %[temp3], 31 \n\t" \
- "sra %[temp5], %[temp1], 31 \n\t" \
- "sra %[temp6], %[temp0], 31 \n\t" \
- "sra %[temp7], %[temp8], 31 \n\t" \
- "xor %[temp3], %[temp3], %[temp4] \n\t" \
- "xor %[temp1], %[temp1], %[temp5] \n\t" \
- "xor %[temp0], %[temp0], %[temp6] \n\t" \
- "xor %[temp8], %[temp8], %[temp7] \n\t" \
- "subu %[temp3], %[temp3], %[temp4] \n\t" \
- "subu %[temp1], %[temp1], %[temp5] \n\t" \
- "subu %[temp0], %[temp0], %[temp6] \n\t" \
- "subu %[temp8], %[temp8], %[temp7] \n\t" \
- "lhu %[temp4], " #E "(%[w]) \n\t" \
- "lhu %[temp5], " #F "(%[w]) \n\t" \
- "lhu %[temp6], " #G "(%[w]) \n\t" \
- "lhu %[temp7], " #H "(%[w]) \n\t" \
- "madd %[temp4], %[temp3] \n\t" \
- "madd %[temp5], %[temp1] \n\t" \
- "madd %[temp6], %[temp0] \n\t" \
- "madd %[temp7], %[temp8] \n\t" \
- "lw %[temp0], " #A "(%[tmp]) \n\t" \
- "lw %[temp1], " #C "(%[tmp]) \n\t" \
- "lw %[temp2], " #B "(%[tmp]) \n\t" \
- "lw %[temp3], " #D "(%[tmp]) \n\t" \
- "addu %[temp8], %[temp0], %[temp1] \n\t" \
- "subu %[temp0], %[temp0], %[temp1] \n\t" \
- "addu %[temp1], %[temp2], %[temp3] \n\t" \
- "subu %[temp2], %[temp2], %[temp3] \n\t" \
- "addu %[temp3], %[temp8], %[temp1] \n\t" \
- "subu %[temp1], %[temp8], %[temp1] \n\t" \
- "addu %[temp8], %[temp0], %[temp2] \n\t" \
- "subu %[temp0], %[temp0], %[temp2] \n\t" \
- "sra %[temp2], %[temp3], 31 \n\t" \
- "xor %[temp3], %[temp3], %[temp2] \n\t" \
- "subu %[temp3], %[temp3], %[temp2] \n\t" \
- "msub %[temp4], %[temp3] \n\t" \
- "sra %[temp2], %[temp8], 31 \n\t" \
- "sra %[temp3], %[temp0], 31 \n\t" \
- "sra %[temp4], %[temp1], 31 \n\t" \
- "xor %[temp8], %[temp8], %[temp2] \n\t" \
- "xor %[temp0], %[temp0], %[temp3] \n\t" \
- "xor %[temp1], %[temp1], %[temp4] \n\t" \
- "subu %[temp8], %[temp8], %[temp2] \n\t" \
- "subu %[temp0], %[temp0], %[temp3] \n\t" \
- "subu %[temp1], %[temp1], %[temp4] \n\t" \
- "msub %[temp5], %[temp8] \n\t" \
- "msub %[temp6], %[temp0] \n\t" \
- "msub %[temp7], %[temp1] \n\t"
-
-static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- int tmp[32];
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
-
- __asm__ volatile(
- HORIZONTAL_PASS(0, 0, 4, 8, 12, 64, 68, 72, 76)
- HORIZONTAL_PASS(1, 16, 20, 24, 28, 80, 84, 88, 92)
- HORIZONTAL_PASS(2, 32, 36, 40, 44, 96, 100, 104, 108)
- HORIZONTAL_PASS(3, 48, 52, 56, 60, 112, 116, 120, 124)
- "mthi $zero \n\t"
- "mtlo $zero \n\t"
- VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24)
- VERTICAL_PASS( 4, 20, 36, 52, 68, 84, 100, 116, 2, 10, 18, 26)
- VERTICAL_PASS( 8, 24, 40, 56, 72, 88, 104, 120, 4, 12, 20, 28)
- VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30)
- "mflo %[temp0] \n\t"
- "sra %[temp1], %[temp0], 31 \n\t"
- "xor %[temp0], %[temp0], %[temp1] \n\t"
- "subu %[temp0], %[temp0], %[temp1] \n\t"
- "sra %[temp0], %[temp0], 5 \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
- : [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp)
- : "memory", "hi", "lo"
- );
-
- return temp0;
-}
-
-#undef VERTICAL_PASS
-#undef HORIZONTAL_PASS
-
-static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- int D = 0;
- int x, y;
- for (y = 0; y < 16 * BPS; y += 4 * BPS) {
- for (x = 0; x < 16; x += 4) {
- D += Disto4x4(a + x + y, b + x + y, w);
- }
- }
- return D;
-}
-
-// macro for one horizontal pass in FTransform
-// temp0..temp15 holds tmp[0]..tmp[15]
-// A - offset in bytes to load from src and ref buffers
-// TEMP0..TEMP3 - registers for corresponding tmp elements
-#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \
- "lw %[" #TEMP1 "], 0(%[args]) \n\t" \
- "lw %[" #TEMP2 "], 4(%[args]) \n\t" \
- "lbu %[temp16], 0+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
- "lbu %[temp17], 0+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \
- "lbu %[temp18], 1+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
- "lbu %[temp19], 1+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \
- "subu %[temp20], %[temp16], %[temp17] \n\t" \
- "lbu %[temp16], 2+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
- "lbu %[temp17], 2+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \
- "subu %[" #TEMP0 "], %[temp18], %[temp19] \n\t" \
- "lbu %[temp18], 3+" XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
- "lbu %[temp19], 3+" XSTR(BPS) "*" #A "(%[" #TEMP2 "]) \n\t" \
- "subu %[" #TEMP1 "], %[temp16], %[temp17] \n\t" \
- "subu %[" #TEMP2 "], %[temp18], %[temp19] \n\t" \
- "addu %[" #TEMP3 "], %[temp20], %[" #TEMP2 "] \n\t" \
- "subu %[" #TEMP2 "], %[temp20], %[" #TEMP2 "] \n\t" \
- "addu %[temp20], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \
- "subu %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \
- "mul %[temp16], %[" #TEMP2 "], %[c5352] \n\t" \
- "mul %[temp17], %[" #TEMP2 "], %[c2217] \n\t" \
- "mul %[temp18], %[" #TEMP0 "], %[c5352] \n\t" \
- "mul %[temp19], %[" #TEMP0 "], %[c2217] \n\t" \
- "addu %[" #TEMP1 "], %[" #TEMP3 "], %[temp20] \n\t" \
- "subu %[temp20], %[" #TEMP3 "], %[temp20] \n\t" \
- "sll %[" #TEMP0 "], %[" #TEMP1 "], 3 \n\t" \
- "sll %[" #TEMP2 "], %[temp20], 3 \n\t" \
- "addiu %[temp16], %[temp16], 1812 \n\t" \
- "addiu %[temp17], %[temp17], 937 \n\t" \
- "addu %[temp16], %[temp16], %[temp19] \n\t" \
- "subu %[temp17], %[temp17], %[temp18] \n\t" \
- "sra %[" #TEMP1 "], %[temp16], 9 \n\t" \
- "sra %[" #TEMP3 "], %[temp17], 9 \n\t"
-
-// macro for one vertical pass in FTransform
-// temp0..temp15 holds tmp[0]..tmp[15]
-// A..D - offsets in bytes to store to out buffer
-// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements
-#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \
- "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \
- "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \
- "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \
- "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \
- "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \
- "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \
- "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \
- "mul %[temp18], %[temp18], %[c5352] \n\t" \
- "addiu %[temp16], %[temp16], 7 \n\t" \
- "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \
- "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \
- "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \
- "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \
- "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \
- "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \
- "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \
- "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \
- "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \
- "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \
- "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \
- "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \
- "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \
- "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \
- "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \
- "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \
- "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t"
-
-static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
- int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16;
- int temp17, temp18, temp19, temp20;
- const int c2217 = 2217;
- const int c5352 = 5352;
- const int* const args[3] =
- { (const int*)src, (const int*)ref, (const int*)out };
-
- __asm__ volatile(
- HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3)
- HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7)
- HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11)
- HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15)
- "lw %[temp20], 8(%[args]) \n\t"
- VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12)
- VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13)
- VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14)
- VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15)
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
- [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
- [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
- [temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
- : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352)
- : "memory", "hi", "lo"
- );
-}
-
-#undef VERTICAL_PASS
-#undef HORIZONTAL_PASS
-
-#if !defined(WORK_AROUND_GCC)
-
-#define GET_SSE_INNER(A, B, C, D) \
- "lbu %[temp0], " #A "(%[a]) \n\t" \
- "lbu %[temp1], " #A "(%[b]) \n\t" \
- "lbu %[temp2], " #B "(%[a]) \n\t" \
- "lbu %[temp3], " #B "(%[b]) \n\t" \
- "lbu %[temp4], " #C "(%[a]) \n\t" \
- "lbu %[temp5], " #C "(%[b]) \n\t" \
- "lbu %[temp6], " #D "(%[a]) \n\t" \
- "lbu %[temp7], " #D "(%[b]) \n\t" \
- "subu %[temp0], %[temp0], %[temp1] \n\t" \
- "subu %[temp2], %[temp2], %[temp3] \n\t" \
- "subu %[temp4], %[temp4], %[temp5] \n\t" \
- "subu %[temp6], %[temp6], %[temp7] \n\t" \
- "madd %[temp0], %[temp0] \n\t" \
- "madd %[temp2], %[temp2] \n\t" \
- "madd %[temp4], %[temp4] \n\t" \
- "madd %[temp6], %[temp6] \n\t"
-
-#define GET_SSE(A, B, C, D) \
- GET_SSE_INNER(A, A + 1, A + 2, A + 3) \
- GET_SSE_INNER(B, B + 1, B + 2, B + 3) \
- GET_SSE_INNER(C, C + 1, C + 2, C + 3) \
- GET_SSE_INNER(D, D + 1, D + 2, D + 3)
-
-static int SSE16x16(const uint8_t* a, const uint8_t* b) {
- int count;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
-
- __asm__ volatile(
- "mult $zero, $zero \n\t"
-
- GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
- GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
- GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
- GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
- GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
- GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
- GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
- GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
- GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS)
- GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS)
- GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS)
- GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS)
- GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS)
- GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS)
- GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS)
- GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS)
-
- "mflo %[count] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
- : [a]"r"(a), [b]"r"(b)
- : "memory", "hi", "lo"
- );
- return count;
-}
-
-static int SSE16x8(const uint8_t* a, const uint8_t* b) {
- int count;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
-
- __asm__ volatile(
- "mult $zero, $zero \n\t"
-
- GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
- GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
- GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
- GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
- GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
- GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
- GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
- GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
-
- "mflo %[count] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
- : [a]"r"(a), [b]"r"(b)
- : "memory", "hi", "lo"
- );
- return count;
-}
-
-static int SSE8x8(const uint8_t* a, const uint8_t* b) {
- int count;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
-
- __asm__ volatile(
- "mult $zero, $zero \n\t"
-
- GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS)
- GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS)
- GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS)
- GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS)
-
- "mflo %[count] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
- : [a]"r"(a), [b]"r"(b)
- : "memory", "hi", "lo"
- );
- return count;
-}
-
-static int SSE4x4(const uint8_t* a, const uint8_t* b) {
- int count;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
-
- __asm__ volatile(
- "mult $zero, $zero \n\t"
-
- GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS)
-
- "mflo %[count] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
- : [a]"r"(a), [b]"r"(b)
- : "memory", "hi", "lo"
- );
- return count;
-}
-
-#undef GET_SSE
-#undef GET_SSE_INNER
-
-#endif // !WORK_AROUND_GCC
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspInitMIPS32(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPS32(void) {
- VP8ITransform = ITransform;
- VP8FTransform = FTransform;
- VP8EncQuantizeBlock = QuantizeBlock;
- VP8EncQuantize2Blocks = Quantize2Blocks;
- VP8TDisto4x4 = Disto4x4;
- VP8TDisto16x16 = Disto16x16;
-#if !defined(WORK_AROUND_GCC)
- VP8SSE16x16 = SSE16x16;
- VP8SSE8x8 = SSE8x8;
- VP8SSE16x8 = SSE16x8;
- VP8SSE4x4 = SSE4x4;
-#endif
-}
-
-#else // !WEBP_USE_MIPS32
-
-WEBP_DSP_INIT_STUB(VP8EncDspInitMIPS32)
-
-#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/enc_mips_dsp_r2.c b/drivers/webp/dsp/enc_mips_dsp_r2.c
deleted file mode 100644
index 7ab96f6800..0000000000
--- a/drivers/webp/dsp/enc_mips_dsp_r2.c
+++ /dev/null
@@ -1,1510 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS version of speed-critical encoding functions.
-//
-// Author(s): Darko Laus (darko.laus@imgtec.com)
-// Mirko Raus (mirko.raus@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include "./mips_macro.h"
-#include "../enc/cost.h"
-#include "../enc/vp8enci.h"
-
-static const int kC1 = 20091 + (1 << 16);
-static const int kC2 = 35468;
-
-// O - output
-// I - input (macro doesn't change it)
-#define ADD_SUB_HALVES_X4(O0, O1, O2, O3, O4, O5, O6, O7, \
- I0, I1, I2, I3, I4, I5, I6, I7) \
- "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \
- "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t" \
- "addq.ph %[" #O2 "], %[" #I2 "], %[" #I3 "] \n\t" \
- "subq.ph %[" #O3 "], %[" #I2 "], %[" #I3 "] \n\t" \
- "addq.ph %[" #O4 "], %[" #I4 "], %[" #I5 "] \n\t" \
- "subq.ph %[" #O5 "], %[" #I4 "], %[" #I5 "] \n\t" \
- "addq.ph %[" #O6 "], %[" #I6 "], %[" #I7 "] \n\t" \
- "subq.ph %[" #O7 "], %[" #I6 "], %[" #I7 "] \n\t"
-
-// IO - input/output
-#define ABS_X8(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7) \
- "absq_s.ph %[" #IO0 "], %[" #IO0 "] \n\t" \
- "absq_s.ph %[" #IO1 "], %[" #IO1 "] \n\t" \
- "absq_s.ph %[" #IO2 "], %[" #IO2 "] \n\t" \
- "absq_s.ph %[" #IO3 "], %[" #IO3 "] \n\t" \
- "absq_s.ph %[" #IO4 "], %[" #IO4 "] \n\t" \
- "absq_s.ph %[" #IO5 "], %[" #IO5 "] \n\t" \
- "absq_s.ph %[" #IO6 "], %[" #IO6 "] \n\t" \
- "absq_s.ph %[" #IO7 "], %[" #IO7 "] \n\t"
-
-// dpa.w.ph $ac0 temp0 ,temp1
-// $ac += temp0[31..16] * temp1[31..16] + temp0[15..0] * temp1[15..0]
-// dpax.w.ph $ac0 temp0 ,temp1
-// $ac += temp0[31..16] * temp1[15..0] + temp0[15..0] * temp1[31..16]
-// O - output
-// I - input (macro doesn't change it)
-#define MUL_HALF(O0, I0, I1, I2, I3, I4, I5, I6, I7, \
- I8, I9, I10, I11, I12, I13, I14, I15) \
- "mult $ac0, $zero, $zero \n\t" \
- "dpa.w.ph $ac0, %[" #I2 "], %[" #I0 "] \n\t" \
- "dpax.w.ph $ac0, %[" #I5 "], %[" #I6 "] \n\t" \
- "dpa.w.ph $ac0, %[" #I8 "], %[" #I9 "] \n\t" \
- "dpax.w.ph $ac0, %[" #I11 "], %[" #I4 "] \n\t" \
- "dpa.w.ph $ac0, %[" #I12 "], %[" #I7 "] \n\t" \
- "dpax.w.ph $ac0, %[" #I13 "], %[" #I1 "] \n\t" \
- "dpa.w.ph $ac0, %[" #I14 "], %[" #I3 "] \n\t" \
- "dpax.w.ph $ac0, %[" #I15 "], %[" #I10 "] \n\t" \
- "mflo %[" #O0 "], $ac0 \n\t"
-
-#define OUTPUT_EARLY_CLOBBER_REGS_17() \
- OUTPUT_EARLY_CLOBBER_REGS_10(), \
- [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \
- [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \
- [temp17]"=&r"(temp17)
-
-// macro for one horizontal pass in FTransform
-// temp0..temp15 holds tmp[0]..tmp[15]
-// A - offset in bytes to load from src and ref buffers
-// TEMP0..TEMP3 - registers for corresponding tmp elements
-#define HORIZONTAL_PASS(A, TEMP0, TEMP1, TEMP2, TEMP3) \
- "lw %[" #TEMP0 "], 0(%[args]) \n\t" \
- "lw %[" #TEMP1 "], 4(%[args]) \n\t" \
- "lw %[" #TEMP2 "], " XSTR(BPS) "*" #A "(%[" #TEMP0 "]) \n\t" \
- "lw %[" #TEMP3 "], " XSTR(BPS) "*" #A "(%[" #TEMP1 "]) \n\t" \
- "preceu.ph.qbl %[" #TEMP0 "], %[" #TEMP2 "] \n\t" \
- "preceu.ph.qbl %[" #TEMP1 "], %[" #TEMP3 "] \n\t" \
- "preceu.ph.qbr %[" #TEMP2 "], %[" #TEMP2 "] \n\t" \
- "preceu.ph.qbr %[" #TEMP3 "], %[" #TEMP3 "] \n\t" \
- "subq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \
- "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP3 "] \n\t" \
- "rotr %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \
- "addq.ph %[" #TEMP1 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \
- "subq.ph %[" #TEMP3 "], %[" #TEMP2 "], %[" #TEMP0 "] \n\t" \
- "seh %[" #TEMP0 "], %[" #TEMP1 "] \n\t" \
- "sra %[temp16], %[" #TEMP1 "], 16 \n\t" \
- "seh %[temp19], %[" #TEMP3 "] \n\t" \
- "sra %[" #TEMP3 "], %[" #TEMP3 "], 16 \n\t" \
- "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp16] \n\t" \
- "addu %[" #TEMP0 "], %[" #TEMP0 "], %[temp16] \n\t" \
- "mul %[temp17], %[temp19], %[c2217] \n\t" \
- "mul %[temp18], %[" #TEMP3 "], %[c5352] \n\t" \
- "mul %[" #TEMP1 "], %[temp19], %[c5352] \n\t" \
- "mul %[temp16], %[" #TEMP3 "], %[c2217] \n\t" \
- "sll %[" #TEMP2 "], %[" #TEMP2 "], 3 \n\t" \
- "sll %[" #TEMP0 "], %[" #TEMP0 "], 3 \n\t" \
- "subu %[" #TEMP3 "], %[temp17], %[temp18] \n\t" \
- "addu %[" #TEMP1 "], %[temp16], %[" #TEMP1 "] \n\t" \
- "addiu %[" #TEMP3 "], %[" #TEMP3 "], 937 \n\t" \
- "addiu %[" #TEMP1 "], %[" #TEMP1 "], 1812 \n\t" \
- "sra %[" #TEMP3 "], %[" #TEMP3 "], 9 \n\t" \
- "sra %[" #TEMP1 "], %[" #TEMP1 "], 9 \n\t"
-
-// macro for one vertical pass in FTransform
-// temp0..temp15 holds tmp[0]..tmp[15]
-// A..D - offsets in bytes to store to out buffer
-// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements
-#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \
- "addu %[temp16], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \
- "subu %[temp19], %[" #TEMP0 "], %[" #TEMP12 "] \n\t" \
- "addu %[temp17], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \
- "subu %[temp18], %[" #TEMP4 "], %[" #TEMP8 "] \n\t" \
- "mul %[" #TEMP8 "], %[temp19], %[c2217] \n\t" \
- "mul %[" #TEMP12 "], %[temp18], %[c2217] \n\t" \
- "mul %[" #TEMP4 "], %[temp19], %[c5352] \n\t" \
- "mul %[temp18], %[temp18], %[c5352] \n\t" \
- "addiu %[temp16], %[temp16], 7 \n\t" \
- "addu %[" #TEMP0 "], %[temp16], %[temp17] \n\t" \
- "sra %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \
- "addu %[" #TEMP12 "], %[" #TEMP12 "], %[" #TEMP4 "] \n\t" \
- "subu %[" #TEMP4 "], %[temp16], %[temp17] \n\t" \
- "sra %[" #TEMP4 "], %[" #TEMP4 "], 4 \n\t" \
- "addiu %[" #TEMP8 "], %[" #TEMP8 "], 30000 \n\t" \
- "addiu %[" #TEMP12 "], %[" #TEMP12 "], 12000 \n\t" \
- "addiu %[" #TEMP8 "], %[" #TEMP8 "], 21000 \n\t" \
- "subu %[" #TEMP8 "], %[" #TEMP8 "], %[temp18] \n\t" \
- "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \
- "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \
- "addiu %[temp16], %[" #TEMP12 "], 1 \n\t" \
- "movn %[" #TEMP12 "], %[temp16], %[temp19] \n\t" \
- "sh %[" #TEMP0 "], " #A "(%[temp20]) \n\t" \
- "sh %[" #TEMP4 "], " #C "(%[temp20]) \n\t" \
- "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \
- "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t"
-
-static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
- const int c2217 = 2217;
- const int c5352 = 5352;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
- int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16;
- int temp17, temp18, temp19, temp20;
- const int* const args[3] =
- { (const int*)src, (const int*)ref, (const int*)out };
-
- __asm__ volatile (
- HORIZONTAL_PASS(0, temp0, temp1, temp2, temp3)
- HORIZONTAL_PASS(1, temp4, temp5, temp6, temp7)
- HORIZONTAL_PASS(2, temp8, temp9, temp10, temp11)
- HORIZONTAL_PASS(3, temp12, temp13, temp14, temp15)
- "lw %[temp20], 8(%[args]) \n\t"
- VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12)
- VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13)
- VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14)
- VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15)
- OUTPUT_EARLY_CLOBBER_REGS_18(),
- [temp0]"=&r"(temp0), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
- : [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352)
- : "memory", "hi", "lo"
- );
-}
-
-#undef VERTICAL_PASS
-#undef HORIZONTAL_PASS
-
-static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
- uint8_t* dst) {
- int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
- int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
-
- __asm__ volatile (
- "ulw %[temp1], 0(%[in]) \n\t"
- "ulw %[temp2], 16(%[in]) \n\t"
- LOAD_IN_X2(temp5, temp6, 24, 26)
- ADD_SUB_HALVES(temp3, temp4, temp1, temp2)
- LOAD_IN_X2(temp1, temp2, 8, 10)
- MUL_SHIFT_SUM(temp7, temp8, temp9, temp10, temp11, temp12, temp13, temp14,
- temp10, temp8, temp9, temp7, temp1, temp2, temp5, temp6,
- temp13, temp11, temp14, temp12)
- INSERT_HALF_X2(temp8, temp7, temp10, temp9)
- "ulw %[temp17], 4(%[in]) \n\t"
- "ulw %[temp18], 20(%[in]) \n\t"
- ADD_SUB_HALVES(temp1, temp2, temp3, temp8)
- ADD_SUB_HALVES(temp5, temp6, temp4, temp7)
- ADD_SUB_HALVES(temp7, temp8, temp17, temp18)
- LOAD_IN_X2(temp17, temp18, 12, 14)
- LOAD_IN_X2(temp9, temp10, 28, 30)
- MUL_SHIFT_SUM(temp11, temp12, temp13, temp14, temp15, temp16, temp4, temp17,
- temp12, temp14, temp11, temp13, temp17, temp18, temp9, temp10,
- temp15, temp4, temp16, temp17)
- INSERT_HALF_X2(temp11, temp12, temp13, temp14)
- ADD_SUB_HALVES(temp17, temp8, temp8, temp11)
- ADD_SUB_HALVES(temp3, temp4, temp7, temp12)
-
- // horizontal
- SRA_16(temp9, temp10, temp11, temp12, temp1, temp2, temp5, temp6)
- INSERT_HALF_X2(temp1, temp6, temp5, temp2)
- SRA_16(temp13, temp14, temp15, temp16, temp3, temp4, temp17, temp8)
- "repl.ph %[temp2], 0x4 \n\t"
- INSERT_HALF_X2(temp3, temp8, temp17, temp4)
- "addq.ph %[temp1], %[temp1], %[temp2] \n\t"
- "addq.ph %[temp6], %[temp6], %[temp2] \n\t"
- ADD_SUB_HALVES(temp2, temp4, temp1, temp3)
- ADD_SUB_HALVES(temp5, temp7, temp6, temp8)
- MUL_SHIFT_SUM(temp1, temp3, temp6, temp8, temp9, temp13, temp17, temp18,
- temp3, temp13, temp1, temp9, temp9, temp13, temp11, temp15,
- temp6, temp17, temp8, temp18)
- MUL_SHIFT_SUM(temp6, temp8, temp18, temp17, temp11, temp15, temp12, temp16,
- temp8, temp15, temp6, temp11, temp12, temp16, temp10, temp14,
- temp18, temp12, temp17, temp16)
- INSERT_HALF_X2(temp1, temp3, temp9, temp13)
- INSERT_HALF_X2(temp6, temp8, temp11, temp15)
- SHIFT_R_SUM_X2(temp9, temp10, temp11, temp12, temp13, temp14, temp15,
- temp16, temp2, temp4, temp5, temp7, temp3, temp1, temp8,
- temp6)
- PACK_2_HALVES_TO_WORD(temp1, temp2, temp3, temp4, temp9, temp12, temp13,
- temp16, temp11, temp10, temp15, temp14)
- LOAD_WITH_OFFSET_X4(temp10, temp11, temp14, temp15, ref,
- 0, 0, 0, 0,
- 0, 1, 2, 3,
- BPS)
- CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp17, temp18, temp10,
- temp11, temp10, temp11, temp14, temp15)
- STORE_SAT_SUM_X2(temp5, temp6, temp7, temp8, temp17, temp18, temp10, temp11,
- temp9, temp12, temp1, temp2, temp13, temp16, temp3, temp4,
- dst, 0, 1, 2, 3, BPS)
-
- OUTPUT_EARLY_CLOBBER_REGS_18()
- : [dst]"r"(dst), [in]"r"(in), [kC1]"r"(kC1), [kC2]"r"(kC2), [ref]"r"(ref)
- : "memory", "hi", "lo"
- );
-}
-
-static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
- int do_two) {
- ITransformOne(ref, in, dst);
- if (do_two) {
- ITransformOne(ref + 4, in + 16, dst + 4);
- }
-}
-
-static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
- int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17;
-
- __asm__ volatile (
- LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, a,
- 0, 0, 0, 0,
- 0, 1, 2, 3,
- BPS)
- CONVERT_2_BYTES_TO_HALF(temp5, temp6, temp7, temp8, temp9,temp10, temp11,
- temp12, temp1, temp2, temp3, temp4)
- ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8,
- temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12)
- PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5,
- temp7, temp2, temp4, temp6, temp8)
- ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10,
- temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12)
- ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12,
- temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10)
- ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2,
- temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12)
- ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2)
- LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w,
- 0, 4, 8, 12,
- 0, 0, 0, 0,
- 0)
- LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w,
- 0, 4, 8, 12,
- 1, 1, 1, 1,
- 16)
- MUL_HALF(temp17, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8,
- temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16)
- LOAD_WITH_OFFSET_X4(temp1, temp2, temp3, temp4, b,
- 0, 0, 0, 0,
- 0, 1, 2, 3,
- BPS)
- CONVERT_2_BYTES_TO_HALF(temp5,temp6, temp7, temp8, temp9,temp10, temp11,
- temp12, temp1, temp2, temp3, temp4)
- ADD_SUB_HALVES_X4(temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8,
- temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12)
- PACK_2_HALVES_TO_WORD(temp9, temp10, temp11, temp12, temp1, temp3, temp5,
- temp7, temp2, temp4, temp6, temp8)
- ADD_SUB_HALVES_X4(temp2, temp4, temp6, temp8, temp9, temp1, temp3, temp10,
- temp1, temp9, temp3, temp10, temp5, temp11, temp7, temp12)
- ADD_SUB_HALVES_X4(temp5, temp11, temp7, temp2, temp9, temp3, temp6, temp12,
- temp2, temp9, temp6, temp3, temp4, temp1, temp8, temp10)
- ADD_SUB_HALVES_X4(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2,
- temp5, temp7, temp11, temp2, temp9, temp6, temp3, temp12)
- ABS_X8(temp1, temp4, temp10, temp8, temp7, temp11, temp5, temp2)
- LOAD_WITH_OFFSET_X4(temp3, temp6, temp9, temp12, w,
- 0, 4, 8, 12,
- 0, 0, 0, 0,
- 0)
- LOAD_WITH_OFFSET_X4(temp13, temp14, temp15, temp16, w,
- 0, 4, 8, 12,
- 1, 1, 1, 1,
- 16)
- MUL_HALF(temp3, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8,
- temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16)
- OUTPUT_EARLY_CLOBBER_REGS_17()
- : [a]"r"(a), [b]"r"(b), [w]"r"(w)
- : "memory", "hi", "lo"
- );
- return abs(temp3 - temp17) >> 5;
-}
-
-static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- int D = 0;
- int x, y;
- for (y = 0; y < 16 * BPS; y += 4 * BPS) {
- for (x = 0; x < 16; x += 4) {
- D += Disto4x4(a + x + y, b + x + y, w);
- }
- }
- return D;
-}
-
-//------------------------------------------------------------------------------
-// Intra predictions
-
-#define FILL_PART(J, SIZE) \
- "usw %[value], 0+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
- "usw %[value], 4+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
- ".if " #SIZE " == 16 \n\t" \
- "usw %[value], 8+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
- "usw %[value], 12+" #J "*" XSTR(BPS) "(%[dst]) \n\t" \
- ".endif \n\t"
-
-#define FILL_8_OR_16(DST, VALUE, SIZE) do { \
- int value = (VALUE); \
- __asm__ volatile ( \
- "replv.qb %[value], %[value] \n\t" \
- FILL_PART( 0, SIZE) \
- FILL_PART( 1, SIZE) \
- FILL_PART( 2, SIZE) \
- FILL_PART( 3, SIZE) \
- FILL_PART( 4, SIZE) \
- FILL_PART( 5, SIZE) \
- FILL_PART( 6, SIZE) \
- FILL_PART( 7, SIZE) \
- ".if " #SIZE " == 16 \n\t" \
- FILL_PART( 8, 16) \
- FILL_PART( 9, 16) \
- FILL_PART(10, 16) \
- FILL_PART(11, 16) \
- FILL_PART(12, 16) \
- FILL_PART(13, 16) \
- FILL_PART(14, 16) \
- FILL_PART(15, 16) \
- ".endif \n\t" \
- : [value]"+&r"(value) \
- : [dst]"r"((DST)) \
- : "memory" \
- ); \
-} while (0)
-
-#define VERTICAL_PRED(DST, TOP, SIZE) \
-static WEBP_INLINE void VerticalPred##SIZE(uint8_t* (DST), \
- const uint8_t* (TOP)) { \
- int j; \
- if ((TOP)) { \
- for (j = 0; j < (SIZE); ++j) memcpy((DST) + j * BPS, (TOP), (SIZE)); \
- } else { \
- FILL_8_OR_16((DST), 127, (SIZE)); \
- } \
-}
-
-VERTICAL_PRED(dst, top, 8)
-VERTICAL_PRED(dst, top, 16)
-
-#undef VERTICAL_PRED
-
-#define HORIZONTAL_PRED(DST, LEFT, SIZE) \
-static WEBP_INLINE void HorizontalPred##SIZE(uint8_t* (DST), \
- const uint8_t* (LEFT)) { \
- if (LEFT) { \
- int j; \
- for (j = 0; j < (SIZE); ++j) { \
- memset((DST) + j * BPS, (LEFT)[j], (SIZE)); \
- } \
- } else { \
- FILL_8_OR_16((DST), 129, (SIZE)); \
- } \
-}
-
-HORIZONTAL_PRED(dst, left, 8)
-HORIZONTAL_PRED(dst, left, 16)
-
-#undef HORIZONTAL_PRED
-
-#define CLIPPING() \
- "preceu.ph.qbl %[temp2], %[temp0] \n\t" \
- "preceu.ph.qbr %[temp0], %[temp0] \n\t" \
- "preceu.ph.qbl %[temp3], %[temp1] \n\t" \
- "preceu.ph.qbr %[temp1], %[temp1] \n\t" \
- "addu.ph %[temp2], %[temp2], %[leftY_1] \n\t" \
- "addu.ph %[temp0], %[temp0], %[leftY_1] \n\t" \
- "addu.ph %[temp3], %[temp3], %[leftY_1] \n\t" \
- "addu.ph %[temp1], %[temp1], %[leftY_1] \n\t" \
- "shll_s.ph %[temp2], %[temp2], 7 \n\t" \
- "shll_s.ph %[temp0], %[temp0], 7 \n\t" \
- "shll_s.ph %[temp3], %[temp3], 7 \n\t" \
- "shll_s.ph %[temp1], %[temp1], 7 \n\t" \
- "precrqu_s.qb.ph %[temp0], %[temp2], %[temp0] \n\t" \
- "precrqu_s.qb.ph %[temp1], %[temp3], %[temp1] \n\t"
-
-#define CLIP_8B_TO_DST(DST, LEFT, TOP, SIZE) do { \
- int leftY_1 = ((int)(LEFT)[y] << 16) + (LEFT)[y]; \
- int temp0, temp1, temp2, temp3; \
- __asm__ volatile ( \
- "replv.ph %[leftY_1], %[leftY_1] \n\t" \
- "ulw %[temp0], 0(%[top]) \n\t" \
- "ulw %[temp1], 4(%[top]) \n\t" \
- "subu.ph %[leftY_1], %[leftY_1], %[left_1] \n\t" \
- CLIPPING() \
- "usw %[temp0], 0(%[dst]) \n\t" \
- "usw %[temp1], 4(%[dst]) \n\t" \
- ".if " #SIZE " == 16 \n\t" \
- "ulw %[temp0], 8(%[top]) \n\t" \
- "ulw %[temp1], 12(%[top]) \n\t" \
- CLIPPING() \
- "usw %[temp0], 8(%[dst]) \n\t" \
- "usw %[temp1], 12(%[dst]) \n\t" \
- ".endif \n\t" \
- : [leftY_1]"+&r"(leftY_1), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \
- : [left_1]"r"(left_1), [top]"r"((TOP)), [dst]"r"((DST)) \
- : "memory" \
- ); \
-} while (0)
-
-#define CLIP_TO_DST(DST, LEFT, TOP, SIZE) do { \
- int y; \
- const int left_1 = ((int)(LEFT)[-1] << 16) + (LEFT)[-1]; \
- for (y = 0; y < (SIZE); ++y) { \
- CLIP_8B_TO_DST((DST), (LEFT), (TOP), (SIZE)); \
- (DST) += BPS; \
- } \
-} while (0)
-
-#define TRUE_MOTION(DST, LEFT, TOP, SIZE) \
-static WEBP_INLINE void TrueMotion##SIZE(uint8_t* (DST), const uint8_t* (LEFT),\
- const uint8_t* (TOP)) { \
- if ((LEFT) != NULL) { \
- if ((TOP) != NULL) { \
- CLIP_TO_DST((DST), (LEFT), (TOP), (SIZE)); \
- } else { \
- HorizontalPred##SIZE((DST), (LEFT)); \
- } \
- } else { \
- /* true motion without left samples (hence: with default 129 value) */ \
- /* is equivalent to VE prediction where you just copy the top samples. */ \
- /* Note that if top samples are not available, the default value is */ \
- /* then 129, and not 127 as in the VerticalPred case. */ \
- if ((TOP) != NULL) { \
- VerticalPred##SIZE((DST), (TOP)); \
- } else { \
- FILL_8_OR_16((DST), 129, (SIZE)); \
- } \
- } \
-}
-
-TRUE_MOTION(dst, left, top, 8)
-TRUE_MOTION(dst, left, top, 16)
-
-#undef TRUE_MOTION
-#undef CLIP_TO_DST
-#undef CLIP_8B_TO_DST
-#undef CLIPPING
-
-static WEBP_INLINE void DCMode16(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- int DC, DC1;
- int temp0, temp1, temp2, temp3;
-
- __asm__ volatile(
- "beqz %[top], 2f \n\t"
- LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, top,
- 0, 4, 8, 12,
- 0, 0, 0, 0,
- 0)
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "raddu.w.qb %[temp1], %[temp1] \n\t"
- "raddu.w.qb %[temp2], %[temp2] \n\t"
- "raddu.w.qb %[temp3], %[temp3] \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "addu %[temp2], %[temp2], %[temp3] \n\t"
- "addu %[DC], %[temp0], %[temp2] \n\t"
- "move %[DC1], %[DC] \n\t"
- "beqz %[left], 1f \n\t"
- LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left,
- 0, 4, 8, 12,
- 0, 0, 0, 0,
- 0)
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "raddu.w.qb %[temp1], %[temp1] \n\t"
- "raddu.w.qb %[temp2], %[temp2] \n\t"
- "raddu.w.qb %[temp3], %[temp3] \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "addu %[temp2], %[temp2], %[temp3] \n\t"
- "addu %[DC1], %[temp0], %[temp2] \n\t"
- "1: \n\t"
- "addu %[DC], %[DC], %[DC1] \n\t"
- "j 3f \n\t"
- "2: \n\t"
- "beqz %[left], 4f \n\t"
- LOAD_WITH_OFFSET_X4(temp0, temp1, temp2, temp3, left,
- 0, 4, 8, 12,
- 0, 0, 0, 0,
- 0)
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "raddu.w.qb %[temp1], %[temp1] \n\t"
- "raddu.w.qb %[temp2], %[temp2] \n\t"
- "raddu.w.qb %[temp3], %[temp3] \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "addu %[temp2], %[temp2], %[temp3] \n\t"
- "addu %[DC], %[temp0], %[temp2] \n\t"
- "addu %[DC], %[DC], %[DC] \n\t"
- "3: \n\t"
- "shra_r.w %[DC], %[DC], 5 \n\t"
- "j 5f \n\t"
- "4: \n\t"
- "li %[DC], 0x80 \n\t"
- "5: \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1)
- : [left]"r"(left), [top]"r"(top)
- : "memory"
- );
-
- FILL_8_OR_16(dst, DC, 16);
-}
-
-static WEBP_INLINE void DCMode8(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- int DC, DC1;
- int temp0, temp1, temp2, temp3;
-
- __asm__ volatile(
- "beqz %[top], 2f \n\t"
- "ulw %[temp0], 0(%[top]) \n\t"
- "ulw %[temp1], 4(%[top]) \n\t"
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "raddu.w.qb %[temp1], %[temp1] \n\t"
- "addu %[DC], %[temp0], %[temp1] \n\t"
- "move %[DC1], %[DC] \n\t"
- "beqz %[left], 1f \n\t"
- "ulw %[temp2], 0(%[left]) \n\t"
- "ulw %[temp3], 4(%[left]) \n\t"
- "raddu.w.qb %[temp2], %[temp2] \n\t"
- "raddu.w.qb %[temp3], %[temp3] \n\t"
- "addu %[DC1], %[temp2], %[temp3] \n\t"
- "1: \n\t"
- "addu %[DC], %[DC], %[DC1] \n\t"
- "j 3f \n\t"
- "2: \n\t"
- "beqz %[left], 4f \n\t"
- "ulw %[temp2], 0(%[left]) \n\t"
- "ulw %[temp3], 4(%[left]) \n\t"
- "raddu.w.qb %[temp2], %[temp2] \n\t"
- "raddu.w.qb %[temp3], %[temp3] \n\t"
- "addu %[DC], %[temp2], %[temp3] \n\t"
- "addu %[DC], %[DC], %[DC] \n\t"
- "3: \n\t"
- "shra_r.w %[DC], %[DC], 4 \n\t"
- "j 5f \n\t"
- "4: \n\t"
- "li %[DC], 0x80 \n\t"
- "5: \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [DC]"=&r"(DC),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [DC1]"=&r"(DC1)
- : [left]"r"(left), [top]"r"(top)
- : "memory"
- );
-
- FILL_8_OR_16(dst, DC, 8);
-}
-
-static void DC4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1;
- __asm__ volatile(
- "ulw %[temp0], 0(%[top]) \n\t"
- "ulw %[temp1], -5(%[top]) \n\t"
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "raddu.w.qb %[temp1], %[temp1] \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "addiu %[temp0], %[temp0], 4 \n\t"
- "srl %[temp0], %[temp0], 3 \n\t"
- "replv.qb %[temp0], %[temp0] \n\t"
- "usw %[temp0], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp0], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp0], 3*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void TM4(uint8_t* dst, const uint8_t* top) {
- int a10, a32, temp0, temp1, temp2, temp3, temp4, temp5;
- const int c35 = 0xff00ff;
- __asm__ volatile (
- "lbu %[temp1], 0(%[top]) \n\t"
- "lbu %[a10], 1(%[top]) \n\t"
- "lbu %[temp2], 2(%[top]) \n\t"
- "lbu %[a32], 3(%[top]) \n\t"
- "ulw %[temp0], -5(%[top]) \n\t"
- "lbu %[temp4], -1(%[top]) \n\t"
- "append %[a10], %[temp1], 16 \n\t"
- "append %[a32], %[temp2], 16 \n\t"
- "replv.ph %[temp4], %[temp4] \n\t"
- "shrl.ph %[temp1], %[temp0], 8 \n\t"
- "and %[temp0], %[temp0], %[c35] \n\t"
- "subu.ph %[temp1], %[temp1], %[temp4] \n\t"
- "subu.ph %[temp0], %[temp0], %[temp4] \n\t"
- "srl %[temp2], %[temp1], 16 \n\t"
- "srl %[temp3], %[temp0], 16 \n\t"
- "replv.ph %[temp2], %[temp2] \n\t"
- "replv.ph %[temp3], %[temp3] \n\t"
- "replv.ph %[temp4], %[temp1] \n\t"
- "replv.ph %[temp5], %[temp0] \n\t"
- "addu.ph %[temp0], %[temp3], %[a10] \n\t"
- "addu.ph %[temp1], %[temp3], %[a32] \n\t"
- "addu.ph %[temp3], %[temp2], %[a10] \n\t"
- "addu.ph %[temp2], %[temp2], %[a32] \n\t"
- "shll_s.ph %[temp0], %[temp0], 7 \n\t"
- "shll_s.ph %[temp1], %[temp1], 7 \n\t"
- "shll_s.ph %[temp3], %[temp3], 7 \n\t"
- "shll_s.ph %[temp2], %[temp2], 7 \n\t"
- "precrqu_s.qb.ph %[temp0], %[temp1], %[temp0] \n\t"
- "precrqu_s.qb.ph %[temp1], %[temp2], %[temp3] \n\t"
- "addu.ph %[temp2], %[temp5], %[a10] \n\t"
- "addu.ph %[temp3], %[temp5], %[a32] \n\t"
- "addu.ph %[temp5], %[temp4], %[a10] \n\t"
- "addu.ph %[temp4], %[temp4], %[a32] \n\t"
- "shll_s.ph %[temp2], %[temp2], 7 \n\t"
- "shll_s.ph %[temp3], %[temp3], 7 \n\t"
- "shll_s.ph %[temp4], %[temp4], 7 \n\t"
- "shll_s.ph %[temp5], %[temp5], 7 \n\t"
- "precrqu_s.qb.ph %[temp2], %[temp3], %[temp2] \n\t"
- "precrqu_s.qb.ph %[temp3], %[temp4], %[temp5] \n\t"
- "usw %[temp1], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp3], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp2], 3*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [a10]"=&r"(a10), [a32]"=&r"(a32)
- : [c35]"r"(c35), [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void VE4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
- __asm__ volatile(
- "ulw %[temp0], -1(%[top]) \n\t"
- "ulh %[temp1], 3(%[top]) \n\t"
- "preceu.ph.qbr %[temp2], %[temp0] \n\t"
- "preceu.ph.qbl %[temp3], %[temp0] \n\t"
- "preceu.ph.qbr %[temp4], %[temp1] \n\t"
- "packrl.ph %[temp5], %[temp3], %[temp2] \n\t"
- "packrl.ph %[temp6], %[temp4], %[temp3] \n\t"
- "shll.ph %[temp5], %[temp5], 1 \n\t"
- "shll.ph %[temp6], %[temp6], 1 \n\t"
- "addq.ph %[temp2], %[temp5], %[temp2] \n\t"
- "addq.ph %[temp6], %[temp6], %[temp4] \n\t"
- "addq.ph %[temp2], %[temp2], %[temp3] \n\t"
- "addq.ph %[temp6], %[temp6], %[temp3] \n\t"
- "shra_r.ph %[temp2], %[temp2], 2 \n\t"
- "shra_r.ph %[temp6], %[temp6], 2 \n\t"
- "precr.qb.ph %[temp4], %[temp6], %[temp2] \n\t"
- "usw %[temp4], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp4], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp4], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void HE4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
- __asm__ volatile(
- "ulw %[temp0], -4(%[top]) \n\t"
- "lbu %[temp1], -5(%[top]) \n\t"
- "preceu.ph.qbr %[temp2], %[temp0] \n\t"
- "preceu.ph.qbl %[temp3], %[temp0] \n\t"
- "replv.ph %[temp4], %[temp1] \n\t"
- "packrl.ph %[temp5], %[temp3], %[temp2] \n\t"
- "packrl.ph %[temp6], %[temp2], %[temp4] \n\t"
- "shll.ph %[temp5], %[temp5], 1 \n\t"
- "shll.ph %[temp6], %[temp6], 1 \n\t"
- "addq.ph %[temp3], %[temp3], %[temp5] \n\t"
- "addq.ph %[temp3], %[temp3], %[temp2] \n\t"
- "addq.ph %[temp2], %[temp2], %[temp6] \n\t"
- "addq.ph %[temp2], %[temp2], %[temp4] \n\t"
- "shra_r.ph %[temp3], %[temp3], 2 \n\t"
- "shra_r.ph %[temp2], %[temp2], 2 \n\t"
- "replv.qb %[temp0], %[temp3] \n\t"
- "replv.qb %[temp1], %[temp2] \n\t"
- "srl %[temp3], %[temp3], 16 \n\t"
- "srl %[temp2], %[temp2], 16 \n\t"
- "replv.qb %[temp3], %[temp3] \n\t"
- "replv.qb %[temp2], %[temp2] \n\t"
- "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp0], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp2], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp1], 3*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void RD4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- int temp6, temp7, temp8, temp9, temp10, temp11;
- __asm__ volatile(
- "ulw %[temp0], -5(%[top]) \n\t"
- "ulw %[temp1], -1(%[top]) \n\t"
- "preceu.ph.qbl %[temp2], %[temp0] \n\t"
- "preceu.ph.qbr %[temp3], %[temp0] \n\t"
- "preceu.ph.qbr %[temp4], %[temp1] \n\t"
- "preceu.ph.qbl %[temp5], %[temp1] \n\t"
- "packrl.ph %[temp6], %[temp2], %[temp3] \n\t"
- "packrl.ph %[temp7], %[temp4], %[temp2] \n\t"
- "packrl.ph %[temp8], %[temp5], %[temp4] \n\t"
- "shll.ph %[temp6], %[temp6], 1 \n\t"
- "addq.ph %[temp9], %[temp2], %[temp6] \n\t"
- "shll.ph %[temp7], %[temp7], 1 \n\t"
- "addq.ph %[temp9], %[temp9], %[temp3] \n\t"
- "shll.ph %[temp8], %[temp8], 1 \n\t"
- "shra_r.ph %[temp9], %[temp9], 2 \n\t"
- "addq.ph %[temp10], %[temp4], %[temp7] \n\t"
- "addq.ph %[temp11], %[temp5], %[temp8] \n\t"
- "addq.ph %[temp10], %[temp10], %[temp2] \n\t"
- "addq.ph %[temp11], %[temp11], %[temp4] \n\t"
- "shra_r.ph %[temp10], %[temp10], 2 \n\t"
- "shra_r.ph %[temp11], %[temp11], 2 \n\t"
- "lbu %[temp0], 3(%[top]) \n\t"
- "lbu %[temp1], 2(%[top]) \n\t"
- "lbu %[temp2], 1(%[top]) \n\t"
- "sll %[temp1], %[temp1], 1 \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "addu %[temp0], %[temp0], %[temp2] \n\t"
- "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t"
- "shra_r.w %[temp0], %[temp0], 2 \n\t"
- "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t"
- "usw %[temp9], 3*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp10], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "prepend %[temp9], %[temp11], 8 \n\t"
- "prepend %[temp10], %[temp0], 8 \n\t"
- "usw %[temp9], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp10], 0*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void VR4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8, temp9;
- __asm__ volatile (
- "ulw %[temp0], -4(%[top]) \n\t"
- "ulw %[temp1], 0(%[top]) \n\t"
- "preceu.ph.qbl %[temp2], %[temp0] \n\t"
- "preceu.ph.qbr %[temp0], %[temp0] \n\t"
- "preceu.ph.qbla %[temp3], %[temp1] \n\t"
- "preceu.ph.qbra %[temp1], %[temp1] \n\t"
- "packrl.ph %[temp7], %[temp3], %[temp2] \n\t"
- "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t"
- "move %[temp6], %[temp1] \n\t"
- "append %[temp1], %[temp2], 16 \n\t"
- "shll.ph %[temp9], %[temp6], 1 \n\t"
- "addqh_r.ph %[temp5], %[temp7], %[temp6] \n\t"
- "shll.ph %[temp8], %[temp7], 1 \n\t"
- "addu.ph %[temp3], %[temp7], %[temp3] \n\t"
- "addu.ph %[temp1], %[temp1], %[temp6] \n\t"
- "packrl.ph %[temp7], %[temp2], %[temp0] \n\t"
- "addu.ph %[temp6], %[temp0], %[temp2] \n\t"
- "addu.ph %[temp3], %[temp3], %[temp9] \n\t"
- "addu.ph %[temp1], %[temp1], %[temp8] \n\t"
- "shll.ph %[temp7], %[temp7], 1 \n\t"
- "shra_r.ph %[temp3], %[temp3], 2 \n\t"
- "shra_r.ph %[temp1], %[temp1], 2 \n\t"
- "addu.ph %[temp6], %[temp6], %[temp7] \n\t"
- "shra_r.ph %[temp6], %[temp6], 2 \n\t"
- "precrq.ph.w %[temp8], %[temp4], %[temp5] \n\t"
- "append %[temp4], %[temp5], 16 \n\t"
- "precrq.ph.w %[temp2], %[temp3], %[temp1] \n\t"
- "append %[temp3], %[temp1], 16 \n\t"
- "precr.qb.ph %[temp8], %[temp8], %[temp4] \n\t"
- "precr.qb.ph %[temp3], %[temp2], %[temp3] \n\t"
- "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "append %[temp3], %[temp6], 8 \n\t"
- "srl %[temp6], %[temp6], 16 \n\t"
- "append %[temp8], %[temp6], 8 \n\t"
- "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void LD4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- int temp6, temp7, temp8, temp9, temp10, temp11;
- __asm__ volatile(
- "ulw %[temp0], 0(%[top]) \n\t"
- "ulw %[temp1], 4(%[top]) \n\t"
- "preceu.ph.qbl %[temp2], %[temp0] \n\t"
- "preceu.ph.qbr %[temp3], %[temp0] \n\t"
- "preceu.ph.qbr %[temp4], %[temp1] \n\t"
- "preceu.ph.qbl %[temp5], %[temp1] \n\t"
- "packrl.ph %[temp6], %[temp2], %[temp3] \n\t"
- "packrl.ph %[temp7], %[temp4], %[temp2] \n\t"
- "packrl.ph %[temp8], %[temp5], %[temp4] \n\t"
- "shll.ph %[temp6], %[temp6], 1 \n\t"
- "addq.ph %[temp9], %[temp2], %[temp6] \n\t"
- "shll.ph %[temp7], %[temp7], 1 \n\t"
- "addq.ph %[temp9], %[temp9], %[temp3] \n\t"
- "shll.ph %[temp8], %[temp8], 1 \n\t"
- "shra_r.ph %[temp9], %[temp9], 2 \n\t"
- "addq.ph %[temp10], %[temp4], %[temp7] \n\t"
- "addq.ph %[temp11], %[temp5], %[temp8] \n\t"
- "addq.ph %[temp10], %[temp10], %[temp2] \n\t"
- "addq.ph %[temp11], %[temp11], %[temp4] \n\t"
- "shra_r.ph %[temp10], %[temp10], 2 \n\t"
- "shra_r.ph %[temp11], %[temp11], 2 \n\t"
- "srl %[temp1], %[temp1], 24 \n\t"
- "sll %[temp1], %[temp1], 1 \n\t"
- "raddu.w.qb %[temp5], %[temp5] \n\t"
- "precr.qb.ph %[temp9], %[temp10], %[temp9] \n\t"
- "precr.qb.ph %[temp10], %[temp11], %[temp10] \n\t"
- "addu %[temp1], %[temp1], %[temp5] \n\t"
- "shra_r.w %[temp1], %[temp1], 2 \n\t"
- "usw %[temp9], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp10], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "prepend %[temp9], %[temp11], 8 \n\t"
- "prepend %[temp10], %[temp1], 8 \n\t"
- "usw %[temp9], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp10], 3*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void VL4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8, temp9;
- __asm__ volatile (
- "ulw %[temp0], 0(%[top]) \n\t"
- "ulw %[temp1], 4(%[top]) \n\t"
- "preceu.ph.qbla %[temp2], %[temp0] \n\t"
- "preceu.ph.qbra %[temp0], %[temp0] \n\t"
- "preceu.ph.qbl %[temp3], %[temp1] \n\t"
- "preceu.ph.qbr %[temp1], %[temp1] \n\t"
- "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t"
- "packrl.ph %[temp7], %[temp1], %[temp0] \n\t"
- "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t"
- "shll.ph %[temp9], %[temp2], 1 \n\t"
- "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t"
- "shll.ph %[temp8], %[temp7], 1 \n\t"
- "addu.ph %[temp2], %[temp2], %[temp6] \n\t"
- "addu.ph %[temp0], %[temp0], %[temp7] \n\t"
- "packrl.ph %[temp7], %[temp3], %[temp1] \n\t"
- "addu.ph %[temp6], %[temp1], %[temp3] \n\t"
- "addu.ph %[temp2], %[temp2], %[temp8] \n\t"
- "addu.ph %[temp0], %[temp0], %[temp9] \n\t"
- "shll.ph %[temp7], %[temp7], 1 \n\t"
- "shra_r.ph %[temp2], %[temp2], 2 \n\t"
- "shra_r.ph %[temp0], %[temp0], 2 \n\t"
- "addu.ph %[temp6], %[temp6], %[temp7] \n\t"
- "shra_r.ph %[temp6], %[temp6], 2 \n\t"
- "precrq.ph.w %[temp8], %[temp5], %[temp4] \n\t"
- "append %[temp5], %[temp4], 16 \n\t"
- "precrq.ph.w %[temp3], %[temp2], %[temp0] \n\t"
- "append %[temp2], %[temp0], 16 \n\t"
- "precr.qb.ph %[temp8], %[temp8], %[temp5] \n\t"
- "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t"
- "usw %[temp8], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "prepend %[temp8], %[temp6], 8 \n\t"
- "usw %[temp3], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "srl %[temp6], %[temp6], 16 \n\t"
- "prepend %[temp3], %[temp6], 8 \n\t"
- "usw %[temp8], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp3], 3*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void HD4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8, temp9;
- __asm__ volatile (
- "ulw %[temp0], -5(%[top]) \n\t"
- "ulw %[temp1], -1(%[top]) \n\t"
- "preceu.ph.qbla %[temp2], %[temp0] \n\t"
- "preceu.ph.qbra %[temp0], %[temp0] \n\t"
- "preceu.ph.qbl %[temp3], %[temp1] \n\t"
- "preceu.ph.qbr %[temp1], %[temp1] \n\t"
- "addqh_r.ph %[temp4], %[temp0], %[temp2] \n\t"
- "packrl.ph %[temp7], %[temp1], %[temp0] \n\t"
- "precrq.ph.w %[temp6], %[temp1], %[temp2] \n\t"
- "shll.ph %[temp9], %[temp2], 1 \n\t"
- "addqh_r.ph %[temp5], %[temp7], %[temp2] \n\t"
- "shll.ph %[temp8], %[temp7], 1 \n\t"
- "addu.ph %[temp2], %[temp2], %[temp6] \n\t"
- "addu.ph %[temp0], %[temp0], %[temp7] \n\t"
- "packrl.ph %[temp7], %[temp3], %[temp1] \n\t"
- "addu.ph %[temp6], %[temp1], %[temp3] \n\t"
- "addu.ph %[temp2], %[temp2], %[temp8] \n\t"
- "addu.ph %[temp0], %[temp0], %[temp9] \n\t"
- "shll.ph %[temp7], %[temp7], 1 \n\t"
- "shra_r.ph %[temp2], %[temp2], 2 \n\t"
- "shra_r.ph %[temp0], %[temp0], 2 \n\t"
- "addu.ph %[temp6], %[temp6], %[temp7] \n\t"
- "shra_r.ph %[temp6], %[temp6], 2 \n\t"
- "precrq.ph.w %[temp1], %[temp2], %[temp5] \n\t"
- "precrq.ph.w %[temp3], %[temp0], %[temp4] \n\t"
- "precr.qb.ph %[temp7], %[temp6], %[temp1] \n\t"
- "precr.qb.ph %[temp6], %[temp1], %[temp3] \n\t"
- "usw %[temp7], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp6], 1*" XSTR(BPS) "(%[dst]) \n\t"
- "append %[temp2], %[temp5], 16 \n\t"
- "append %[temp0], %[temp4], 16 \n\t"
- "precr.qb.ph %[temp5], %[temp3], %[temp2] \n\t"
- "precr.qb.ph %[temp4], %[temp2], %[temp0] \n\t"
- "usw %[temp5], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp4], 3*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-static void HU4(uint8_t* dst, const uint8_t* top) {
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
- __asm__ volatile (
- "ulw %[temp0], -5(%[top]) \n\t"
- "preceu.ph.qbl %[temp1], %[temp0] \n\t"
- "preceu.ph.qbr %[temp2], %[temp0] \n\t"
- "packrl.ph %[temp3], %[temp1], %[temp2] \n\t"
- "replv.qb %[temp7], %[temp2] \n\t"
- "addqh_r.ph %[temp4], %[temp1], %[temp3] \n\t"
- "addqh_r.ph %[temp5], %[temp3], %[temp2] \n\t"
- "shll.ph %[temp6], %[temp3], 1 \n\t"
- "addu.ph %[temp3], %[temp2], %[temp3] \n\t"
- "addu.ph %[temp6], %[temp1], %[temp6] \n\t"
- "shll.ph %[temp0], %[temp2], 1 \n\t"
- "addu.ph %[temp6], %[temp6], %[temp2] \n\t"
- "addu.ph %[temp0], %[temp3], %[temp0] \n\t"
- "shra_r.ph %[temp6], %[temp6], 2 \n\t"
- "shra_r.ph %[temp0], %[temp0], 2 \n\t"
- "packrl.ph %[temp3], %[temp6], %[temp5] \n\t"
- "precrq.ph.w %[temp2], %[temp6], %[temp4] \n\t"
- "append %[temp0], %[temp5], 16 \n\t"
- "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t"
- "usw %[temp3], 0*" XSTR(BPS) "(%[dst]) \n\t"
- "precr.qb.ph %[temp1], %[temp7], %[temp0] \n\t"
- "usw %[temp7], 3*" XSTR(BPS) "(%[dst]) \n\t"
- "packrl.ph %[temp2], %[temp1], %[temp3] \n\t"
- "usw %[temp1], 2*" XSTR(BPS) "(%[dst]) \n\t"
- "usw %[temp2], 1*" XSTR(BPS) "(%[dst]) \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7)
- : [top]"r"(top), [dst]"r"(dst)
- : "memory"
- );
-}
-
-//------------------------------------------------------------------------------
-// Chroma 8x8 prediction (paragraph 12.2)
-
-static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- // U block
- DCMode8(C8DC8 + dst, left, top);
- VerticalPred8(C8VE8 + dst, top);
- HorizontalPred8(C8HE8 + dst, left);
- TrueMotion8(C8TM8 + dst, left, top);
- // V block
- dst += 8;
- if (top) top += 8;
- if (left) left += 16;
- DCMode8(C8DC8 + dst, left, top);
- VerticalPred8(C8VE8 + dst, top);
- HorizontalPred8(C8HE8 + dst, left);
- TrueMotion8(C8TM8 + dst, left, top);
-}
-
-//------------------------------------------------------------------------------
-// luma 16x16 prediction (paragraph 12.3)
-
-static void Intra16Preds(uint8_t* dst,
- const uint8_t* left, const uint8_t* top) {
- DCMode16(I16DC16 + dst, left, top);
- VerticalPred16(I16VE16 + dst, top);
- HorizontalPred16(I16HE16 + dst, left);
- TrueMotion16(I16TM16 + dst, left, top);
-}
-
-// Left samples are top[-5 .. -2], top_left is top[-1], top are
-// located at top[0..3], and top right is top[4..7]
-static void Intra4Preds(uint8_t* dst, const uint8_t* top) {
- DC4(I4DC4 + dst, top);
- TM4(I4TM4 + dst, top);
- VE4(I4VE4 + dst, top);
- HE4(I4HE4 + dst, top);
- RD4(I4RD4 + dst, top);
- VR4(I4VR4 + dst, top);
- LD4(I4LD4 + dst, top);
- VL4(I4VL4 + dst, top);
- HD4(I4HD4 + dst, top);
- HU4(I4HU4 + dst, top);
-}
-
-//------------------------------------------------------------------------------
-// Metric
-
-#if !defined(WORK_AROUND_GCC)
-
-#define GET_SSE_INNER(A) \
- "lw %[temp0], " #A "(%[a]) \n\t" \
- "lw %[temp1], " #A "(%[b]) \n\t" \
- "preceu.ph.qbr %[temp2], %[temp0] \n\t" \
- "preceu.ph.qbl %[temp0], %[temp0] \n\t" \
- "preceu.ph.qbr %[temp3], %[temp1] \n\t" \
- "preceu.ph.qbl %[temp1], %[temp1] \n\t" \
- "subq.ph %[temp2], %[temp2], %[temp3] \n\t" \
- "subq.ph %[temp0], %[temp0], %[temp1] \n\t" \
- "dpa.w.ph $ac0, %[temp2], %[temp2] \n\t" \
- "dpa.w.ph $ac0, %[temp0], %[temp0] \n\t"
-
-#define GET_SSE(A, B, C, D) \
- GET_SSE_INNER(A) \
- GET_SSE_INNER(B) \
- GET_SSE_INNER(C) \
- GET_SSE_INNER(D)
-
-static int SSE16x16(const uint8_t* a, const uint8_t* b) {
- int count;
- int temp0, temp1, temp2, temp3;
- __asm__ volatile (
- "mult $zero, $zero \n\t"
- GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
- GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
- GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
- GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
- GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
- GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
- GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
- GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
- GET_SSE( 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS)
- GET_SSE( 9 * BPS, 4 + 9 * BPS, 8 + 9 * BPS, 12 + 9 * BPS)
- GET_SSE(10 * BPS, 4 + 10 * BPS, 8 + 10 * BPS, 12 + 10 * BPS)
- GET_SSE(11 * BPS, 4 + 11 * BPS, 8 + 11 * BPS, 12 + 11 * BPS)
- GET_SSE(12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS)
- GET_SSE(13 * BPS, 4 + 13 * BPS, 8 + 13 * BPS, 12 + 13 * BPS)
- GET_SSE(14 * BPS, 4 + 14 * BPS, 8 + 14 * BPS, 12 + 14 * BPS)
- GET_SSE(15 * BPS, 4 + 15 * BPS, 8 + 15 * BPS, 12 + 15 * BPS)
- "mflo %[count] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [count]"=&r"(count)
- : [a]"r"(a), [b]"r"(b)
- : "memory", "hi", "lo"
- );
- return count;
-}
-
-static int SSE16x8(const uint8_t* a, const uint8_t* b) {
- int count;
- int temp0, temp1, temp2, temp3;
- __asm__ volatile (
- "mult $zero, $zero \n\t"
- GET_SSE( 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS)
- GET_SSE( 1 * BPS, 4 + 1 * BPS, 8 + 1 * BPS, 12 + 1 * BPS)
- GET_SSE( 2 * BPS, 4 + 2 * BPS, 8 + 2 * BPS, 12 + 2 * BPS)
- GET_SSE( 3 * BPS, 4 + 3 * BPS, 8 + 3 * BPS, 12 + 3 * BPS)
- GET_SSE( 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS)
- GET_SSE( 5 * BPS, 4 + 5 * BPS, 8 + 5 * BPS, 12 + 5 * BPS)
- GET_SSE( 6 * BPS, 4 + 6 * BPS, 8 + 6 * BPS, 12 + 6 * BPS)
- GET_SSE( 7 * BPS, 4 + 7 * BPS, 8 + 7 * BPS, 12 + 7 * BPS)
- "mflo %[count] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [count]"=&r"(count)
- : [a]"r"(a), [b]"r"(b)
- : "memory", "hi", "lo"
- );
- return count;
-}
-
-static int SSE8x8(const uint8_t* a, const uint8_t* b) {
- int count;
- int temp0, temp1, temp2, temp3;
- __asm__ volatile (
- "mult $zero, $zero \n\t"
- GET_SSE(0 * BPS, 4 + 0 * BPS, 1 * BPS, 4 + 1 * BPS)
- GET_SSE(2 * BPS, 4 + 2 * BPS, 3 * BPS, 4 + 3 * BPS)
- GET_SSE(4 * BPS, 4 + 4 * BPS, 5 * BPS, 4 + 5 * BPS)
- GET_SSE(6 * BPS, 4 + 6 * BPS, 7 * BPS, 4 + 7 * BPS)
- "mflo %[count] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [count]"=&r"(count)
- : [a]"r"(a), [b]"r"(b)
- : "memory", "hi", "lo"
- );
- return count;
-}
-
-static int SSE4x4(const uint8_t* a, const uint8_t* b) {
- int count;
- int temp0, temp1, temp2, temp3;
- __asm__ volatile (
- "mult $zero, $zero \n\t"
- GET_SSE(0 * BPS, 1 * BPS, 2 * BPS, 3 * BPS)
- "mflo %[count] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [count]"=&r"(count)
- : [a]"r"(a), [b]"r"(b)
- : "memory", "hi", "lo"
- );
- return count;
-}
-
-#undef GET_SSE
-#undef GET_SSE_INNER
-
-#endif // !WORK_AROUND_GCC
-
-#undef FILL_8_OR_16
-#undef FILL_PART
-#undef OUTPUT_EARLY_CLOBBER_REGS_17
-#undef MUL_HALF
-#undef ABS_X8
-#undef ADD_SUB_HALVES_X4
-
-//------------------------------------------------------------------------------
-// Quantization
-//
-
-// macro for one pass through for loop in QuantizeBlock reading 2 values at time
-// QUANTDIV macro inlined
-// J - offset in bytes (kZigzag[n] * 2)
-// K - offset in bytes (kZigzag[n] * 4)
-// N - offset in bytes (n * 2)
-// N1 - offset in bytes ((n + 1) * 2)
-#define QUANTIZE_ONE(J, K, N, N1) \
- "ulw %[temp1], " #J "(%[ppin]) \n\t" \
- "ulw %[temp2], " #J "(%[ppsharpen]) \n\t" \
- "lhu %[temp3], " #K "(%[ppzthresh]) \n\t" \
- "lhu %[temp6], " #K "+4(%[ppzthresh]) \n\t" \
- "absq_s.ph %[temp4], %[temp1] \n\t" \
- "ins %[temp3], %[temp6], 16, 16 \n\t" \
- "addu.ph %[coeff], %[temp4], %[temp2] \n\t" \
- "shra.ph %[sign], %[temp1], 15 \n\t" \
- "li %[level], 0x10001 \n\t" \
- "cmp.lt.ph %[temp3], %[coeff] \n\t" \
- "lhu %[temp1], " #J "(%[ppiq]) \n\t" \
- "pick.ph %[temp5], %[level], $0 \n\t" \
- "lw %[temp2], " #K "(%[ppbias]) \n\t" \
- "beqz %[temp5], 0f \n\t" \
- "lhu %[temp3], " #J "(%[ppq]) \n\t" \
- "beq %[temp5], %[level], 1f \n\t" \
- "andi %[temp5], %[temp5], 0x1 \n\t" \
- "andi %[temp4], %[coeff], 0xffff \n\t" \
- "beqz %[temp5], 2f \n\t" \
- "mul %[level], %[temp4], %[temp1] \n\t" \
- "sh $0, " #J "+2(%[ppin]) \n\t" \
- "sh $0, " #N1 "(%[pout]) \n\t" \
- "addu %[level], %[level], %[temp2] \n\t" \
- "sra %[level], %[level], 17 \n\t" \
- "slt %[temp4], %[max_level], %[level] \n\t" \
- "movn %[level], %[max_level], %[temp4] \n\t" \
- "andi %[temp6], %[sign], 0xffff \n\t" \
- "xor %[level], %[level], %[temp6] \n\t" \
- "subu %[level], %[level], %[temp6] \n\t" \
- "mul %[temp5], %[level], %[temp3] \n\t" \
- "or %[ret], %[ret], %[level] \n\t" \
- "sh %[level], " #N "(%[pout]) \n\t" \
- "sh %[temp5], " #J "(%[ppin]) \n\t" \
- "j 3f \n\t" \
-"2: \n\t" \
- "lhu %[temp1], " #J "+2(%[ppiq]) \n\t" \
- "srl %[temp5], %[coeff], 16 \n\t" \
- "mul %[level], %[temp5], %[temp1] \n\t" \
- "lw %[temp2], " #K "+4(%[ppbias]) \n\t" \
- "lhu %[temp3], " #J "+2(%[ppq]) \n\t" \
- "addu %[level], %[level], %[temp2] \n\t" \
- "sra %[level], %[level], 17 \n\t" \
- "srl %[temp6], %[sign], 16 \n\t" \
- "slt %[temp4], %[max_level], %[level] \n\t" \
- "movn %[level], %[max_level], %[temp4] \n\t" \
- "xor %[level], %[level], %[temp6] \n\t" \
- "subu %[level], %[level], %[temp6] \n\t" \
- "mul %[temp5], %[level], %[temp3] \n\t" \
- "sh $0, " #J "(%[ppin]) \n\t" \
- "sh $0, " #N "(%[pout]) \n\t" \
- "or %[ret], %[ret], %[level] \n\t" \
- "sh %[temp5], " #J "+2(%[ppin]) \n\t" \
- "sh %[level], " #N1 "(%[pout]) \n\t" \
- "j 3f \n\t" \
-"1: \n\t" \
- "lhu %[temp1], " #J "(%[ppiq]) \n\t" \
- "lw %[temp2], " #K "(%[ppbias]) \n\t" \
- "ulw %[temp3], " #J "(%[ppq]) \n\t" \
- "andi %[temp5], %[coeff], 0xffff \n\t" \
- "srl %[temp0], %[coeff], 16 \n\t" \
- "lhu %[temp6], " #J "+2(%[ppiq]) \n\t" \
- "lw %[coeff], " #K "+4(%[ppbias]) \n\t" \
- "mul %[level], %[temp5], %[temp1] \n\t" \
- "mul %[temp4], %[temp0], %[temp6] \n\t" \
- "addu %[level], %[level], %[temp2] \n\t" \
- "addu %[temp4], %[temp4], %[coeff] \n\t" \
- "precrq.ph.w %[level], %[temp4], %[level] \n\t" \
- "shra.ph %[level], %[level], 1 \n\t" \
- "cmp.lt.ph %[max_level1],%[level] \n\t" \
- "pick.ph %[level], %[max_level], %[level] \n\t" \
- "xor %[level], %[level], %[sign] \n\t" \
- "subu.ph %[level], %[level], %[sign] \n\t" \
- "mul.ph %[temp3], %[level], %[temp3] \n\t" \
- "or %[ret], %[ret], %[level] \n\t" \
- "sh %[level], " #N "(%[pout]) \n\t" \
- "srl %[level], %[level], 16 \n\t" \
- "sh %[level], " #N1 "(%[pout]) \n\t" \
- "usw %[temp3], " #J "(%[ppin]) \n\t" \
- "j 3f \n\t" \
-"0: \n\t" \
- "sh $0, " #N "(%[pout]) \n\t" \
- "sh $0, " #N1 "(%[pout]) \n\t" \
- "usw $0, " #J "(%[ppin]) \n\t" \
-"3: \n\t"
-
-static int QuantizeBlock(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- int temp0, temp1, temp2, temp3, temp4, temp5,temp6;
- int sign, coeff, level;
- int max_level = MAX_LEVEL;
- int max_level1 = max_level << 16 | max_level;
- int ret = 0;
-
- int16_t* ppin = &in[0];
- int16_t* pout = &out[0];
- const uint16_t* ppsharpen = &mtx->sharpen_[0];
- const uint32_t* ppzthresh = &mtx->zthresh_[0];
- const uint16_t* ppq = &mtx->q_[0];
- const uint16_t* ppiq = &mtx->iq_[0];
- const uint32_t* ppbias = &mtx->bias_[0];
-
- __asm__ volatile (
- QUANTIZE_ONE( 0, 0, 0, 2)
- QUANTIZE_ONE( 4, 8, 10, 12)
- QUANTIZE_ONE( 8, 16, 4, 8)
- QUANTIZE_ONE(12, 24, 14, 24)
- QUANTIZE_ONE(16, 32, 6, 16)
- QUANTIZE_ONE(20, 40, 22, 26)
- QUANTIZE_ONE(24, 48, 18, 20)
- QUANTIZE_ONE(28, 56, 28, 30)
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [sign]"=&r"(sign), [coeff]"=&r"(coeff),
- [level]"=&r"(level), [temp6]"=&r"(temp6), [ret]"+&r"(ret)
- : [ppin]"r"(ppin), [pout]"r"(pout), [max_level1]"r"(max_level1),
- [ppiq]"r"(ppiq), [max_level]"r"(max_level),
- [ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh),
- [ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq)
- : "memory", "hi", "lo"
- );
-
- return (ret != 0);
-}
-
-static int Quantize2Blocks(int16_t in[32], int16_t out[32],
- const VP8Matrix* const mtx) {
- int nz;
- nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0;
- nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1;
- return nz;
-}
-
-#undef QUANTIZE_ONE
-
-// macro for one horizontal pass in FTransformWHT
-// temp0..temp7 holds tmp[0]..tmp[15]
-// A, B, C, D - offset in bytes to load from in buffer
-// TEMP0, TEMP1 - registers for corresponding tmp elements
-#define HORIZONTAL_PASS_WHT(A, B, C, D, TEMP0, TEMP1) \
- "lh %[" #TEMP0 "], " #A "(%[in]) \n\t" \
- "lh %[" #TEMP1 "], " #B "(%[in]) \n\t" \
- "lh %[temp8], " #C "(%[in]) \n\t" \
- "lh %[temp9], " #D "(%[in]) \n\t" \
- "ins %[" #TEMP1 "], %[" #TEMP0 "], 16, 16 \n\t" \
- "ins %[temp9], %[temp8], 16, 16 \n\t" \
- "subq.ph %[temp8], %[" #TEMP1 "], %[temp9] \n\t" \
- "addq.ph %[temp9], %[" #TEMP1 "], %[temp9] \n\t" \
- "precrq.ph.w %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \
- "append %[temp8], %[temp9], 16 \n\t" \
- "subq.ph %[" #TEMP1 "], %[" #TEMP0 "], %[temp8] \n\t" \
- "addq.ph %[" #TEMP0 "], %[" #TEMP0 "], %[temp8] \n\t" \
- "rotr %[" #TEMP1 "], %[" #TEMP1 "], 16 \n\t"
-
-// macro for one vertical pass in FTransformWHT
-// temp0..temp7 holds tmp[0]..tmp[15]
-// A, B, C, D - offsets in bytes to store to out buffer
-// TEMP0, TEMP2, TEMP4 and TEMP6 - registers for corresponding tmp elements
-#define VERTICAL_PASS_WHT(A, B, C, D, TEMP0, TEMP2, TEMP4, TEMP6) \
- "addq.ph %[temp8], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \
- "addq.ph %[temp9], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \
- "subq.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \
- "subq.ph %[" #TEMP6 "], %[" #TEMP0 "], %[" #TEMP4 "] \n\t" \
- "addqh.ph %[" #TEMP0 "], %[temp8], %[temp9] \n\t" \
- "subqh.ph %[" #TEMP4 "], %[" #TEMP6 "], %[" #TEMP2 "] \n\t" \
- "addqh.ph %[" #TEMP2 "], %[" #TEMP2 "], %[" #TEMP6 "] \n\t" \
- "subqh.ph %[" #TEMP6 "], %[temp8], %[temp9] \n\t" \
- "usw %[" #TEMP0 "], " #A "(%[out]) \n\t" \
- "usw %[" #TEMP2 "], " #B "(%[out]) \n\t" \
- "usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \
- "usw %[" #TEMP6 "], " #D "(%[out]) \n\t"
-
-static void FTransformWHT(const int16_t* in, int16_t* out) {
- int temp0, temp1, temp2, temp3, temp4;
- int temp5, temp6, temp7, temp8, temp9;
-
- __asm__ volatile (
- HORIZONTAL_PASS_WHT( 0, 32, 64, 96, temp0, temp1)
- HORIZONTAL_PASS_WHT(128, 160, 192, 224, temp2, temp3)
- HORIZONTAL_PASS_WHT(256, 288, 320, 352, temp4, temp5)
- HORIZONTAL_PASS_WHT(384, 416, 448, 480, temp6, temp7)
- VERTICAL_PASS_WHT(0, 8, 16, 24, temp0, temp2, temp4, temp6)
- VERTICAL_PASS_WHT(4, 12, 20, 28, temp1, temp3, temp5, temp7)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
- [temp9]"=&r"(temp9)
- : [in]"r"(in), [out]"r"(out)
- : "memory"
- );
-}
-
-#undef VERTICAL_PASS_WHT
-#undef HORIZONTAL_PASS_WHT
-
-// macro for converting coefficients to bin
-// convert 8 coeffs at time
-// A, B, C, D - offsets in bytes to load from out buffer
-#define CONVERT_COEFFS_TO_BIN(A, B, C, D) \
- "ulw %[temp0], " #A "(%[out]) \n\t" \
- "ulw %[temp1], " #B "(%[out]) \n\t" \
- "ulw %[temp2], " #C "(%[out]) \n\t" \
- "ulw %[temp3], " #D "(%[out]) \n\t" \
- "absq_s.ph %[temp0], %[temp0] \n\t" \
- "absq_s.ph %[temp1], %[temp1] \n\t" \
- "absq_s.ph %[temp2], %[temp2] \n\t" \
- "absq_s.ph %[temp3], %[temp3] \n\t" \
- "shra.ph %[temp0], %[temp0], 3 \n\t" \
- "shra.ph %[temp1], %[temp1], 3 \n\t" \
- "shra.ph %[temp2], %[temp2], 3 \n\t" \
- "shra.ph %[temp3], %[temp3], 3 \n\t" \
- "shll_s.ph %[temp0], %[temp0], 10 \n\t" \
- "shll_s.ph %[temp1], %[temp1], 10 \n\t" \
- "shll_s.ph %[temp2], %[temp2], 10 \n\t" \
- "shll_s.ph %[temp3], %[temp3], 10 \n\t" \
- "shrl.ph %[temp0], %[temp0], 10 \n\t" \
- "shrl.ph %[temp1], %[temp1], 10 \n\t" \
- "shrl.ph %[temp2], %[temp2], 10 \n\t" \
- "shrl.ph %[temp3], %[temp3], 10 \n\t" \
- "shll.ph %[temp0], %[temp0], 2 \n\t" \
- "shll.ph %[temp1], %[temp1], 2 \n\t" \
- "shll.ph %[temp2], %[temp2], 2 \n\t" \
- "shll.ph %[temp3], %[temp3], 2 \n\t" \
- "ext %[temp4], %[temp0], 0, 16 \n\t" \
- "ext %[temp0], %[temp0], 16, 16 \n\t" \
- "addu %[temp4], %[temp4], %[dist] \n\t" \
- "addu %[temp0], %[temp0], %[dist] \n\t" \
- "ext %[temp5], %[temp1], 0, 16 \n\t" \
- "lw %[temp8], 0(%[temp4]) \n\t" \
- "ext %[temp1], %[temp1], 16, 16 \n\t" \
- "addu %[temp5], %[temp5], %[dist] \n\t" \
- "addiu %[temp8], %[temp8], 1 \n\t" \
- "sw %[temp8], 0(%[temp4]) \n\t" \
- "lw %[temp8], 0(%[temp0]) \n\t" \
- "addu %[temp1], %[temp1], %[dist] \n\t" \
- "ext %[temp6], %[temp2], 0, 16 \n\t" \
- "addiu %[temp8], %[temp8], 1 \n\t" \
- "sw %[temp8], 0(%[temp0]) \n\t" \
- "lw %[temp8], 0(%[temp5]) \n\t" \
- "ext %[temp2], %[temp2], 16, 16 \n\t" \
- "addu %[temp6], %[temp6], %[dist] \n\t" \
- "addiu %[temp8], %[temp8], 1 \n\t" \
- "sw %[temp8], 0(%[temp5]) \n\t" \
- "lw %[temp8], 0(%[temp1]) \n\t" \
- "addu %[temp2], %[temp2], %[dist] \n\t" \
- "ext %[temp7], %[temp3], 0, 16 \n\t" \
- "addiu %[temp8], %[temp8], 1 \n\t" \
- "sw %[temp8], 0(%[temp1]) \n\t" \
- "lw %[temp8], 0(%[temp6]) \n\t" \
- "ext %[temp3], %[temp3], 16, 16 \n\t" \
- "addu %[temp7], %[temp7], %[dist] \n\t" \
- "addiu %[temp8], %[temp8], 1 \n\t" \
- "sw %[temp8], 0(%[temp6]) \n\t" \
- "lw %[temp8], 0(%[temp2]) \n\t" \
- "addu %[temp3], %[temp3], %[dist] \n\t" \
- "addiu %[temp8], %[temp8], 1 \n\t" \
- "sw %[temp8], 0(%[temp2]) \n\t" \
- "lw %[temp8], 0(%[temp7]) \n\t" \
- "addiu %[temp8], %[temp8], 1 \n\t" \
- "sw %[temp8], 0(%[temp7]) \n\t" \
- "lw %[temp8], 0(%[temp3]) \n\t" \
- "addiu %[temp8], %[temp8], 1 \n\t" \
- "sw %[temp8], 0(%[temp3]) \n\t"
-
-static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block,
- VP8Histogram* const histo) {
- int j;
- int distribution[MAX_COEFF_THRESH + 1] = { 0 };
- const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH;
- for (j = start_block; j < end_block; ++j) {
- int16_t out[16];
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
-
- VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
-
- // Convert coefficients to bin.
- __asm__ volatile (
- CONVERT_COEFFS_TO_BIN( 0, 4, 8, 12)
- CONVERT_COEFFS_TO_BIN(16, 20, 24, 28)
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
- : [dist]"r"(distribution), [out]"r"(out), [max_coeff]"r"(max_coeff)
- : "memory"
- );
- }
- VP8SetHistogramData(distribution, histo);
-}
-
-#undef CONVERT_COEFFS_TO_BIN
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspInitMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPSdspR2(void) {
- VP8FTransform = FTransform;
- VP8ITransform = ITransform;
- VP8TDisto4x4 = Disto4x4;
- VP8TDisto16x16 = Disto16x16;
- VP8EncPredLuma16 = Intra16Preds;
- VP8EncPredChroma8 = IntraChromaPreds;
- VP8EncPredLuma4 = Intra4Preds;
-#if !defined(WORK_AROUND_GCC)
- VP8SSE16x16 = SSE16x16;
- VP8SSE8x8 = SSE8x8;
- VP8SSE16x8 = SSE16x8;
- VP8SSE4x4 = SSE4x4;
-#endif
- VP8EncQuantizeBlock = QuantizeBlock;
- VP8EncQuantize2Blocks = Quantize2Blocks;
- VP8FTransformWHT = FTransformWHT;
- VP8CollectHistogram = CollectHistogram;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(VP8EncDspInitMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/enc_neon.c b/drivers/webp/dsp/enc_neon.c
deleted file mode 100644
index 46f6bf9a33..0000000000
--- a/drivers/webp/dsp/enc_neon.c
+++ /dev/null
@@ -1,920 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// ARM NEON version of speed-critical encoding functions.
-//
-// adapted from libvpx (http://www.webmproject.org/code/)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_NEON)
-
-#include <assert.h>
-
-#include "./neon.h"
-#include "../enc/vp8enci.h"
-
-//------------------------------------------------------------------------------
-// Transforms (Paragraph 14.4)
-
-// Inverse transform.
-// This code is pretty much the same as TransformOne in the dec_neon.c, except
-// for subtraction to *ref. See the comments there for algorithmic explanations.
-
-static const int16_t kC1 = 20091;
-static const int16_t kC2 = 17734; // half of kC2, actually. See comment above.
-
-// This code works but is *slower* than the inlined-asm version below
-// (with gcc-4.6). So we disable it for now. Later, it'll be conditional to
-// WEBP_USE_INTRINSICS define.
-// With gcc-4.8, it's a little faster speed than inlined-assembly.
-#if defined(WEBP_USE_INTRINSICS)
-
-// Treats 'v' as an uint8x8_t and zero extends to an int16x8_t.
-static WEBP_INLINE int16x8_t ConvertU8ToS16(uint32x2_t v) {
- return vreinterpretq_s16_u16(vmovl_u8(vreinterpret_u8_u32(v)));
-}
-
-// Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result
-// to the corresponding rows of 'dst'.
-static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst,
- const int16x8_t dst01,
- const int16x8_t dst23) {
- // Unsigned saturate to 8b.
- const uint8x8_t dst01_u8 = vqmovun_s16(dst01);
- const uint8x8_t dst23_u8 = vqmovun_s16(dst23);
-
- // Store the results.
- vst1_lane_u32((uint32_t*)(dst + 0 * BPS), vreinterpret_u32_u8(dst01_u8), 0);
- vst1_lane_u32((uint32_t*)(dst + 1 * BPS), vreinterpret_u32_u8(dst01_u8), 1);
- vst1_lane_u32((uint32_t*)(dst + 2 * BPS), vreinterpret_u32_u8(dst23_u8), 0);
- vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1);
-}
-
-static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23,
- const uint8_t* const ref, uint8_t* const dst) {
- uint32x2_t dst01 = vdup_n_u32(0);
- uint32x2_t dst23 = vdup_n_u32(0);
-
- // Load the source pixels.
- dst01 = vld1_lane_u32((uint32_t*)(ref + 0 * BPS), dst01, 0);
- dst23 = vld1_lane_u32((uint32_t*)(ref + 2 * BPS), dst23, 0);
- dst01 = vld1_lane_u32((uint32_t*)(ref + 1 * BPS), dst01, 1);
- dst23 = vld1_lane_u32((uint32_t*)(ref + 3 * BPS), dst23, 1);
-
- {
- // Convert to 16b.
- const int16x8_t dst01_s16 = ConvertU8ToS16(dst01);
- const int16x8_t dst23_s16 = ConvertU8ToS16(dst23);
-
- // Descale with rounding.
- const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3);
- const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3);
- // Add the inverse transform.
- SaturateAndStore4x4(dst, out01, out23);
- }
-}
-
-static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1,
- int16x8x2_t* const out) {
- // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1
- // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3
- const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ...
- // b0 d0 b1 d1 b2 d2 ...
- *out = vzipq_s16(tmp0.val[0], tmp0.val[1]);
-}
-
-static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) {
- // {rows} = in0 | in4
- // in8 | in12
- // B1 = in4 | in12
- const int16x8_t B1 =
- vcombine_s16(vget_high_s16(rows->val[0]), vget_high_s16(rows->val[1]));
- // C0 = kC1 * in4 | kC1 * in12
- // C1 = kC2 * in4 | kC2 * in12
- const int16x8_t C0 = vsraq_n_s16(B1, vqdmulhq_n_s16(B1, kC1), 1);
- const int16x8_t C1 = vqdmulhq_n_s16(B1, kC2);
- const int16x4_t a = vqadd_s16(vget_low_s16(rows->val[0]),
- vget_low_s16(rows->val[1])); // in0 + in8
- const int16x4_t b = vqsub_s16(vget_low_s16(rows->val[0]),
- vget_low_s16(rows->val[1])); // in0 - in8
- // c = kC2 * in4 - kC1 * in12
- // d = kC1 * in4 + kC2 * in12
- const int16x4_t c = vqsub_s16(vget_low_s16(C1), vget_high_s16(C0));
- const int16x4_t d = vqadd_s16(vget_low_s16(C0), vget_high_s16(C1));
- const int16x8_t D0 = vcombine_s16(a, b); // D0 = a | b
- const int16x8_t D1 = vcombine_s16(d, c); // D1 = d | c
- const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c
- const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c
- const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp));
- Transpose8x2(E0, E1, rows);
-}
-
-static void ITransformOne(const uint8_t* ref,
- const int16_t* in, uint8_t* dst) {
- int16x8x2_t rows;
- INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8));
- TransformPass(&rows);
- TransformPass(&rows);
- Add4x4(rows.val[0], rows.val[1], ref, dst);
-}
-
-#else
-
-static void ITransformOne(const uint8_t* ref,
- const int16_t* in, uint8_t* dst) {
- const int kBPS = BPS;
- const int16_t kC1C2[] = { kC1, kC2, 0, 0 };
-
- __asm__ volatile (
- "vld1.16 {q1, q2}, [%[in]] \n"
- "vld1.16 {d0}, [%[kC1C2]] \n"
-
- // d2: in[0]
- // d3: in[8]
- // d4: in[4]
- // d5: in[12]
- "vswp d3, d4 \n"
-
- // q8 = {in[4], in[12]} * kC1 * 2 >> 16
- // q9 = {in[4], in[12]} * kC2 >> 16
- "vqdmulh.s16 q8, q2, d0[0] \n"
- "vqdmulh.s16 q9, q2, d0[1] \n"
-
- // d22 = a = in[0] + in[8]
- // d23 = b = in[0] - in[8]
- "vqadd.s16 d22, d2, d3 \n"
- "vqsub.s16 d23, d2, d3 \n"
-
- // q8 = in[4]/[12] * kC1 >> 16
- "vshr.s16 q8, q8, #1 \n"
-
- // Add {in[4], in[12]} back after the multiplication.
- "vqadd.s16 q8, q2, q8 \n"
-
- // d20 = c = in[4]*kC2 - in[12]*kC1
- // d21 = d = in[4]*kC1 + in[12]*kC2
- "vqsub.s16 d20, d18, d17 \n"
- "vqadd.s16 d21, d19, d16 \n"
-
- // d2 = tmp[0] = a + d
- // d3 = tmp[1] = b + c
- // d4 = tmp[2] = b - c
- // d5 = tmp[3] = a - d
- "vqadd.s16 d2, d22, d21 \n"
- "vqadd.s16 d3, d23, d20 \n"
- "vqsub.s16 d4, d23, d20 \n"
- "vqsub.s16 d5, d22, d21 \n"
-
- "vzip.16 q1, q2 \n"
- "vzip.16 q1, q2 \n"
-
- "vswp d3, d4 \n"
-
- // q8 = {tmp[4], tmp[12]} * kC1 * 2 >> 16
- // q9 = {tmp[4], tmp[12]} * kC2 >> 16
- "vqdmulh.s16 q8, q2, d0[0] \n"
- "vqdmulh.s16 q9, q2, d0[1] \n"
-
- // d22 = a = tmp[0] + tmp[8]
- // d23 = b = tmp[0] - tmp[8]
- "vqadd.s16 d22, d2, d3 \n"
- "vqsub.s16 d23, d2, d3 \n"
-
- "vshr.s16 q8, q8, #1 \n"
- "vqadd.s16 q8, q2, q8 \n"
-
- // d20 = c = in[4]*kC2 - in[12]*kC1
- // d21 = d = in[4]*kC1 + in[12]*kC2
- "vqsub.s16 d20, d18, d17 \n"
- "vqadd.s16 d21, d19, d16 \n"
-
- // d2 = tmp[0] = a + d
- // d3 = tmp[1] = b + c
- // d4 = tmp[2] = b - c
- // d5 = tmp[3] = a - d
- "vqadd.s16 d2, d22, d21 \n"
- "vqadd.s16 d3, d23, d20 \n"
- "vqsub.s16 d4, d23, d20 \n"
- "vqsub.s16 d5, d22, d21 \n"
-
- "vld1.32 d6[0], [%[ref]], %[kBPS] \n"
- "vld1.32 d6[1], [%[ref]], %[kBPS] \n"
- "vld1.32 d7[0], [%[ref]], %[kBPS] \n"
- "vld1.32 d7[1], [%[ref]], %[kBPS] \n"
-
- "sub %[ref], %[ref], %[kBPS], lsl #2 \n"
-
- // (val) + 4 >> 3
- "vrshr.s16 d2, d2, #3 \n"
- "vrshr.s16 d3, d3, #3 \n"
- "vrshr.s16 d4, d4, #3 \n"
- "vrshr.s16 d5, d5, #3 \n"
-
- "vzip.16 q1, q2 \n"
- "vzip.16 q1, q2 \n"
-
- // Must accumulate before saturating
- "vmovl.u8 q8, d6 \n"
- "vmovl.u8 q9, d7 \n"
-
- "vqadd.s16 q1, q1, q8 \n"
- "vqadd.s16 q2, q2, q9 \n"
-
- "vqmovun.s16 d0, q1 \n"
- "vqmovun.s16 d1, q2 \n"
-
- "vst1.32 d0[0], [%[dst]], %[kBPS] \n"
- "vst1.32 d0[1], [%[dst]], %[kBPS] \n"
- "vst1.32 d1[0], [%[dst]], %[kBPS] \n"
- "vst1.32 d1[1], [%[dst]] \n"
-
- : [in] "+r"(in), [dst] "+r"(dst) // modified registers
- : [kBPS] "r"(kBPS), [kC1C2] "r"(kC1C2), [ref] "r"(ref) // constants
- : "memory", "q0", "q1", "q2", "q8", "q9", "q10", "q11" // clobbered
- );
-}
-
-#endif // WEBP_USE_INTRINSICS
-
-static void ITransform(const uint8_t* ref,
- const int16_t* in, uint8_t* dst, int do_two) {
- ITransformOne(ref, in, dst);
- if (do_two) {
- ITransformOne(ref + 4, in + 16, dst + 4);
- }
-}
-
-// Load all 4x4 pixels into a single uint8x16_t variable.
-static uint8x16_t Load4x4(const uint8_t* src) {
- uint32x4_t out = vdupq_n_u32(0);
- out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0);
- out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1);
- out = vld1q_lane_u32((const uint32_t*)(src + 2 * BPS), out, 2);
- out = vld1q_lane_u32((const uint32_t*)(src + 3 * BPS), out, 3);
- return vreinterpretq_u8_u32(out);
-}
-
-// Forward transform.
-
-#if defined(WEBP_USE_INTRINSICS)
-
-static WEBP_INLINE void Transpose4x4_S16(const int16x4_t A, const int16x4_t B,
- const int16x4_t C, const int16x4_t D,
- int16x8_t* const out01,
- int16x8_t* const out32) {
- const int16x4x2_t AB = vtrn_s16(A, B);
- const int16x4x2_t CD = vtrn_s16(C, D);
- const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]),
- vreinterpret_s32_s16(CD.val[0]));
- const int32x2x2_t tmp13 = vtrn_s32(vreinterpret_s32_s16(AB.val[1]),
- vreinterpret_s32_s16(CD.val[1]));
- *out01 = vreinterpretq_s16_s64(
- vcombine_s64(vreinterpret_s64_s32(tmp02.val[0]),
- vreinterpret_s64_s32(tmp13.val[0])));
- *out32 = vreinterpretq_s16_s64(
- vcombine_s64(vreinterpret_s64_s32(tmp13.val[1]),
- vreinterpret_s64_s32(tmp02.val[1])));
-}
-
-static WEBP_INLINE int16x8_t DiffU8ToS16(const uint8x8_t a,
- const uint8x8_t b) {
- return vreinterpretq_s16_u16(vsubl_u8(a, b));
-}
-
-static void FTransform(const uint8_t* src, const uint8_t* ref,
- int16_t* out) {
- int16x8_t d0d1, d3d2; // working 4x4 int16 variables
- {
- const uint8x16_t S0 = Load4x4(src);
- const uint8x16_t R0 = Load4x4(ref);
- const int16x8_t D0D1 = DiffU8ToS16(vget_low_u8(S0), vget_low_u8(R0));
- const int16x8_t D2D3 = DiffU8ToS16(vget_high_u8(S0), vget_high_u8(R0));
- const int16x4_t D0 = vget_low_s16(D0D1);
- const int16x4_t D1 = vget_high_s16(D0D1);
- const int16x4_t D2 = vget_low_s16(D2D3);
- const int16x4_t D3 = vget_high_s16(D2D3);
- Transpose4x4_S16(D0, D1, D2, D3, &d0d1, &d3d2);
- }
- { // 1rst pass
- const int32x4_t kCst937 = vdupq_n_s32(937);
- const int32x4_t kCst1812 = vdupq_n_s32(1812);
- const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1)
- const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2)
- const int16x8_t a0a1_2 = vshlq_n_s16(a0a1, 3);
- const int16x4_t tmp0 = vadd_s16(vget_low_s16(a0a1_2),
- vget_high_s16(a0a1_2));
- const int16x4_t tmp2 = vsub_s16(vget_low_s16(a0a1_2),
- vget_high_s16(a0a1_2));
- const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217);
- const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217);
- const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352);
- const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352);
- const int16x4_t tmp1 = vshrn_n_s32(vaddq_s32(a2_p_a3, kCst1812), 9);
- const int16x4_t tmp3 = vshrn_n_s32(vaddq_s32(a3_m_a2, kCst937), 9);
- Transpose4x4_S16(tmp0, tmp1, tmp2, tmp3, &d0d1, &d3d2);
- }
- { // 2nd pass
- // the (1<<16) addition is for the replacement: a3!=0 <-> 1-(a3==0)
- const int32x4_t kCst12000 = vdupq_n_s32(12000 + (1 << 16));
- const int32x4_t kCst51000 = vdupq_n_s32(51000);
- const int16x8_t a0a1 = vaddq_s16(d0d1, d3d2); // d0+d3 | d1+d2 (=a0|a1)
- const int16x8_t a3a2 = vsubq_s16(d0d1, d3d2); // d0-d3 | d1-d2 (=a3|a2)
- const int16x4_t a0_k7 = vadd_s16(vget_low_s16(a0a1), vdup_n_s16(7));
- const int16x4_t out0 = vshr_n_s16(vadd_s16(a0_k7, vget_high_s16(a0a1)), 4);
- const int16x4_t out2 = vshr_n_s16(vsub_s16(a0_k7, vget_high_s16(a0a1)), 4);
- const int32x4_t a3_2217 = vmull_n_s16(vget_low_s16(a3a2), 2217);
- const int32x4_t a2_2217 = vmull_n_s16(vget_high_s16(a3a2), 2217);
- const int32x4_t a2_p_a3 = vmlal_n_s16(a2_2217, vget_low_s16(a3a2), 5352);
- const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352);
- const int16x4_t tmp1 = vaddhn_s32(a2_p_a3, kCst12000);
- const int16x4_t out3 = vaddhn_s32(a3_m_a2, kCst51000);
- const int16x4_t a3_eq_0 =
- vreinterpret_s16_u16(vceq_s16(vget_low_s16(a3a2), vdup_n_s16(0)));
- const int16x4_t out1 = vadd_s16(tmp1, a3_eq_0);
- vst1_s16(out + 0, out0);
- vst1_s16(out + 4, out1);
- vst1_s16(out + 8, out2);
- vst1_s16(out + 12, out3);
- }
-}
-
-#else
-
-// adapted from vp8/encoder/arm/neon/shortfdct_neon.asm
-static const int16_t kCoeff16[] = {
- 5352, 5352, 5352, 5352, 2217, 2217, 2217, 2217
-};
-static const int32_t kCoeff32[] = {
- 1812, 1812, 1812, 1812,
- 937, 937, 937, 937,
- 12000, 12000, 12000, 12000,
- 51000, 51000, 51000, 51000
-};
-
-static void FTransform(const uint8_t* src, const uint8_t* ref,
- int16_t* out) {
- const int kBPS = BPS;
- const uint8_t* src_ptr = src;
- const uint8_t* ref_ptr = ref;
- const int16_t* coeff16 = kCoeff16;
- const int32_t* coeff32 = kCoeff32;
-
- __asm__ volatile (
- // load src into q4, q5 in high half
- "vld1.8 {d8}, [%[src_ptr]], %[kBPS] \n"
- "vld1.8 {d10}, [%[src_ptr]], %[kBPS] \n"
- "vld1.8 {d9}, [%[src_ptr]], %[kBPS] \n"
- "vld1.8 {d11}, [%[src_ptr]] \n"
-
- // load ref into q6, q7 in high half
- "vld1.8 {d12}, [%[ref_ptr]], %[kBPS] \n"
- "vld1.8 {d14}, [%[ref_ptr]], %[kBPS] \n"
- "vld1.8 {d13}, [%[ref_ptr]], %[kBPS] \n"
- "vld1.8 {d15}, [%[ref_ptr]] \n"
-
- // Pack the high values in to q4 and q6
- "vtrn.32 q4, q5 \n"
- "vtrn.32 q6, q7 \n"
-
- // d[0-3] = src - ref
- "vsubl.u8 q0, d8, d12 \n"
- "vsubl.u8 q1, d9, d13 \n"
-
- // load coeff16 into q8(d16=5352, d17=2217)
- "vld1.16 {q8}, [%[coeff16]] \n"
-
- // load coeff32 high half into q9 = 1812, q10 = 937
- "vld1.32 {q9, q10}, [%[coeff32]]! \n"
-
- // load coeff32 low half into q11=12000, q12=51000
- "vld1.32 {q11,q12}, [%[coeff32]] \n"
-
- // part 1
- // Transpose. Register dN is the same as dN in C
- "vtrn.32 d0, d2 \n"
- "vtrn.32 d1, d3 \n"
- "vtrn.16 d0, d1 \n"
- "vtrn.16 d2, d3 \n"
-
- "vadd.s16 d4, d0, d3 \n" // a0 = d0 + d3
- "vadd.s16 d5, d1, d2 \n" // a1 = d1 + d2
- "vsub.s16 d6, d1, d2 \n" // a2 = d1 - d2
- "vsub.s16 d7, d0, d3 \n" // a3 = d0 - d3
-
- "vadd.s16 d0, d4, d5 \n" // a0 + a1
- "vshl.s16 d0, d0, #3 \n" // temp[0+i*4] = (a0+a1) << 3
- "vsub.s16 d2, d4, d5 \n" // a0 - a1
- "vshl.s16 d2, d2, #3 \n" // (temp[2+i*4] = (a0-a1) << 3
-
- "vmlal.s16 q9, d7, d16 \n" // a3*5352 + 1812
- "vmlal.s16 q10, d7, d17 \n" // a3*2217 + 937
- "vmlal.s16 q9, d6, d17 \n" // a2*2217 + a3*5352 + 1812
- "vmlsl.s16 q10, d6, d16 \n" // a3*2217 + 937 - a2*5352
-
- // temp[1+i*4] = (d2*2217 + d3*5352 + 1812) >> 9
- // temp[3+i*4] = (d3*2217 + 937 - d2*5352) >> 9
- "vshrn.s32 d1, q9, #9 \n"
- "vshrn.s32 d3, q10, #9 \n"
-
- // part 2
- // transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12]
- "vtrn.32 d0, d2 \n"
- "vtrn.32 d1, d3 \n"
- "vtrn.16 d0, d1 \n"
- "vtrn.16 d2, d3 \n"
-
- "vmov.s16 d26, #7 \n"
-
- "vadd.s16 d4, d0, d3 \n" // a1 = ip[0] + ip[12]
- "vadd.s16 d5, d1, d2 \n" // b1 = ip[4] + ip[8]
- "vsub.s16 d6, d1, d2 \n" // c1 = ip[4] - ip[8]
- "vadd.s16 d4, d4, d26 \n" // a1 + 7
- "vsub.s16 d7, d0, d3 \n" // d1 = ip[0] - ip[12]
-
- "vadd.s16 d0, d4, d5 \n" // op[0] = a1 + b1 + 7
- "vsub.s16 d2, d4, d5 \n" // op[8] = a1 - b1 + 7
-
- "vmlal.s16 q11, d7, d16 \n" // d1*5352 + 12000
- "vmlal.s16 q12, d7, d17 \n" // d1*2217 + 51000
-
- "vceq.s16 d4, d7, #0 \n"
-
- "vshr.s16 d0, d0, #4 \n"
- "vshr.s16 d2, d2, #4 \n"
-
- "vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000
- "vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000
-
- "vmvn d4, d4 \n" // !(d1 == 0)
- // op[4] = (c1*2217 + d1*5352 + 12000)>>16
- "vshrn.s32 d1, q11, #16 \n"
- // op[4] += (d1!=0)
- "vsub.s16 d1, d1, d4 \n"
- // op[12]= (d1*2217 - c1*5352 + 51000)>>16
- "vshrn.s32 d3, q12, #16 \n"
-
- // set result to out array
- "vst1.16 {q0, q1}, [%[out]] \n"
- : [src_ptr] "+r"(src_ptr), [ref_ptr] "+r"(ref_ptr),
- [coeff32] "+r"(coeff32) // modified registers
- : [kBPS] "r"(kBPS), [coeff16] "r"(coeff16),
- [out] "r"(out) // constants
- : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9",
- "q10", "q11", "q12", "q13" // clobbered
- );
-}
-
-#endif
-
-#define LOAD_LANE_16b(VALUE, LANE) do { \
- (VALUE) = vld1_lane_s16(src, (VALUE), (LANE)); \
- src += stride; \
-} while (0)
-
-static void FTransformWHT(const int16_t* src, int16_t* out) {
- const int stride = 16;
- const int16x4_t zero = vdup_n_s16(0);
- int32x4x4_t tmp0;
- int16x4x4_t in;
- INIT_VECTOR4(in, zero, zero, zero, zero);
- LOAD_LANE_16b(in.val[0], 0);
- LOAD_LANE_16b(in.val[1], 0);
- LOAD_LANE_16b(in.val[2], 0);
- LOAD_LANE_16b(in.val[3], 0);
- LOAD_LANE_16b(in.val[0], 1);
- LOAD_LANE_16b(in.val[1], 1);
- LOAD_LANE_16b(in.val[2], 1);
- LOAD_LANE_16b(in.val[3], 1);
- LOAD_LANE_16b(in.val[0], 2);
- LOAD_LANE_16b(in.val[1], 2);
- LOAD_LANE_16b(in.val[2], 2);
- LOAD_LANE_16b(in.val[3], 2);
- LOAD_LANE_16b(in.val[0], 3);
- LOAD_LANE_16b(in.val[1], 3);
- LOAD_LANE_16b(in.val[2], 3);
- LOAD_LANE_16b(in.val[3], 3);
-
- {
- // a0 = in[0 * 16] + in[2 * 16]
- // a1 = in[1 * 16] + in[3 * 16]
- // a2 = in[1 * 16] - in[3 * 16]
- // a3 = in[0 * 16] - in[2 * 16]
- const int32x4_t a0 = vaddl_s16(in.val[0], in.val[2]);
- const int32x4_t a1 = vaddl_s16(in.val[1], in.val[3]);
- const int32x4_t a2 = vsubl_s16(in.val[1], in.val[3]);
- const int32x4_t a3 = vsubl_s16(in.val[0], in.val[2]);
- tmp0.val[0] = vaddq_s32(a0, a1);
- tmp0.val[1] = vaddq_s32(a3, a2);
- tmp0.val[2] = vsubq_s32(a3, a2);
- tmp0.val[3] = vsubq_s32(a0, a1);
- }
- {
- const int32x4x4_t tmp1 = Transpose4x4(tmp0);
- // a0 = tmp[0 + i] + tmp[ 8 + i]
- // a1 = tmp[4 + i] + tmp[12 + i]
- // a2 = tmp[4 + i] - tmp[12 + i]
- // a3 = tmp[0 + i] - tmp[ 8 + i]
- const int32x4_t a0 = vaddq_s32(tmp1.val[0], tmp1.val[2]);
- const int32x4_t a1 = vaddq_s32(tmp1.val[1], tmp1.val[3]);
- const int32x4_t a2 = vsubq_s32(tmp1.val[1], tmp1.val[3]);
- const int32x4_t a3 = vsubq_s32(tmp1.val[0], tmp1.val[2]);
- const int32x4_t b0 = vhaddq_s32(a0, a1); // (a0 + a1) >> 1
- const int32x4_t b1 = vhaddq_s32(a3, a2); // (a3 + a2) >> 1
- const int32x4_t b2 = vhsubq_s32(a3, a2); // (a3 - a2) >> 1
- const int32x4_t b3 = vhsubq_s32(a0, a1); // (a0 - a1) >> 1
- const int16x4_t out0 = vmovn_s32(b0);
- const int16x4_t out1 = vmovn_s32(b1);
- const int16x4_t out2 = vmovn_s32(b2);
- const int16x4_t out3 = vmovn_s32(b3);
-
- vst1_s16(out + 0, out0);
- vst1_s16(out + 4, out1);
- vst1_s16(out + 8, out2);
- vst1_s16(out + 12, out3);
- }
-}
-#undef LOAD_LANE_16b
-
-//------------------------------------------------------------------------------
-// Texture distortion
-//
-// We try to match the spectral content (weighted) between source and
-// reconstructed samples.
-
-// a 0123, b 0123
-// a 4567, b 4567
-// a 89ab, b 89ab
-// a cdef, b cdef
-//
-// transpose
-//
-// a 048c, b 048c
-// a 159d, b 159d
-// a 26ae, b 26ae
-// a 37bf, b 37bf
-//
-static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16(int16x8x4_t q4_in) {
- const int16x8x2_t q2_tmp0 = vtrnq_s16(q4_in.val[0], q4_in.val[1]);
- const int16x8x2_t q2_tmp1 = vtrnq_s16(q4_in.val[2], q4_in.val[3]);
- const int32x4x2_t q2_tmp2 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[0]),
- vreinterpretq_s32_s16(q2_tmp1.val[0]));
- const int32x4x2_t q2_tmp3 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[1]),
- vreinterpretq_s32_s16(q2_tmp1.val[1]));
- q4_in.val[0] = vreinterpretq_s16_s32(q2_tmp2.val[0]);
- q4_in.val[2] = vreinterpretq_s16_s32(q2_tmp2.val[1]);
- q4_in.val[1] = vreinterpretq_s16_s32(q2_tmp3.val[0]);
- q4_in.val[3] = vreinterpretq_s16_s32(q2_tmp3.val[1]);
- return q4_in;
-}
-
-static WEBP_INLINE int16x8x4_t DistoHorizontalPass(const int16x8x4_t q4_in) {
- // {a0, a1} = {in[0] + in[2], in[1] + in[3]}
- // {a3, a2} = {in[0] - in[2], in[1] - in[3]}
- const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]);
- const int16x8_t q_a1 = vaddq_s16(q4_in.val[1], q4_in.val[3]);
- const int16x8_t q_a3 = vsubq_s16(q4_in.val[0], q4_in.val[2]);
- const int16x8_t q_a2 = vsubq_s16(q4_in.val[1], q4_in.val[3]);
- int16x8x4_t q4_out;
- // tmp[0] = a0 + a1
- // tmp[1] = a3 + a2
- // tmp[2] = a3 - a2
- // tmp[3] = a0 - a1
- INIT_VECTOR4(q4_out,
- vabsq_s16(vaddq_s16(q_a0, q_a1)),
- vabsq_s16(vaddq_s16(q_a3, q_a2)),
- vabdq_s16(q_a3, q_a2), vabdq_s16(q_a0, q_a1));
- return q4_out;
-}
-
-static WEBP_INLINE int16x8x4_t DistoVerticalPass(const uint8x8x4_t q4_in) {
- const int16x8_t q_a0 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[0],
- q4_in.val[2]));
- const int16x8_t q_a1 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[1],
- q4_in.val[3]));
- const int16x8_t q_a2 = vreinterpretq_s16_u16(vsubl_u8(q4_in.val[1],
- q4_in.val[3]));
- const int16x8_t q_a3 = vreinterpretq_s16_u16(vsubl_u8(q4_in.val[0],
- q4_in.val[2]));
- int16x8x4_t q4_out;
-
- INIT_VECTOR4(q4_out,
- vaddq_s16(q_a0, q_a1), vaddq_s16(q_a3, q_a2),
- vsubq_s16(q_a3, q_a2), vsubq_s16(q_a0, q_a1));
- return q4_out;
-}
-
-static WEBP_INLINE int16x4x4_t DistoLoadW(const uint16_t* w) {
- const uint16x8_t q_w07 = vld1q_u16(&w[0]);
- const uint16x8_t q_w8f = vld1q_u16(&w[8]);
- int16x4x4_t d4_w;
- INIT_VECTOR4(d4_w,
- vget_low_s16(vreinterpretq_s16_u16(q_w07)),
- vget_high_s16(vreinterpretq_s16_u16(q_w07)),
- vget_low_s16(vreinterpretq_s16_u16(q_w8f)),
- vget_high_s16(vreinterpretq_s16_u16(q_w8f)));
- return d4_w;
-}
-
-static WEBP_INLINE int32x2_t DistoSum(const int16x8x4_t q4_in,
- const int16x4x4_t d4_w) {
- int32x2_t d_sum;
- // sum += w[ 0] * abs(b0);
- // sum += w[ 4] * abs(b1);
- // sum += w[ 8] * abs(b2);
- // sum += w[12] * abs(b3);
- int32x4_t q_sum0 = vmull_s16(d4_w.val[0], vget_low_s16(q4_in.val[0]));
- int32x4_t q_sum1 = vmull_s16(d4_w.val[1], vget_low_s16(q4_in.val[1]));
- int32x4_t q_sum2 = vmull_s16(d4_w.val[2], vget_low_s16(q4_in.val[2]));
- int32x4_t q_sum3 = vmull_s16(d4_w.val[3], vget_low_s16(q4_in.val[3]));
- q_sum0 = vmlsl_s16(q_sum0, d4_w.val[0], vget_high_s16(q4_in.val[0]));
- q_sum1 = vmlsl_s16(q_sum1, d4_w.val[1], vget_high_s16(q4_in.val[1]));
- q_sum2 = vmlsl_s16(q_sum2, d4_w.val[2], vget_high_s16(q4_in.val[2]));
- q_sum3 = vmlsl_s16(q_sum3, d4_w.val[3], vget_high_s16(q4_in.val[3]));
-
- q_sum0 = vaddq_s32(q_sum0, q_sum1);
- q_sum2 = vaddq_s32(q_sum2, q_sum3);
- q_sum2 = vaddq_s32(q_sum0, q_sum2);
- d_sum = vpadd_s32(vget_low_s32(q_sum2), vget_high_s32(q_sum2));
- d_sum = vpadd_s32(d_sum, d_sum);
- return d_sum;
-}
-
-#define LOAD_LANE_32b(src, VALUE, LANE) \
- (VALUE) = vld1_lane_u32((const uint32_t*)(src), (VALUE), (LANE))
-
-// Hadamard transform
-// Returns the weighted sum of the absolute value of transformed coefficients.
-// w[] contains a row-major 4 by 4 symmetric matrix.
-static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- uint32x2_t d_in_ab_0123 = vdup_n_u32(0);
- uint32x2_t d_in_ab_4567 = vdup_n_u32(0);
- uint32x2_t d_in_ab_89ab = vdup_n_u32(0);
- uint32x2_t d_in_ab_cdef = vdup_n_u32(0);
- uint8x8x4_t d4_in;
-
- // load data a, b
- LOAD_LANE_32b(a + 0 * BPS, d_in_ab_0123, 0);
- LOAD_LANE_32b(a + 1 * BPS, d_in_ab_4567, 0);
- LOAD_LANE_32b(a + 2 * BPS, d_in_ab_89ab, 0);
- LOAD_LANE_32b(a + 3 * BPS, d_in_ab_cdef, 0);
- LOAD_LANE_32b(b + 0 * BPS, d_in_ab_0123, 1);
- LOAD_LANE_32b(b + 1 * BPS, d_in_ab_4567, 1);
- LOAD_LANE_32b(b + 2 * BPS, d_in_ab_89ab, 1);
- LOAD_LANE_32b(b + 3 * BPS, d_in_ab_cdef, 1);
- INIT_VECTOR4(d4_in,
- vreinterpret_u8_u32(d_in_ab_0123),
- vreinterpret_u8_u32(d_in_ab_4567),
- vreinterpret_u8_u32(d_in_ab_89ab),
- vreinterpret_u8_u32(d_in_ab_cdef));
-
- {
- // Vertical pass first to avoid a transpose (vertical and horizontal passes
- // are commutative because w/kWeightY is symmetric) and subsequent
- // transpose.
- const int16x8x4_t q4_v = DistoVerticalPass(d4_in);
- const int16x4x4_t d4_w = DistoLoadW(w);
- // horizontal pass
- const int16x8x4_t q4_t = DistoTranspose4x4S16(q4_v);
- const int16x8x4_t q4_h = DistoHorizontalPass(q4_t);
- int32x2_t d_sum = DistoSum(q4_h, d4_w);
-
- // abs(sum2 - sum1) >> 5
- d_sum = vabs_s32(d_sum);
- d_sum = vshr_n_s32(d_sum, 5);
- return vget_lane_s32(d_sum, 0);
- }
-}
-#undef LOAD_LANE_32b
-
-static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- int D = 0;
- int x, y;
- for (y = 0; y < 16 * BPS; y += 4 * BPS) {
- for (x = 0; x < 16; x += 4) {
- D += Disto4x4(a + x + y, b + x + y, w);
- }
- }
- return D;
-}
-
-//------------------------------------------------------------------------------
-
-static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block,
- VP8Histogram* const histo) {
- const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH);
- int j;
- int distribution[MAX_COEFF_THRESH + 1] = { 0 };
- for (j = start_block; j < end_block; ++j) {
- int16_t out[16];
- FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
- {
- int k;
- const int16x8_t a0 = vld1q_s16(out + 0);
- const int16x8_t b0 = vld1q_s16(out + 8);
- const uint16x8_t a1 = vreinterpretq_u16_s16(vabsq_s16(a0));
- const uint16x8_t b1 = vreinterpretq_u16_s16(vabsq_s16(b0));
- const uint16x8_t a2 = vshrq_n_u16(a1, 3);
- const uint16x8_t b2 = vshrq_n_u16(b1, 3);
- const uint16x8_t a3 = vminq_u16(a2, max_coeff_thresh);
- const uint16x8_t b3 = vminq_u16(b2, max_coeff_thresh);
- vst1q_s16(out + 0, vreinterpretq_s16_u16(a3));
- vst1q_s16(out + 8, vreinterpretq_s16_u16(b3));
- // Convert coefficients to bin.
- for (k = 0; k < 16; ++k) {
- ++distribution[out[k]];
- }
- }
- }
- VP8SetHistogramData(distribution, histo);
-}
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE void AccumulateSSE16(const uint8_t* const a,
- const uint8_t* const b,
- uint32x4_t* const sum) {
- const uint8x16_t a0 = vld1q_u8(a);
- const uint8x16_t b0 = vld1q_u8(b);
- const uint8x16_t abs_diff = vabdq_u8(a0, b0);
- uint16x8_t prod = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff));
- prod = vmlal_u8(prod, vget_high_u8(abs_diff), vget_high_u8(abs_diff));
- *sum = vpadalq_u16(*sum, prod); // pair-wise add and accumulate
-}
-
-// Horizontal sum of all four uint32_t values in 'sum'.
-static int SumToInt(uint32x4_t sum) {
- const uint64x2_t sum2 = vpaddlq_u32(sum);
- const uint64_t sum3 = vgetq_lane_u64(sum2, 0) + vgetq_lane_u64(sum2, 1);
- return (int)sum3;
-}
-
-static int SSE16x16(const uint8_t* a, const uint8_t* b) {
- uint32x4_t sum = vdupq_n_u32(0);
- int y;
- for (y = 0; y < 16; ++y) {
- AccumulateSSE16(a + y * BPS, b + y * BPS, &sum);
- }
- return SumToInt(sum);
-}
-
-static int SSE16x8(const uint8_t* a, const uint8_t* b) {
- uint32x4_t sum = vdupq_n_u32(0);
- int y;
- for (y = 0; y < 8; ++y) {
- AccumulateSSE16(a + y * BPS, b + y * BPS, &sum);
- }
- return SumToInt(sum);
-}
-
-static int SSE8x8(const uint8_t* a, const uint8_t* b) {
- uint32x4_t sum = vdupq_n_u32(0);
- int y;
- for (y = 0; y < 8; ++y) {
- const uint8x8_t a0 = vld1_u8(a + y * BPS);
- const uint8x8_t b0 = vld1_u8(b + y * BPS);
- const uint8x8_t abs_diff = vabd_u8(a0, b0);
- const uint16x8_t prod = vmull_u8(abs_diff, abs_diff);
- sum = vpadalq_u16(sum, prod);
- }
- return SumToInt(sum);
-}
-
-static int SSE4x4(const uint8_t* a, const uint8_t* b) {
- const uint8x16_t a0 = Load4x4(a);
- const uint8x16_t b0 = Load4x4(b);
- const uint8x16_t abs_diff = vabdq_u8(a0, b0);
- uint16x8_t prod = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff));
- prod = vmlal_u8(prod, vget_high_u8(abs_diff), vget_high_u8(abs_diff));
- return SumToInt(vpaddlq_u16(prod));
-}
-
-//------------------------------------------------------------------------------
-
-// Compilation with gcc-4.6.x is problematic for now.
-#if !defined(WORK_AROUND_GCC)
-
-static int16x8_t Quantize(int16_t* const in,
- const VP8Matrix* const mtx, int offset) {
- const uint16x8_t sharp = vld1q_u16(&mtx->sharpen_[offset]);
- const uint16x8_t q = vld1q_u16(&mtx->q_[offset]);
- const uint16x8_t iq = vld1q_u16(&mtx->iq_[offset]);
- const uint32x4_t bias0 = vld1q_u32(&mtx->bias_[offset + 0]);
- const uint32x4_t bias1 = vld1q_u32(&mtx->bias_[offset + 4]);
-
- const int16x8_t a = vld1q_s16(in + offset); // in
- const uint16x8_t b = vreinterpretq_u16_s16(vabsq_s16(a)); // coeff = abs(in)
- const int16x8_t sign = vshrq_n_s16(a, 15); // sign
- const uint16x8_t c = vaddq_u16(b, sharp); // + sharpen
- const uint32x4_t m0 = vmull_u16(vget_low_u16(c), vget_low_u16(iq));
- const uint32x4_t m1 = vmull_u16(vget_high_u16(c), vget_high_u16(iq));
- const uint32x4_t m2 = vhaddq_u32(m0, bias0);
- const uint32x4_t m3 = vhaddq_u32(m1, bias1); // (coeff * iQ + bias) >> 1
- const uint16x8_t c0 = vcombine_u16(vshrn_n_u32(m2, 16),
- vshrn_n_u32(m3, 16)); // QFIX=17 = 16+1
- const uint16x8_t c1 = vminq_u16(c0, vdupq_n_u16(MAX_LEVEL));
- const int16x8_t c2 = veorq_s16(vreinterpretq_s16_u16(c1), sign);
- const int16x8_t c3 = vsubq_s16(c2, sign); // restore sign
- const int16x8_t c4 = vmulq_s16(c3, vreinterpretq_s16_u16(q));
- vst1q_s16(in + offset, c4);
- assert(QFIX == 17); // this function can't work as is if QFIX != 16+1
- return c3;
-}
-
-static const uint8_t kShuffles[4][8] = {
- { 0, 1, 2, 3, 8, 9, 16, 17 },
- { 10, 11, 4, 5, 6, 7, 12, 13 },
- { 18, 19, 24, 25, 26, 27, 20, 21 },
- { 14, 15, 22, 23, 28, 29, 30, 31 }
-};
-
-static int QuantizeBlock(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- const int16x8_t out0 = Quantize(in, mtx, 0);
- const int16x8_t out1 = Quantize(in, mtx, 8);
- uint8x8x4_t shuffles;
- // vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
- // non-standard versions there.
-#if defined(__APPLE__) && defined(__aarch64__) && \
- defined(__apple_build_version__) && (__apple_build_version__< 6020037)
- uint8x16x2_t all_out;
- INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1));
- INIT_VECTOR4(shuffles,
- vtbl2q_u8(all_out, vld1_u8(kShuffles[0])),
- vtbl2q_u8(all_out, vld1_u8(kShuffles[1])),
- vtbl2q_u8(all_out, vld1_u8(kShuffles[2])),
- vtbl2q_u8(all_out, vld1_u8(kShuffles[3])));
-#else
- uint8x8x4_t all_out;
- INIT_VECTOR4(all_out,
- vreinterpret_u8_s16(vget_low_s16(out0)),
- vreinterpret_u8_s16(vget_high_s16(out0)),
- vreinterpret_u8_s16(vget_low_s16(out1)),
- vreinterpret_u8_s16(vget_high_s16(out1)));
- INIT_VECTOR4(shuffles,
- vtbl4_u8(all_out, vld1_u8(kShuffles[0])),
- vtbl4_u8(all_out, vld1_u8(kShuffles[1])),
- vtbl4_u8(all_out, vld1_u8(kShuffles[2])),
- vtbl4_u8(all_out, vld1_u8(kShuffles[3])));
-#endif
- // Zigzag reordering
- vst1_u8((uint8_t*)(out + 0), shuffles.val[0]);
- vst1_u8((uint8_t*)(out + 4), shuffles.val[1]);
- vst1_u8((uint8_t*)(out + 8), shuffles.val[2]);
- vst1_u8((uint8_t*)(out + 12), shuffles.val[3]);
- // test zeros
- if (*(uint64_t*)(out + 0) != 0) return 1;
- if (*(uint64_t*)(out + 4) != 0) return 1;
- if (*(uint64_t*)(out + 8) != 0) return 1;
- if (*(uint64_t*)(out + 12) != 0) return 1;
- return 0;
-}
-
-static int Quantize2Blocks(int16_t in[32], int16_t out[32],
- const VP8Matrix* const mtx) {
- int nz;
- nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0;
- nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1;
- return nz;
-}
-
-#endif // !WORK_AROUND_GCC
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspInitNEON(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) {
- VP8ITransform = ITransform;
- VP8FTransform = FTransform;
-
- VP8FTransformWHT = FTransformWHT;
-
- VP8TDisto4x4 = Disto4x4;
- VP8TDisto16x16 = Disto16x16;
- VP8CollectHistogram = CollectHistogram;
- VP8SSE16x16 = SSE16x16;
- VP8SSE16x8 = SSE16x8;
- VP8SSE8x8 = SSE8x8;
- VP8SSE4x4 = SSE4x4;
-#if !defined(WORK_AROUND_GCC)
- VP8EncQuantizeBlock = QuantizeBlock;
- VP8EncQuantize2Blocks = Quantize2Blocks;
-#endif
-}
-
-#else // !WEBP_USE_NEON
-
-WEBP_DSP_INIT_STUB(VP8EncDspInitNEON)
-
-#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/enc_sse2.c b/drivers/webp/dsp/enc_sse2.c
deleted file mode 100644
index 4a2e3ce14f..0000000000
--- a/drivers/webp/dsp/enc_sse2.c
+++ /dev/null
@@ -1,1340 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 version of speed-critical encoding functions.
-//
-// Author: Christian Duvivier (cduvivier@google.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-#include <stdlib.h> // for abs()
-#include <emmintrin.h>
-
-#include "./common_sse2.h"
-#include "../enc/cost.h"
-#include "../enc/vp8enci.h"
-
-//------------------------------------------------------------------------------
-// Transforms (Paragraph 14.4)
-
-// Does one or two inverse transforms.
-static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
- int do_two) {
- // This implementation makes use of 16-bit fixed point versions of two
- // multiply constants:
- // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
- // K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16
- //
- // To be able to use signed 16-bit integers, we use the following trick to
- // have constants within range:
- // - Associated constants are obtained by subtracting the 16-bit fixed point
- // version of one:
- // k = K - (1 << 16) => K = k + (1 << 16)
- // K1 = 85267 => k1 = 20091
- // K2 = 35468 => k2 = -30068
- // - The multiplication of a variable by a constant become the sum of the
- // variable and the multiplication of that variable by the associated
- // constant:
- // (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
- const __m128i k1 = _mm_set1_epi16(20091);
- const __m128i k2 = _mm_set1_epi16(-30068);
- __m128i T0, T1, T2, T3;
-
- // Load and concatenate the transform coefficients (we'll do two inverse
- // transforms in parallel). In the case of only one inverse transform, the
- // second half of the vectors will just contain random value we'll never
- // use nor store.
- __m128i in0, in1, in2, in3;
- {
- in0 = _mm_loadl_epi64((const __m128i*)&in[0]);
- in1 = _mm_loadl_epi64((const __m128i*)&in[4]);
- in2 = _mm_loadl_epi64((const __m128i*)&in[8]);
- in3 = _mm_loadl_epi64((const __m128i*)&in[12]);
- // a00 a10 a20 a30 x x x x
- // a01 a11 a21 a31 x x x x
- // a02 a12 a22 a32 x x x x
- // a03 a13 a23 a33 x x x x
- if (do_two) {
- const __m128i inB0 = _mm_loadl_epi64((const __m128i*)&in[16]);
- const __m128i inB1 = _mm_loadl_epi64((const __m128i*)&in[20]);
- const __m128i inB2 = _mm_loadl_epi64((const __m128i*)&in[24]);
- const __m128i inB3 = _mm_loadl_epi64((const __m128i*)&in[28]);
- in0 = _mm_unpacklo_epi64(in0, inB0);
- in1 = _mm_unpacklo_epi64(in1, inB1);
- in2 = _mm_unpacklo_epi64(in2, inB2);
- in3 = _mm_unpacklo_epi64(in3, inB3);
- // a00 a10 a20 a30 b00 b10 b20 b30
- // a01 a11 a21 a31 b01 b11 b21 b31
- // a02 a12 a22 a32 b02 b12 b22 b32
- // a03 a13 a23 a33 b03 b13 b23 b33
- }
- }
-
- // Vertical pass and subsequent transpose.
- {
- // First pass, c and d calculations are longer because of the "trick"
- // multiplications.
- const __m128i a = _mm_add_epi16(in0, in2);
- const __m128i b = _mm_sub_epi16(in0, in2);
- // c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3
- const __m128i c1 = _mm_mulhi_epi16(in1, k2);
- const __m128i c2 = _mm_mulhi_epi16(in3, k1);
- const __m128i c3 = _mm_sub_epi16(in1, in3);
- const __m128i c4 = _mm_sub_epi16(c1, c2);
- const __m128i c = _mm_add_epi16(c3, c4);
- // d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3
- const __m128i d1 = _mm_mulhi_epi16(in1, k1);
- const __m128i d2 = _mm_mulhi_epi16(in3, k2);
- const __m128i d3 = _mm_add_epi16(in1, in3);
- const __m128i d4 = _mm_add_epi16(d1, d2);
- const __m128i d = _mm_add_epi16(d3, d4);
-
- // Second pass.
- const __m128i tmp0 = _mm_add_epi16(a, d);
- const __m128i tmp1 = _mm_add_epi16(b, c);
- const __m128i tmp2 = _mm_sub_epi16(b, c);
- const __m128i tmp3 = _mm_sub_epi16(a, d);
-
- // Transpose the two 4x4.
- VP8Transpose_2_4x4_16b(&tmp0, &tmp1, &tmp2, &tmp3, &T0, &T1, &T2, &T3);
- }
-
- // Horizontal pass and subsequent transpose.
- {
- // First pass, c and d calculations are longer because of the "trick"
- // multiplications.
- const __m128i four = _mm_set1_epi16(4);
- const __m128i dc = _mm_add_epi16(T0, four);
- const __m128i a = _mm_add_epi16(dc, T2);
- const __m128i b = _mm_sub_epi16(dc, T2);
- // c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3
- const __m128i c1 = _mm_mulhi_epi16(T1, k2);
- const __m128i c2 = _mm_mulhi_epi16(T3, k1);
- const __m128i c3 = _mm_sub_epi16(T1, T3);
- const __m128i c4 = _mm_sub_epi16(c1, c2);
- const __m128i c = _mm_add_epi16(c3, c4);
- // d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3
- const __m128i d1 = _mm_mulhi_epi16(T1, k1);
- const __m128i d2 = _mm_mulhi_epi16(T3, k2);
- const __m128i d3 = _mm_add_epi16(T1, T3);
- const __m128i d4 = _mm_add_epi16(d1, d2);
- const __m128i d = _mm_add_epi16(d3, d4);
-
- // Second pass.
- const __m128i tmp0 = _mm_add_epi16(a, d);
- const __m128i tmp1 = _mm_add_epi16(b, c);
- const __m128i tmp2 = _mm_sub_epi16(b, c);
- const __m128i tmp3 = _mm_sub_epi16(a, d);
- const __m128i shifted0 = _mm_srai_epi16(tmp0, 3);
- const __m128i shifted1 = _mm_srai_epi16(tmp1, 3);
- const __m128i shifted2 = _mm_srai_epi16(tmp2, 3);
- const __m128i shifted3 = _mm_srai_epi16(tmp3, 3);
-
- // Transpose the two 4x4.
- VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1,
- &T2, &T3);
- }
-
- // Add inverse transform to 'ref' and store.
- {
- const __m128i zero = _mm_setzero_si128();
- // Load the reference(s).
- __m128i ref0, ref1, ref2, ref3;
- if (do_two) {
- // Load eight bytes/pixels per line.
- ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]);
- ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]);
- ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]);
- ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]);
- } else {
- // Load four bytes/pixels per line.
- ref0 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[0 * BPS]));
- ref1 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[1 * BPS]));
- ref2 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[2 * BPS]));
- ref3 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[3 * BPS]));
- }
- // Convert to 16b.
- ref0 = _mm_unpacklo_epi8(ref0, zero);
- ref1 = _mm_unpacklo_epi8(ref1, zero);
- ref2 = _mm_unpacklo_epi8(ref2, zero);
- ref3 = _mm_unpacklo_epi8(ref3, zero);
- // Add the inverse transform(s).
- ref0 = _mm_add_epi16(ref0, T0);
- ref1 = _mm_add_epi16(ref1, T1);
- ref2 = _mm_add_epi16(ref2, T2);
- ref3 = _mm_add_epi16(ref3, T3);
- // Unsigned saturate to 8b.
- ref0 = _mm_packus_epi16(ref0, ref0);
- ref1 = _mm_packus_epi16(ref1, ref1);
- ref2 = _mm_packus_epi16(ref2, ref2);
- ref3 = _mm_packus_epi16(ref3, ref3);
- // Store the results.
- if (do_two) {
- // Store eight bytes/pixels per line.
- _mm_storel_epi64((__m128i*)&dst[0 * BPS], ref0);
- _mm_storel_epi64((__m128i*)&dst[1 * BPS], ref1);
- _mm_storel_epi64((__m128i*)&dst[2 * BPS], ref2);
- _mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3);
- } else {
- // Store four bytes/pixels per line.
- WebPUint32ToMem(&dst[0 * BPS], _mm_cvtsi128_si32(ref0));
- WebPUint32ToMem(&dst[1 * BPS], _mm_cvtsi128_si32(ref1));
- WebPUint32ToMem(&dst[2 * BPS], _mm_cvtsi128_si32(ref2));
- WebPUint32ToMem(&dst[3 * BPS], _mm_cvtsi128_si32(ref3));
- }
- }
-}
-
-static void FTransformPass1(const __m128i* const in01,
- const __m128i* const in23,
- __m128i* const out01,
- __m128i* const out32) {
- const __m128i k937 = _mm_set1_epi32(937);
- const __m128i k1812 = _mm_set1_epi32(1812);
-
- const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8);
- const __m128i k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8);
- const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352,
- 2217, 5352, 2217, 5352);
- const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217,
- -5352, 2217, -5352, 2217);
-
- // *in01 = 00 01 10 11 02 03 12 13
- // *in23 = 20 21 30 31 22 23 32 33
- const __m128i shuf01_p = _mm_shufflehi_epi16(*in01, _MM_SHUFFLE(2, 3, 0, 1));
- const __m128i shuf23_p = _mm_shufflehi_epi16(*in23, _MM_SHUFFLE(2, 3, 0, 1));
- // 00 01 10 11 03 02 13 12
- // 20 21 30 31 23 22 33 32
- const __m128i s01 = _mm_unpacklo_epi64(shuf01_p, shuf23_p);
- const __m128i s32 = _mm_unpackhi_epi64(shuf01_p, shuf23_p);
- // 00 01 10 11 20 21 30 31
- // 03 02 13 12 23 22 33 32
- const __m128i a01 = _mm_add_epi16(s01, s32);
- const __m128i a32 = _mm_sub_epi16(s01, s32);
- // [d0 + d3 | d1 + d2 | ...] = [a0 a1 | a0' a1' | ... ]
- // [d0 - d3 | d1 - d2 | ...] = [a3 a2 | a3' a2' | ... ]
-
- const __m128i tmp0 = _mm_madd_epi16(a01, k88p); // [ (a0 + a1) << 3, ... ]
- const __m128i tmp2 = _mm_madd_epi16(a01, k88m); // [ (a0 - a1) << 3, ... ]
- const __m128i tmp1_1 = _mm_madd_epi16(a32, k5352_2217p);
- const __m128i tmp3_1 = _mm_madd_epi16(a32, k5352_2217m);
- const __m128i tmp1_2 = _mm_add_epi32(tmp1_1, k1812);
- const __m128i tmp3_2 = _mm_add_epi32(tmp3_1, k937);
- const __m128i tmp1 = _mm_srai_epi32(tmp1_2, 9);
- const __m128i tmp3 = _mm_srai_epi32(tmp3_2, 9);
- const __m128i s03 = _mm_packs_epi32(tmp0, tmp2);
- const __m128i s12 = _mm_packs_epi32(tmp1, tmp3);
- const __m128i s_lo = _mm_unpacklo_epi16(s03, s12); // 0 1 0 1 0 1...
- const __m128i s_hi = _mm_unpackhi_epi16(s03, s12); // 2 3 2 3 2 3
- const __m128i v23 = _mm_unpackhi_epi32(s_lo, s_hi);
- *out01 = _mm_unpacklo_epi32(s_lo, s_hi);
- *out32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2..
-}
-
-static void FTransformPass2(const __m128i* const v01, const __m128i* const v32,
- int16_t* out) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i seven = _mm_set1_epi16(7);
- const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217,
- 5352, 2217, 5352, 2217);
- const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352,
- 2217, -5352, 2217, -5352);
- const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16));
- const __m128i k51000 = _mm_set1_epi32(51000);
-
- // Same operations are done on the (0,3) and (1,2) pairs.
- // a0 = v0 + v3
- // a1 = v1 + v2
- // a3 = v0 - v3
- // a2 = v1 - v2
- const __m128i a01 = _mm_add_epi16(*v01, *v32);
- const __m128i a32 = _mm_sub_epi16(*v01, *v32);
- const __m128i a11 = _mm_unpackhi_epi64(a01, a01);
- const __m128i a22 = _mm_unpackhi_epi64(a32, a32);
- const __m128i a01_plus_7 = _mm_add_epi16(a01, seven);
-
- // d0 = (a0 + a1 + 7) >> 4;
- // d2 = (a0 - a1 + 7) >> 4;
- const __m128i c0 = _mm_add_epi16(a01_plus_7, a11);
- const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11);
- const __m128i d0 = _mm_srai_epi16(c0, 4);
- const __m128i d2 = _mm_srai_epi16(c2, 4);
-
- // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16)
- // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16)
- const __m128i b23 = _mm_unpacklo_epi16(a22, a32);
- const __m128i c1 = _mm_madd_epi16(b23, k5352_2217);
- const __m128i c3 = _mm_madd_epi16(b23, k2217_5352);
- const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one);
- const __m128i d3 = _mm_add_epi32(c3, k51000);
- const __m128i e1 = _mm_srai_epi32(d1, 16);
- const __m128i e3 = _mm_srai_epi32(d3, 16);
- const __m128i f1 = _mm_packs_epi32(e1, e1);
- const __m128i f3 = _mm_packs_epi32(e3, e3);
- // f1 = f1 + (a3 != 0);
- // The compare will return (0xffff, 0) for (==0, !=0). To turn that into the
- // desired (0, 1), we add one earlier through k12000_plus_one.
- // -> f1 = f1 + 1 - (a3 == 0)
- const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero));
-
- const __m128i d0_g1 = _mm_unpacklo_epi64(d0, g1);
- const __m128i d2_f3 = _mm_unpacklo_epi64(d2, f3);
- _mm_storeu_si128((__m128i*)&out[0], d0_g1);
- _mm_storeu_si128((__m128i*)&out[8], d2_f3);
-}
-
-static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
- const __m128i zero = _mm_setzero_si128();
- // Load src.
- const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]);
- const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]);
- const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]);
- const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]);
- // 00 01 02 03 *
- // 10 11 12 13 *
- // 20 21 22 23 *
- // 30 31 32 33 *
- // Shuffle.
- const __m128i src_0 = _mm_unpacklo_epi16(src0, src1);
- const __m128i src_1 = _mm_unpacklo_epi16(src2, src3);
- // 00 01 10 11 02 03 12 13 * * ...
- // 20 21 30 31 22 22 32 33 * * ...
-
- // Load ref.
- const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]);
- const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]);
- const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]);
- const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]);
- const __m128i ref_0 = _mm_unpacklo_epi16(ref0, ref1);
- const __m128i ref_1 = _mm_unpacklo_epi16(ref2, ref3);
-
- // Convert both to 16 bit.
- const __m128i src_0_16b = _mm_unpacklo_epi8(src_0, zero);
- const __m128i src_1_16b = _mm_unpacklo_epi8(src_1, zero);
- const __m128i ref_0_16b = _mm_unpacklo_epi8(ref_0, zero);
- const __m128i ref_1_16b = _mm_unpacklo_epi8(ref_1, zero);
-
- // Compute the difference.
- const __m128i row01 = _mm_sub_epi16(src_0_16b, ref_0_16b);
- const __m128i row23 = _mm_sub_epi16(src_1_16b, ref_1_16b);
- __m128i v01, v32;
-
- // First pass
- FTransformPass1(&row01, &row23, &v01, &v32);
-
- // Second pass
- FTransformPass2(&v01, &v32, out);
-}
-
-static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) {
- const __m128i zero = _mm_setzero_si128();
-
- // Load src and convert to 16b.
- const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]);
- const __m128i src1 = _mm_loadl_epi64((const __m128i*)&src[1 * BPS]);
- const __m128i src2 = _mm_loadl_epi64((const __m128i*)&src[2 * BPS]);
- const __m128i src3 = _mm_loadl_epi64((const __m128i*)&src[3 * BPS]);
- const __m128i src_0 = _mm_unpacklo_epi8(src0, zero);
- const __m128i src_1 = _mm_unpacklo_epi8(src1, zero);
- const __m128i src_2 = _mm_unpacklo_epi8(src2, zero);
- const __m128i src_3 = _mm_unpacklo_epi8(src3, zero);
- // Load ref and convert to 16b.
- const __m128i ref0 = _mm_loadl_epi64((const __m128i*)&ref[0 * BPS]);
- const __m128i ref1 = _mm_loadl_epi64((const __m128i*)&ref[1 * BPS]);
- const __m128i ref2 = _mm_loadl_epi64((const __m128i*)&ref[2 * BPS]);
- const __m128i ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]);
- const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero);
- const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero);
- const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero);
- const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero);
- // Compute difference. -> 00 01 02 03 00' 01' 02' 03'
- const __m128i diff0 = _mm_sub_epi16(src_0, ref_0);
- const __m128i diff1 = _mm_sub_epi16(src_1, ref_1);
- const __m128i diff2 = _mm_sub_epi16(src_2, ref_2);
- const __m128i diff3 = _mm_sub_epi16(src_3, ref_3);
-
- // Unpack and shuffle
- // 00 01 02 03 0 0 0 0
- // 10 11 12 13 0 0 0 0
- // 20 21 22 23 0 0 0 0
- // 30 31 32 33 0 0 0 0
- const __m128i shuf01l = _mm_unpacklo_epi32(diff0, diff1);
- const __m128i shuf23l = _mm_unpacklo_epi32(diff2, diff3);
- const __m128i shuf01h = _mm_unpackhi_epi32(diff0, diff1);
- const __m128i shuf23h = _mm_unpackhi_epi32(diff2, diff3);
- __m128i v01l, v32l;
- __m128i v01h, v32h;
-
- // First pass
- FTransformPass1(&shuf01l, &shuf23l, &v01l, &v32l);
- FTransformPass1(&shuf01h, &shuf23h, &v01h, &v32h);
-
- // Second pass
- FTransformPass2(&v01l, &v32l, out + 0);
- FTransformPass2(&v01h, &v32h, out + 16);
-}
-
-static void FTransformWHTRow(const int16_t* const in, __m128i* const out) {
- const __m128i kMult = _mm_set_epi16(-1, 1, -1, 1, 1, 1, 1, 1);
- const __m128i src0 = _mm_loadl_epi64((__m128i*)&in[0 * 16]);
- const __m128i src1 = _mm_loadl_epi64((__m128i*)&in[1 * 16]);
- const __m128i src2 = _mm_loadl_epi64((__m128i*)&in[2 * 16]);
- const __m128i src3 = _mm_loadl_epi64((__m128i*)&in[3 * 16]);
- const __m128i A01 = _mm_unpacklo_epi16(src0, src1); // A0 A1 | ...
- const __m128i A23 = _mm_unpacklo_epi16(src2, src3); // A2 A3 | ...
- const __m128i B0 = _mm_adds_epi16(A01, A23); // a0 | a1 | ...
- const __m128i B1 = _mm_subs_epi16(A01, A23); // a3 | a2 | ...
- const __m128i C0 = _mm_unpacklo_epi32(B0, B1); // a0 | a1 | a3 | a2 | ...
- const __m128i C1 = _mm_unpacklo_epi32(B1, B0); // a3 | a2 | a0 | a1 | ...
- const __m128i D = _mm_unpacklo_epi64(C0, C1); // a0 a1 a3 a2 a3 a2 a0 a1
- *out = _mm_madd_epi16(D, kMult);
-}
-
-static void FTransformWHT(const int16_t* in, int16_t* out) {
- // Input is 12b signed.
- __m128i row0, row1, row2, row3;
- // Rows are 14b signed.
- FTransformWHTRow(in + 0 * 64, &row0);
- FTransformWHTRow(in + 1 * 64, &row1);
- FTransformWHTRow(in + 2 * 64, &row2);
- FTransformWHTRow(in + 3 * 64, &row3);
-
- {
- // The a* are 15b signed.
- const __m128i a0 = _mm_add_epi32(row0, row2);
- const __m128i a1 = _mm_add_epi32(row1, row3);
- const __m128i a2 = _mm_sub_epi32(row1, row3);
- const __m128i a3 = _mm_sub_epi32(row0, row2);
- const __m128i a0a3 = _mm_packs_epi32(a0, a3);
- const __m128i a1a2 = _mm_packs_epi32(a1, a2);
-
- // The b* are 16b signed.
- const __m128i b0b1 = _mm_add_epi16(a0a3, a1a2);
- const __m128i b3b2 = _mm_sub_epi16(a0a3, a1a2);
- const __m128i tmp_b2b3 = _mm_unpackhi_epi64(b3b2, b3b2);
- const __m128i b2b3 = _mm_unpacklo_epi64(tmp_b2b3, b3b2);
-
- _mm_storeu_si128((__m128i*)&out[0], _mm_srai_epi16(b0b1, 1));
- _mm_storeu_si128((__m128i*)&out[8], _mm_srai_epi16(b2b3, 1));
- }
-}
-
-//------------------------------------------------------------------------------
-// Compute susceptibility based on DCT-coeff histograms:
-// the higher, the "easier" the macroblock is to compress.
-
-static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block,
- VP8Histogram* const histo) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
- int j;
- int distribution[MAX_COEFF_THRESH + 1] = { 0 };
- for (j = start_block; j < end_block; ++j) {
- int16_t out[16];
- int k;
-
- FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
-
- // Convert coefficients to bin (within out[]).
- {
- // Load.
- const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]);
- const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]);
- const __m128i d0 = _mm_sub_epi16(zero, out0);
- const __m128i d1 = _mm_sub_epi16(zero, out1);
- const __m128i abs0 = _mm_max_epi16(out0, d0); // abs(v), 16b
- const __m128i abs1 = _mm_max_epi16(out1, d1);
- // v = abs(out) >> 3
- const __m128i v0 = _mm_srai_epi16(abs0, 3);
- const __m128i v1 = _mm_srai_epi16(abs1, 3);
- // bin = min(v, MAX_COEFF_THRESH)
- const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh);
- const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh);
- // Store.
- _mm_storeu_si128((__m128i*)&out[0], bin0);
- _mm_storeu_si128((__m128i*)&out[8], bin1);
- }
-
- // Convert coefficients to bin.
- for (k = 0; k < 16; ++k) {
- ++distribution[out[k]];
- }
- }
- VP8SetHistogramData(distribution, histo);
-}
-
-//------------------------------------------------------------------------------
-// Intra predictions
-
-// helper for chroma-DC predictions
-static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) {
- int j;
- const __m128i values = _mm_set1_epi8(v);
- for (j = 0; j < 8; ++j) {
- _mm_storel_epi64((__m128i*)(dst + j * BPS), values);
- }
-}
-
-static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) {
- int j;
- const __m128i values = _mm_set1_epi8(v);
- for (j = 0; j < 16; ++j) {
- _mm_store_si128((__m128i*)(dst + j * BPS), values);
- }
-}
-
-static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) {
- if (size == 4) {
- int j;
- for (j = 0; j < 4; ++j) {
- memset(dst + j * BPS, value, 4);
- }
- } else if (size == 8) {
- Put8x8uv(value, dst);
- } else {
- Put16(value, dst);
- }
-}
-
-static WEBP_INLINE void VE8uv(uint8_t* dst, const uint8_t* top) {
- int j;
- const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
- for (j = 0; j < 8; ++j) {
- _mm_storel_epi64((__m128i*)(dst + j * BPS), top_values);
- }
-}
-
-static WEBP_INLINE void VE16(uint8_t* dst, const uint8_t* top) {
- const __m128i top_values = _mm_load_si128((const __m128i*)top);
- int j;
- for (j = 0; j < 16; ++j) {
- _mm_store_si128((__m128i*)(dst + j * BPS), top_values);
- }
-}
-
-static WEBP_INLINE void VerticalPred(uint8_t* dst,
- const uint8_t* top, int size) {
- if (top != NULL) {
- if (size == 8) {
- VE8uv(dst, top);
- } else {
- VE16(dst, top);
- }
- } else {
- Fill(dst, 127, size);
- }
-}
-
-static WEBP_INLINE void HE8uv(uint8_t* dst, const uint8_t* left) {
- int j;
- for (j = 0; j < 8; ++j) {
- const __m128i values = _mm_set1_epi8(left[j]);
- _mm_storel_epi64((__m128i*)dst, values);
- dst += BPS;
- }
-}
-
-static WEBP_INLINE void HE16(uint8_t* dst, const uint8_t* left) {
- int j;
- for (j = 0; j < 16; ++j) {
- const __m128i values = _mm_set1_epi8(left[j]);
- _mm_store_si128((__m128i*)dst, values);
- dst += BPS;
- }
-}
-
-static WEBP_INLINE void HorizontalPred(uint8_t* dst,
- const uint8_t* left, int size) {
- if (left != NULL) {
- if (size == 8) {
- HE8uv(dst, left);
- } else {
- HE16(dst, left);
- }
- } else {
- Fill(dst, 129, size);
- }
-}
-
-static WEBP_INLINE void TM(uint8_t* dst, const uint8_t* left,
- const uint8_t* top, int size) {
- const __m128i zero = _mm_setzero_si128();
- int y;
- if (size == 8) {
- const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
- const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
- for (y = 0; y < 8; ++y, dst += BPS) {
- const int val = left[y] - left[-1];
- const __m128i base = _mm_set1_epi16(val);
- const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
- _mm_storel_epi64((__m128i*)dst, out);
- }
- } else {
- const __m128i top_values = _mm_load_si128((const __m128i*)top);
- const __m128i top_base_0 = _mm_unpacklo_epi8(top_values, zero);
- const __m128i top_base_1 = _mm_unpackhi_epi8(top_values, zero);
- for (y = 0; y < 16; ++y, dst += BPS) {
- const int val = left[y] - left[-1];
- const __m128i base = _mm_set1_epi16(val);
- const __m128i out_0 = _mm_add_epi16(base, top_base_0);
- const __m128i out_1 = _mm_add_epi16(base, top_base_1);
- const __m128i out = _mm_packus_epi16(out_0, out_1);
- _mm_store_si128((__m128i*)dst, out);
- }
- }
-}
-
-static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left,
- const uint8_t* top, int size) {
- if (left != NULL) {
- if (top != NULL) {
- TM(dst, left, top, size);
- } else {
- HorizontalPred(dst, left, size);
- }
- } else {
- // true motion without left samples (hence: with default 129 value)
- // is equivalent to VE prediction where you just copy the top samples.
- // Note that if top samples are not available, the default value is
- // then 129, and not 127 as in the VerticalPred case.
- if (top != NULL) {
- VerticalPred(dst, top, size);
- } else {
- Fill(dst, 129, size);
- }
- }
-}
-
-static WEBP_INLINE void DC8uv(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
- const __m128i left_values = _mm_loadl_epi64((const __m128i*)left);
- const __m128i combined = _mm_unpacklo_epi64(top_values, left_values);
- const int DC = VP8HorizontalAdd8b(&combined) + 8;
- Put8x8uv(DC >> 4, dst);
-}
-
-static WEBP_INLINE void DC8uvNoLeft(uint8_t* dst, const uint8_t* top) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
- const __m128i sum = _mm_sad_epu8(top_values, zero);
- const int DC = _mm_cvtsi128_si32(sum) + 4;
- Put8x8uv(DC >> 3, dst);
-}
-
-static WEBP_INLINE void DC8uvNoTop(uint8_t* dst, const uint8_t* left) {
- // 'left' is contiguous so we can reuse the top summation.
- DC8uvNoLeft(dst, left);
-}
-
-static WEBP_INLINE void DC8uvNoTopLeft(uint8_t* dst) {
- Put8x8uv(0x80, dst);
-}
-
-static WEBP_INLINE void DC8uvMode(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- if (top != NULL) {
- if (left != NULL) { // top and left present
- DC8uv(dst, left, top);
- } else { // top, but no left
- DC8uvNoLeft(dst, top);
- }
- } else if (left != NULL) { // left but no top
- DC8uvNoTop(dst, left);
- } else { // no top, no left, nothing.
- DC8uvNoTopLeft(dst);
- }
-}
-
-static WEBP_INLINE void DC16(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- const __m128i top_row = _mm_load_si128((const __m128i*)top);
- const __m128i left_row = _mm_load_si128((const __m128i*)left);
- const int DC =
- VP8HorizontalAdd8b(&top_row) + VP8HorizontalAdd8b(&left_row) + 16;
- Put16(DC >> 5, dst);
-}
-
-static WEBP_INLINE void DC16NoLeft(uint8_t* dst, const uint8_t* top) {
- const __m128i top_row = _mm_load_si128((const __m128i*)top);
- const int DC = VP8HorizontalAdd8b(&top_row) + 8;
- Put16(DC >> 4, dst);
-}
-
-static WEBP_INLINE void DC16NoTop(uint8_t* dst, const uint8_t* left) {
- // 'left' is contiguous so we can reuse the top summation.
- DC16NoLeft(dst, left);
-}
-
-static WEBP_INLINE void DC16NoTopLeft(uint8_t* dst) {
- Put16(0x80, dst);
-}
-
-static WEBP_INLINE void DC16Mode(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- if (top != NULL) {
- if (left != NULL) { // top and left present
- DC16(dst, left, top);
- } else { // top, but no left
- DC16NoLeft(dst, top);
- }
- } else if (left != NULL) { // left but no top
- DC16NoTop(dst, left);
- } else { // no top, no left, nothing.
- DC16NoTopLeft(dst);
- }
-}
-
-//------------------------------------------------------------------------------
-// 4x4 predictions
-
-#define DST(x, y) dst[(x) + (y) * BPS]
-#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
-#define AVG2(a, b) (((a) + (b) + 1) >> 1)
-
-// We use the following 8b-arithmetic tricks:
-// (a + 2 * b + c + 2) >> 2 = (AC + b + 1) >> 1
-// where: AC = (a + c) >> 1 = [(a + c + 1) >> 1] - [(a^c) & 1]
-// and:
-// (a + 2 * b + c + 2) >> 2 = (AB + BC + 1) >> 1 - (ab|bc)&lsb
-// where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1
-// and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1
-
-static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical
- const __m128i one = _mm_set1_epi8(1);
- const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(top - 1));
- const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
- const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
- const __m128i a = _mm_avg_epu8(ABCDEFGH, CDEFGH00);
- const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one);
- const __m128i b = _mm_subs_epu8(a, lsb);
- const __m128i avg = _mm_avg_epu8(b, BCDEFGH0);
- const uint32_t vals = _mm_cvtsi128_si32(avg);
- int i;
- for (i = 0; i < 4; ++i) {
- WebPUint32ToMem(dst + i * BPS, vals);
- }
-}
-
-static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal
- const int X = top[-1];
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int L = top[-5];
- WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J));
- WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K));
- WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L));
- WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L));
-}
-
-static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) {
- uint32_t dc = 4;
- int i;
- for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i];
- Fill(dst, dc >> 3, 4);
-}
-
-static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { // Down-Left
- const __m128i one = _mm_set1_epi8(1);
- const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top);
- const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1);
- const __m128i CDEFGH00 = _mm_srli_si128(ABCDEFGH, 2);
- const __m128i CDEFGHH0 = _mm_insert_epi16(CDEFGH00, top[7], 3);
- const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, CDEFGHH0);
- const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
- const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
- const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg ));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
-}
-
-static WEBP_INLINE void VR4(uint8_t* dst,
- const uint8_t* top) { // Vertical-Right
- const __m128i one = _mm_set1_epi8(1);
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int X = top[-1];
- const __m128i XABCD = _mm_loadl_epi64((const __m128i*)(top - 1));
- const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
- const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
- const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
- const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0);
- const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
- const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
- const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
- const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd ));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh ));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
-
- // these two are hard to implement in SSE2, so we keep the C-version:
- DST(0, 2) = AVG3(J, I, X);
- DST(0, 3) = AVG3(K, J, I);
-}
-
-static WEBP_INLINE void VL4(uint8_t* dst,
- const uint8_t* top) { // Vertical-Left
- const __m128i one = _mm_set1_epi8(1);
- const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top);
- const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1);
- const __m128i CDEFGH__ = _mm_srli_si128(ABCDEFGH, 2);
- const __m128i avg1 = _mm_avg_epu8(ABCDEFGH, BCDEFGH_);
- const __m128i avg2 = _mm_avg_epu8(CDEFGH__, BCDEFGH_);
- const __m128i avg3 = _mm_avg_epu8(avg1, avg2);
- const __m128i lsb1 = _mm_and_si128(_mm_xor_si128(avg1, avg2), one);
- const __m128i ab = _mm_xor_si128(ABCDEFGH, BCDEFGH_);
- const __m128i bc = _mm_xor_si128(CDEFGH__, BCDEFGH_);
- const __m128i abbc = _mm_or_si128(ab, bc);
- const __m128i lsb2 = _mm_and_si128(abbc, lsb1);
- const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
- const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 ));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 ));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
-
- // these two are hard to get and irregular
- DST(3, 2) = (extra_out >> 0) & 0xff;
- DST(3, 3) = (extra_out >> 8) & 0xff;
-}
-
-static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { // Down-right
- const __m128i one = _mm_set1_epi8(1);
- const __m128i LKJIXABC = _mm_loadl_epi64((const __m128i*)(top - 5));
- const __m128i LKJIXABCD = _mm_insert_epi16(LKJIXABC, top[3], 4);
- const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1);
- const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2);
- const __m128i avg1 = _mm_avg_epu8(JIXABCD__, LKJIXABCD);
- const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
- const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
- const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
- WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg ));
- WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
- WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
- WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
-}
-
-static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) {
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int L = top[-5];
- DST(0, 0) = AVG2(I, J);
- DST(2, 0) = DST(0, 1) = AVG2(J, K);
- DST(2, 1) = DST(0, 2) = AVG2(K, L);
- DST(1, 0) = AVG3(I, J, K);
- DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
- DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
- DST(3, 2) = DST(2, 2) =
- DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
-}
-
-static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) {
- const int X = top[-1];
- const int I = top[-2];
- const int J = top[-3];
- const int K = top[-4];
- const int L = top[-5];
- const int A = top[0];
- const int B = top[1];
- const int C = top[2];
-
- DST(0, 0) = DST(2, 1) = AVG2(I, X);
- DST(0, 1) = DST(2, 2) = AVG2(J, I);
- DST(0, 2) = DST(2, 3) = AVG2(K, J);
- DST(0, 3) = AVG2(L, K);
-
- DST(3, 0) = AVG3(A, B, C);
- DST(2, 0) = AVG3(X, A, B);
- DST(1, 0) = DST(3, 1) = AVG3(I, X, A);
- DST(1, 1) = DST(3, 2) = AVG3(J, I, X);
- DST(1, 2) = DST(3, 3) = AVG3(K, J, I);
- DST(1, 3) = AVG3(L, K, J);
-}
-
-static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top));
- const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
- int y;
- for (y = 0; y < 4; ++y, dst += BPS) {
- const int val = top[-2 - y] - top[-1];
- const __m128i base = _mm_set1_epi16(val);
- const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
- WebPUint32ToMem(dst, _mm_cvtsi128_si32(out));
- }
-}
-
-#undef DST
-#undef AVG3
-#undef AVG2
-
-//------------------------------------------------------------------------------
-// luma 4x4 prediction
-
-// Left samples are top[-5 .. -2], top_left is top[-1], top are
-// located at top[0..3], and top right is top[4..7]
-static void Intra4Preds(uint8_t* dst, const uint8_t* top) {
- DC4(I4DC4 + dst, top);
- TM4(I4TM4 + dst, top);
- VE4(I4VE4 + dst, top);
- HE4(I4HE4 + dst, top);
- RD4(I4RD4 + dst, top);
- VR4(I4VR4 + dst, top);
- LD4(I4LD4 + dst, top);
- VL4(I4VL4 + dst, top);
- HD4(I4HD4 + dst, top);
- HU4(I4HU4 + dst, top);
-}
-
-//------------------------------------------------------------------------------
-// Chroma 8x8 prediction (paragraph 12.2)
-
-static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
- const uint8_t* top) {
- // U block
- DC8uvMode(C8DC8 + dst, left, top);
- VerticalPred(C8VE8 + dst, top, 8);
- HorizontalPred(C8HE8 + dst, left, 8);
- TrueMotion(C8TM8 + dst, left, top, 8);
- // V block
- dst += 8;
- if (top != NULL) top += 8;
- if (left != NULL) left += 16;
- DC8uvMode(C8DC8 + dst, left, top);
- VerticalPred(C8VE8 + dst, top, 8);
- HorizontalPred(C8HE8 + dst, left, 8);
- TrueMotion(C8TM8 + dst, left, top, 8);
-}
-
-//------------------------------------------------------------------------------
-// luma 16x16 prediction (paragraph 12.3)
-
-static void Intra16Preds(uint8_t* dst,
- const uint8_t* left, const uint8_t* top) {
- DC16Mode(I16DC16 + dst, left, top);
- VerticalPred(I16VE16 + dst, top, 16);
- HorizontalPred(I16HE16 + dst, left, 16);
- TrueMotion(I16TM16 + dst, left, top, 16);
-}
-
-//------------------------------------------------------------------------------
-// Metric
-
-static WEBP_INLINE void SubtractAndAccumulate(const __m128i a, const __m128i b,
- __m128i* const sum) {
- // take abs(a-b) in 8b
- const __m128i a_b = _mm_subs_epu8(a, b);
- const __m128i b_a = _mm_subs_epu8(b, a);
- const __m128i abs_a_b = _mm_or_si128(a_b, b_a);
- // zero-extend to 16b
- const __m128i zero = _mm_setzero_si128();
- const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero);
- const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero);
- // multiply with self
- const __m128i sum1 = _mm_madd_epi16(C0, C0);
- const __m128i sum2 = _mm_madd_epi16(C1, C1);
- *sum = _mm_add_epi32(sum1, sum2);
-}
-
-static WEBP_INLINE int SSE_16xN(const uint8_t* a, const uint8_t* b,
- int num_pairs) {
- __m128i sum = _mm_setzero_si128();
- int32_t tmp[4];
- int i;
-
- for (i = 0; i < num_pairs; ++i) {
- const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[BPS * 0]);
- const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[BPS * 0]);
- const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[BPS * 1]);
- const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[BPS * 1]);
- __m128i sum1, sum2;
- SubtractAndAccumulate(a0, b0, &sum1);
- SubtractAndAccumulate(a1, b1, &sum2);
- sum = _mm_add_epi32(sum, _mm_add_epi32(sum1, sum2));
- a += 2 * BPS;
- b += 2 * BPS;
- }
- _mm_storeu_si128((__m128i*)tmp, sum);
- return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
-}
-
-static int SSE16x16(const uint8_t* a, const uint8_t* b) {
- return SSE_16xN(a, b, 8);
-}
-
-static int SSE16x8(const uint8_t* a, const uint8_t* b) {
- return SSE_16xN(a, b, 4);
-}
-
-#define LOAD_8x16b(ptr) \
- _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr)), zero)
-
-static int SSE8x8(const uint8_t* a, const uint8_t* b) {
- const __m128i zero = _mm_setzero_si128();
- int num_pairs = 4;
- __m128i sum = zero;
- int32_t tmp[4];
- while (num_pairs-- > 0) {
- const __m128i a0 = LOAD_8x16b(&a[BPS * 0]);
- const __m128i a1 = LOAD_8x16b(&a[BPS * 1]);
- const __m128i b0 = LOAD_8x16b(&b[BPS * 0]);
- const __m128i b1 = LOAD_8x16b(&b[BPS * 1]);
- // subtract
- const __m128i c0 = _mm_subs_epi16(a0, b0);
- const __m128i c1 = _mm_subs_epi16(a1, b1);
- // multiply/accumulate with self
- const __m128i d0 = _mm_madd_epi16(c0, c0);
- const __m128i d1 = _mm_madd_epi16(c1, c1);
- // collect
- const __m128i sum01 = _mm_add_epi32(d0, d1);
- sum = _mm_add_epi32(sum, sum01);
- a += 2 * BPS;
- b += 2 * BPS;
- }
- _mm_storeu_si128((__m128i*)tmp, sum);
- return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
-}
-#undef LOAD_8x16b
-
-static int SSE4x4(const uint8_t* a, const uint8_t* b) {
- const __m128i zero = _mm_setzero_si128();
-
- // Load values. Note that we read 8 pixels instead of 4,
- // but the a/b buffers are over-allocated to that effect.
- const __m128i a0 = _mm_loadl_epi64((const __m128i*)&a[BPS * 0]);
- const __m128i a1 = _mm_loadl_epi64((const __m128i*)&a[BPS * 1]);
- const __m128i a2 = _mm_loadl_epi64((const __m128i*)&a[BPS * 2]);
- const __m128i a3 = _mm_loadl_epi64((const __m128i*)&a[BPS * 3]);
- const __m128i b0 = _mm_loadl_epi64((const __m128i*)&b[BPS * 0]);
- const __m128i b1 = _mm_loadl_epi64((const __m128i*)&b[BPS * 1]);
- const __m128i b2 = _mm_loadl_epi64((const __m128i*)&b[BPS * 2]);
- const __m128i b3 = _mm_loadl_epi64((const __m128i*)&b[BPS * 3]);
- // Combine pair of lines.
- const __m128i a01 = _mm_unpacklo_epi32(a0, a1);
- const __m128i a23 = _mm_unpacklo_epi32(a2, a3);
- const __m128i b01 = _mm_unpacklo_epi32(b0, b1);
- const __m128i b23 = _mm_unpacklo_epi32(b2, b3);
- // Convert to 16b.
- const __m128i a01s = _mm_unpacklo_epi8(a01, zero);
- const __m128i a23s = _mm_unpacklo_epi8(a23, zero);
- const __m128i b01s = _mm_unpacklo_epi8(b01, zero);
- const __m128i b23s = _mm_unpacklo_epi8(b23, zero);
- // subtract, square and accumulate
- const __m128i d0 = _mm_subs_epi16(a01s, b01s);
- const __m128i d1 = _mm_subs_epi16(a23s, b23s);
- const __m128i e0 = _mm_madd_epi16(d0, d0);
- const __m128i e1 = _mm_madd_epi16(d1, d1);
- const __m128i sum = _mm_add_epi32(e0, e1);
-
- int32_t tmp[4];
- _mm_storeu_si128((__m128i*)tmp, sum);
- return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
-}
-
-//------------------------------------------------------------------------------
-// Texture distortion
-//
-// We try to match the spectral content (weighted) between source and
-// reconstructed samples.
-
-// Hadamard transform
-// Returns the weighted sum of the absolute value of transformed coefficients.
-// w[] contains a row-major 4 by 4 symmetric matrix.
-static int TTransform(const uint8_t* inA, const uint8_t* inB,
- const uint16_t* const w) {
- int32_t sum[4];
- __m128i tmp_0, tmp_1, tmp_2, tmp_3;
- const __m128i zero = _mm_setzero_si128();
-
- // Load and combine inputs.
- {
- const __m128i inA_0 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 0]);
- const __m128i inA_1 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 1]);
- const __m128i inA_2 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 2]);
- const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]);
- const __m128i inB_0 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 0]);
- const __m128i inB_1 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 1]);
- const __m128i inB_2 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 2]);
- const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]);
-
- // Combine inA and inB (we'll do two transforms in parallel).
- const __m128i inAB_0 = _mm_unpacklo_epi32(inA_0, inB_0);
- const __m128i inAB_1 = _mm_unpacklo_epi32(inA_1, inB_1);
- const __m128i inAB_2 = _mm_unpacklo_epi32(inA_2, inB_2);
- const __m128i inAB_3 = _mm_unpacklo_epi32(inA_3, inB_3);
- tmp_0 = _mm_unpacklo_epi8(inAB_0, zero);
- tmp_1 = _mm_unpacklo_epi8(inAB_1, zero);
- tmp_2 = _mm_unpacklo_epi8(inAB_2, zero);
- tmp_3 = _mm_unpacklo_epi8(inAB_3, zero);
- // a00 a01 a02 a03 b00 b01 b02 b03
- // a10 a11 a12 a13 b10 b11 b12 b13
- // a20 a21 a22 a23 b20 b21 b22 b23
- // a30 a31 a32 a33 b30 b31 b32 b33
- }
-
- // Vertical pass first to avoid a transpose (vertical and horizontal passes
- // are commutative because w/kWeightY is symmetric) and subsequent transpose.
- {
- // Calculate a and b (two 4x4 at once).
- const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
- const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
- const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
- const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
- const __m128i b0 = _mm_add_epi16(a0, a1);
- const __m128i b1 = _mm_add_epi16(a3, a2);
- const __m128i b2 = _mm_sub_epi16(a3, a2);
- const __m128i b3 = _mm_sub_epi16(a0, a1);
- // a00 a01 a02 a03 b00 b01 b02 b03
- // a10 a11 a12 a13 b10 b11 b12 b13
- // a20 a21 a22 a23 b20 b21 b22 b23
- // a30 a31 a32 a33 b30 b31 b32 b33
-
- // Transpose the two 4x4.
- VP8Transpose_2_4x4_16b(&b0, &b1, &b2, &b3, &tmp_0, &tmp_1, &tmp_2, &tmp_3);
- }
-
- // Horizontal pass and difference of weighted sums.
- {
- // Load all inputs.
- const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]);
- const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]);
-
- // Calculate a and b (two 4x4 at once).
- const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
- const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
- const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
- const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
- const __m128i b0 = _mm_add_epi16(a0, a1);
- const __m128i b1 = _mm_add_epi16(a3, a2);
- const __m128i b2 = _mm_sub_epi16(a3, a2);
- const __m128i b3 = _mm_sub_epi16(a0, a1);
-
- // Separate the transforms of inA and inB.
- __m128i A_b0 = _mm_unpacklo_epi64(b0, b1);
- __m128i A_b2 = _mm_unpacklo_epi64(b2, b3);
- __m128i B_b0 = _mm_unpackhi_epi64(b0, b1);
- __m128i B_b2 = _mm_unpackhi_epi64(b2, b3);
-
- {
- const __m128i d0 = _mm_sub_epi16(zero, A_b0);
- const __m128i d1 = _mm_sub_epi16(zero, A_b2);
- const __m128i d2 = _mm_sub_epi16(zero, B_b0);
- const __m128i d3 = _mm_sub_epi16(zero, B_b2);
- A_b0 = _mm_max_epi16(A_b0, d0); // abs(v), 16b
- A_b2 = _mm_max_epi16(A_b2, d1);
- B_b0 = _mm_max_epi16(B_b0, d2);
- B_b2 = _mm_max_epi16(B_b2, d3);
- }
-
- // weighted sums
- A_b0 = _mm_madd_epi16(A_b0, w_0);
- A_b2 = _mm_madd_epi16(A_b2, w_8);
- B_b0 = _mm_madd_epi16(B_b0, w_0);
- B_b2 = _mm_madd_epi16(B_b2, w_8);
- A_b0 = _mm_add_epi32(A_b0, A_b2);
- B_b0 = _mm_add_epi32(B_b0, B_b2);
-
- // difference of weighted sums
- A_b0 = _mm_sub_epi32(A_b0, B_b0);
- _mm_storeu_si128((__m128i*)&sum[0], A_b0);
- }
- return sum[0] + sum[1] + sum[2] + sum[3];
-}
-
-static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- const int diff_sum = TTransform(a, b, w);
- return abs(diff_sum) >> 5;
-}
-
-static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- int D = 0;
- int x, y;
- for (y = 0; y < 16 * BPS; y += 4 * BPS) {
- for (x = 0; x < 16; x += 4) {
- D += Disto4x4(a + x + y, b + x + y, w);
- }
- }
- return D;
-}
-
-//------------------------------------------------------------------------------
-// Quantization
-//
-
-static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16],
- const uint16_t* const sharpen,
- const VP8Matrix* const mtx) {
- const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL);
- const __m128i zero = _mm_setzero_si128();
- __m128i coeff0, coeff8;
- __m128i out0, out8;
- __m128i packed_out;
-
- // Load all inputs.
- __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]);
- __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]);
- const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]);
- const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]);
- const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]);
- const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]);
-
- // extract sign(in) (0x0000 if positive, 0xffff if negative)
- const __m128i sign0 = _mm_cmpgt_epi16(zero, in0);
- const __m128i sign8 = _mm_cmpgt_epi16(zero, in8);
-
- // coeff = abs(in) = (in ^ sign) - sign
- coeff0 = _mm_xor_si128(in0, sign0);
- coeff8 = _mm_xor_si128(in8, sign8);
- coeff0 = _mm_sub_epi16(coeff0, sign0);
- coeff8 = _mm_sub_epi16(coeff8, sign8);
-
- // coeff = abs(in) + sharpen
- if (sharpen != NULL) {
- const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]);
- const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]);
- coeff0 = _mm_add_epi16(coeff0, sharpen0);
- coeff8 = _mm_add_epi16(coeff8, sharpen8);
- }
-
- // out = (coeff * iQ + B) >> QFIX
- {
- // doing calculations with 32b precision (QFIX=17)
- // out = (coeff * iQ)
- const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0);
- const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0);
- const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8);
- const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8);
- __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H);
- __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H);
- __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H);
- __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H);
- // out = (coeff * iQ + B)
- const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]);
- const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]);
- const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]);
- const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]);
- out_00 = _mm_add_epi32(out_00, bias_00);
- out_04 = _mm_add_epi32(out_04, bias_04);
- out_08 = _mm_add_epi32(out_08, bias_08);
- out_12 = _mm_add_epi32(out_12, bias_12);
- // out = QUANTDIV(coeff, iQ, B, QFIX)
- out_00 = _mm_srai_epi32(out_00, QFIX);
- out_04 = _mm_srai_epi32(out_04, QFIX);
- out_08 = _mm_srai_epi32(out_08, QFIX);
- out_12 = _mm_srai_epi32(out_12, QFIX);
-
- // pack result as 16b
- out0 = _mm_packs_epi32(out_00, out_04);
- out8 = _mm_packs_epi32(out_08, out_12);
-
- // if (coeff > 2047) coeff = 2047
- out0 = _mm_min_epi16(out0, max_coeff_2047);
- out8 = _mm_min_epi16(out8, max_coeff_2047);
- }
-
- // get sign back (if (sign[j]) out_n = -out_n)
- out0 = _mm_xor_si128(out0, sign0);
- out8 = _mm_xor_si128(out8, sign8);
- out0 = _mm_sub_epi16(out0, sign0);
- out8 = _mm_sub_epi16(out8, sign8);
-
- // in = out * Q
- in0 = _mm_mullo_epi16(out0, q0);
- in8 = _mm_mullo_epi16(out8, q8);
-
- _mm_storeu_si128((__m128i*)&in[0], in0);
- _mm_storeu_si128((__m128i*)&in[8], in8);
-
- // zigzag the output before storing it.
- //
- // The zigzag pattern can almost be reproduced with a small sequence of
- // shuffles. After it, we only need to swap the 7th (ending up in third
- // position instead of twelfth) and 8th values.
- {
- __m128i outZ0, outZ8;
- outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0));
- outZ0 = _mm_shuffle_epi32 (outZ0, _MM_SHUFFLE(3, 1, 2, 0));
- outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2));
- outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1));
- outZ8 = _mm_shuffle_epi32 (outZ8, _MM_SHUFFLE(3, 1, 2, 0));
- outZ8 = _mm_shufflelo_epi16(outZ8, _MM_SHUFFLE(1, 3, 2, 0));
- _mm_storeu_si128((__m128i*)&out[0], outZ0);
- _mm_storeu_si128((__m128i*)&out[8], outZ8);
- packed_out = _mm_packs_epi16(outZ0, outZ8);
- }
- {
- const int16_t outZ_12 = out[12];
- const int16_t outZ_3 = out[3];
- out[3] = outZ_12;
- out[12] = outZ_3;
- }
-
- // detect if all 'out' values are zeroes or not
- return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff);
-}
-
-static int QuantizeBlock(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx);
-}
-
-static int QuantizeBlockWHT(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- return DoQuantizeBlock(in, out, NULL, mtx);
-}
-
-static int Quantize2Blocks(int16_t in[32], int16_t out[32],
- const VP8Matrix* const mtx) {
- int nz;
- const uint16_t* const sharpen = &mtx->sharpen_[0];
- nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0;
- nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1;
- return nz;
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspInitSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE2(void) {
- VP8CollectHistogram = CollectHistogram;
- VP8EncPredLuma16 = Intra16Preds;
- VP8EncPredChroma8 = IntraChromaPreds;
- VP8EncPredLuma4 = Intra4Preds;
- VP8EncQuantizeBlock = QuantizeBlock;
- VP8EncQuantize2Blocks = Quantize2Blocks;
- VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
- VP8ITransform = ITransform;
- VP8FTransform = FTransform;
- VP8FTransform2 = FTransform2;
- VP8FTransformWHT = FTransformWHT;
- VP8SSE16x16 = SSE16x16;
- VP8SSE16x8 = SSE16x8;
- VP8SSE8x8 = SSE8x8;
- VP8SSE4x4 = SSE4x4;
- VP8TDisto4x4 = Disto4x4;
- VP8TDisto16x16 = Disto16x16;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(VP8EncDspInitSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/enc_sse41.c b/drivers/webp/dsp/enc_sse41.c
deleted file mode 100644
index a1783901a6..0000000000
--- a/drivers/webp/dsp/enc_sse41.c
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE4 version of some encoding functions.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE41)
-#include <smmintrin.h>
-#include <stdlib.h> // for abs()
-
-#include "./common_sse2.h"
-#include "../enc/vp8enci.h"
-
-//------------------------------------------------------------------------------
-// Compute susceptibility based on DCT-coeff histograms.
-
-static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
- int start_block, int end_block,
- VP8Histogram* const histo) {
- const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
- int j;
- int distribution[MAX_COEFF_THRESH + 1] = { 0 };
- for (j = start_block; j < end_block; ++j) {
- int16_t out[16];
- int k;
-
- VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
-
- // Convert coefficients to bin (within out[]).
- {
- // Load.
- const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]);
- const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]);
- // v = abs(out) >> 3
- const __m128i abs0 = _mm_abs_epi16(out0);
- const __m128i abs1 = _mm_abs_epi16(out1);
- const __m128i v0 = _mm_srai_epi16(abs0, 3);
- const __m128i v1 = _mm_srai_epi16(abs1, 3);
- // bin = min(v, MAX_COEFF_THRESH)
- const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh);
- const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh);
- // Store.
- _mm_storeu_si128((__m128i*)&out[0], bin0);
- _mm_storeu_si128((__m128i*)&out[8], bin1);
- }
-
- // Convert coefficients to bin.
- for (k = 0; k < 16; ++k) {
- ++distribution[out[k]];
- }
- }
- VP8SetHistogramData(distribution, histo);
-}
-
-//------------------------------------------------------------------------------
-// Texture distortion
-//
-// We try to match the spectral content (weighted) between source and
-// reconstructed samples.
-
-// Hadamard transform
-// Returns the weighted sum of the absolute value of transformed coefficients.
-// w[] contains a row-major 4 by 4 symmetric matrix.
-static int TTransform(const uint8_t* inA, const uint8_t* inB,
- const uint16_t* const w) {
- int32_t sum[4];
- __m128i tmp_0, tmp_1, tmp_2, tmp_3;
-
- // Load and combine inputs.
- {
- const __m128i inA_0 = _mm_loadu_si128((const __m128i*)&inA[BPS * 0]);
- const __m128i inA_1 = _mm_loadu_si128((const __m128i*)&inA[BPS * 1]);
- const __m128i inA_2 = _mm_loadu_si128((const __m128i*)&inA[BPS * 2]);
- // In SSE4.1, with gcc 4.8 at least (maybe other versions),
- // _mm_loadu_si128 is faster than _mm_loadl_epi64. But for the last lump
- // of inA and inB, _mm_loadl_epi64 is still used not to have an out of
- // bound read.
- const __m128i inA_3 = _mm_loadl_epi64((const __m128i*)&inA[BPS * 3]);
- const __m128i inB_0 = _mm_loadu_si128((const __m128i*)&inB[BPS * 0]);
- const __m128i inB_1 = _mm_loadu_si128((const __m128i*)&inB[BPS * 1]);
- const __m128i inB_2 = _mm_loadu_si128((const __m128i*)&inB[BPS * 2]);
- const __m128i inB_3 = _mm_loadl_epi64((const __m128i*)&inB[BPS * 3]);
-
- // Combine inA and inB (we'll do two transforms in parallel).
- const __m128i inAB_0 = _mm_unpacklo_epi32(inA_0, inB_0);
- const __m128i inAB_1 = _mm_unpacklo_epi32(inA_1, inB_1);
- const __m128i inAB_2 = _mm_unpacklo_epi32(inA_2, inB_2);
- const __m128i inAB_3 = _mm_unpacklo_epi32(inA_3, inB_3);
- tmp_0 = _mm_cvtepu8_epi16(inAB_0);
- tmp_1 = _mm_cvtepu8_epi16(inAB_1);
- tmp_2 = _mm_cvtepu8_epi16(inAB_2);
- tmp_3 = _mm_cvtepu8_epi16(inAB_3);
- // a00 a01 a02 a03 b00 b01 b02 b03
- // a10 a11 a12 a13 b10 b11 b12 b13
- // a20 a21 a22 a23 b20 b21 b22 b23
- // a30 a31 a32 a33 b30 b31 b32 b33
- }
-
- // Vertical pass first to avoid a transpose (vertical and horizontal passes
- // are commutative because w/kWeightY is symmetric) and subsequent transpose.
- {
- // Calculate a and b (two 4x4 at once).
- const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
- const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
- const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
- const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
- const __m128i b0 = _mm_add_epi16(a0, a1);
- const __m128i b1 = _mm_add_epi16(a3, a2);
- const __m128i b2 = _mm_sub_epi16(a3, a2);
- const __m128i b3 = _mm_sub_epi16(a0, a1);
- // a00 a01 a02 a03 b00 b01 b02 b03
- // a10 a11 a12 a13 b10 b11 b12 b13
- // a20 a21 a22 a23 b20 b21 b22 b23
- // a30 a31 a32 a33 b30 b31 b32 b33
-
- // Transpose the two 4x4.
- VP8Transpose_2_4x4_16b(&b0, &b1, &b2, &b3, &tmp_0, &tmp_1, &tmp_2, &tmp_3);
- }
-
- // Horizontal pass and difference of weighted sums.
- {
- // Load all inputs.
- const __m128i w_0 = _mm_loadu_si128((const __m128i*)&w[0]);
- const __m128i w_8 = _mm_loadu_si128((const __m128i*)&w[8]);
-
- // Calculate a and b (two 4x4 at once).
- const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
- const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
- const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
- const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
- const __m128i b0 = _mm_add_epi16(a0, a1);
- const __m128i b1 = _mm_add_epi16(a3, a2);
- const __m128i b2 = _mm_sub_epi16(a3, a2);
- const __m128i b3 = _mm_sub_epi16(a0, a1);
-
- // Separate the transforms of inA and inB.
- __m128i A_b0 = _mm_unpacklo_epi64(b0, b1);
- __m128i A_b2 = _mm_unpacklo_epi64(b2, b3);
- __m128i B_b0 = _mm_unpackhi_epi64(b0, b1);
- __m128i B_b2 = _mm_unpackhi_epi64(b2, b3);
-
- A_b0 = _mm_abs_epi16(A_b0);
- A_b2 = _mm_abs_epi16(A_b2);
- B_b0 = _mm_abs_epi16(B_b0);
- B_b2 = _mm_abs_epi16(B_b2);
-
- // weighted sums
- A_b0 = _mm_madd_epi16(A_b0, w_0);
- A_b2 = _mm_madd_epi16(A_b2, w_8);
- B_b0 = _mm_madd_epi16(B_b0, w_0);
- B_b2 = _mm_madd_epi16(B_b2, w_8);
- A_b0 = _mm_add_epi32(A_b0, A_b2);
- B_b0 = _mm_add_epi32(B_b0, B_b2);
-
- // difference of weighted sums
- A_b2 = _mm_sub_epi32(A_b0, B_b0);
- _mm_storeu_si128((__m128i*)&sum[0], A_b2);
- }
- return sum[0] + sum[1] + sum[2] + sum[3];
-}
-
-static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- const int diff_sum = TTransform(a, b, w);
- return abs(diff_sum) >> 5;
-}
-
-static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
- const uint16_t* const w) {
- int D = 0;
- int x, y;
- for (y = 0; y < 16 * BPS; y += 4 * BPS) {
- for (x = 0; x < 16; x += 4) {
- D += Disto4x4(a + x + y, b + x + y, w);
- }
- }
- return D;
-}
-
-//------------------------------------------------------------------------------
-// Quantization
-//
-
-// Generates a pshufb constant for shuffling 16b words.
-#define PSHUFB_CST(A,B,C,D,E,F,G,H) \
- _mm_set_epi8(2 * (H) + 1, 2 * (H) + 0, 2 * (G) + 1, 2 * (G) + 0, \
- 2 * (F) + 1, 2 * (F) + 0, 2 * (E) + 1, 2 * (E) + 0, \
- 2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \
- 2 * (B) + 1, 2 * (B) + 0, 2 * (A) + 1, 2 * (A) + 0)
-
-static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16],
- const uint16_t* const sharpen,
- const VP8Matrix* const mtx) {
- const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL);
- const __m128i zero = _mm_setzero_si128();
- __m128i out0, out8;
- __m128i packed_out;
-
- // Load all inputs.
- __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]);
- __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]);
- const __m128i iq0 = _mm_loadu_si128((const __m128i*)&mtx->iq_[0]);
- const __m128i iq8 = _mm_loadu_si128((const __m128i*)&mtx->iq_[8]);
- const __m128i q0 = _mm_loadu_si128((const __m128i*)&mtx->q_[0]);
- const __m128i q8 = _mm_loadu_si128((const __m128i*)&mtx->q_[8]);
-
- // coeff = abs(in)
- __m128i coeff0 = _mm_abs_epi16(in0);
- __m128i coeff8 = _mm_abs_epi16(in8);
-
- // coeff = abs(in) + sharpen
- if (sharpen != NULL) {
- const __m128i sharpen0 = _mm_loadu_si128((const __m128i*)&sharpen[0]);
- const __m128i sharpen8 = _mm_loadu_si128((const __m128i*)&sharpen[8]);
- coeff0 = _mm_add_epi16(coeff0, sharpen0);
- coeff8 = _mm_add_epi16(coeff8, sharpen8);
- }
-
- // out = (coeff * iQ + B) >> QFIX
- {
- // doing calculations with 32b precision (QFIX=17)
- // out = (coeff * iQ)
- const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0);
- const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0);
- const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8);
- const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8);
- __m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H);
- __m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H);
- __m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H);
- __m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H);
- // out = (coeff * iQ + B)
- const __m128i bias_00 = _mm_loadu_si128((const __m128i*)&mtx->bias_[0]);
- const __m128i bias_04 = _mm_loadu_si128((const __m128i*)&mtx->bias_[4]);
- const __m128i bias_08 = _mm_loadu_si128((const __m128i*)&mtx->bias_[8]);
- const __m128i bias_12 = _mm_loadu_si128((const __m128i*)&mtx->bias_[12]);
- out_00 = _mm_add_epi32(out_00, bias_00);
- out_04 = _mm_add_epi32(out_04, bias_04);
- out_08 = _mm_add_epi32(out_08, bias_08);
- out_12 = _mm_add_epi32(out_12, bias_12);
- // out = QUANTDIV(coeff, iQ, B, QFIX)
- out_00 = _mm_srai_epi32(out_00, QFIX);
- out_04 = _mm_srai_epi32(out_04, QFIX);
- out_08 = _mm_srai_epi32(out_08, QFIX);
- out_12 = _mm_srai_epi32(out_12, QFIX);
-
- // pack result as 16b
- out0 = _mm_packs_epi32(out_00, out_04);
- out8 = _mm_packs_epi32(out_08, out_12);
-
- // if (coeff > 2047) coeff = 2047
- out0 = _mm_min_epi16(out0, max_coeff_2047);
- out8 = _mm_min_epi16(out8, max_coeff_2047);
- }
-
- // put sign back
- out0 = _mm_sign_epi16(out0, in0);
- out8 = _mm_sign_epi16(out8, in8);
-
- // in = out * Q
- in0 = _mm_mullo_epi16(out0, q0);
- in8 = _mm_mullo_epi16(out8, q8);
-
- _mm_storeu_si128((__m128i*)&in[0], in0);
- _mm_storeu_si128((__m128i*)&in[8], in8);
-
- // zigzag the output before storing it. The re-ordering is:
- // 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15
- // -> 0 1 4[8]5 2 3 6 | 9 12 13 10 [7]11 14 15
- // There's only two misplaced entries ([8] and [7]) that are crossing the
- // reg's boundaries.
- // We use pshufb instead of pshuflo/pshufhi.
- {
- const __m128i kCst_lo = PSHUFB_CST(0, 1, 4, -1, 5, 2, 3, 6);
- const __m128i kCst_7 = PSHUFB_CST(-1, -1, -1, -1, 7, -1, -1, -1);
- const __m128i tmp_lo = _mm_shuffle_epi8(out0, kCst_lo);
- const __m128i tmp_7 = _mm_shuffle_epi8(out0, kCst_7); // extract #7
- const __m128i kCst_hi = PSHUFB_CST(1, 4, 5, 2, -1, 3, 6, 7);
- const __m128i kCst_8 = PSHUFB_CST(-1, -1, -1, 0, -1, -1, -1, -1);
- const __m128i tmp_hi = _mm_shuffle_epi8(out8, kCst_hi);
- const __m128i tmp_8 = _mm_shuffle_epi8(out8, kCst_8); // extract #8
- const __m128i out_z0 = _mm_or_si128(tmp_lo, tmp_8);
- const __m128i out_z8 = _mm_or_si128(tmp_hi, tmp_7);
- _mm_storeu_si128((__m128i*)&out[0], out_z0);
- _mm_storeu_si128((__m128i*)&out[8], out_z8);
- packed_out = _mm_packs_epi16(out_z0, out_z8);
- }
-
- // detect if all 'out' values are zeroes or not
- return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff);
-}
-
-#undef PSHUFB_CST
-
-static int QuantizeBlock(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx);
-}
-
-static int QuantizeBlockWHT(int16_t in[16], int16_t out[16],
- const VP8Matrix* const mtx) {
- return DoQuantizeBlock(in, out, NULL, mtx);
-}
-
-static int Quantize2Blocks(int16_t in[32], int16_t out[32],
- const VP8Matrix* const mtx) {
- int nz;
- const uint16_t* const sharpen = &mtx->sharpen_[0];
- nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0;
- nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1;
- return nz;
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8EncDspInitSSE41(void);
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE41(void) {
- VP8CollectHistogram = CollectHistogram;
- VP8EncQuantizeBlock = QuantizeBlock;
- VP8EncQuantize2Blocks = Quantize2Blocks;
- VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
- VP8TDisto4x4 = Disto4x4;
- VP8TDisto16x16 = Disto16x16;
-}
-
-#else // !WEBP_USE_SSE41
-
-WEBP_DSP_INIT_STUB(VP8EncDspInitSSE41)
-
-#endif // WEBP_USE_SSE41
diff --git a/drivers/webp/dsp/filters.c b/drivers/webp/dsp/filters.c
deleted file mode 100644
index 9f04faf0cb..0000000000
--- a/drivers/webp/dsp/filters.c
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Spatial prediction using various filters
-//
-// Author: Urvang (urvang@google.com)
-
-#include "./dsp.h"
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-//------------------------------------------------------------------------------
-// Helpful macro.
-
-# define SANITY_CHECK(in, out) \
- assert(in != NULL); \
- assert(out != NULL); \
- assert(width > 0); \
- assert(height > 0); \
- assert(stride >= width); \
- assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \
- (void)height; // Silence unused warning.
-
-static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
- uint8_t* dst, int length, int inverse) {
- int i;
- if (inverse) {
- for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i];
- } else {
- for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i];
- }
-}
-
-//------------------------------------------------------------------------------
-// Horizontal filter.
-
-static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows,
- int inverse, uint8_t* out) {
- const uint8_t* preds;
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
- preds = inverse ? out : in;
-
- if (row == 0) {
- // Leftmost pixel is the same as input for topmost scanline.
- out[0] = in[0];
- PredictLine(in + 1, preds, out + 1, width - 1, inverse);
- row = 1;
- preds += stride;
- in += stride;
- out += stride;
- }
-
- // Filter line-by-line.
- while (row < last_row) {
- // Leftmost pixel is predicted from above.
- PredictLine(in, preds - stride, out, 1, inverse);
- PredictLine(in + 1, preds, out + 1, width - 1, inverse);
- ++row;
- preds += stride;
- in += stride;
- out += stride;
- }
-}
-
-//------------------------------------------------------------------------------
-// Vertical filter.
-
-static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows,
- int inverse, uint8_t* out) {
- const uint8_t* preds;
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
- preds = inverse ? out : in;
-
- if (row == 0) {
- // Very first top-left pixel is copied.
- out[0] = in[0];
- // Rest of top scan-line is left-predicted.
- PredictLine(in + 1, preds, out + 1, width - 1, inverse);
- row = 1;
- in += stride;
- out += stride;
- } else {
- // We are starting from in-between. Make sure 'preds' points to prev row.
- preds -= stride;
- }
-
- // Filter line-by-line.
- while (row < last_row) {
- PredictLine(in, preds, out, width, inverse);
- ++row;
- preds += stride;
- in += stride;
- out += stride;
- }
-}
-
-//------------------------------------------------------------------------------
-// Gradient filter.
-
-static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
- const int g = a + b - c;
- return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
-}
-
-static WEBP_INLINE void DoGradientFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows,
- int inverse, uint8_t* out) {
- const uint8_t* preds;
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
- preds = inverse ? out : in;
-
- // left prediction for top scan-line
- if (row == 0) {
- out[0] = in[0];
- PredictLine(in + 1, preds, out + 1, width - 1, inverse);
- row = 1;
- preds += stride;
- in += stride;
- out += stride;
- }
-
- // Filter line-by-line.
- while (row < last_row) {
- int w;
- // leftmost pixel: predict from above.
- PredictLine(in, preds - stride, out, 1, inverse);
- for (w = 1; w < width; ++w) {
- const int pred = GradientPredictor(preds[w - 1],
- preds[w - stride],
- preds[w - stride - 1]);
- out[w] = in[w] + (inverse ? pred : -pred);
- }
- ++row;
- preds += stride;
- in += stride;
- out += stride;
- }
-}
-
-#undef SANITY_CHECK
-
-//------------------------------------------------------------------------------
-
-static void HorizontalFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data);
-}
-
-static void VerticalFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data);
-}
-
-
-static void GradientFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data);
-}
-
-
-//------------------------------------------------------------------------------
-
-static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- uint8_t pred = (prev == NULL) ? 0 : prev[0];
- int i;
- for (i = 0; i < width; ++i) {
- out[i] = pred + in[i];
- pred = out[i];
- }
-}
-
-static void VerticalUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- if (prev == NULL) {
- HorizontalUnfilter(NULL, in, out, width);
- } else {
- int i;
- for (i = 0; i < width; ++i) out[i] = prev[i] + in[i];
- }
-}
-
-static void GradientUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- if (prev == NULL) {
- HorizontalUnfilter(NULL, in, out, width);
- } else {
- uint8_t top = prev[0], top_left = top, left = top;
- int i;
- for (i = 0; i < width; ++i) {
- top = prev[i]; // need to read this first, in case prev==out
- left = in[i] + GradientPredictor(left, top, top_left);
- top_left = top;
- out[i] = left;
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// Init function
-
-WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
-WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
-
-extern void VP8FiltersInitMIPSdspR2(void);
-extern void VP8FiltersInitSSE2(void);
-
-static volatile VP8CPUInfo filters_last_cpuinfo_used =
- (VP8CPUInfo)&filters_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) {
- if (filters_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- WebPUnfilters[WEBP_FILTER_NONE] = NULL;
- WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter;
- WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter;
- WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter;
-
- WebPFilters[WEBP_FILTER_NONE] = NULL;
- WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
- WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
- WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
-
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- VP8FiltersInitSSE2();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- VP8FiltersInitMIPSdspR2();
- }
-#endif
- }
- filters_last_cpuinfo_used = VP8GetCPUInfo;
-}
diff --git a/drivers/webp/dsp/filters_mips_dsp_r2.c b/drivers/webp/dsp/filters_mips_dsp_r2.c
deleted file mode 100644
index 1d82e3c2e1..0000000000
--- a/drivers/webp/dsp/filters_mips_dsp_r2.c
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Spatial prediction using various filters
-//
-// Author(s): Branimir Vasic (branimir.vasic@imgtec.com)
-// Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include "../dsp/dsp.h"
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-//------------------------------------------------------------------------------
-// Helpful macro.
-
-# define SANITY_CHECK(in, out) \
- assert(in != NULL); \
- assert(out != NULL); \
- assert(width > 0); \
- assert(height > 0); \
- assert(stride >= width); \
- assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \
- (void)height; // Silence unused warning.
-
-#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \
- const uint8_t* psrc = (uint8_t*)(SRC); \
- uint8_t* pdst = (uint8_t*)(DST); \
- const int ilength = (int)(LENGTH); \
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6; \
- __asm__ volatile ( \
- ".set push \n\t" \
- ".set noreorder \n\t" \
- "srl %[temp0], %[length], 2 \n\t" \
- "beqz %[temp0], 4f \n\t" \
- " andi %[temp6], %[length], 3 \n\t" \
- ".if " #INVERSE " \n\t" \
- "1: \n\t" \
- "lbu %[temp1], -1(%[dst]) \n\t" \
- "lbu %[temp2], 0(%[src]) \n\t" \
- "lbu %[temp3], 1(%[src]) \n\t" \
- "lbu %[temp4], 2(%[src]) \n\t" \
- "lbu %[temp5], 3(%[src]) \n\t" \
- "addu %[temp1], %[temp1], %[temp2] \n\t" \
- "addu %[temp2], %[temp1], %[temp3] \n\t" \
- "addu %[temp3], %[temp2], %[temp4] \n\t" \
- "addu %[temp4], %[temp3], %[temp5] \n\t" \
- "sb %[temp1], 0(%[dst]) \n\t" \
- "sb %[temp2], 1(%[dst]) \n\t" \
- "sb %[temp3], 2(%[dst]) \n\t" \
- "sb %[temp4], 3(%[dst]) \n\t" \
- "addiu %[src], %[src], 4 \n\t" \
- "addiu %[temp0], %[temp0], -1 \n\t" \
- "bnez %[temp0], 1b \n\t" \
- " addiu %[dst], %[dst], 4 \n\t" \
- ".else \n\t" \
- "1: \n\t" \
- "ulw %[temp1], -1(%[src]) \n\t" \
- "ulw %[temp2], 0(%[src]) \n\t" \
- "addiu %[src], %[src], 4 \n\t" \
- "addiu %[temp0], %[temp0], -1 \n\t" \
- "subu.qb %[temp3], %[temp2], %[temp1] \n\t" \
- "usw %[temp3], 0(%[dst]) \n\t" \
- "bnez %[temp0], 1b \n\t" \
- " addiu %[dst], %[dst], 4 \n\t" \
- ".endif \n\t" \
- "4: \n\t" \
- "beqz %[temp6], 3f \n\t" \
- " nop \n\t" \
- "2: \n\t" \
- "lbu %[temp2], 0(%[src]) \n\t" \
- ".if " #INVERSE " \n\t" \
- "lbu %[temp1], -1(%[dst]) \n\t" \
- "addu %[temp3], %[temp1], %[temp2] \n\t" \
- ".else \n\t" \
- "lbu %[temp1], -1(%[src]) \n\t" \
- "subu %[temp3], %[temp1], %[temp2] \n\t" \
- ".endif \n\t" \
- "addiu %[src], %[src], 1 \n\t" \
- "sb %[temp3], 0(%[dst]) \n\t" \
- "addiu %[temp6], %[temp6], -1 \n\t" \
- "bnez %[temp6], 2b \n\t" \
- " addiu %[dst], %[dst], 1 \n\t" \
- "3: \n\t" \
- ".set pop \n\t" \
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
- [temp6]"=&r"(temp6), [dst]"+&r"(pdst), [src]"+&r"(psrc) \
- : [length]"r"(ilength) \
- : "memory" \
- ); \
- } while (0)
-
-static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst,
- int length) {
- DO_PREDICT_LINE(src, dst, length, 0);
-}
-
-#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) do { \
- const uint8_t* psrc = (uint8_t*)(SRC); \
- const uint8_t* ppred = (uint8_t*)(PRED); \
- uint8_t* pdst = (uint8_t*)(DST); \
- const int ilength = (int)(LENGTH); \
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \
- __asm__ volatile ( \
- ".set push \n\t" \
- ".set noreorder \n\t" \
- "srl %[temp0], %[length], 0x3 \n\t" \
- "beqz %[temp0], 4f \n\t" \
- " andi %[temp7], %[length], 0x7 \n\t" \
- "1: \n\t" \
- "ulw %[temp1], 0(%[src]) \n\t" \
- "ulw %[temp2], 0(%[pred]) \n\t" \
- "ulw %[temp3], 4(%[src]) \n\t" \
- "ulw %[temp4], 4(%[pred]) \n\t" \
- "addiu %[src], %[src], 8 \n\t" \
- ".if " #INVERSE " \n\t" \
- "addu.qb %[temp5], %[temp1], %[temp2] \n\t" \
- "addu.qb %[temp6], %[temp3], %[temp4] \n\t" \
- ".else \n\t" \
- "subu.qb %[temp5], %[temp1], %[temp2] \n\t" \
- "subu.qb %[temp6], %[temp3], %[temp4] \n\t" \
- ".endif \n\t" \
- "addiu %[pred], %[pred], 8 \n\t" \
- "usw %[temp5], 0(%[dst]) \n\t" \
- "usw %[temp6], 4(%[dst]) \n\t" \
- "addiu %[temp0], %[temp0], -1 \n\t" \
- "bnez %[temp0], 1b \n\t" \
- " addiu %[dst], %[dst], 8 \n\t" \
- "4: \n\t" \
- "beqz %[temp7], 3f \n\t" \
- " nop \n\t" \
- "2: \n\t" \
- "lbu %[temp1], 0(%[src]) \n\t" \
- "lbu %[temp2], 0(%[pred]) \n\t" \
- "addiu %[src], %[src], 1 \n\t" \
- "addiu %[pred], %[pred], 1 \n\t" \
- ".if " #INVERSE " \n\t" \
- "addu %[temp3], %[temp1], %[temp2] \n\t" \
- ".else \n\t" \
- "subu %[temp3], %[temp1], %[temp2] \n\t" \
- ".endif \n\t" \
- "sb %[temp3], 0(%[dst]) \n\t" \
- "addiu %[temp7], %[temp7], -1 \n\t" \
- "bnez %[temp7], 2b \n\t" \
- " addiu %[dst], %[dst], 1 \n\t" \
- "3: \n\t" \
- ".set pop \n\t" \
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [pred]"+&r"(ppred), \
- [dst]"+&r"(pdst), [src]"+&r"(psrc) \
- : [length]"r"(ilength) \
- : "memory" \
- ); \
- } while (0)
-
-#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST) do { \
- int temp1, temp2, temp3; \
- __asm__ volatile ( \
- "lbu %[temp1], 0(%[src]) \n\t" \
- "lbu %[temp2], 0(%[pred]) \n\t" \
- "subu %[temp3], %[temp1], %[temp2] \n\t" \
- "sb %[temp3], 0(%[dst]) \n\t" \
- : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \
- : [pred]"r"((PRED)), [dst]"r"((DST)), [src]"r"((SRC)) \
- : "memory" \
- ); \
- } while (0)
-
-//------------------------------------------------------------------------------
-// Horizontal filter.
-
-#define FILTER_LINE_BY_LINE do { \
- while (row < last_row) { \
- PREDICT_LINE_ONE_PASS(in, preds - stride, out); \
- DO_PREDICT_LINE(in + 1, out + 1, width - 1, 0); \
- ++row; \
- preds += stride; \
- in += stride; \
- out += stride; \
- } \
- } while (0)
-
-static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows,
- uint8_t* out) {
- const uint8_t* preds;
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
- preds = in;
-
- if (row == 0) {
- // Leftmost pixel is the same as input for topmost scanline.
- out[0] = in[0];
- PredictLine(in + 1, out + 1, width - 1);
- row = 1;
- preds += stride;
- in += stride;
- out += stride;
- }
-
- // Filter line-by-line.
- FILTER_LINE_BY_LINE;
-}
-#undef FILTER_LINE_BY_LINE
-
-static void HorizontalFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoHorizontalFilter(data, width, height, stride, 0, height, filtered_data);
-}
-
-//------------------------------------------------------------------------------
-// Vertical filter.
-
-#define FILTER_LINE_BY_LINE do { \
- while (row < last_row) { \
- DO_PREDICT_LINE_VERTICAL(in, preds, out, width, 0); \
- ++row; \
- preds += stride; \
- in += stride; \
- out += stride; \
- } \
- } while (0)
-
-static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows, uint8_t* out) {
- const uint8_t* preds;
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
- preds = in;
-
- if (row == 0) {
- // Very first top-left pixel is copied.
- out[0] = in[0];
- // Rest of top scan-line is left-predicted.
- PredictLine(in + 1, out + 1, width - 1);
- row = 1;
- in += stride;
- out += stride;
- } else {
- // We are starting from in-between. Make sure 'preds' points to prev row.
- preds -= stride;
- }
-
- // Filter line-by-line.
- FILTER_LINE_BY_LINE;
-}
-#undef FILTER_LINE_BY_LINE
-
-static void VerticalFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoVerticalFilter(data, width, height, stride, 0, height, filtered_data);
-}
-
-//------------------------------------------------------------------------------
-// Gradient filter.
-
-static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
- int temp0;
- __asm__ volatile (
- "addu %[temp0], %[a], %[b] \n\t"
- "subu %[temp0], %[temp0], %[c] \n\t"
- "shll_s.w %[temp0], %[temp0], 23 \n\t"
- "precrqu_s.qb.ph %[temp0], %[temp0], $zero \n\t"
- "srl %[temp0], %[temp0], 24 \n\t"
- : [temp0]"=&r"(temp0)
- : [a]"r"(a),[b]"r"(b),[c]"r"(c)
- );
- return temp0;
-}
-
-#define FILTER_LINE_BY_LINE(PREDS, OPERATION) do { \
- while (row < last_row) { \
- int w; \
- PREDICT_LINE_ONE_PASS(in, PREDS - stride, out); \
- for (w = 1; w < width; ++w) { \
- const int pred = GradientPredictor(PREDS[w - 1], \
- PREDS[w - stride], \
- PREDS[w - stride - 1]); \
- out[w] = in[w] OPERATION pred; \
- } \
- ++row; \
- in += stride; \
- out += stride; \
- } \
- } while (0)
-
-static WEBP_INLINE void DoGradientFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows, uint8_t* out) {
- const uint8_t* preds;
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
- preds = in;
-
- // left prediction for top scan-line
- if (row == 0) {
- out[0] = in[0];
- PredictLine(in + 1, out + 1, width - 1);
- row = 1;
- preds += stride;
- in += stride;
- out += stride;
- }
-
- // Filter line-by-line.
- FILTER_LINE_BY_LINE(in, -);
-}
-#undef FILTER_LINE_BY_LINE
-
-static void GradientFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoGradientFilter(data, width, height, stride, 0, height, filtered_data);
-}
-
-//------------------------------------------------------------------------------
-
-static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- out[0] = in[0] + (prev == NULL ? 0 : prev[0]);
- DO_PREDICT_LINE(in + 1, out + 1, width - 1, 1);
-}
-
-static void VerticalUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- if (prev == NULL) {
- HorizontalUnfilter(NULL, in, out, width);
- } else {
- DO_PREDICT_LINE_VERTICAL(in, prev, out, width, 1);
- }
-}
-
-static void GradientUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- if (prev == NULL) {
- HorizontalUnfilter(NULL, in, out, width);
- } else {
- uint8_t top = prev[0], top_left = top, left = top;
- int i;
- for (i = 0; i < width; ++i) {
- top = prev[i]; // need to read this first, in case prev==dst
- left = in[i] + GradientPredictor(left, top, top_left);
- top_left = top;
- out[i] = left;
- }
- }
-}
-
-#undef DO_PREDICT_LINE_VERTICAL
-#undef PREDICT_LINE_ONE_PASS
-#undef DO_PREDICT_LINE
-#undef SANITY_CHECK
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8FiltersInitMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMIPSdspR2(void) {
- WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter;
- WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter;
- WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter;
-
- WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
- WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
- WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(VP8FiltersInitMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/filters_sse2.c b/drivers/webp/dsp/filters_sse2.c
deleted file mode 100644
index 67f77999e6..0000000000
--- a/drivers/webp/dsp/filters_sse2.c
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 variant of alpha filters
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-
-#include <assert.h>
-#include <emmintrin.h>
-#include <stdlib.h>
-#include <string.h>
-
-//------------------------------------------------------------------------------
-// Helpful macro.
-
-# define SANITY_CHECK(in, out) \
- assert(in != NULL); \
- assert(out != NULL); \
- assert(width > 0); \
- assert(height > 0); \
- assert(stride >= width); \
- assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \
- (void)height; // Silence unused warning.
-
-static void PredictLineTop(const uint8_t* src, const uint8_t* pred,
- uint8_t* dst, int length) {
- int i;
- const int max_pos = length & ~31;
- assert(length >= 0);
- for (i = 0; i < max_pos; i += 32) {
- const __m128i A0 = _mm_loadu_si128((const __m128i*)&src[i + 0]);
- const __m128i A1 = _mm_loadu_si128((const __m128i*)&src[i + 16]);
- const __m128i B0 = _mm_loadu_si128((const __m128i*)&pred[i + 0]);
- const __m128i B1 = _mm_loadu_si128((const __m128i*)&pred[i + 16]);
- const __m128i C0 = _mm_sub_epi8(A0, B0);
- const __m128i C1 = _mm_sub_epi8(A1, B1);
- _mm_storeu_si128((__m128i*)&dst[i + 0], C0);
- _mm_storeu_si128((__m128i*)&dst[i + 16], C1);
- }
- for (; i < length; ++i) dst[i] = src[i] - pred[i];
-}
-
-// Special case for left-based prediction (when preds==dst-1 or preds==src-1).
-static void PredictLineLeft(const uint8_t* src, uint8_t* dst, int length) {
- int i;
- const int max_pos = length & ~31;
- assert(length >= 0);
- for (i = 0; i < max_pos; i += 32) {
- const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + i + 0 ));
- const __m128i B0 = _mm_loadu_si128((const __m128i*)(src + i + 0 - 1));
- const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + i + 16 ));
- const __m128i B1 = _mm_loadu_si128((const __m128i*)(src + i + 16 - 1));
- const __m128i C0 = _mm_sub_epi8(A0, B0);
- const __m128i C1 = _mm_sub_epi8(A1, B1);
- _mm_storeu_si128((__m128i*)(dst + i + 0), C0);
- _mm_storeu_si128((__m128i*)(dst + i + 16), C1);
- }
- for (; i < length; ++i) dst[i] = src[i] - src[i - 1];
-}
-
-//------------------------------------------------------------------------------
-// Horizontal filter.
-
-static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows,
- uint8_t* out) {
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
-
- if (row == 0) {
- // Leftmost pixel is the same as input for topmost scanline.
- out[0] = in[0];
- PredictLineLeft(in + 1, out + 1, width - 1);
- row = 1;
- in += stride;
- out += stride;
- }
-
- // Filter line-by-line.
- while (row < last_row) {
- // Leftmost pixel is predicted from above.
- out[0] = in[0] - in[-stride];
- PredictLineLeft(in + 1, out + 1, width - 1);
- ++row;
- in += stride;
- out += stride;
- }
-}
-
-//------------------------------------------------------------------------------
-// Vertical filter.
-
-static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows, uint8_t* out) {
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
-
- if (row == 0) {
- // Very first top-left pixel is copied.
- out[0] = in[0];
- // Rest of top scan-line is left-predicted.
- PredictLineLeft(in + 1, out + 1, width - 1);
- row = 1;
- in += stride;
- out += stride;
- }
-
- // Filter line-by-line.
- while (row < last_row) {
- PredictLineTop(in, in - stride, out, width);
- ++row;
- in += stride;
- out += stride;
- }
-}
-
-//------------------------------------------------------------------------------
-// Gradient filter.
-
-static WEBP_INLINE int GradientPredictorC(uint8_t a, uint8_t b, uint8_t c) {
- const int g = a + b - c;
- return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
-}
-
-static void GradientPredictDirect(const uint8_t* const row,
- const uint8_t* const top,
- uint8_t* const out, int length) {
- const int max_pos = length & ~7;
- int i;
- const __m128i zero = _mm_setzero_si128();
- for (i = 0; i < max_pos; i += 8) {
- const __m128i A0 = _mm_loadl_epi64((const __m128i*)&row[i - 1]);
- const __m128i B0 = _mm_loadl_epi64((const __m128i*)&top[i]);
- const __m128i C0 = _mm_loadl_epi64((const __m128i*)&top[i - 1]);
- const __m128i D = _mm_loadl_epi64((const __m128i*)&row[i]);
- const __m128i A1 = _mm_unpacklo_epi8(A0, zero);
- const __m128i B1 = _mm_unpacklo_epi8(B0, zero);
- const __m128i C1 = _mm_unpacklo_epi8(C0, zero);
- const __m128i E = _mm_add_epi16(A1, B1);
- const __m128i F = _mm_sub_epi16(E, C1);
- const __m128i G = _mm_packus_epi16(F, zero);
- const __m128i H = _mm_sub_epi8(D, G);
- _mm_storel_epi64((__m128i*)(out + i), H);
- }
- for (; i < length; ++i) {
- out[i] = row[i] - GradientPredictorC(row[i - 1], top[i], top[i - 1]);
- }
-}
-
-static WEBP_INLINE void DoGradientFilter(const uint8_t* in,
- int width, int height, int stride,
- int row, int num_rows,
- uint8_t* out) {
- const size_t start_offset = row * stride;
- const int last_row = row + num_rows;
- SANITY_CHECK(in, out);
- in += start_offset;
- out += start_offset;
-
- // left prediction for top scan-line
- if (row == 0) {
- out[0] = in[0];
- PredictLineLeft(in + 1, out + 1, width - 1);
- row = 1;
- in += stride;
- out += stride;
- }
-
- // Filter line-by-line.
- while (row < last_row) {
- out[0] = in[0] - in[-stride];
- GradientPredictDirect(in + 1, in + 1 - stride, out + 1, width - 1);
- ++row;
- in += stride;
- out += stride;
- }
-}
-
-#undef SANITY_CHECK
-
-//------------------------------------------------------------------------------
-
-static void HorizontalFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoHorizontalFilter(data, width, height, stride, 0, height, filtered_data);
-}
-
-static void VerticalFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoVerticalFilter(data, width, height, stride, 0, height, filtered_data);
-}
-
-static void GradientFilter(const uint8_t* data, int width, int height,
- int stride, uint8_t* filtered_data) {
- DoGradientFilter(data, width, height, stride, 0, height, filtered_data);
-}
-
-//------------------------------------------------------------------------------
-// Inverse transforms
-
-static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- int i;
- __m128i last;
- out[0] = in[0] + (prev == NULL ? 0 : prev[0]);
- if (width <= 1) return;
- last = _mm_set_epi32(0, 0, 0, out[0]);
- for (i = 1; i + 8 <= width; i += 8) {
- const __m128i A0 = _mm_loadl_epi64((const __m128i*)(in + i));
- const __m128i A1 = _mm_add_epi8(A0, last);
- const __m128i A2 = _mm_slli_si128(A1, 1);
- const __m128i A3 = _mm_add_epi8(A1, A2);
- const __m128i A4 = _mm_slli_si128(A3, 2);
- const __m128i A5 = _mm_add_epi8(A3, A4);
- const __m128i A6 = _mm_slli_si128(A5, 4);
- const __m128i A7 = _mm_add_epi8(A5, A6);
- _mm_storel_epi64((__m128i*)(out + i), A7);
- last = _mm_srli_epi64(A7, 56);
- }
- for (; i < width; ++i) out[i] = in[i] + out[i - 1];
-}
-
-static void VerticalUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- if (prev == NULL) {
- HorizontalUnfilter(NULL, in, out, width);
- } else {
- int i;
- const int max_pos = width & ~31;
- assert(width >= 0);
- for (i = 0; i < max_pos; i += 32) {
- const __m128i A0 = _mm_loadu_si128((const __m128i*)&in[i + 0]);
- const __m128i A1 = _mm_loadu_si128((const __m128i*)&in[i + 16]);
- const __m128i B0 = _mm_loadu_si128((const __m128i*)&prev[i + 0]);
- const __m128i B1 = _mm_loadu_si128((const __m128i*)&prev[i + 16]);
- const __m128i C0 = _mm_add_epi8(A0, B0);
- const __m128i C1 = _mm_add_epi8(A1, B1);
- _mm_storeu_si128((__m128i*)&out[i + 0], C0);
- _mm_storeu_si128((__m128i*)&out[i + 16], C1);
- }
- for (; i < width; ++i) out[i] = in[i] + prev[i];
- }
-}
-
-static void GradientPredictInverse(const uint8_t* const in,
- const uint8_t* const top,
- uint8_t* const row, int length) {
- if (length > 0) {
- int i;
- const int max_pos = length & ~7;
- const __m128i zero = _mm_setzero_si128();
- __m128i A = _mm_set_epi32(0, 0, 0, row[-1]); // left sample
- for (i = 0; i < max_pos; i += 8) {
- const __m128i tmp0 = _mm_loadl_epi64((const __m128i*)&top[i]);
- const __m128i tmp1 = _mm_loadl_epi64((const __m128i*)&top[i - 1]);
- const __m128i B = _mm_unpacklo_epi8(tmp0, zero);
- const __m128i C = _mm_unpacklo_epi8(tmp1, zero);
- const __m128i D = _mm_loadl_epi64((const __m128i*)&in[i]); // base input
- const __m128i E = _mm_sub_epi16(B, C); // unclipped gradient basis B - C
- __m128i out = zero; // accumulator for output
- __m128i mask_hi = _mm_set_epi32(0, 0, 0, 0xff);
- int k = 8;
- while (1) {
- const __m128i tmp3 = _mm_add_epi16(A, E); // delta = A + B - C
- const __m128i tmp4 = _mm_packus_epi16(tmp3, zero); // saturate delta
- const __m128i tmp5 = _mm_add_epi8(tmp4, D); // add to in[]
- A = _mm_and_si128(tmp5, mask_hi); // 1-complement clip
- out = _mm_or_si128(out, A); // accumulate output
- if (--k == 0) break;
- A = _mm_slli_si128(A, 1); // rotate left sample
- mask_hi = _mm_slli_si128(mask_hi, 1); // rotate mask
- A = _mm_unpacklo_epi8(A, zero); // convert 8b->16b
- }
- A = _mm_srli_si128(A, 7); // prepare left sample for next iteration
- _mm_storel_epi64((__m128i*)&row[i], out);
- }
- for (; i < length; ++i) {
- row[i] = in[i] + GradientPredictorC(row[i - 1], top[i], top[i - 1]);
- }
- }
-}
-
-static void GradientUnfilter(const uint8_t* prev, const uint8_t* in,
- uint8_t* out, int width) {
- if (prev == NULL) {
- HorizontalUnfilter(NULL, in, out, width);
- } else {
- out[0] = in[0] + prev[0]; // predict from above
- GradientPredictInverse(in + 1, prev + 1, out + 1, width - 1);
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8FiltersInitSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitSSE2(void) {
- WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter;
- WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter;
- WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter;
-
- WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
- WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
- WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(VP8FiltersInitSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/lossless.c b/drivers/webp/dsp/lossless.c
deleted file mode 100644
index af913efccb..0000000000
--- a/drivers/webp/dsp/lossless.c
+++ /dev/null
@@ -1,633 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Image transforms and color space conversion methods for lossless decoder.
-//
-// Authors: Vikas Arora (vikaas.arora@gmail.com)
-// Jyrki Alakuijala (jyrki@google.com)
-// Urvang Joshi (urvang@google.com)
-
-#include "./dsp.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include "../dec/vp8li.h"
-#include "../utils/endian_inl.h"
-#include "./lossless.h"
-
-#define MAX_DIFF_COST (1e30f)
-
-//------------------------------------------------------------------------------
-// Image transforms.
-
-// In-place sum of each component with mod 256.
-static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
- *a = VP8LAddPixels(*a, b);
-}
-
-static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
- return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1);
-}
-
-static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
- return Average2(Average2(a0, a2), a1);
-}
-
-static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
- uint32_t a2, uint32_t a3) {
- return Average2(Average2(a0, a1), Average2(a2, a3));
-}
-
-static WEBP_INLINE uint32_t Clip255(uint32_t a) {
- if (a < 256) {
- return a;
- }
- // return 0, when a is a negative integer.
- // return 255, when a is positive.
- return ~a >> 24;
-}
-
-static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) {
- return Clip255(a + b - c);
-}
-
-static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
- uint32_t c2) {
- const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
- const int r = AddSubtractComponentFull((c0 >> 16) & 0xff,
- (c1 >> 16) & 0xff,
- (c2 >> 16) & 0xff);
- const int g = AddSubtractComponentFull((c0 >> 8) & 0xff,
- (c1 >> 8) & 0xff,
- (c2 >> 8) & 0xff);
- const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
- return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
-}
-
-static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) {
- return Clip255(a + (a - b) / 2);
-}
-
-static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
- uint32_t c2) {
- const uint32_t ave = Average2(c0, c1);
- const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24);
- const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff);
- const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff);
- const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff);
- return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
-}
-
-// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined.
-#if defined(__arm__) && LOCAL_GCC_VERSION == 0x409
-# define LOCAL_INLINE __attribute__ ((noinline))
-#else
-# define LOCAL_INLINE WEBP_INLINE
-#endif
-
-static LOCAL_INLINE int Sub3(int a, int b, int c) {
- const int pb = b - c;
- const int pa = a - c;
- return abs(pb) - abs(pa);
-}
-
-#undef LOCAL_INLINE
-
-static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
- const int pa_minus_pb =
- Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
- Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
- Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) +
- Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff);
- return (pa_minus_pb <= 0) ? a : b;
-}
-
-//------------------------------------------------------------------------------
-// Predictors
-
-static uint32_t Predictor0(uint32_t left, const uint32_t* const top) {
- (void)top;
- (void)left;
- return ARGB_BLACK;
-}
-static uint32_t Predictor1(uint32_t left, const uint32_t* const top) {
- (void)top;
- return left;
-}
-static uint32_t Predictor2(uint32_t left, const uint32_t* const top) {
- (void)left;
- return top[0];
-}
-static uint32_t Predictor3(uint32_t left, const uint32_t* const top) {
- (void)left;
- return top[1];
-}
-static uint32_t Predictor4(uint32_t left, const uint32_t* const top) {
- (void)left;
- return top[-1];
-}
-static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average3(left, top[0], top[1]);
- return pred;
-}
-static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average2(left, top[-1]);
- return pred;
-}
-static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average2(left, top[0]);
- return pred;
-}
-static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average2(top[-1], top[0]);
- (void)left;
- return pred;
-}
-static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average2(top[0], top[1]);
- (void)left;
- return pred;
-}
-static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
- return pred;
-}
-static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Select(top[0], left, top[-1]);
- return pred;
-}
-static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
- return pred;
-}
-static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
- return pred;
-}
-
-//------------------------------------------------------------------------------
-
-// Inverse prediction.
-static void PredictorInverseTransform(const VP8LTransform* const transform,
- int y_start, int y_end, uint32_t* data) {
- const int width = transform->xsize_;
- if (y_start == 0) { // First Row follows the L (mode=1) mode.
- int x;
- const uint32_t pred0 = Predictor0(data[-1], NULL);
- AddPixelsEq(data, pred0);
- for (x = 1; x < width; ++x) {
- const uint32_t pred1 = Predictor1(data[x - 1], NULL);
- AddPixelsEq(data + x, pred1);
- }
- data += width;
- ++y_start;
- }
-
- {
- int y = y_start;
- const int tile_width = 1 << transform->bits_;
- const int mask = tile_width - 1;
- const int safe_width = width & ~mask;
- const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
- const uint32_t* pred_mode_base =
- transform->data_ + (y >> transform->bits_) * tiles_per_row;
-
- while (y < y_end) {
- const uint32_t pred2 = Predictor2(data[-1], data - width);
- const uint32_t* pred_mode_src = pred_mode_base;
- VP8LPredictorFunc pred_func;
- int x = 1;
- int t = 1;
- // First pixel follows the T (mode=2) mode.
- AddPixelsEq(data, pred2);
- // .. the rest:
- while (x < safe_width) {
- pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf];
- for (; t < tile_width; ++t, ++x) {
- const uint32_t pred = pred_func(data[x - 1], data + x - width);
- AddPixelsEq(data + x, pred);
- }
- t = 0;
- }
- if (x < width) {
- pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf];
- for (; x < width; ++x) {
- const uint32_t pred = pred_func(data[x - 1], data + x - width);
- AddPixelsEq(data + x, pred);
- }
- }
- data += width;
- ++y;
- if ((y & mask) == 0) { // Use the same mask, since tiles are squares.
- pred_mode_base += tiles_per_row;
- }
- }
- }
-}
-
-// Add green to blue and red channels (i.e. perform the inverse transform of
-// 'subtract green').
-void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) {
- int i;
- for (i = 0; i < num_pixels; ++i) {
- const uint32_t argb = data[i];
- const uint32_t green = ((argb >> 8) & 0xff);
- uint32_t red_blue = (argb & 0x00ff00ffu);
- red_blue += (green << 16) | green;
- red_blue &= 0x00ff00ffu;
- data[i] = (argb & 0xff00ff00u) | red_blue;
- }
-}
-
-static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
- int8_t color) {
- return (uint32_t)((int)(color_pred) * color) >> 5;
-}
-
-static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
- VP8LMultipliers* const m) {
- m->green_to_red_ = (color_code >> 0) & 0xff;
- m->green_to_blue_ = (color_code >> 8) & 0xff;
- m->red_to_blue_ = (color_code >> 16) & 0xff;
-}
-
-void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data,
- int num_pixels) {
- int i;
- for (i = 0; i < num_pixels; ++i) {
- const uint32_t argb = data[i];
- const uint32_t green = argb >> 8;
- const uint32_t red = argb >> 16;
- uint32_t new_red = red;
- uint32_t new_blue = argb;
- new_red += ColorTransformDelta(m->green_to_red_, green);
- new_red &= 0xff;
- new_blue += ColorTransformDelta(m->green_to_blue_, green);
- new_blue += ColorTransformDelta(m->red_to_blue_, new_red);
- new_blue &= 0xff;
- data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
- }
-}
-
-// Color space inverse transform.
-static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
- int y_start, int y_end, uint32_t* data) {
- const int width = transform->xsize_;
- const int tile_width = 1 << transform->bits_;
- const int mask = tile_width - 1;
- const int safe_width = width & ~mask;
- const int remaining_width = width - safe_width;
- const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
- int y = y_start;
- const uint32_t* pred_row =
- transform->data_ + (y >> transform->bits_) * tiles_per_row;
-
- while (y < y_end) {
- const uint32_t* pred = pred_row;
- VP8LMultipliers m = { 0, 0, 0 };
- const uint32_t* const data_safe_end = data + safe_width;
- const uint32_t* const data_end = data + width;
- while (data < data_safe_end) {
- ColorCodeToMultipliers(*pred++, &m);
- VP8LTransformColorInverse(&m, data, tile_width);
- data += tile_width;
- }
- if (data < data_end) { // Left-overs using C-version.
- ColorCodeToMultipliers(*pred++, &m);
- VP8LTransformColorInverse(&m, data, remaining_width);
- data += remaining_width;
- }
- ++y;
- if ((y & mask) == 0) pred_row += tiles_per_row;
- }
-}
-
-// Separate out pixels packed together using pixel-bundling.
-// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t).
-#define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \
- GET_INDEX, GET_VALUE) \
-static void F_NAME(const TYPE* src, const uint32_t* const color_map, \
- TYPE* dst, int y_start, int y_end, int width) { \
- int y; \
- for (y = y_start; y < y_end; ++y) { \
- int x; \
- for (x = 0; x < width; ++x) { \
- *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \
- } \
- } \
-} \
-STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \
- int y_start, int y_end, const TYPE* src, \
- TYPE* dst) { \
- int y; \
- const int bits_per_pixel = 8 >> transform->bits_; \
- const int width = transform->xsize_; \
- const uint32_t* const color_map = transform->data_; \
- if (bits_per_pixel < 8) { \
- const int pixels_per_byte = 1 << transform->bits_; \
- const int count_mask = pixels_per_byte - 1; \
- const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \
- for (y = y_start; y < y_end; ++y) { \
- uint32_t packed_pixels = 0; \
- int x; \
- for (x = 0; x < width; ++x) { \
- /* We need to load fresh 'packed_pixels' once every */ \
- /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \
- /* is a power of 2, so can just use a mask for that, instead of */ \
- /* decrementing a counter. */ \
- if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \
- *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \
- packed_pixels >>= bits_per_pixel; \
- } \
- } \
- } else { \
- VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \
- } \
-}
-
-COLOR_INDEX_INVERSE(ColorIndexInverseTransform, MapARGB, static, uint32_t, 32b,
- VP8GetARGBIndex, VP8GetARGBValue)
-COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha, , uint8_t,
- 8b, VP8GetAlphaIndex, VP8GetAlphaValue)
-
-#undef COLOR_INDEX_INVERSE
-
-void VP8LInverseTransform(const VP8LTransform* const transform,
- int row_start, int row_end,
- const uint32_t* const in, uint32_t* const out) {
- const int width = transform->xsize_;
- assert(row_start < row_end);
- assert(row_end <= transform->ysize_);
- switch (transform->type_) {
- case SUBTRACT_GREEN:
- VP8LAddGreenToBlueAndRed(out, (row_end - row_start) * width);
- break;
- case PREDICTOR_TRANSFORM:
- PredictorInverseTransform(transform, row_start, row_end, out);
- if (row_end != transform->ysize_) {
- // The last predicted row in this iteration will be the top-pred row
- // for the first row in next iteration.
- memcpy(out - width, out + (row_end - row_start - 1) * width,
- width * sizeof(*out));
- }
- break;
- case CROSS_COLOR_TRANSFORM:
- ColorSpaceInverseTransform(transform, row_start, row_end, out);
- break;
- case COLOR_INDEXING_TRANSFORM:
- if (in == out && transform->bits_ > 0) {
- // Move packed pixels to the end of unpacked region, so that unpacking
- // can occur seamlessly.
- // Also, note that this is the only transform that applies on
- // the effective width of VP8LSubSampleSize(xsize_, bits_). All other
- // transforms work on effective width of xsize_.
- const int out_stride = (row_end - row_start) * width;
- const int in_stride = (row_end - row_start) *
- VP8LSubSampleSize(transform->xsize_, transform->bits_);
- uint32_t* const src = out + out_stride - in_stride;
- memmove(src, out, in_stride * sizeof(*src));
- ColorIndexInverseTransform(transform, row_start, row_end, src, out);
- } else {
- ColorIndexInverseTransform(transform, row_start, row_end, in, out);
- }
- break;
- }
-}
-
-//------------------------------------------------------------------------------
-// Color space conversion.
-
-static int is_big_endian(void) {
- static const union {
- uint16_t w;
- uint8_t b[2];
- } tmp = { 1 };
- return (tmp.b[0] != 1);
-}
-
-void VP8LConvertBGRAToRGB_C(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const src_end = src + num_pixels;
- while (src < src_end) {
- const uint32_t argb = *src++;
- *dst++ = (argb >> 16) & 0xff;
- *dst++ = (argb >> 8) & 0xff;
- *dst++ = (argb >> 0) & 0xff;
- }
-}
-
-void VP8LConvertBGRAToRGBA_C(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const src_end = src + num_pixels;
- while (src < src_end) {
- const uint32_t argb = *src++;
- *dst++ = (argb >> 16) & 0xff;
- *dst++ = (argb >> 8) & 0xff;
- *dst++ = (argb >> 0) & 0xff;
- *dst++ = (argb >> 24) & 0xff;
- }
-}
-
-void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const src_end = src + num_pixels;
- while (src < src_end) {
- const uint32_t argb = *src++;
- const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf);
- const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf);
-#ifdef WEBP_SWAP_16BIT_CSP
- *dst++ = ba;
- *dst++ = rg;
-#else
- *dst++ = rg;
- *dst++ = ba;
-#endif
- }
-}
-
-void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const src_end = src + num_pixels;
- while (src < src_end) {
- const uint32_t argb = *src++;
- const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7);
- const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f);
-#ifdef WEBP_SWAP_16BIT_CSP
- *dst++ = gb;
- *dst++ = rg;
-#else
- *dst++ = rg;
- *dst++ = gb;
-#endif
- }
-}
-
-void VP8LConvertBGRAToBGR_C(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const src_end = src + num_pixels;
- while (src < src_end) {
- const uint32_t argb = *src++;
- *dst++ = (argb >> 0) & 0xff;
- *dst++ = (argb >> 8) & 0xff;
- *dst++ = (argb >> 16) & 0xff;
- }
-}
-
-static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst,
- int swap_on_big_endian) {
- if (is_big_endian() == swap_on_big_endian) {
- const uint32_t* const src_end = src + num_pixels;
- while (src < src_end) {
- const uint32_t argb = *src++;
-
-#if !defined(WORDS_BIGENDIAN)
-#if !defined(WEBP_REFERENCE_IMPLEMENTATION)
- WebPUint32ToMem(dst, BSwap32(argb));
-#else // WEBP_REFERENCE_IMPLEMENTATION
- dst[0] = (argb >> 24) & 0xff;
- dst[1] = (argb >> 16) & 0xff;
- dst[2] = (argb >> 8) & 0xff;
- dst[3] = (argb >> 0) & 0xff;
-#endif
-#else // WORDS_BIGENDIAN
- dst[0] = (argb >> 0) & 0xff;
- dst[1] = (argb >> 8) & 0xff;
- dst[2] = (argb >> 16) & 0xff;
- dst[3] = (argb >> 24) & 0xff;
-#endif
- dst += sizeof(argb);
- }
- } else {
- memcpy(dst, src, num_pixels * sizeof(*src));
- }
-}
-
-void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
- WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) {
- switch (out_colorspace) {
- case MODE_RGB:
- VP8LConvertBGRAToRGB(in_data, num_pixels, rgba);
- break;
- case MODE_RGBA:
- VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba);
- break;
- case MODE_rgbA:
- VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba);
- WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
- break;
- case MODE_BGR:
- VP8LConvertBGRAToBGR(in_data, num_pixels, rgba);
- break;
- case MODE_BGRA:
- CopyOrSwap(in_data, num_pixels, rgba, 1);
- break;
- case MODE_bgrA:
- CopyOrSwap(in_data, num_pixels, rgba, 1);
- WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
- break;
- case MODE_ARGB:
- CopyOrSwap(in_data, num_pixels, rgba, 0);
- break;
- case MODE_Argb:
- CopyOrSwap(in_data, num_pixels, rgba, 0);
- WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0);
- break;
- case MODE_RGBA_4444:
- VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
- break;
- case MODE_rgbA_4444:
- VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
- WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0);
- break;
- case MODE_RGB_565:
- VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba);
- break;
- default:
- assert(0); // Code flow should not reach here.
- }
-}
-
-//------------------------------------------------------------------------------
-
-VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed;
-VP8LPredictorFunc VP8LPredictors[16];
-
-VP8LTransformColorFunc VP8LTransformColorInverse;
-
-VP8LConvertFunc VP8LConvertBGRAToRGB;
-VP8LConvertFunc VP8LConvertBGRAToRGBA;
-VP8LConvertFunc VP8LConvertBGRAToRGBA4444;
-VP8LConvertFunc VP8LConvertBGRAToRGB565;
-VP8LConvertFunc VP8LConvertBGRAToBGR;
-
-VP8LMapARGBFunc VP8LMapColor32b;
-VP8LMapAlphaFunc VP8LMapColor8b;
-
-extern void VP8LDspInitSSE2(void);
-extern void VP8LDspInitNEON(void);
-extern void VP8LDspInitMIPSdspR2(void);
-
-static volatile VP8CPUInfo lossless_last_cpuinfo_used =
- (VP8CPUInfo)&lossless_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) {
- if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- VP8LPredictors[0] = Predictor0;
- VP8LPredictors[1] = Predictor1;
- VP8LPredictors[2] = Predictor2;
- VP8LPredictors[3] = Predictor3;
- VP8LPredictors[4] = Predictor4;
- VP8LPredictors[5] = Predictor5;
- VP8LPredictors[6] = Predictor6;
- VP8LPredictors[7] = Predictor7;
- VP8LPredictors[8] = Predictor8;
- VP8LPredictors[9] = Predictor9;
- VP8LPredictors[10] = Predictor10;
- VP8LPredictors[11] = Predictor11;
- VP8LPredictors[12] = Predictor12;
- VP8LPredictors[13] = Predictor13;
- VP8LPredictors[14] = Predictor0; // <- padding security sentinels
- VP8LPredictors[15] = Predictor0;
-
- VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C;
-
- VP8LTransformColorInverse = VP8LTransformColorInverse_C;
-
- VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C;
- VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C;
- VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C;
- VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C;
- VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C;
-
- VP8LMapColor32b = MapARGB;
- VP8LMapColor8b = MapAlpha;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- VP8LDspInitSSE2();
- }
-#endif
-#if defined(WEBP_USE_NEON)
- if (VP8GetCPUInfo(kNEON)) {
- VP8LDspInitNEON();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- VP8LDspInitMIPSdspR2();
- }
-#endif
- }
- lossless_last_cpuinfo_used = VP8GetCPUInfo;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dsp/lossless.h b/drivers/webp/dsp/lossless.h
deleted file mode 100644
index 7709b4fe85..0000000000
--- a/drivers/webp/dsp/lossless.h
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Image transforms and color space conversion methods for lossless decoder.
-//
-// Authors: Vikas Arora (vikaas.arora@gmail.com)
-// Jyrki Alakuijala (jyrki@google.com)
-
-#ifndef WEBP_DSP_LOSSLESS_H_
-#define WEBP_DSP_LOSSLESS_H_
-
-#include "webp/types.h"
-#include "webp/decode.h"
-
-#include "../enc/histogram.h"
-#include "../utils/utils.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
-#include "../enc/delta_palettization.h"
-#endif // WEBP_EXPERIMENTAL_FEATURES
-
-//------------------------------------------------------------------------------
-// Decoding
-
-typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top);
-extern VP8LPredictorFunc VP8LPredictors[16];
-
-typedef void (*VP8LProcessBlueAndRedFunc)(uint32_t* argb_data, int num_pixels);
-extern VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed;
-
-typedef struct {
- // Note: the members are uint8_t, so that any negative values are
- // automatically converted to "mod 256" values.
- uint8_t green_to_red_;
- uint8_t green_to_blue_;
- uint8_t red_to_blue_;
-} VP8LMultipliers;
-typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m,
- uint32_t* argb_data, int num_pixels);
-extern VP8LTransformColorFunc VP8LTransformColorInverse;
-
-struct VP8LTransform; // Defined in dec/vp8li.h.
-
-// Performs inverse transform of data given transform information, start and end
-// rows. Transform will be applied to rows [row_start, row_end[.
-// The *in and *out pointers refer to source and destination data respectively
-// corresponding to the intermediate row (row_start).
-void VP8LInverseTransform(const struct VP8LTransform* const transform,
- int row_start, int row_end,
- const uint32_t* const in, uint32_t* const out);
-
-// Color space conversion.
-typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels,
- uint8_t* dst);
-extern VP8LConvertFunc VP8LConvertBGRAToRGB;
-extern VP8LConvertFunc VP8LConvertBGRAToRGBA;
-extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444;
-extern VP8LConvertFunc VP8LConvertBGRAToRGB565;
-extern VP8LConvertFunc VP8LConvertBGRAToBGR;
-
-// Converts from BGRA to other color spaces.
-void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
- WEBP_CSP_MODE out_colorspace, uint8_t* const rgba);
-
-// color mapping related functions.
-static WEBP_INLINE uint32_t VP8GetARGBIndex(uint32_t idx) {
- return (idx >> 8) & 0xff;
-}
-
-static WEBP_INLINE uint8_t VP8GetAlphaIndex(uint8_t idx) {
- return idx;
-}
-
-static WEBP_INLINE uint32_t VP8GetARGBValue(uint32_t val) {
- return val;
-}
-
-static WEBP_INLINE uint8_t VP8GetAlphaValue(uint32_t val) {
- return (val >> 8) & 0xff;
-}
-
-typedef void (*VP8LMapARGBFunc)(const uint32_t* src,
- const uint32_t* const color_map,
- uint32_t* dst, int y_start,
- int y_end, int width);
-typedef void (*VP8LMapAlphaFunc)(const uint8_t* src,
- const uint32_t* const color_map,
- uint8_t* dst, int y_start,
- int y_end, int width);
-
-extern VP8LMapARGBFunc VP8LMapColor32b;
-extern VP8LMapAlphaFunc VP8LMapColor8b;
-
-// Similar to the static method ColorIndexInverseTransform() that is part of
-// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than
-// uint32_t) arguments for 'src' and 'dst'.
-void VP8LColorIndexInverseTransformAlpha(
- const struct VP8LTransform* const transform, int y_start, int y_end,
- const uint8_t* src, uint8_t* dst);
-
-// Expose some C-only fallback functions
-void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
- uint32_t* data, int num_pixels);
-
-void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst);
-void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst);
-void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
- int num_pixels, uint8_t* dst);
-void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
- int num_pixels, uint8_t* dst);
-void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst);
-void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels);
-
-// Must be called before calling any of the above methods.
-void VP8LDspInit(void);
-
-//------------------------------------------------------------------------------
-// Encoding
-
-extern VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
-extern VP8LTransformColorFunc VP8LTransformColor;
-typedef void (*VP8LCollectColorBlueTransformsFunc)(
- const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_blue, int red_to_blue, int histo[]);
-extern VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms;
-
-typedef void (*VP8LCollectColorRedTransformsFunc)(
- const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_red, int histo[]);
-extern VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms;
-
-// Expose some C-only fallback functions
-void VP8LTransformColor_C(const VP8LMultipliers* const m,
- uint32_t* data, int num_pixels);
-void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels);
-void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_red, int histo[]);
-void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_blue, int red_to_blue,
- int histo[]);
-
-//------------------------------------------------------------------------------
-// Image transforms.
-
-void VP8LResidualImage(int width, int height, int bits, int low_effort,
- uint32_t* const argb, uint32_t* const argb_scratch,
- uint32_t* const image, int near_lossless, int exact,
- int used_subtract_green);
-
-void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
- uint32_t* const argb, uint32_t* image);
-
-//------------------------------------------------------------------------------
-// Misc methods.
-
-// Computes sampled size of 'size' when sampling using 'sampling bits'.
-static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size,
- uint32_t sampling_bits) {
- return (size + (1 << sampling_bits) - 1) >> sampling_bits;
-}
-
-// Converts near lossless quality into max number of bits shaved off.
-static WEBP_INLINE int VP8LNearLosslessBits(int near_lossless_quality) {
- // 100 -> 0
- // 80..99 -> 1
- // 60..79 -> 2
- // 40..59 -> 3
- // 20..39 -> 4
- // 0..19 -> 5
- return 5 - near_lossless_quality / 20;
-}
-
-// -----------------------------------------------------------------------------
-// Faster logarithm for integers. Small values use a look-up table.
-
-// The threshold till approximate version of log_2 can be used.
-// Practically, we can get rid of the call to log() as the two values match to
-// very high degree (the ratio of these two is 0.99999x).
-// Keeping a high threshold for now.
-#define APPROX_LOG_WITH_CORRECTION_MAX 65536
-#define APPROX_LOG_MAX 4096
-#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
-#define LOG_LOOKUP_IDX_MAX 256
-extern const float kLog2Table[LOG_LOOKUP_IDX_MAX];
-extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX];
-typedef float (*VP8LFastLog2SlowFunc)(uint32_t v);
-
-extern VP8LFastLog2SlowFunc VP8LFastLog2Slow;
-extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow;
-
-static WEBP_INLINE float VP8LFastLog2(uint32_t v) {
- return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v);
-}
-// Fast calculation of v * log2(v) for integer input.
-static WEBP_INLINE float VP8LFastSLog2(uint32_t v) {
- return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v);
-}
-
-// -----------------------------------------------------------------------------
-// Huffman-cost related functions.
-
-typedef double (*VP8LCostFunc)(const uint32_t* population, int length);
-typedef double (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y,
- int length);
-typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256],
- const int Y[256]);
-
-extern VP8LCostFunc VP8LExtraCost;
-extern VP8LCostCombinedFunc VP8LExtraCostCombined;
-extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
-
-typedef struct { // small struct to hold counters
- int counts[2]; // index: 0=zero steak, 1=non-zero streak
- int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
-} VP8LStreaks;
-
-typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X,
- const uint32_t* Y, int length);
-
-extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount;
-
-typedef struct { // small struct to hold bit entropy results
- double entropy; // entropy
- uint32_t sum; // sum of the population
- int nonzeros; // number of non-zero elements in the population
- uint32_t max_val; // maximum value in the population
- uint32_t nonzero_code; // index of the last non-zero in the population
-} VP8LBitEntropy;
-
-void VP8LBitEntropyInit(VP8LBitEntropy* const entropy);
-
-// Get the combined symbol bit entropy and Huffman cost stats for the
-// distributions 'X' and 'Y'. Those results can then be refined according to
-// codec specific heuristics.
-void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X,
- const uint32_t* const Y, int length,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats);
-// Get the entropy for the distribution 'X'.
-void VP8LGetEntropyUnrefined(const uint32_t* const X, int length,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats);
-
-void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n,
- VP8LBitEntropy* const entropy);
-
-typedef void (*GetEntropyUnrefinedHelperFunc)(uint32_t val, int i,
- uint32_t* const val_prev,
- int* const i_prev,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats);
-// Internal function used by VP8LGet*EntropyUnrefined.
-extern GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper;
-
-typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out);
-extern VP8LHistogramAddFunc VP8LHistogramAdd;
-
-// -----------------------------------------------------------------------------
-// PrefixEncode()
-
-typedef int (*VP8LVectorMismatchFunc)(const uint32_t* const array1,
- const uint32_t* const array2, int length);
-// Returns the first index where array1 and array2 are different.
-extern VP8LVectorMismatchFunc VP8LVectorMismatch;
-
-static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) {
- const int log_floor = BitsLog2Floor(n);
- if (n == (n & ~(n - 1))) // zero or a power of two.
- return log_floor;
- else
- return log_floor + 1;
-}
-
-// Splitting of distance and length codes into prefixes and
-// extra bits. The prefixes are encoded with an entropy code
-// while the extra bits are stored just as normal bits.
-static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code,
- int* const extra_bits) {
- const int highest_bit = BitsLog2Floor(--distance);
- const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
- *extra_bits = highest_bit - 1;
- *code = 2 * highest_bit + second_highest_bit;
-}
-
-static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code,
- int* const extra_bits,
- int* const extra_bits_value) {
- const int highest_bit = BitsLog2Floor(--distance);
- const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
- *extra_bits = highest_bit - 1;
- *extra_bits_value = distance & ((1 << *extra_bits) - 1);
- *code = 2 * highest_bit + second_highest_bit;
-}
-
-#define PREFIX_LOOKUP_IDX_MAX 512
-typedef struct {
- int8_t code_;
- int8_t extra_bits_;
-} VP8LPrefixCode;
-
-// These tables are derived using VP8LPrefixEncodeNoLUT.
-extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX];
-extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX];
-static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code,
- int* const extra_bits) {
- if (distance < PREFIX_LOOKUP_IDX_MAX) {
- const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance];
- *code = prefix_code.code_;
- *extra_bits = prefix_code.extra_bits_;
- } else {
- VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits);
- }
-}
-
-static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code,
- int* const extra_bits,
- int* const extra_bits_value) {
- if (distance < PREFIX_LOOKUP_IDX_MAX) {
- const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance];
- *code = prefix_code.code_;
- *extra_bits = prefix_code.extra_bits_;
- *extra_bits_value = kPrefixEncodeExtraBitsValue[distance];
- } else {
- VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value);
- }
-}
-
-// Sum of each component, mod 256.
-static WEBP_INLINE uint32_t VP8LAddPixels(uint32_t a, uint32_t b) {
- const uint32_t alpha_and_green = (a & 0xff00ff00u) + (b & 0xff00ff00u);
- const uint32_t red_and_blue = (a & 0x00ff00ffu) + (b & 0x00ff00ffu);
- return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
-}
-
-// Difference of each component, mod 256.
-static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
- const uint32_t alpha_and_green =
- 0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u);
- const uint32_t red_and_blue =
- 0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu);
- return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
-}
-
-void VP8LBundleColorMap(const uint8_t* const row, int width,
- int xbits, uint32_t* const dst);
-
-// Must be called before calling any of the above methods.
-void VP8LEncDspInit(void);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // WEBP_DSP_LOSSLESS_H_
diff --git a/drivers/webp/dsp/lossless_enc.c b/drivers/webp/dsp/lossless_enc.c
deleted file mode 100644
index 256f6f5f8b..0000000000
--- a/drivers/webp/dsp/lossless_enc.c
+++ /dev/null
@@ -1,1439 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Image transform methods for lossless encoder.
-//
-// Authors: Vikas Arora (vikaas.arora@gmail.com)
-// Jyrki Alakuijala (jyrki@google.com)
-// Urvang Joshi (urvang@google.com)
-
-#include "./dsp.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include "../dec/vp8li.h"
-#include "../utils/endian_inl.h"
-#include "./lossless.h"
-#include "./yuv.h"
-
-#define MAX_DIFF_COST (1e30f)
-
-static const int kPredLowEffort = 11;
-static const uint32_t kMaskAlpha = 0xff000000;
-
-// lookup table for small values of log2(int)
-const float kLog2Table[LOG_LOOKUP_IDX_MAX] = {
- 0.0000000000000000f, 0.0000000000000000f,
- 1.0000000000000000f, 1.5849625007211560f,
- 2.0000000000000000f, 2.3219280948873621f,
- 2.5849625007211560f, 2.8073549220576041f,
- 3.0000000000000000f, 3.1699250014423121f,
- 3.3219280948873621f, 3.4594316186372973f,
- 3.5849625007211560f, 3.7004397181410921f,
- 3.8073549220576041f, 3.9068905956085187f,
- 4.0000000000000000f, 4.0874628412503390f,
- 4.1699250014423121f, 4.2479275134435852f,
- 4.3219280948873626f, 4.3923174227787606f,
- 4.4594316186372973f, 4.5235619560570130f,
- 4.5849625007211560f, 4.6438561897747243f,
- 4.7004397181410917f, 4.7548875021634682f,
- 4.8073549220576037f, 4.8579809951275718f,
- 4.9068905956085187f, 4.9541963103868749f,
- 5.0000000000000000f, 5.0443941193584533f,
- 5.0874628412503390f, 5.1292830169449663f,
- 5.1699250014423121f, 5.2094533656289501f,
- 5.2479275134435852f, 5.2854022188622487f,
- 5.3219280948873626f, 5.3575520046180837f,
- 5.3923174227787606f, 5.4262647547020979f,
- 5.4594316186372973f, 5.4918530963296747f,
- 5.5235619560570130f, 5.5545888516776376f,
- 5.5849625007211560f, 5.6147098441152083f,
- 5.6438561897747243f, 5.6724253419714951f,
- 5.7004397181410917f, 5.7279204545631987f,
- 5.7548875021634682f, 5.7813597135246599f,
- 5.8073549220576037f, 5.8328900141647412f,
- 5.8579809951275718f, 5.8826430493618415f,
- 5.9068905956085187f, 5.9307373375628866f,
- 5.9541963103868749f, 5.9772799234999167f,
- 6.0000000000000000f, 6.0223678130284543f,
- 6.0443941193584533f, 6.0660891904577720f,
- 6.0874628412503390f, 6.1085244567781691f,
- 6.1292830169449663f, 6.1497471195046822f,
- 6.1699250014423121f, 6.1898245588800175f,
- 6.2094533656289501f, 6.2288186904958804f,
- 6.2479275134435852f, 6.2667865406949010f,
- 6.2854022188622487f, 6.3037807481771030f,
- 6.3219280948873626f, 6.3398500028846243f,
- 6.3575520046180837f, 6.3750394313469245f,
- 6.3923174227787606f, 6.4093909361377017f,
- 6.4262647547020979f, 6.4429434958487279f,
- 6.4594316186372973f, 6.4757334309663976f,
- 6.4918530963296747f, 6.5077946401986963f,
- 6.5235619560570130f, 6.5391588111080309f,
- 6.5545888516776376f, 6.5698556083309478f,
- 6.5849625007211560f, 6.5999128421871278f,
- 6.6147098441152083f, 6.6293566200796094f,
- 6.6438561897747243f, 6.6582114827517946f,
- 6.6724253419714951f, 6.6865005271832185f,
- 6.7004397181410917f, 6.7142455176661224f,
- 6.7279204545631987f, 6.7414669864011464f,
- 6.7548875021634682f, 6.7681843247769259f,
- 6.7813597135246599f, 6.7944158663501061f,
- 6.8073549220576037f, 6.8201789624151878f,
- 6.8328900141647412f, 6.8454900509443747f,
- 6.8579809951275718f, 6.8703647195834047f,
- 6.8826430493618415f, 6.8948177633079437f,
- 6.9068905956085187f, 6.9188632372745946f,
- 6.9307373375628866f, 6.9425145053392398f,
- 6.9541963103868749f, 6.9657842846620869f,
- 6.9772799234999167f, 6.9886846867721654f,
- 7.0000000000000000f, 7.0112272554232539f,
- 7.0223678130284543f, 7.0334230015374501f,
- 7.0443941193584533f, 7.0552824355011898f,
- 7.0660891904577720f, 7.0768155970508308f,
- 7.0874628412503390f, 7.0980320829605263f,
- 7.1085244567781691f, 7.1189410727235076f,
- 7.1292830169449663f, 7.1395513523987936f,
- 7.1497471195046822f, 7.1598713367783890f,
- 7.1699250014423121f, 7.1799090900149344f,
- 7.1898245588800175f, 7.1996723448363644f,
- 7.2094533656289501f, 7.2191685204621611f,
- 7.2288186904958804f, 7.2384047393250785f,
- 7.2479275134435852f, 7.2573878426926521f,
- 7.2667865406949010f, 7.2761244052742375f,
- 7.2854022188622487f, 7.2946207488916270f,
- 7.3037807481771030f, 7.3128829552843557f,
- 7.3219280948873626f, 7.3309168781146167f,
- 7.3398500028846243f, 7.3487281542310771f,
- 7.3575520046180837f, 7.3663222142458160f,
- 7.3750394313469245f, 7.3837042924740519f,
- 7.3923174227787606f, 7.4008794362821843f,
- 7.4093909361377017f, 7.4178525148858982f,
- 7.4262647547020979f, 7.4346282276367245f,
- 7.4429434958487279f, 7.4512111118323289f,
- 7.4594316186372973f, 7.4676055500829976f,
- 7.4757334309663976f, 7.4838157772642563f,
- 7.4918530963296747f, 7.4998458870832056f,
- 7.5077946401986963f, 7.5156998382840427f,
- 7.5235619560570130f, 7.5313814605163118f,
- 7.5391588111080309f, 7.5468944598876364f,
- 7.5545888516776376f, 7.5622424242210728f,
- 7.5698556083309478f, 7.5774288280357486f,
- 7.5849625007211560f, 7.5924570372680806f,
- 7.5999128421871278f, 7.6073303137496104f,
- 7.6147098441152083f, 7.6220518194563764f,
- 7.6293566200796094f, 7.6366246205436487f,
- 7.6438561897747243f, 7.6510516911789281f,
- 7.6582114827517946f, 7.6653359171851764f,
- 7.6724253419714951f, 7.6794800995054464f,
- 7.6865005271832185f, 7.6934869574993252f,
- 7.7004397181410917f, 7.7073591320808825f,
- 7.7142455176661224f, 7.7210991887071855f,
- 7.7279204545631987f, 7.7347096202258383f,
- 7.7414669864011464f, 7.7481928495894605f,
- 7.7548875021634682f, 7.7615512324444795f,
- 7.7681843247769259f, 7.7747870596011736f,
- 7.7813597135246599f, 7.7879025593914317f,
- 7.7944158663501061f, 7.8008998999203047f,
- 7.8073549220576037f, 7.8137811912170374f,
- 7.8201789624151878f, 7.8265484872909150f,
- 7.8328900141647412f, 7.8392037880969436f,
- 7.8454900509443747f, 7.8517490414160571f,
- 7.8579809951275718f, 7.8641861446542797f,
- 7.8703647195834047f, 7.8765169465649993f,
- 7.8826430493618415f, 7.8887432488982591f,
- 7.8948177633079437f, 7.9008668079807486f,
- 7.9068905956085187f, 7.9128893362299619f,
- 7.9188632372745946f, 7.9248125036057812f,
- 7.9307373375628866f, 7.9366379390025709f,
- 7.9425145053392398f, 7.9483672315846778f,
- 7.9541963103868749f, 7.9600019320680805f,
- 7.9657842846620869f, 7.9715435539507719f,
- 7.9772799234999167f, 7.9829935746943103f,
- 7.9886846867721654f, 7.9943534368588577f
-};
-
-const float kSLog2Table[LOG_LOOKUP_IDX_MAX] = {
- 0.00000000f, 0.00000000f, 2.00000000f, 4.75488750f,
- 8.00000000f, 11.60964047f, 15.50977500f, 19.65148445f,
- 24.00000000f, 28.52932501f, 33.21928095f, 38.05374781f,
- 43.01955001f, 48.10571634f, 53.30296891f, 58.60335893f,
- 64.00000000f, 69.48686830f, 75.05865003f, 80.71062276f,
- 86.43856190f, 92.23866588f, 98.10749561f, 104.04192499f,
- 110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f,
- 134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f,
- 160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f,
- 186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f,
- 212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f,
- 240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f,
- 268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f,
- 296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f,
- 325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f,
- 354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f,
- 384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f,
- 413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f,
- 444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f,
- 474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f,
- 505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f,
- 536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f,
- 568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f,
- 600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f,
- 632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f,
- 664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f,
- 696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f,
- 729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f,
- 762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f,
- 795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f,
- 828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f,
- 862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f,
- 896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f,
- 929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f,
- 963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f,
- 998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f,
- 1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f,
- 1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f,
- 1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f,
- 1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f,
- 1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f,
- 1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f,
- 1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f,
- 1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f,
- 1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f,
- 1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f,
- 1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f,
- 1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f,
- 1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f,
- 1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f,
- 1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f,
- 1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f,
- 1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f,
- 1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f,
- 1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f,
- 1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f,
- 1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f,
- 1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f,
- 1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f,
- 1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f,
- 1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f,
- 1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f,
- 1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f,
- 2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f
-};
-
-const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = {
- { 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1},
- { 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2},
- { 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3},
- { 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3},
- { 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},
- {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},
- {10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
- {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
- {11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
- {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
- {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
- {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
- {12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
- {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
- {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
- {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
- {13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
- {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
- {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
- {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
- {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
- {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
- {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
- {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
- {14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
- {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
- {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
- {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
- {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
- {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
- {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
- {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
- {15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
- {16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
- {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
-};
-
-const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = {
- 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3,
- 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
- 127,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126
-};
-
-static float FastSLog2Slow(uint32_t v) {
- assert(v >= LOG_LOOKUP_IDX_MAX);
- if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
- int log_cnt = 0;
- uint32_t y = 1;
- int correction = 0;
- const float v_f = (float)v;
- const uint32_t orig_v = v;
- do {
- ++log_cnt;
- v = v >> 1;
- y = y << 1;
- } while (v >= LOG_LOOKUP_IDX_MAX);
- // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256
- // Xf = floor(Xf) * (1 + (v % y) / v)
- // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)
- // The correction factor: log(1 + d) ~ d; for very small d values, so
- // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v
- // LOG_2_RECIPROCAL ~ 23/16
- correction = (23 * (orig_v & (y - 1))) >> 4;
- return v_f * (kLog2Table[v] + log_cnt) + correction;
- } else {
- return (float)(LOG_2_RECIPROCAL * v * log((double)v));
- }
-}
-
-static float FastLog2Slow(uint32_t v) {
- assert(v >= LOG_LOOKUP_IDX_MAX);
- if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
- int log_cnt = 0;
- uint32_t y = 1;
- const uint32_t orig_v = v;
- double log_2;
- do {
- ++log_cnt;
- v = v >> 1;
- y = y << 1;
- } while (v >= LOG_LOOKUP_IDX_MAX);
- log_2 = kLog2Table[v] + log_cnt;
- if (orig_v >= APPROX_LOG_MAX) {
- // Since the division is still expensive, add this correction factor only
- // for large values of 'v'.
- const int correction = (23 * (orig_v & (y - 1))) >> 4;
- log_2 += (double)correction / orig_v;
- }
- return (float)log_2;
- } else {
- return (float)(LOG_2_RECIPROCAL * log((double)v));
- }
-}
-
-// Mostly used to reduce code size + readability
-static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; }
-static WEBP_INLINE int GetMax(int a, int b) { return (a < b) ? b : a; }
-
-//------------------------------------------------------------------------------
-// Methods to calculate Entropy (Shannon).
-
-static float PredictionCostSpatial(const int counts[256], int weight_0,
- double exp_val) {
- const int significant_symbols = 256 >> 4;
- const double exp_decay_factor = 0.6;
- double bits = weight_0 * counts[0];
- int i;
- for (i = 1; i < significant_symbols; ++i) {
- bits += exp_val * (counts[i] + counts[256 - i]);
- exp_val *= exp_decay_factor;
- }
- return (float)(-0.1 * bits);
-}
-
-// Compute the combined Shanon's entropy for distribution {X} and {X+Y}
-static float CombinedShannonEntropy(const int X[256], const int Y[256]) {
- int i;
- double retval = 0.;
- int sumX = 0, sumXY = 0;
- for (i = 0; i < 256; ++i) {
- const int x = X[i];
- if (x != 0) {
- const int xy = x + Y[i];
- sumX += x;
- retval -= VP8LFastSLog2(x);
- sumXY += xy;
- retval -= VP8LFastSLog2(xy);
- } else if (Y[i] != 0) {
- sumXY += Y[i];
- retval -= VP8LFastSLog2(Y[i]);
- }
- }
- retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY);
- return (float)retval;
-}
-
-static float PredictionCostSpatialHistogram(const int accumulated[4][256],
- const int tile[4][256]) {
- int i;
- double retval = 0;
- for (i = 0; i < 4; ++i) {
- const double kExpValue = 0.94;
- retval += PredictionCostSpatial(tile[i], 1, kExpValue);
- retval += VP8LCombinedShannonEntropy(tile[i], accumulated[i]);
- }
- return (float)retval;
-}
-
-void VP8LBitEntropyInit(VP8LBitEntropy* const entropy) {
- entropy->entropy = 0.;
- entropy->sum = 0;
- entropy->nonzeros = 0;
- entropy->max_val = 0;
- entropy->nonzero_code = VP8L_NON_TRIVIAL_SYM;
-}
-
-void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n,
- VP8LBitEntropy* const entropy) {
- int i;
-
- VP8LBitEntropyInit(entropy);
-
- for (i = 0; i < n; ++i) {
- if (array[i] != 0) {
- entropy->sum += array[i];
- entropy->nonzero_code = i;
- ++entropy->nonzeros;
- entropy->entropy -= VP8LFastSLog2(array[i]);
- if (entropy->max_val < array[i]) {
- entropy->max_val = array[i];
- }
- }
- }
- entropy->entropy += VP8LFastSLog2(entropy->sum);
-}
-
-static WEBP_INLINE void GetEntropyUnrefinedHelper(
- uint32_t val, int i, uint32_t* const val_prev, int* const i_prev,
- VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) {
- const int streak = i - *i_prev;
-
- // Gather info for the bit entropy.
- if (*val_prev != 0) {
- bit_entropy->sum += (*val_prev) * streak;
- bit_entropy->nonzeros += streak;
- bit_entropy->nonzero_code = *i_prev;
- bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak;
- if (bit_entropy->max_val < *val_prev) {
- bit_entropy->max_val = *val_prev;
- }
- }
-
- // Gather info for the Huffman cost.
- stats->counts[*val_prev != 0] += (streak > 3);
- stats->streaks[*val_prev != 0][(streak > 3)] += streak;
-
- *val_prev = val;
- *i_prev = i;
-}
-
-void VP8LGetEntropyUnrefined(const uint32_t* const X, int length,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats) {
- int i;
- int i_prev = 0;
- uint32_t x_prev = X[0];
-
- memset(stats, 0, sizeof(*stats));
- VP8LBitEntropyInit(bit_entropy);
-
- for (i = 1; i < length; ++i) {
- const uint32_t x = X[i];
- if (x != x_prev) {
- VP8LGetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats);
- }
- }
- VP8LGetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats);
-
- bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum);
-}
-
-void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X,
- const uint32_t* const Y, int length,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats) {
- int i = 1;
- int i_prev = 0;
- uint32_t xy_prev = X[0] + Y[0];
-
- memset(stats, 0, sizeof(*stats));
- VP8LBitEntropyInit(bit_entropy);
-
- for (i = 1; i < length; ++i) {
- const uint32_t xy = X[i] + Y[i];
- if (xy != xy_prev) {
- VP8LGetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy,
- stats);
- }
- }
- VP8LGetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats);
-
- bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum);
-}
-
-static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) {
- ++histo_argb[0][argb >> 24];
- ++histo_argb[1][(argb >> 16) & 0xff];
- ++histo_argb[2][(argb >> 8) & 0xff];
- ++histo_argb[3][argb & 0xff];
-}
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE uint32_t Predict(VP8LPredictorFunc pred_func,
- int x, int y,
- const uint32_t* current_row,
- const uint32_t* upper_row) {
- if (y == 0) {
- return (x == 0) ? ARGB_BLACK : current_row[x - 1]; // Left.
- } else if (x == 0) {
- return upper_row[x]; // Top.
- } else {
- return pred_func(current_row[x - 1], upper_row + x);
- }
-}
-
-static int MaxDiffBetweenPixels(uint32_t p1, uint32_t p2) {
- const int diff_a = abs((int)(p1 >> 24) - (int)(p2 >> 24));
- const int diff_r = abs((int)((p1 >> 16) & 0xff) - (int)((p2 >> 16) & 0xff));
- const int diff_g = abs((int)((p1 >> 8) & 0xff) - (int)((p2 >> 8) & 0xff));
- const int diff_b = abs((int)(p1 & 0xff) - (int)(p2 & 0xff));
- return GetMax(GetMax(diff_a, diff_r), GetMax(diff_g, diff_b));
-}
-
-static int MaxDiffAroundPixel(uint32_t current, uint32_t up, uint32_t down,
- uint32_t left, uint32_t right) {
- const int diff_up = MaxDiffBetweenPixels(current, up);
- const int diff_down = MaxDiffBetweenPixels(current, down);
- const int diff_left = MaxDiffBetweenPixels(current, left);
- const int diff_right = MaxDiffBetweenPixels(current, right);
- return GetMax(GetMax(diff_up, diff_down), GetMax(diff_left, diff_right));
-}
-
-static uint32_t AddGreenToBlueAndRed(uint32_t argb) {
- const uint32_t green = (argb >> 8) & 0xff;
- uint32_t red_blue = argb & 0x00ff00ffu;
- red_blue += (green << 16) | green;
- red_blue &= 0x00ff00ffu;
- return (argb & 0xff00ff00u) | red_blue;
-}
-
-static void MaxDiffsForRow(int width, int stride, const uint32_t* const argb,
- uint8_t* const max_diffs, int used_subtract_green) {
- uint32_t current, up, down, left, right;
- int x;
- if (width <= 2) return;
- current = argb[0];
- right = argb[1];
- if (used_subtract_green) {
- current = AddGreenToBlueAndRed(current);
- right = AddGreenToBlueAndRed(right);
- }
- // max_diffs[0] and max_diffs[width - 1] are never used.
- for (x = 1; x < width - 1; ++x) {
- up = argb[-stride + x];
- down = argb[stride + x];
- left = current;
- current = right;
- right = argb[x + 1];
- if (used_subtract_green) {
- up = AddGreenToBlueAndRed(up);
- down = AddGreenToBlueAndRed(down);
- right = AddGreenToBlueAndRed(right);
- }
- max_diffs[x] = MaxDiffAroundPixel(current, up, down, left, right);
- }
-}
-
-// Quantize the difference between the actual component value and its prediction
-// to a multiple of quantization, working modulo 256, taking care not to cross
-// a boundary (inclusive upper limit).
-static uint8_t NearLosslessComponent(uint8_t value, uint8_t predict,
- uint8_t boundary, int quantization) {
- const int residual = (value - predict) & 0xff;
- const int boundary_residual = (boundary - predict) & 0xff;
- const int lower = residual & ~(quantization - 1);
- const int upper = lower + quantization;
- // Resolve ties towards a value closer to the prediction (i.e. towards lower
- // if value comes after prediction and towards upper otherwise).
- const int bias = ((boundary - value) & 0xff) < boundary_residual;
- if (residual - lower < upper - residual + bias) {
- // lower is closer to residual than upper.
- if (residual > boundary_residual && lower <= boundary_residual) {
- // Halve quantization step to avoid crossing boundary. This midpoint is
- // on the same side of boundary as residual because midpoint >= residual
- // (since lower is closer than upper) and residual is above the boundary.
- return lower + (quantization >> 1);
- }
- return lower;
- } else {
- // upper is closer to residual than lower.
- if (residual <= boundary_residual && upper > boundary_residual) {
- // Halve quantization step to avoid crossing boundary. This midpoint is
- // on the same side of boundary as residual because midpoint <= residual
- // (since upper is closer than lower) and residual is below the boundary.
- return lower + (quantization >> 1);
- }
- return upper & 0xff;
- }
-}
-
-// Quantize every component of the difference between the actual pixel value and
-// its prediction to a multiple of a quantization (a power of 2, not larger than
-// max_quantization which is a power of 2, smaller than max_diff). Take care if
-// value and predict have undergone subtract green, which means that red and
-// blue are represented as offsets from green.
-static uint32_t NearLossless(uint32_t value, uint32_t predict,
- int max_quantization, int max_diff,
- int used_subtract_green) {
- int quantization;
- uint8_t new_green = 0;
- uint8_t green_diff = 0;
- uint8_t a, r, g, b;
- if (max_diff <= 2) {
- return VP8LSubPixels(value, predict);
- }
- quantization = max_quantization;
- while (quantization >= max_diff) {
- quantization >>= 1;
- }
- if ((value >> 24) == 0 || (value >> 24) == 0xff) {
- // Preserve transparency of fully transparent or fully opaque pixels.
- a = ((value >> 24) - (predict >> 24)) & 0xff;
- } else {
- a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization);
- }
- g = NearLosslessComponent((value >> 8) & 0xff, (predict >> 8) & 0xff, 0xff,
- quantization);
- if (used_subtract_green) {
- // The green offset will be added to red and blue components during decoding
- // to obtain the actual red and blue values.
- new_green = ((predict >> 8) + g) & 0xff;
- // The amount by which green has been adjusted during quantization. It is
- // subtracted from red and blue for compensation, to avoid accumulating two
- // quantization errors in them.
- green_diff = (new_green - (value >> 8)) & 0xff;
- }
- r = NearLosslessComponent(((value >> 16) - green_diff) & 0xff,
- (predict >> 16) & 0xff, 0xff - new_green,
- quantization);
- b = NearLosslessComponent((value - green_diff) & 0xff, predict & 0xff,
- 0xff - new_green, quantization);
- return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
-}
-
-// Returns the difference between the pixel and its prediction. In case of a
-// lossy encoding, updates the source image to avoid propagating the deviation
-// further to pixels which depend on the current pixel for their predictions.
-static WEBP_INLINE uint32_t GetResidual(int width, int height,
- uint32_t* const upper_row,
- uint32_t* const current_row,
- const uint8_t* const max_diffs,
- int mode, VP8LPredictorFunc pred_func,
- int x, int y, int max_quantization,
- int exact, int used_subtract_green) {
- const uint32_t predict = Predict(pred_func, x, y, current_row, upper_row);
- uint32_t residual;
- if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 ||
- x == 0 || x == width - 1) {
- residual = VP8LSubPixels(current_row[x], predict);
- } else {
- residual = NearLossless(current_row[x], predict, max_quantization,
- max_diffs[x], used_subtract_green);
- // Update the source image.
- current_row[x] = VP8LAddPixels(predict, residual);
- // x is never 0 here so we do not need to update upper_row like below.
- }
- if (!exact && (current_row[x] & kMaskAlpha) == 0) {
- // If alpha is 0, cleanup RGB. We can choose the RGB values of the residual
- // for best compression. The prediction of alpha itself can be non-zero and
- // must be kept though. We choose RGB of the residual to be 0.
- residual &= kMaskAlpha;
- // Update the source image.
- current_row[x] = predict & ~kMaskAlpha;
- // The prediction for the rightmost pixel in a row uses the leftmost pixel
- // in that row as its top-right context pixel. Hence if we change the
- // leftmost pixel of current_row, the corresponding change must be applied
- // to upper_row as well where top-right context is being read from.
- if (x == 0 && y != 0) upper_row[width] = current_row[0];
- }
- return residual;
-}
-
-// Returns best predictor and updates the accumulated histogram.
-// If max_quantization > 1, assumes that near lossless processing will be
-// applied, quantizing residuals to multiples of quantization levels up to
-// max_quantization (the actual quantization level depends on smoothness near
-// the given pixel).
-static int GetBestPredictorForTile(int width, int height,
- int tile_x, int tile_y, int bits,
- int accumulated[4][256],
- uint32_t* const argb_scratch,
- const uint32_t* const argb,
- int max_quantization,
- int exact, int used_subtract_green) {
- const int kNumPredModes = 14;
- const int start_x = tile_x << bits;
- const int start_y = tile_y << bits;
- const int tile_size = 1 << bits;
- const int max_y = GetMin(tile_size, height - start_y);
- const int max_x = GetMin(tile_size, width - start_x);
- // Whether there exist columns just outside the tile.
- const int have_left = (start_x > 0);
- const int have_right = (max_x < width - start_x);
- // Position and size of the strip covering the tile and adjacent columns if
- // they exist.
- const int context_start_x = start_x - have_left;
- const int context_width = max_x + have_left + have_right;
- // The width of upper_row and current_row is one pixel larger than image width
- // to allow the top right pixel to point to the leftmost pixel of the next row
- // when at the right edge.
- uint32_t* upper_row = argb_scratch;
- uint32_t* current_row = upper_row + width + 1;
- uint8_t* const max_diffs = (uint8_t*)(current_row + width + 1);
- float best_diff = MAX_DIFF_COST;
- int best_mode = 0;
- int mode;
- int histo_stack_1[4][256];
- int histo_stack_2[4][256];
- // Need pointers to be able to swap arrays.
- int (*histo_argb)[256] = histo_stack_1;
- int (*best_histo)[256] = histo_stack_2;
- int i, j;
-
- for (mode = 0; mode < kNumPredModes; ++mode) {
- const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
- float cur_diff;
- int relative_y;
- memset(histo_argb, 0, sizeof(histo_stack_1));
- if (start_y > 0) {
- // Read the row above the tile which will become the first upper_row.
- // Include a pixel to the left if it exists; include a pixel to the right
- // in all cases (wrapping to the leftmost pixel of the next row if it does
- // not exist).
- memcpy(current_row + context_start_x,
- argb + (start_y - 1) * width + context_start_x,
- sizeof(*argb) * (max_x + have_left + 1));
- }
- for (relative_y = 0; relative_y < max_y; ++relative_y) {
- const int y = start_y + relative_y;
- int relative_x;
- uint32_t* tmp = upper_row;
- upper_row = current_row;
- current_row = tmp;
- // Read current_row. Include a pixel to the left if it exists; include a
- // pixel to the right in all cases except at the bottom right corner of
- // the image (wrapping to the leftmost pixel of the next row if it does
- // not exist in the current row).
- memcpy(current_row + context_start_x,
- argb + y * width + context_start_x,
- sizeof(*argb) * (max_x + have_left + (y + 1 < height)));
- if (max_quantization > 1 && y >= 1 && y + 1 < height) {
- MaxDiffsForRow(context_width, width, argb + y * width + context_start_x,
- max_diffs + context_start_x, used_subtract_green);
- }
-
- for (relative_x = 0; relative_x < max_x; ++relative_x) {
- const int x = start_x + relative_x;
- UpdateHisto(histo_argb,
- GetResidual(width, height, upper_row, current_row,
- max_diffs, mode, pred_func, x, y,
- max_quantization, exact, used_subtract_green));
- }
- }
- cur_diff = PredictionCostSpatialHistogram(
- (const int (*)[256])accumulated, (const int (*)[256])histo_argb);
- if (cur_diff < best_diff) {
- int (*tmp)[256] = histo_argb;
- histo_argb = best_histo;
- best_histo = tmp;
- best_diff = cur_diff;
- best_mode = mode;
- }
- }
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 256; j++) {
- accumulated[i][j] += best_histo[i][j];
- }
- }
-
- return best_mode;
-}
-
-// Converts pixels of the image to residuals with respect to predictions.
-// If max_quantization > 1, applies near lossless processing, quantizing
-// residuals to multiples of quantization levels up to max_quantization
-// (the actual quantization level depends on smoothness near the given pixel).
-static void CopyImageWithPrediction(int width, int height,
- int bits, uint32_t* const modes,
- uint32_t* const argb_scratch,
- uint32_t* const argb,
- int low_effort, int max_quantization,
- int exact, int used_subtract_green) {
- const int tiles_per_row = VP8LSubSampleSize(width, bits);
- const int mask = (1 << bits) - 1;
- // The width of upper_row and current_row is one pixel larger than image width
- // to allow the top right pixel to point to the leftmost pixel of the next row
- // when at the right edge.
- uint32_t* upper_row = argb_scratch;
- uint32_t* current_row = upper_row + width + 1;
- uint8_t* current_max_diffs = (uint8_t*)(current_row + width + 1);
- uint8_t* lower_max_diffs = current_max_diffs + width;
- int y;
- int mode = 0;
- VP8LPredictorFunc pred_func = NULL;
-
- for (y = 0; y < height; ++y) {
- int x;
- uint32_t* const tmp32 = upper_row;
- upper_row = current_row;
- current_row = tmp32;
- memcpy(current_row, argb + y * width,
- sizeof(*argb) * (width + (y + 1 < height)));
-
- if (low_effort) {
- for (x = 0; x < width; ++x) {
- const uint32_t predict = Predict(VP8LPredictors[kPredLowEffort], x, y,
- current_row, upper_row);
- argb[y * width + x] = VP8LSubPixels(current_row[x], predict);
- }
- } else {
- if (max_quantization > 1) {
- // Compute max_diffs for the lower row now, because that needs the
- // contents of argb for the current row, which we will overwrite with
- // residuals before proceeding with the next row.
- uint8_t* const tmp8 = current_max_diffs;
- current_max_diffs = lower_max_diffs;
- lower_max_diffs = tmp8;
- if (y + 2 < height) {
- MaxDiffsForRow(width, width, argb + (y + 1) * width, lower_max_diffs,
- used_subtract_green);
- }
- }
- for (x = 0; x < width; ++x) {
- if ((x & mask) == 0) {
- mode = (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff;
- pred_func = VP8LPredictors[mode];
- }
- argb[y * width + x] = GetResidual(
- width, height, upper_row, current_row, current_max_diffs, mode,
- pred_func, x, y, max_quantization, exact, used_subtract_green);
- }
- }
- }
-}
-
-// Finds the best predictor for each tile, and converts the image to residuals
-// with respect to predictions. If near_lossless_quality < 100, applies
-// near lossless processing, shaving off more bits of residuals for lower
-// qualities.
-void VP8LResidualImage(int width, int height, int bits, int low_effort,
- uint32_t* const argb, uint32_t* const argb_scratch,
- uint32_t* const image, int near_lossless_quality,
- int exact, int used_subtract_green) {
- const int tiles_per_row = VP8LSubSampleSize(width, bits);
- const int tiles_per_col = VP8LSubSampleSize(height, bits);
- int tile_y;
- int histo[4][256];
- const int max_quantization = 1 << VP8LNearLosslessBits(near_lossless_quality);
- if (low_effort) {
- int i;
- for (i = 0; i < tiles_per_row * tiles_per_col; ++i) {
- image[i] = ARGB_BLACK | (kPredLowEffort << 8);
- }
- } else {
- memset(histo, 0, sizeof(histo));
- for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
- int tile_x;
- for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
- const int pred = GetBestPredictorForTile(width, height, tile_x, tile_y,
- bits, histo, argb_scratch, argb, max_quantization, exact,
- used_subtract_green);
- image[tile_y * tiles_per_row + tile_x] = ARGB_BLACK | (pred << 8);
- }
- }
- }
-
- CopyImageWithPrediction(width, height, bits, image, argb_scratch, argb,
- low_effort, max_quantization, exact,
- used_subtract_green);
-}
-
-void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) {
- int i;
- for (i = 0; i < num_pixels; ++i) {
- const uint32_t argb = argb_data[i];
- const uint32_t green = (argb >> 8) & 0xff;
- const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;
- const uint32_t new_b = ((argb & 0xff) - green) & 0xff;
- argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b;
- }
-}
-
-static WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) {
- m->green_to_red_ = 0;
- m->green_to_blue_ = 0;
- m->red_to_blue_ = 0;
-}
-
-static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
- int8_t color) {
- return (uint32_t)((int)(color_pred) * color) >> 5;
-}
-
-static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
- VP8LMultipliers* const m) {
- m->green_to_red_ = (color_code >> 0) & 0xff;
- m->green_to_blue_ = (color_code >> 8) & 0xff;
- m->red_to_blue_ = (color_code >> 16) & 0xff;
-}
-
-static WEBP_INLINE uint32_t MultipliersToColorCode(
- const VP8LMultipliers* const m) {
- return 0xff000000u |
- ((uint32_t)(m->red_to_blue_) << 16) |
- ((uint32_t)(m->green_to_blue_) << 8) |
- m->green_to_red_;
-}
-
-void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
- int num_pixels) {
- int i;
- for (i = 0; i < num_pixels; ++i) {
- const uint32_t argb = data[i];
- const uint32_t green = argb >> 8;
- const uint32_t red = argb >> 16;
- uint32_t new_red = red;
- uint32_t new_blue = argb;
- new_red -= ColorTransformDelta(m->green_to_red_, green);
- new_red &= 0xff;
- new_blue -= ColorTransformDelta(m->green_to_blue_, green);
- new_blue -= ColorTransformDelta(m->red_to_blue_, red);
- new_blue &= 0xff;
- data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
- }
-}
-
-static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
- uint32_t argb) {
- const uint32_t green = argb >> 8;
- uint32_t new_red = argb >> 16;
- new_red -= ColorTransformDelta(green_to_red, green);
- return (new_red & 0xff);
-}
-
-static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
- uint8_t red_to_blue,
- uint32_t argb) {
- const uint32_t green = argb >> 8;
- const uint32_t red = argb >> 16;
- uint8_t new_blue = argb;
- new_blue -= ColorTransformDelta(green_to_blue, green);
- new_blue -= ColorTransformDelta(red_to_blue, red);
- return (new_blue & 0xff);
-}
-
-static float PredictionCostCrossColor(const int accumulated[256],
- const int counts[256]) {
- // Favor low entropy, locally and globally.
- // Favor small absolute values for PredictionCostSpatial
- static const double kExpValue = 2.4;
- return VP8LCombinedShannonEntropy(counts, accumulated) +
- PredictionCostSpatial(counts, 3, kExpValue);
-}
-
-void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_red, int histo[]) {
- while (tile_height-- > 0) {
- int x;
- for (x = 0; x < tile_width; ++x) {
- ++histo[TransformColorRed(green_to_red, argb[x])];
- }
- argb += stride;
- }
-}
-
-static float GetPredictionCostCrossColorRed(
- const uint32_t* argb, int stride, int tile_width, int tile_height,
- VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red,
- const int accumulated_red_histo[256]) {
- int histo[256] = { 0 };
- float cur_diff;
-
- VP8LCollectColorRedTransforms(argb, stride, tile_width, tile_height,
- green_to_red, histo);
-
- cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo);
- if ((uint8_t)green_to_red == prev_x.green_to_red_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if ((uint8_t)green_to_red == prev_y.green_to_red_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if (green_to_red == 0) {
- cur_diff -= 3;
- }
- return cur_diff;
-}
-
-static void GetBestGreenToRed(
- const uint32_t* argb, int stride, int tile_width, int tile_height,
- VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality,
- const int accumulated_red_histo[256], VP8LMultipliers* const best_tx) {
- const int kMaxIters = 4 + ((7 * quality) >> 8); // in range [4..6]
- int green_to_red_best = 0;
- int iter, offset;
- float best_diff = GetPredictionCostCrossColorRed(
- argb, stride, tile_width, tile_height, prev_x, prev_y,
- green_to_red_best, accumulated_red_histo);
- for (iter = 0; iter < kMaxIters; ++iter) {
- // ColorTransformDelta is a 3.5 bit fixed point, so 32 is equal to
- // one in color computation. Having initial delta here as 1 is sufficient
- // to explore the range of (-2, 2).
- const int delta = 32 >> iter;
- // Try a negative and a positive delta from the best known value.
- for (offset = -delta; offset <= delta; offset += 2 * delta) {
- const int green_to_red_cur = offset + green_to_red_best;
- const float cur_diff = GetPredictionCostCrossColorRed(
- argb, stride, tile_width, tile_height, prev_x, prev_y,
- green_to_red_cur, accumulated_red_histo);
- if (cur_diff < best_diff) {
- best_diff = cur_diff;
- green_to_red_best = green_to_red_cur;
- }
- }
- }
- best_tx->green_to_red_ = green_to_red_best;
-}
-
-void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_blue, int red_to_blue,
- int histo[]) {
- while (tile_height-- > 0) {
- int x;
- for (x = 0; x < tile_width; ++x) {
- ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[x])];
- }
- argb += stride;
- }
-}
-
-static float GetPredictionCostCrossColorBlue(
- const uint32_t* argb, int stride, int tile_width, int tile_height,
- VP8LMultipliers prev_x, VP8LMultipliers prev_y,
- int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256]) {
- int histo[256] = { 0 };
- float cur_diff;
-
- VP8LCollectColorBlueTransforms(argb, stride, tile_width, tile_height,
- green_to_blue, red_to_blue, histo);
-
- cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo);
- if ((uint8_t)green_to_blue == prev_x.green_to_blue_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if ((uint8_t)green_to_blue == prev_y.green_to_blue_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if ((uint8_t)red_to_blue == prev_x.red_to_blue_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if ((uint8_t)red_to_blue == prev_y.red_to_blue_) {
- cur_diff -= 3; // favor keeping the areas locally similar
- }
- if (green_to_blue == 0) {
- cur_diff -= 3;
- }
- if (red_to_blue == 0) {
- cur_diff -= 3;
- }
- return cur_diff;
-}
-
-#define kGreenRedToBlueNumAxis 8
-#define kGreenRedToBlueMaxIters 7
-static void GetBestGreenRedToBlue(
- const uint32_t* argb, int stride, int tile_width, int tile_height,
- VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality,
- const int accumulated_blue_histo[256],
- VP8LMultipliers* const best_tx) {
- const int8_t offset[kGreenRedToBlueNumAxis][2] =
- {{0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
- const int8_t delta_lut[kGreenRedToBlueMaxIters] = { 16, 16, 8, 4, 2, 2, 2 };
- const int iters =
- (quality < 25) ? 1 : (quality > 50) ? kGreenRedToBlueMaxIters : 4;
- int green_to_blue_best = 0;
- int red_to_blue_best = 0;
- int iter;
- // Initial value at origin:
- float best_diff = GetPredictionCostCrossColorBlue(
- argb, stride, tile_width, tile_height, prev_x, prev_y,
- green_to_blue_best, red_to_blue_best, accumulated_blue_histo);
- for (iter = 0; iter < iters; ++iter) {
- const int delta = delta_lut[iter];
- int axis;
- for (axis = 0; axis < kGreenRedToBlueNumAxis; ++axis) {
- const int green_to_blue_cur =
- offset[axis][0] * delta + green_to_blue_best;
- const int red_to_blue_cur = offset[axis][1] * delta + red_to_blue_best;
- const float cur_diff = GetPredictionCostCrossColorBlue(
- argb, stride, tile_width, tile_height, prev_x, prev_y,
- green_to_blue_cur, red_to_blue_cur, accumulated_blue_histo);
- if (cur_diff < best_diff) {
- best_diff = cur_diff;
- green_to_blue_best = green_to_blue_cur;
- red_to_blue_best = red_to_blue_cur;
- }
- if (quality < 25 && iter == 4) {
- // Only axis aligned diffs for lower quality.
- break; // next iter.
- }
- }
- if (delta == 2 && green_to_blue_best == 0 && red_to_blue_best == 0) {
- // Further iterations would not help.
- break; // out of iter-loop.
- }
- }
- best_tx->green_to_blue_ = green_to_blue_best;
- best_tx->red_to_blue_ = red_to_blue_best;
-}
-#undef kGreenRedToBlueMaxIters
-#undef kGreenRedToBlueNumAxis
-
-static VP8LMultipliers GetBestColorTransformForTile(
- int tile_x, int tile_y, int bits,
- VP8LMultipliers prev_x,
- VP8LMultipliers prev_y,
- int quality, int xsize, int ysize,
- const int accumulated_red_histo[256],
- const int accumulated_blue_histo[256],
- const uint32_t* const argb) {
- const int max_tile_size = 1 << bits;
- const int tile_y_offset = tile_y * max_tile_size;
- const int tile_x_offset = tile_x * max_tile_size;
- const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize);
- const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize);
- const int tile_width = all_x_max - tile_x_offset;
- const int tile_height = all_y_max - tile_y_offset;
- const uint32_t* const tile_argb = argb + tile_y_offset * xsize
- + tile_x_offset;
- VP8LMultipliers best_tx;
- MultipliersClear(&best_tx);
-
- GetBestGreenToRed(tile_argb, xsize, tile_width, tile_height,
- prev_x, prev_y, quality, accumulated_red_histo, &best_tx);
- GetBestGreenRedToBlue(tile_argb, xsize, tile_width, tile_height,
- prev_x, prev_y, quality, accumulated_blue_histo,
- &best_tx);
- return best_tx;
-}
-
-static void CopyTileWithColorTransform(int xsize, int ysize,
- int tile_x, int tile_y,
- int max_tile_size,
- VP8LMultipliers color_transform,
- uint32_t* argb) {
- const int xscan = GetMin(max_tile_size, xsize - tile_x);
- int yscan = GetMin(max_tile_size, ysize - tile_y);
- argb += tile_y * xsize + tile_x;
- while (yscan-- > 0) {
- VP8LTransformColor(&color_transform, argb, xscan);
- argb += xsize;
- }
-}
-
-void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
- uint32_t* const argb, uint32_t* image) {
- const int max_tile_size = 1 << bits;
- const int tile_xsize = VP8LSubSampleSize(width, bits);
- const int tile_ysize = VP8LSubSampleSize(height, bits);
- int accumulated_red_histo[256] = { 0 };
- int accumulated_blue_histo[256] = { 0 };
- int tile_x, tile_y;
- VP8LMultipliers prev_x, prev_y;
- MultipliersClear(&prev_y);
- MultipliersClear(&prev_x);
- for (tile_y = 0; tile_y < tile_ysize; ++tile_y) {
- for (tile_x = 0; tile_x < tile_xsize; ++tile_x) {
- int y;
- const int tile_x_offset = tile_x * max_tile_size;
- const int tile_y_offset = tile_y * max_tile_size;
- const int all_x_max = GetMin(tile_x_offset + max_tile_size, width);
- const int all_y_max = GetMin(tile_y_offset + max_tile_size, height);
- const int offset = tile_y * tile_xsize + tile_x;
- if (tile_y != 0) {
- ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y);
- }
- prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits,
- prev_x, prev_y,
- quality, width, height,
- accumulated_red_histo,
- accumulated_blue_histo,
- argb);
- image[offset] = MultipliersToColorCode(&prev_x);
- CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset,
- max_tile_size, prev_x, argb);
-
- // Gather accumulated histogram data.
- for (y = tile_y_offset; y < all_y_max; ++y) {
- int ix = y * width + tile_x_offset;
- const int ix_end = ix + all_x_max - tile_x_offset;
- for (; ix < ix_end; ++ix) {
- const uint32_t pix = argb[ix];
- if (ix >= 2 &&
- pix == argb[ix - 2] &&
- pix == argb[ix - 1]) {
- continue; // repeated pixels are handled by backward references
- }
- if (ix >= width + 2 &&
- argb[ix - 2] == argb[ix - width - 2] &&
- argb[ix - 1] == argb[ix - width - 1] &&
- pix == argb[ix - width]) {
- continue; // repeated pixels are handled by backward references
- }
- ++accumulated_red_histo[(pix >> 16) & 0xff];
- ++accumulated_blue_histo[(pix >> 0) & 0xff];
- }
- }
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
-static int VectorMismatch(const uint32_t* const array1,
- const uint32_t* const array2, int length) {
- int match_len = 0;
-
- while (match_len < length && array1[match_len] == array2[match_len]) {
- ++match_len;
- }
- return match_len;
-}
-
-// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.
-void VP8LBundleColorMap(const uint8_t* const row, int width,
- int xbits, uint32_t* const dst) {
- int x;
- if (xbits > 0) {
- const int bit_depth = 1 << (3 - xbits);
- const int mask = (1 << xbits) - 1;
- uint32_t code = 0xff000000;
- for (x = 0; x < width; ++x) {
- const int xsub = x & mask;
- if (xsub == 0) {
- code = 0xff000000;
- }
- code |= row[x] << (8 + bit_depth * xsub);
- dst[x >> xbits] = code;
- }
- } else {
- for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8);
- }
-}
-
-//------------------------------------------------------------------------------
-
-static double ExtraCost(const uint32_t* population, int length) {
- int i;
- double cost = 0.;
- for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2];
- return cost;
-}
-
-static double ExtraCostCombined(const uint32_t* X, const uint32_t* Y,
- int length) {
- int i;
- double cost = 0.;
- for (i = 2; i < length - 2; ++i) {
- const int xy = X[i + 2] + Y[i + 2];
- cost += (i >> 1) * xy;
- }
- return cost;
-}
-
-//------------------------------------------------------------------------------
-
-static void HistogramAdd(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
- int i;
- const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
- assert(a->palette_code_bits_ == b->palette_code_bits_);
- if (b != out) {
- for (i = 0; i < literal_size; ++i) {
- out->literal_[i] = a->literal_[i] + b->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] = a->distance_[i] + b->distance_[i];
- }
- for (i = 0; i < NUM_LITERAL_CODES; ++i) {
- out->red_[i] = a->red_[i] + b->red_[i];
- out->blue_[i] = a->blue_[i] + b->blue_[i];
- out->alpha_[i] = a->alpha_[i] + b->alpha_[i];
- }
- } else {
- for (i = 0; i < literal_size; ++i) {
- out->literal_[i] += a->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] += a->distance_[i];
- }
- for (i = 0; i < NUM_LITERAL_CODES; ++i) {
- out->red_[i] += a->red_[i];
- out->blue_[i] += a->blue_[i];
- out->alpha_[i] += a->alpha_[i];
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
-VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
-
-VP8LTransformColorFunc VP8LTransformColor;
-
-VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms;
-VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms;
-
-VP8LFastLog2SlowFunc VP8LFastLog2Slow;
-VP8LFastLog2SlowFunc VP8LFastSLog2Slow;
-
-VP8LCostFunc VP8LExtraCost;
-VP8LCostCombinedFunc VP8LExtraCostCombined;
-VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
-
-GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper;
-
-VP8LHistogramAddFunc VP8LHistogramAdd;
-
-VP8LVectorMismatchFunc VP8LVectorMismatch;
-
-extern void VP8LEncDspInitSSE2(void);
-extern void VP8LEncDspInitSSE41(void);
-extern void VP8LEncDspInitNEON(void);
-extern void VP8LEncDspInitMIPS32(void);
-extern void VP8LEncDspInitMIPSdspR2(void);
-
-static volatile VP8CPUInfo lossless_enc_last_cpuinfo_used =
- (VP8CPUInfo)&lossless_enc_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
- if (lossless_enc_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- VP8LDspInit();
-
- VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C;
-
- VP8LTransformColor = VP8LTransformColor_C;
-
- VP8LCollectColorBlueTransforms = VP8LCollectColorBlueTransforms_C;
- VP8LCollectColorRedTransforms = VP8LCollectColorRedTransforms_C;
-
- VP8LFastLog2Slow = FastLog2Slow;
- VP8LFastSLog2Slow = FastSLog2Slow;
-
- VP8LExtraCost = ExtraCost;
- VP8LExtraCostCombined = ExtraCostCombined;
- VP8LCombinedShannonEntropy = CombinedShannonEntropy;
-
- VP8LGetEntropyUnrefinedHelper = GetEntropyUnrefinedHelper;
-
- VP8LHistogramAdd = HistogramAdd;
-
- VP8LVectorMismatch = VectorMismatch;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- VP8LEncDspInitSSE2();
-#if defined(WEBP_USE_SSE41)
- if (VP8GetCPUInfo(kSSE4_1)) {
- VP8LEncDspInitSSE41();
- }
-#endif
- }
-#endif
-#if defined(WEBP_USE_NEON)
- if (VP8GetCPUInfo(kNEON)) {
- VP8LEncDspInitNEON();
- }
-#endif
-#if defined(WEBP_USE_MIPS32)
- if (VP8GetCPUInfo(kMIPS32)) {
- VP8LEncDspInitMIPS32();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- VP8LEncDspInitMIPSdspR2();
- }
-#endif
- }
- lossless_enc_last_cpuinfo_used = VP8GetCPUInfo;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dsp/lossless_enc_mips32.c b/drivers/webp/dsp/lossless_enc_mips32.c
deleted file mode 100644
index 49c666d4fd..0000000000
--- a/drivers/webp/dsp/lossless_enc_mips32.c
+++ /dev/null
@@ -1,386 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS version of lossless functions
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
-
-#include "./dsp.h"
-#include "./lossless.h"
-
-#if defined(WEBP_USE_MIPS32)
-
-#include <assert.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-static float FastSLog2Slow(uint32_t v) {
- assert(v >= LOG_LOOKUP_IDX_MAX);
- if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
- uint32_t log_cnt, y, correction;
- const int c24 = 24;
- const float v_f = (float)v;
- uint32_t temp;
-
- // Xf = 256 = 2^8
- // log_cnt is index of leading one in upper 24 bits
- __asm__ volatile(
- "clz %[log_cnt], %[v] \n\t"
- "addiu %[y], $zero, 1 \n\t"
- "subu %[log_cnt], %[c24], %[log_cnt] \n\t"
- "sllv %[y], %[y], %[log_cnt] \n\t"
- "srlv %[temp], %[v], %[log_cnt] \n\t"
- : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y),
- [temp]"=r"(temp)
- : [c24]"r"(c24), [v]"r"(v)
- );
-
- // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256
- // Xf = floor(Xf) * (1 + (v % y) / v)
- // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)
- // The correction factor: log(1 + d) ~ d; for very small d values, so
- // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v
- // LOG_2_RECIPROCAL ~ 23/16
-
- // (v % y) = (v % 2^log_cnt) = v & (2^log_cnt - 1)
- correction = (23 * (v & (y - 1))) >> 4;
- return v_f * (kLog2Table[temp] + log_cnt) + correction;
- } else {
- return (float)(LOG_2_RECIPROCAL * v * log((double)v));
- }
-}
-
-static float FastLog2Slow(uint32_t v) {
- assert(v >= LOG_LOOKUP_IDX_MAX);
- if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
- uint32_t log_cnt, y;
- const int c24 = 24;
- double log_2;
- uint32_t temp;
-
- __asm__ volatile(
- "clz %[log_cnt], %[v] \n\t"
- "addiu %[y], $zero, 1 \n\t"
- "subu %[log_cnt], %[c24], %[log_cnt] \n\t"
- "sllv %[y], %[y], %[log_cnt] \n\t"
- "srlv %[temp], %[v], %[log_cnt] \n\t"
- : [log_cnt]"=&r"(log_cnt), [y]"=&r"(y),
- [temp]"=r"(temp)
- : [c24]"r"(c24), [v]"r"(v)
- );
-
- log_2 = kLog2Table[temp] + log_cnt;
- if (v >= APPROX_LOG_MAX) {
- // Since the division is still expensive, add this correction factor only
- // for large values of 'v'.
-
- const uint32_t correction = (23 * (v & (y - 1))) >> 4;
- log_2 += (double)correction / v;
- }
- return (float)log_2;
- } else {
- return (float)(LOG_2_RECIPROCAL * log((double)v));
- }
-}
-
-// C version of this function:
-// int i = 0;
-// int64_t cost = 0;
-// const uint32_t* pop = &population[4];
-// const uint32_t* LoopEnd = &population[length];
-// while (pop != LoopEnd) {
-// ++i;
-// cost += i * *pop;
-// cost += i * *(pop + 1);
-// pop += 2;
-// }
-// return (double)cost;
-static double ExtraCost(const uint32_t* const population, int length) {
- int i, temp0, temp1;
- const uint32_t* pop = &population[4];
- const uint32_t* const LoopEnd = &population[length];
-
- __asm__ volatile(
- "mult $zero, $zero \n\t"
- "xor %[i], %[i], %[i] \n\t"
- "beq %[pop], %[LoopEnd], 2f \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[pop]) \n\t"
- "lw %[temp1], 4(%[pop]) \n\t"
- "addiu %[i], %[i], 1 \n\t"
- "addiu %[pop], %[pop], 8 \n\t"
- "madd %[i], %[temp0] \n\t"
- "madd %[i], %[temp1] \n\t"
- "bne %[pop], %[LoopEnd], 1b \n\t"
- "2: \n\t"
- "mfhi %[temp0] \n\t"
- "mflo %[temp1] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [i]"=&r"(i), [pop]"+r"(pop)
- : [LoopEnd]"r"(LoopEnd)
- : "memory", "hi", "lo"
- );
-
- return (double)((int64_t)temp0 << 32 | temp1);
-}
-
-// C version of this function:
-// int i = 0;
-// int64_t cost = 0;
-// const uint32_t* pX = &X[4];
-// const uint32_t* pY = &Y[4];
-// const uint32_t* LoopEnd = &X[length];
-// while (pX != LoopEnd) {
-// const uint32_t xy0 = *pX + *pY;
-// const uint32_t xy1 = *(pX + 1) + *(pY + 1);
-// ++i;
-// cost += i * xy0;
-// cost += i * xy1;
-// pX += 2;
-// pY += 2;
-// }
-// return (double)cost;
-static double ExtraCostCombined(const uint32_t* const X,
- const uint32_t* const Y, int length) {
- int i, temp0, temp1, temp2, temp3;
- const uint32_t* pX = &X[4];
- const uint32_t* pY = &Y[4];
- const uint32_t* const LoopEnd = &X[length];
-
- __asm__ volatile(
- "mult $zero, $zero \n\t"
- "xor %[i], %[i], %[i] \n\t"
- "beq %[pX], %[LoopEnd], 2f \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[pX]) \n\t"
- "lw %[temp1], 0(%[pY]) \n\t"
- "lw %[temp2], 4(%[pX]) \n\t"
- "lw %[temp3], 4(%[pY]) \n\t"
- "addiu %[i], %[i], 1 \n\t"
- "addu %[temp0], %[temp0], %[temp1] \n\t"
- "addu %[temp2], %[temp2], %[temp3] \n\t"
- "addiu %[pX], %[pX], 8 \n\t"
- "addiu %[pY], %[pY], 8 \n\t"
- "madd %[i], %[temp0] \n\t"
- "madd %[i], %[temp2] \n\t"
- "bne %[pX], %[LoopEnd], 1b \n\t"
- "2: \n\t"
- "mfhi %[temp0] \n\t"
- "mflo %[temp1] \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [i]"=&r"(i), [pX]"+r"(pX), [pY]"+r"(pY)
- : [LoopEnd]"r"(LoopEnd)
- : "memory", "hi", "lo"
- );
-
- return (double)((int64_t)temp0 << 32 | temp1);
-}
-
-#define HUFFMAN_COST_PASS \
- __asm__ volatile( \
- "sll %[temp1], %[temp0], 3 \n\t" \
- "addiu %[temp3], %[streak], -3 \n\t" \
- "addu %[temp2], %[pstreaks], %[temp1] \n\t" \
- "blez %[temp3], 1f \n\t" \
- "srl %[temp1], %[temp1], 1 \n\t" \
- "addu %[temp3], %[pcnts], %[temp1] \n\t" \
- "lw %[temp0], 4(%[temp2]) \n\t" \
- "lw %[temp1], 0(%[temp3]) \n\t" \
- "addu %[temp0], %[temp0], %[streak] \n\t" \
- "addiu %[temp1], %[temp1], 1 \n\t" \
- "sw %[temp0], 4(%[temp2]) \n\t" \
- "sw %[temp1], 0(%[temp3]) \n\t" \
- "b 2f \n\t" \
- "1: \n\t" \
- "lw %[temp0], 0(%[temp2]) \n\t" \
- "addu %[temp0], %[temp0], %[streak] \n\t" \
- "sw %[temp0], 0(%[temp2]) \n\t" \
- "2: \n\t" \
- : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
- [temp3]"=&r"(temp3), [temp0]"+r"(temp0) \
- : [pstreaks]"r"(pstreaks), [pcnts]"r"(pcnts), \
- [streak]"r"(streak) \
- : "memory" \
- );
-
-// Returns the various RLE counts
-static WEBP_INLINE void GetEntropyUnrefinedHelper(
- uint32_t val, int i, uint32_t* const val_prev, int* const i_prev,
- VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats) {
- int* const pstreaks = &stats->streaks[0][0];
- int* const pcnts = &stats->counts[0];
- int temp0, temp1, temp2, temp3;
- const int streak = i - *i_prev;
-
- // Gather info for the bit entropy.
- if (*val_prev != 0) {
- bit_entropy->sum += (*val_prev) * streak;
- bit_entropy->nonzeros += streak;
- bit_entropy->nonzero_code = *i_prev;
- bit_entropy->entropy -= VP8LFastSLog2(*val_prev) * streak;
- if (bit_entropy->max_val < *val_prev) {
- bit_entropy->max_val = *val_prev;
- }
- }
-
- // Gather info for the Huffman cost.
- temp0 = (*val_prev != 0);
- HUFFMAN_COST_PASS
-
- *val_prev = val;
- *i_prev = i;
-}
-
-#define ASM_START \
- __asm__ volatile( \
- ".set push \n\t" \
- ".set at \n\t" \
- ".set macro \n\t" \
- "1: \n\t"
-
-// P2 = P0 + P1
-// A..D - offsets
-// E - temp variable to tell macro
-// if pointer should be incremented
-// literal_ and successive histograms could be unaligned
-// so we must use ulw and usw
-#define ADD_TO_OUT(A, B, C, D, E, P0, P1, P2) \
- "ulw %[temp0], " #A "(%[" #P0 "]) \n\t" \
- "ulw %[temp1], " #B "(%[" #P0 "]) \n\t" \
- "ulw %[temp2], " #C "(%[" #P0 "]) \n\t" \
- "ulw %[temp3], " #D "(%[" #P0 "]) \n\t" \
- "ulw %[temp4], " #A "(%[" #P1 "]) \n\t" \
- "ulw %[temp5], " #B "(%[" #P1 "]) \n\t" \
- "ulw %[temp6], " #C "(%[" #P1 "]) \n\t" \
- "ulw %[temp7], " #D "(%[" #P1 "]) \n\t" \
- "addu %[temp4], %[temp4], %[temp0] \n\t" \
- "addu %[temp5], %[temp5], %[temp1] \n\t" \
- "addu %[temp6], %[temp6], %[temp2] \n\t" \
- "addu %[temp7], %[temp7], %[temp3] \n\t" \
- "addiu %[" #P0 "], %[" #P0 "], 16 \n\t" \
- ".if " #E " == 1 \n\t" \
- "addiu %[" #P1 "], %[" #P1 "], 16 \n\t" \
- ".endif \n\t" \
- "usw %[temp4], " #A "(%[" #P2 "]) \n\t" \
- "usw %[temp5], " #B "(%[" #P2 "]) \n\t" \
- "usw %[temp6], " #C "(%[" #P2 "]) \n\t" \
- "usw %[temp7], " #D "(%[" #P2 "]) \n\t" \
- "addiu %[" #P2 "], %[" #P2 "], 16 \n\t" \
- "bne %[" #P0 "], %[LoopEnd], 1b \n\t" \
- ".set pop \n\t" \
-
-#define ASM_END_COMMON_0 \
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), \
- [pa]"+r"(pa), [pout]"+r"(pout)
-
-#define ASM_END_COMMON_1 \
- : [LoopEnd]"r"(LoopEnd) \
- : "memory", "at" \
- );
-
-#define ASM_END_0 \
- ASM_END_COMMON_0 \
- , [pb]"+r"(pb) \
- ASM_END_COMMON_1
-
-#define ASM_END_1 \
- ASM_END_COMMON_0 \
- ASM_END_COMMON_1
-
-#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \
- const uint32_t* pa = (const uint32_t*)(A); \
- const uint32_t* pb = (const uint32_t*)(B); \
- uint32_t* pout = (uint32_t*)(OUT); \
- const uint32_t* const LoopEnd = pa + (SIZE); \
- assert((SIZE) % 4 == 0); \
- ASM_START \
- ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) \
- ASM_END_0 \
- if ((EXTRA_SIZE) > 0) { \
- const int last = (EXTRA_SIZE); \
- int i; \
- for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \
- } \
-} while (0)
-
-#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE) do { \
- const uint32_t* pa = (const uint32_t*)(A); \
- uint32_t* pout = (uint32_t*)(OUT); \
- const uint32_t* const LoopEnd = pa + (SIZE); \
- assert((SIZE) % 4 == 0); \
- ASM_START \
- ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) \
- ASM_END_1 \
- if ((EXTRA_SIZE) > 0) { \
- const int last = (EXTRA_SIZE); \
- int i; \
- for (i = 0; i < last; ++i) pout[i] += pa[i]; \
- } \
-} while (0)
-
-static void HistogramAdd(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
- uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
- const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_)
- - (NUM_LITERAL_CODES + NUM_LENGTH_CODES);
- assert(a->palette_code_bits_ == b->palette_code_bits_);
-
- if (b != out) {
- ADD_VECTOR(a->literal_, b->literal_, out->literal_,
- NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
- ADD_VECTOR(a->distance_, b->distance_, out->distance_,
- NUM_DISTANCE_CODES, 0);
- ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
- } else {
- ADD_VECTOR_EQ(a->literal_, out->literal_,
- NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
- ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0);
- ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
- }
-}
-
-#undef ADD_VECTOR_EQ
-#undef ADD_VECTOR
-#undef ASM_END_1
-#undef ASM_END_0
-#undef ASM_END_COMMON_1
-#undef ASM_END_COMMON_0
-#undef ADD_TO_OUT
-#undef ASM_START
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8LEncDspInitMIPS32(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) {
- VP8LFastSLog2Slow = FastSLog2Slow;
- VP8LFastLog2Slow = FastLog2Slow;
- VP8LExtraCost = ExtraCost;
- VP8LExtraCostCombined = ExtraCostCombined;
- VP8LGetEntropyUnrefinedHelper = GetEntropyUnrefinedHelper;
- VP8LHistogramAdd = HistogramAdd;
-}
-
-#else // !WEBP_USE_MIPS32
-
-WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPS32)
-
-#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/lossless_enc_mips_dsp_r2.c b/drivers/webp/dsp/lossless_enc_mips_dsp_r2.c
deleted file mode 100644
index 0abf3c4f36..0000000000
--- a/drivers/webp/dsp/lossless_enc_mips_dsp_r2.c
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Image transform methods for lossless encoder.
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include "./lossless.h"
-
-static void SubtractGreenFromBlueAndRed(uint32_t* argb_data,
- int num_pixels) {
- uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
- uint32_t* const p_loop1_end = argb_data + (num_pixels & ~3);
- uint32_t* const p_loop2_end = p_loop1_end + (num_pixels & 3);
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[argb_data], %[p_loop1_end], 3f \n\t"
- " nop \n\t"
- "0: \n\t"
- "lw %[temp0], 0(%[argb_data]) \n\t"
- "lw %[temp1], 4(%[argb_data]) \n\t"
- "lw %[temp2], 8(%[argb_data]) \n\t"
- "lw %[temp3], 12(%[argb_data]) \n\t"
- "ext %[temp4], %[temp0], 8, 8 \n\t"
- "ext %[temp5], %[temp1], 8, 8 \n\t"
- "ext %[temp6], %[temp2], 8, 8 \n\t"
- "ext %[temp7], %[temp3], 8, 8 \n\t"
- "addiu %[argb_data], %[argb_data], 16 \n\t"
- "replv.ph %[temp4], %[temp4] \n\t"
- "replv.ph %[temp5], %[temp5] \n\t"
- "replv.ph %[temp6], %[temp6] \n\t"
- "replv.ph %[temp7], %[temp7] \n\t"
- "subu.qb %[temp0], %[temp0], %[temp4] \n\t"
- "subu.qb %[temp1], %[temp1], %[temp5] \n\t"
- "subu.qb %[temp2], %[temp2], %[temp6] \n\t"
- "subu.qb %[temp3], %[temp3], %[temp7] \n\t"
- "sw %[temp0], -16(%[argb_data]) \n\t"
- "sw %[temp1], -12(%[argb_data]) \n\t"
- "sw %[temp2], -8(%[argb_data]) \n\t"
- "bne %[argb_data], %[p_loop1_end], 0b \n\t"
- " sw %[temp3], -4(%[argb_data]) \n\t"
- "3: \n\t"
- "beq %[argb_data], %[p_loop2_end], 2f \n\t"
- " nop \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[argb_data]) \n\t"
- "addiu %[argb_data], %[argb_data], 4 \n\t"
- "ext %[temp4], %[temp0], 8, 8 \n\t"
- "replv.ph %[temp4], %[temp4] \n\t"
- "subu.qb %[temp0], %[temp0], %[temp4] \n\t"
- "bne %[argb_data], %[p_loop2_end], 1b \n\t"
- " sw %[temp0], -4(%[argb_data]) \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [argb_data]"+&r"(argb_data), [temp0]"=&r"(temp0),
- [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6),
- [temp7]"=&r"(temp7)
- : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
- : "memory"
- );
-}
-
-static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
- int8_t color) {
- return (uint32_t)((int)(color_pred) * color) >> 5;
-}
-
-static void TransformColor(const VP8LMultipliers* const m, uint32_t* data,
- int num_pixels) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- uint32_t argb, argb1, new_red, new_red1;
- const uint32_t G_to_R = m->green_to_red_;
- const uint32_t G_to_B = m->green_to_blue_;
- const uint32_t R_to_B = m->red_to_blue_;
- uint32_t* const p_loop_end = data + (num_pixels & ~1);
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[data], %[p_loop_end], 1f \n\t"
- " nop \n\t"
- "replv.ph %[temp0], %[G_to_R] \n\t"
- "replv.ph %[temp1], %[G_to_B] \n\t"
- "replv.ph %[temp2], %[R_to_B] \n\t"
- "shll.ph %[temp0], %[temp0], 8 \n\t"
- "shll.ph %[temp1], %[temp1], 8 \n\t"
- "shll.ph %[temp2], %[temp2], 8 \n\t"
- "shra.ph %[temp0], %[temp0], 8 \n\t"
- "shra.ph %[temp1], %[temp1], 8 \n\t"
- "shra.ph %[temp2], %[temp2], 8 \n\t"
- "0: \n\t"
- "lw %[argb], 0(%[data]) \n\t"
- "lw %[argb1], 4(%[data]) \n\t"
- "lhu %[new_red], 2(%[data]) \n\t"
- "lhu %[new_red1], 6(%[data]) \n\t"
- "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t"
- "precr.qb.ph %[temp4], %[argb], %[argb1] \n\t"
- "preceu.ph.qbra %[temp3], %[temp3] \n\t"
- "preceu.ph.qbla %[temp4], %[temp4] \n\t"
- "shll.ph %[temp3], %[temp3], 8 \n\t"
- "shll.ph %[temp4], %[temp4], 8 \n\t"
- "shra.ph %[temp3], %[temp3], 8 \n\t"
- "shra.ph %[temp4], %[temp4], 8 \n\t"
- "mul.ph %[temp5], %[temp3], %[temp0] \n\t"
- "mul.ph %[temp3], %[temp3], %[temp1] \n\t"
- "mul.ph %[temp4], %[temp4], %[temp2] \n\t"
- "addiu %[data], %[data], 8 \n\t"
- "ins %[new_red1], %[new_red], 16, 16 \n\t"
- "ins %[argb1], %[argb], 16, 16 \n\t"
- "shra.ph %[temp5], %[temp5], 5 \n\t"
- "shra.ph %[temp3], %[temp3], 5 \n\t"
- "shra.ph %[temp4], %[temp4], 5 \n\t"
- "subu.ph %[new_red1], %[new_red1], %[temp5] \n\t"
- "subu.ph %[argb1], %[argb1], %[temp3] \n\t"
- "preceu.ph.qbra %[temp5], %[new_red1] \n\t"
- "subu.ph %[argb1], %[argb1], %[temp4] \n\t"
- "preceu.ph.qbra %[temp3], %[argb1] \n\t"
- "sb %[temp5], -2(%[data]) \n\t"
- "sb %[temp3], -4(%[data]) \n\t"
- "sra %[temp5], %[temp5], 16 \n\t"
- "sra %[temp3], %[temp3], 16 \n\t"
- "sb %[temp5], -6(%[data]) \n\t"
- "bne %[data], %[p_loop_end], 0b \n\t"
- " sb %[temp3], -8(%[data]) \n\t"
- "1: \n\t"
- ".set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [new_red1]"=&r"(new_red1), [new_red]"=&r"(new_red),
- [argb]"=&r"(argb), [argb1]"=&r"(argb1), [data]"+&r"(data)
- : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B),
- [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end)
- : "memory", "hi", "lo"
- );
-
- if (num_pixels & 1) {
- const uint32_t argb_ = data[0];
- const uint32_t green = argb_ >> 8;
- const uint32_t red = argb_ >> 16;
- uint32_t new_blue = argb_;
- new_red = red;
- new_red -= ColorTransformDelta(m->green_to_red_, green);
- new_red &= 0xff;
- new_blue -= ColorTransformDelta(m->green_to_blue_, green);
- new_blue -= ColorTransformDelta(m->red_to_blue_, red);
- new_blue &= 0xff;
- data[0] = (argb_ & 0xff00ff00u) | (new_red << 16) | (new_blue);
- }
-}
-
-static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
- uint8_t red_to_blue,
- uint32_t argb) {
- const uint32_t green = argb >> 8;
- const uint32_t red = argb >> 16;
- uint8_t new_blue = argb;
- new_blue -= ColorTransformDelta(green_to_blue, green);
- new_blue -= ColorTransformDelta(red_to_blue, red);
- return (new_blue & 0xff);
-}
-
-static void CollectColorBlueTransforms(const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_blue, int red_to_blue,
- int histo[]) {
- const int rtb = (red_to_blue << 16) | (red_to_blue & 0xffff);
- const int gtb = (green_to_blue << 16) | (green_to_blue & 0xffff);
- const uint32_t mask = 0xff00ffu;
- while (tile_height-- > 0) {
- int x;
- const uint32_t* p_argb = argb;
- argb += stride;
- for (x = 0; x < (tile_width >> 1); ++x) {
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
- __asm__ volatile (
- "lw %[temp0], 0(%[p_argb]) \n\t"
- "lw %[temp1], 4(%[p_argb]) \n\t"
- "precr.qb.ph %[temp2], %[temp0], %[temp1] \n\t"
- "ins %[temp1], %[temp0], 16, 16 \n\t"
- "shra.ph %[temp2], %[temp2], 8 \n\t"
- "shra.ph %[temp3], %[temp1], 8 \n\t"
- "mul.ph %[temp5], %[temp2], %[rtb] \n\t"
- "mul.ph %[temp6], %[temp3], %[gtb] \n\t"
- "and %[temp4], %[temp1], %[mask] \n\t"
- "addiu %[p_argb], %[p_argb], 8 \n\t"
- "shra.ph %[temp5], %[temp5], 5 \n\t"
- "shra.ph %[temp6], %[temp6], 5 \n\t"
- "subu.qb %[temp2], %[temp4], %[temp5] \n\t"
- "subu.qb %[temp2], %[temp2], %[temp6] \n\t"
- : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
- [temp5]"=&r"(temp5), [temp6]"=&r"(temp6)
- : [rtb]"r"(rtb), [gtb]"r"(gtb), [mask]"r"(mask)
- : "memory", "hi", "lo"
- );
- ++histo[(uint8_t)(temp2 >> 16)];
- ++histo[(uint8_t)temp2];
- }
- if (tile_width & 1) {
- ++histo[TransformColorBlue(green_to_blue, red_to_blue, *p_argb)];
- }
- }
-}
-
-static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
- uint32_t argb) {
- const uint32_t green = argb >> 8;
- uint32_t new_red = argb >> 16;
- new_red -= ColorTransformDelta(green_to_red, green);
- return (new_red & 0xff);
-}
-
-static void CollectColorRedTransforms(const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_red, int histo[]) {
- const int gtr = (green_to_red << 16) | (green_to_red & 0xffff);
- while (tile_height-- > 0) {
- int x;
- const uint32_t* p_argb = argb;
- argb += stride;
- for (x = 0; x < (tile_width >> 1); ++x) {
- int temp0, temp1, temp2, temp3, temp4;
- __asm__ volatile (
- "lw %[temp0], 0(%[p_argb]) \n\t"
- "lw %[temp1], 4(%[p_argb]) \n\t"
- "precrq.ph.w %[temp4], %[temp0], %[temp1] \n\t"
- "ins %[temp1], %[temp0], 16, 16 \n\t"
- "shra.ph %[temp3], %[temp1], 8 \n\t"
- "mul.ph %[temp2], %[temp3], %[gtr] \n\t"
- "addiu %[p_argb], %[p_argb], 8 \n\t"
- "shra.ph %[temp2], %[temp2], 5 \n\t"
- "subu.qb %[temp2], %[temp4], %[temp2] \n\t"
- : [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4)
- : [gtr]"r"(gtr)
- : "memory", "hi", "lo"
- );
- ++histo[(uint8_t)(temp2 >> 16)];
- ++histo[(uint8_t)temp2];
- }
- if (tile_width & 1) {
- ++histo[TransformColorRed(green_to_red, *p_argb)];
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8LEncDspInitMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPSdspR2(void) {
- VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
- VP8LTransformColor = TransformColor;
- VP8LCollectColorBlueTransforms = CollectColorBlueTransforms;
- VP8LCollectColorRedTransforms = CollectColorRedTransforms;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/lossless_enc_neon.c b/drivers/webp/dsp/lossless_enc_neon.c
deleted file mode 100644
index 4c56f2594b..0000000000
--- a/drivers/webp/dsp/lossless_enc_neon.c
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// NEON variant of methods for lossless encoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_NEON)
-
-#include <arm_neon.h>
-
-#include "./lossless.h"
-#include "./neon.h"
-
-//------------------------------------------------------------------------------
-// Subtract-Green Transform
-
-// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
-// non-standard versions there.
-#if defined(__APPLE__) && defined(__aarch64__) && \
- defined(__apple_build_version__) && (__apple_build_version__< 6020037)
-#define USE_VTBLQ
-#endif
-
-#ifdef USE_VTBLQ
-// 255 = byte will be zeroed
-static const uint8_t kGreenShuffle[16] = {
- 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255
-};
-
-static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
- const uint8x16_t shuffle) {
- return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)),
- vtbl1q_u8(argb, vget_high_u8(shuffle)));
-}
-#else // !USE_VTBLQ
-// 255 = byte will be zeroed
-static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 };
-
-static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
- const uint8x8_t shuffle) {
- return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
- vtbl1_u8(vget_high_u8(argb), shuffle));
-}
-#endif // USE_VTBLQ
-
-static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
- const uint32_t* const end = argb_data + (num_pixels & ~3);
-#ifdef USE_VTBLQ
- const uint8x16_t shuffle = vld1q_u8(kGreenShuffle);
-#else
- const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
-#endif
- for (; argb_data < end; argb_data += 4) {
- const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
- const uint8x16_t greens = DoGreenShuffle(argb, shuffle);
- vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens));
- }
- // fallthrough and finish off with plain-C
- VP8LSubtractGreenFromBlueAndRed_C(argb_data, num_pixels & 3);
-}
-
-//------------------------------------------------------------------------------
-// Color Transform
-
-static void TransformColor(const VP8LMultipliers* const m,
- uint32_t* argb_data, int num_pixels) {
- // sign-extended multiplying constants, pre-shifted by 6.
-#define CST(X) (((int16_t)(m->X << 8)) >> 6)
- const int16_t rb[8] = {
- CST(green_to_blue_), CST(green_to_red_),
- CST(green_to_blue_), CST(green_to_red_),
- CST(green_to_blue_), CST(green_to_red_),
- CST(green_to_blue_), CST(green_to_red_)
- };
- const int16x8_t mults_rb = vld1q_s16(rb);
- const int16_t b2[8] = {
- 0, CST(red_to_blue_), 0, CST(red_to_blue_),
- 0, CST(red_to_blue_), 0, CST(red_to_blue_),
- };
- const int16x8_t mults_b2 = vld1q_s16(b2);
-#undef CST
-#ifdef USE_VTBLQ
- static const uint8_t kg0g0[16] = {
- 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13
- };
- const uint8x16_t shuffle = vld1q_u8(kg0g0);
-#else
- static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 };
- const uint8x8_t shuffle = vld1_u8(k0g0g);
-#endif
- const uint32x4_t mask_rb = vdupq_n_u32(0x00ff00ffu); // red-blue masks
- int i;
- for (i = 0; i + 4 <= num_pixels; i += 4) {
- const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i));
- // 0 g 0 g
- const uint8x16_t greens = DoGreenShuffle(in, shuffle);
- // x dr x db1
- const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb);
- // r 0 b 0
- const int16x8_t B = vshlq_n_s16(vreinterpretq_s16_u8(in), 8);
- // x db2 0 0
- const int16x8_t C = vqdmulhq_s16(B, mults_b2);
- // 0 0 x db2
- const uint32x4_t D = vshrq_n_u32(vreinterpretq_u32_s16(C), 16);
- // x dr x db
- const int8x16_t E = vaddq_s8(vreinterpretq_s8_u32(D),
- vreinterpretq_s8_s16(A));
- // 0 dr 0 db
- const uint32x4_t F = vandq_u32(vreinterpretq_u32_s8(E), mask_rb);
- const int8x16_t out = vsubq_s8(vreinterpretq_s8_u8(in),
- vreinterpretq_s8_u32(F));
- vst1q_s8((int8_t*)(argb_data + i), out);
- }
- // fallthrough and finish off with plain-C
- VP8LTransformColor_C(m, argb_data + i, num_pixels - i);
-}
-
-#undef USE_VTBLQ
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8LEncDspInitNEON(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitNEON(void) {
- VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
- VP8LTransformColor = TransformColor;
-}
-
-#else // !WEBP_USE_NEON
-
-WEBP_DSP_INIT_STUB(VP8LEncDspInitNEON)
-
-#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/lossless_enc_sse2.c b/drivers/webp/dsp/lossless_enc_sse2.c
deleted file mode 100644
index 7c894e7ca4..0000000000
--- a/drivers/webp/dsp/lossless_enc_sse2.c
+++ /dev/null
@@ -1,397 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 variant of methods for lossless encoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-#include <assert.h>
-#include <emmintrin.h>
-#include "./lossless.h"
-
-// For sign-extended multiplying constants, pre-shifted by 5:
-#define CST_5b(X) (((int16_t)((uint16_t)X << 8)) >> 5)
-
-//------------------------------------------------------------------------------
-// Subtract-Green Transform
-
-static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
- int i;
- for (i = 0; i + 4 <= num_pixels; i += 4) {
- const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
- const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g
- const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0));
- const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g
- const __m128i out = _mm_sub_epi8(in, C);
- _mm_storeu_si128((__m128i*)&argb_data[i], out);
- }
- // fallthrough and finish off with plain-C
- VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
-}
-
-//------------------------------------------------------------------------------
-// Color Transform
-
-static void TransformColor(const VP8LMultipliers* const m,
- uint32_t* argb_data, int num_pixels) {
- const __m128i mults_rb = _mm_set_epi16(
- CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
- CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
- CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
- CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_));
- const __m128i mults_b2 = _mm_set_epi16(
- CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0,
- CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0);
- const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks
- const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks
- int i;
- for (i = 0; i + 4 <= num_pixels; i += 4) {
- const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
- const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0
- const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0));
- const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0
- const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1
- const __m128i E = _mm_slli_epi16(in, 8); // r 0 b 0
- const __m128i F = _mm_mulhi_epi16(E, mults_b2); // x db2 0 0
- const __m128i G = _mm_srli_epi32(F, 16); // 0 0 x db2
- const __m128i H = _mm_add_epi8(G, D); // x dr x db
- const __m128i I = _mm_and_si128(H, mask_rb); // 0 dr 0 db
- const __m128i out = _mm_sub_epi8(in, I);
- _mm_storeu_si128((__m128i*)&argb_data[i], out);
- }
- // fallthrough and finish off with plain-C
- VP8LTransformColor_C(m, argb_data + i, num_pixels - i);
-}
-
-//------------------------------------------------------------------------------
-#define SPAN 8
-static void CollectColorBlueTransforms(const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_blue, int red_to_blue,
- int histo[]) {
- const __m128i mults_r = _mm_set_epi16(
- CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0,
- CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0);
- const __m128i mults_g = _mm_set_epi16(
- 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue),
- 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue));
- const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
- const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask
- int y;
- for (y = 0; y < tile_height; ++y) {
- const uint32_t* const src = argb + y * stride;
- int i, x;
- for (x = 0; x + SPAN <= tile_width; x += SPAN) {
- uint16_t values[SPAN];
- const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
- const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
- const __m128i A0 = _mm_slli_epi16(in0, 8); // r 0 | b 0
- const __m128i A1 = _mm_slli_epi16(in1, 8);
- const __m128i B0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0
- const __m128i B1 = _mm_and_si128(in1, mask_g);
- const __m128i C0 = _mm_mulhi_epi16(A0, mults_r); // x db | 0 0
- const __m128i C1 = _mm_mulhi_epi16(A1, mults_r);
- const __m128i D0 = _mm_mulhi_epi16(B0, mults_g); // 0 0 | x db
- const __m128i D1 = _mm_mulhi_epi16(B1, mults_g);
- const __m128i E0 = _mm_sub_epi8(in0, D0); // x x | x b'
- const __m128i E1 = _mm_sub_epi8(in1, D1);
- const __m128i F0 = _mm_srli_epi32(C0, 16); // 0 0 | x db
- const __m128i F1 = _mm_srli_epi32(C1, 16);
- const __m128i G0 = _mm_sub_epi8(E0, F0); // 0 0 | x b'
- const __m128i G1 = _mm_sub_epi8(E1, F1);
- const __m128i H0 = _mm_and_si128(G0, mask_b); // 0 0 | 0 b
- const __m128i H1 = _mm_and_si128(G1, mask_b);
- const __m128i I = _mm_packs_epi32(H0, H1); // 0 b' | 0 b'
- _mm_storeu_si128((__m128i*)values, I);
- for (i = 0; i < SPAN; ++i) ++histo[values[i]];
- }
- }
- {
- const int left_over = tile_width & (SPAN - 1);
- if (left_over > 0) {
- VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride,
- left_over, tile_height,
- green_to_blue, red_to_blue, histo);
- }
- }
-}
-
-static void CollectColorRedTransforms(const uint32_t* argb, int stride,
- int tile_width, int tile_height,
- int green_to_red, int histo[]) {
- const __m128i mults_g = _mm_set_epi16(
- 0, CST_5b(green_to_red), 0, CST_5b(green_to_red),
- 0, CST_5b(green_to_red), 0, CST_5b(green_to_red));
- const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
- const __m128i mask = _mm_set1_epi32(0xff);
-
- int y;
- for (y = 0; y < tile_height; ++y) {
- const uint32_t* const src = argb + y * stride;
- int i, x;
- for (x = 0; x + SPAN <= tile_width; x += SPAN) {
- uint16_t values[SPAN];
- const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
- const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
- const __m128i A0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0
- const __m128i A1 = _mm_and_si128(in1, mask_g);
- const __m128i B0 = _mm_srli_epi32(in0, 16); // 0 0 | x r
- const __m128i B1 = _mm_srli_epi32(in1, 16);
- const __m128i C0 = _mm_mulhi_epi16(A0, mults_g); // 0 0 | x dr
- const __m128i C1 = _mm_mulhi_epi16(A1, mults_g);
- const __m128i E0 = _mm_sub_epi8(B0, C0); // x x | x r'
- const __m128i E1 = _mm_sub_epi8(B1, C1);
- const __m128i F0 = _mm_and_si128(E0, mask); // 0 0 | 0 r'
- const __m128i F1 = _mm_and_si128(E1, mask);
- const __m128i I = _mm_packs_epi32(F0, F1);
- _mm_storeu_si128((__m128i*)values, I);
- for (i = 0; i < SPAN; ++i) ++histo[values[i]];
- }
- }
- {
- const int left_over = tile_width & (SPAN - 1);
- if (left_over > 0) {
- VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride,
- left_over, tile_height,
- green_to_red, histo);
- }
- }
-}
-#undef SPAN
-
-//------------------------------------------------------------------------------
-
-#define LINE_SIZE 16 // 8 or 16
-static void AddVector(const uint32_t* a, const uint32_t* b, uint32_t* out,
- int size) {
- int i;
- assert(size % LINE_SIZE == 0);
- for (i = 0; i < size; i += LINE_SIZE) {
- const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
- const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
-#if (LINE_SIZE == 16)
- const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]);
- const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]);
-#endif
- const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i + 0]);
- const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]);
-#if (LINE_SIZE == 16)
- const __m128i b2 = _mm_loadu_si128((const __m128i*)&b[i + 8]);
- const __m128i b3 = _mm_loadu_si128((const __m128i*)&b[i + 12]);
-#endif
- _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0));
- _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1));
-#if (LINE_SIZE == 16)
- _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2));
- _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
-#endif
- }
-}
-
-static void AddVectorEq(const uint32_t* a, uint32_t* out, int size) {
- int i;
- assert(size % LINE_SIZE == 0);
- for (i = 0; i < size; i += LINE_SIZE) {
- const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
- const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
-#if (LINE_SIZE == 16)
- const __m128i a2 = _mm_loadu_si128((const __m128i*)&a[i + 8]);
- const __m128i a3 = _mm_loadu_si128((const __m128i*)&a[i + 12]);
-#endif
- const __m128i b0 = _mm_loadu_si128((const __m128i*)&out[i + 0]);
- const __m128i b1 = _mm_loadu_si128((const __m128i*)&out[i + 4]);
-#if (LINE_SIZE == 16)
- const __m128i b2 = _mm_loadu_si128((const __m128i*)&out[i + 8]);
- const __m128i b3 = _mm_loadu_si128((const __m128i*)&out[i + 12]);
-#endif
- _mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0));
- _mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1));
-#if (LINE_SIZE == 16)
- _mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2));
- _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
-#endif
- }
-}
-#undef LINE_SIZE
-
-// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
-// that's ok since the histogram values are less than 1<<28 (max picture size).
-static void HistogramAdd(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
- int i;
- const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
- assert(a->palette_code_bits_ == b->palette_code_bits_);
- if (b != out) {
- AddVector(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES);
- AddVector(a->red_, b->red_, out->red_, NUM_LITERAL_CODES);
- AddVector(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES);
- AddVector(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES);
- } else {
- AddVectorEq(a->literal_, out->literal_, NUM_LITERAL_CODES);
- AddVectorEq(a->red_, out->red_, NUM_LITERAL_CODES);
- AddVectorEq(a->blue_, out->blue_, NUM_LITERAL_CODES);
- AddVectorEq(a->alpha_, out->alpha_, NUM_LITERAL_CODES);
- }
- for (i = NUM_LITERAL_CODES; i < literal_size; ++i) {
- out->literal_[i] = a->literal_[i] + b->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] = a->distance_[i] + b->distance_[i];
- }
-}
-
-//------------------------------------------------------------------------------
-// Entropy
-
-// Checks whether the X or Y contribution is worth computing and adding.
-// Used in loop unrolling.
-#define ANALYZE_X_OR_Y(x_or_y, j) \
- do { \
- if (x_or_y[i + j] != 0) retval -= VP8LFastSLog2(x_or_y[i + j]); \
- } while (0)
-
-// Checks whether the X + Y contribution is worth computing and adding.
-// Used in loop unrolling.
-#define ANALYZE_XY(j) \
- do { \
- if (tmp[j] != 0) { \
- retval -= VP8LFastSLog2(tmp[j]); \
- ANALYZE_X_OR_Y(X, j); \
- } \
- } while (0)
-
-static float CombinedShannonEntropy(const int X[256], const int Y[256]) {
- int i;
- double retval = 0.;
- int sumX, sumXY;
- int32_t tmp[4];
- __m128i zero = _mm_setzero_si128();
- // Sums up X + Y, 4 ints at a time (and will merge it at the end for sumXY).
- __m128i sumXY_128 = zero;
- __m128i sumX_128 = zero;
-
- for (i = 0; i < 256; i += 4) {
- const __m128i x = _mm_loadu_si128((const __m128i*)(X + i));
- const __m128i y = _mm_loadu_si128((const __m128i*)(Y + i));
-
- // Check if any X is non-zero: this actually provides a speedup as X is
- // usually sparse.
- if (_mm_movemask_epi8(_mm_cmpeq_epi32(x, zero)) != 0xFFFF) {
- const __m128i xy_128 = _mm_add_epi32(x, y);
- sumXY_128 = _mm_add_epi32(sumXY_128, xy_128);
-
- sumX_128 = _mm_add_epi32(sumX_128, x);
-
- // Analyze the different X + Y.
- _mm_storeu_si128((__m128i*)tmp, xy_128);
-
- ANALYZE_XY(0);
- ANALYZE_XY(1);
- ANALYZE_XY(2);
- ANALYZE_XY(3);
- } else {
- // X is fully 0, so only deal with Y.
- sumXY_128 = _mm_add_epi32(sumXY_128, y);
-
- ANALYZE_X_OR_Y(Y, 0);
- ANALYZE_X_OR_Y(Y, 1);
- ANALYZE_X_OR_Y(Y, 2);
- ANALYZE_X_OR_Y(Y, 3);
- }
- }
-
- // Sum up sumX_128 to get sumX.
- _mm_storeu_si128((__m128i*)tmp, sumX_128);
- sumX = tmp[3] + tmp[2] + tmp[1] + tmp[0];
-
- // Sum up sumXY_128 to get sumXY.
- _mm_storeu_si128((__m128i*)tmp, sumXY_128);
- sumXY = tmp[3] + tmp[2] + tmp[1] + tmp[0];
-
- retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY);
- return (float)retval;
-}
-#undef ANALYZE_X_OR_Y
-#undef ANALYZE_XY
-
-//------------------------------------------------------------------------------
-
-static int VectorMismatch(const uint32_t* const array1,
- const uint32_t* const array2, int length) {
- int match_len;
-
- if (length >= 12) {
- __m128i A0 = _mm_loadu_si128((const __m128i*)&array1[0]);
- __m128i A1 = _mm_loadu_si128((const __m128i*)&array2[0]);
- match_len = 0;
- do {
- // Loop unrolling and early load both provide a speedup of 10% for the
- // current function. Also, max_limit can be MAX_LENGTH=4096 at most.
- const __m128i cmpA = _mm_cmpeq_epi32(A0, A1);
- const __m128i B0 =
- _mm_loadu_si128((const __m128i*)&array1[match_len + 4]);
- const __m128i B1 =
- _mm_loadu_si128((const __m128i*)&array2[match_len + 4]);
- if (_mm_movemask_epi8(cmpA) != 0xffff) break;
- match_len += 4;
-
- {
- const __m128i cmpB = _mm_cmpeq_epi32(B0, B1);
- A0 = _mm_loadu_si128((const __m128i*)&array1[match_len + 4]);
- A1 = _mm_loadu_si128((const __m128i*)&array2[match_len + 4]);
- if (_mm_movemask_epi8(cmpB) != 0xffff) break;
- match_len += 4;
- }
- } while (match_len + 12 < length);
- } else {
- match_len = 0;
- // Unroll the potential first two loops.
- if (length >= 4 &&
- _mm_movemask_epi8(_mm_cmpeq_epi32(
- _mm_loadu_si128((const __m128i*)&array1[0]),
- _mm_loadu_si128((const __m128i*)&array2[0]))) == 0xffff) {
- match_len = 4;
- if (length >= 8 &&
- _mm_movemask_epi8(_mm_cmpeq_epi32(
- _mm_loadu_si128((const __m128i*)&array1[4]),
- _mm_loadu_si128((const __m128i*)&array2[4]))) == 0xffff)
- match_len = 8;
- }
- }
-
- while (match_len < length && array1[match_len] == array2[match_len]) {
- ++match_len;
- }
- return match_len;
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8LEncDspInitSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) {
- VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
- VP8LTransformColor = TransformColor;
- VP8LCollectColorBlueTransforms = CollectColorBlueTransforms;
- VP8LCollectColorRedTransforms = CollectColorRedTransforms;
- VP8LHistogramAdd = HistogramAdd;
- VP8LCombinedShannonEntropy = CombinedShannonEntropy;
- VP8LVectorMismatch = VectorMismatch;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/lossless_enc_sse41.c b/drivers/webp/dsp/lossless_enc_sse41.c
deleted file mode 100644
index 3e493198db..0000000000
--- a/drivers/webp/dsp/lossless_enc_sse41.c
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE4.1 variant of methods for lossless encoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE41)
-#include <assert.h>
-#include <smmintrin.h>
-#include "./lossless.h"
-
-//------------------------------------------------------------------------------
-// Subtract-Green Transform
-
-static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
- int i;
- const __m128i kCstShuffle = _mm_set_epi8(-1, 13, -1, 13, -1, 9, -1, 9,
- -1, 5, -1, 5, -1, 1, -1, 1);
- for (i = 0; i + 4 <= num_pixels; i += 4) {
- const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]);
- const __m128i in_0g0g = _mm_shuffle_epi8(in, kCstShuffle);
- const __m128i out = _mm_sub_epi8(in, in_0g0g);
- _mm_storeu_si128((__m128i*)&argb_data[i], out);
- }
- // fallthrough and finish off with plain-C
- VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8LEncDspInitSSE41(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) {
- VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
-}
-
-#else // !WEBP_USE_SSE41
-
-WEBP_DSP_INIT_STUB(VP8LEncDspInitSSE41)
-
-#endif // WEBP_USE_SSE41
diff --git a/drivers/webp/dsp/lossless_mips_dsp_r2.c b/drivers/webp/dsp/lossless_mips_dsp_r2.c
deleted file mode 100644
index 90aed7f151..0000000000
--- a/drivers/webp/dsp/lossless_mips_dsp_r2.c
+++ /dev/null
@@ -1,680 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Image transforms and color space conversion methods for lossless decoder.
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include "./lossless.h"
-
-#define MAP_COLOR_FUNCS(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \
-static void FUNC_NAME(const TYPE* src, \
- const uint32_t* const color_map, \
- TYPE* dst, int y_start, int y_end, \
- int width) { \
- int y; \
- for (y = y_start; y < y_end; ++y) { \
- int x; \
- for (x = 0; x < (width >> 2); ++x) { \
- int tmp1, tmp2, tmp3, tmp4; \
- __asm__ volatile ( \
- ".ifc " #TYPE ", uint8_t \n\t" \
- "lbu %[tmp1], 0(%[src]) \n\t" \
- "lbu %[tmp2], 1(%[src]) \n\t" \
- "lbu %[tmp3], 2(%[src]) \n\t" \
- "lbu %[tmp4], 3(%[src]) \n\t" \
- "addiu %[src], %[src], 4 \n\t" \
- ".endif \n\t" \
- ".ifc " #TYPE ", uint32_t \n\t" \
- "lw %[tmp1], 0(%[src]) \n\t" \
- "lw %[tmp2], 4(%[src]) \n\t" \
- "lw %[tmp3], 8(%[src]) \n\t" \
- "lw %[tmp4], 12(%[src]) \n\t" \
- "ext %[tmp1], %[tmp1], 8, 8 \n\t" \
- "ext %[tmp2], %[tmp2], 8, 8 \n\t" \
- "ext %[tmp3], %[tmp3], 8, 8 \n\t" \
- "ext %[tmp4], %[tmp4], 8, 8 \n\t" \
- "addiu %[src], %[src], 16 \n\t" \
- ".endif \n\t" \
- "sll %[tmp1], %[tmp1], 2 \n\t" \
- "sll %[tmp2], %[tmp2], 2 \n\t" \
- "sll %[tmp3], %[tmp3], 2 \n\t" \
- "sll %[tmp4], %[tmp4], 2 \n\t" \
- "lwx %[tmp1], %[tmp1](%[color_map]) \n\t" \
- "lwx %[tmp2], %[tmp2](%[color_map]) \n\t" \
- "lwx %[tmp3], %[tmp3](%[color_map]) \n\t" \
- "lwx %[tmp4], %[tmp4](%[color_map]) \n\t" \
- ".ifc " #TYPE ", uint8_t \n\t" \
- "ext %[tmp1], %[tmp1], 8, 8 \n\t" \
- "ext %[tmp2], %[tmp2], 8, 8 \n\t" \
- "ext %[tmp3], %[tmp3], 8, 8 \n\t" \
- "ext %[tmp4], %[tmp4], 8, 8 \n\t" \
- "sb %[tmp1], 0(%[dst]) \n\t" \
- "sb %[tmp2], 1(%[dst]) \n\t" \
- "sb %[tmp3], 2(%[dst]) \n\t" \
- "sb %[tmp4], 3(%[dst]) \n\t" \
- "addiu %[dst], %[dst], 4 \n\t" \
- ".endif \n\t" \
- ".ifc " #TYPE ", uint32_t \n\t" \
- "sw %[tmp1], 0(%[dst]) \n\t" \
- "sw %[tmp2], 4(%[dst]) \n\t" \
- "sw %[tmp3], 8(%[dst]) \n\t" \
- "sw %[tmp4], 12(%[dst]) \n\t" \
- "addiu %[dst], %[dst], 16 \n\t" \
- ".endif \n\t" \
- : [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), [tmp3]"=&r"(tmp3), \
- [tmp4]"=&r"(tmp4), [src]"+&r"(src), [dst]"+r"(dst) \
- : [color_map]"r"(color_map) \
- : "memory" \
- ); \
- } \
- for (x = 0; x < (width & 3); ++x) { \
- *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \
- } \
- } \
-}
-
-MAP_COLOR_FUNCS(MapARGB, uint32_t, VP8GetARGBIndex, VP8GetARGBValue)
-MAP_COLOR_FUNCS(MapAlpha, uint8_t, VP8GetAlphaIndex, VP8GetAlphaValue)
-
-#undef MAP_COLOR_FUNCS
-
-static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
- uint32_t c2) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- __asm__ volatile (
- "preceu.ph.qbr %[temp1], %[c0] \n\t"
- "preceu.ph.qbl %[temp2], %[c0] \n\t"
- "preceu.ph.qbr %[temp3], %[c1] \n\t"
- "preceu.ph.qbl %[temp4], %[c1] \n\t"
- "preceu.ph.qbr %[temp5], %[c2] \n\t"
- "preceu.ph.qbl %[temp0], %[c2] \n\t"
- "subq.ph %[temp3], %[temp3], %[temp5] \n\t"
- "subq.ph %[temp4], %[temp4], %[temp0] \n\t"
- "addq.ph %[temp1], %[temp1], %[temp3] \n\t"
- "addq.ph %[temp2], %[temp2], %[temp4] \n\t"
- "shll_s.ph %[temp1], %[temp1], 7 \n\t"
- "shll_s.ph %[temp2], %[temp2], 7 \n\t"
- "precrqu_s.qb.ph %[temp2], %[temp2], %[temp1] \n\t"
- : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5)
- : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2)
- : "memory"
- );
- return temp2;
-}
-
-static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
- uint32_t c2) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- __asm__ volatile (
- "adduh.qb %[temp5], %[c0], %[c1] \n\t"
- "preceu.ph.qbr %[temp3], %[c2] \n\t"
- "preceu.ph.qbr %[temp1], %[temp5] \n\t"
- "preceu.ph.qbl %[temp2], %[temp5] \n\t"
- "preceu.ph.qbl %[temp4], %[c2] \n\t"
- "subq.ph %[temp3], %[temp1], %[temp3] \n\t"
- "subq.ph %[temp4], %[temp2], %[temp4] \n\t"
- "shrl.ph %[temp5], %[temp3], 15 \n\t"
- "shrl.ph %[temp0], %[temp4], 15 \n\t"
- "addq.ph %[temp3], %[temp3], %[temp5] \n\t"
- "addq.ph %[temp4], %[temp0], %[temp4] \n\t"
- "shra.ph %[temp3], %[temp3], 1 \n\t"
- "shra.ph %[temp4], %[temp4], 1 \n\t"
- "addq.ph %[temp1], %[temp1], %[temp3] \n\t"
- "addq.ph %[temp2], %[temp2], %[temp4] \n\t"
- "shll_s.ph %[temp1], %[temp1], 7 \n\t"
- "shll_s.ph %[temp2], %[temp2], 7 \n\t"
- "precrqu_s.qb.ph %[temp1], %[temp2], %[temp1] \n\t"
- : [temp0]"=r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=r"(temp4), [temp5]"=&r"(temp5)
- : [c0]"r"(c0), [c1]"r"(c1), [c2]"r"(c2)
- : "memory"
- );
- return temp1;
-}
-
-static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- __asm__ volatile (
- "cmpgdu.lt.qb %[temp1], %[c], %[b] \n\t"
- "pick.qb %[temp1], %[b], %[c] \n\t"
- "pick.qb %[temp2], %[c], %[b] \n\t"
- "cmpgdu.lt.qb %[temp4], %[c], %[a] \n\t"
- "pick.qb %[temp4], %[a], %[c] \n\t"
- "pick.qb %[temp5], %[c], %[a] \n\t"
- "subu.qb %[temp3], %[temp1], %[temp2] \n\t"
- "subu.qb %[temp0], %[temp4], %[temp5] \n\t"
- "raddu.w.qb %[temp3], %[temp3] \n\t"
- "raddu.w.qb %[temp0], %[temp0] \n\t"
- "subu %[temp3], %[temp3], %[temp0] \n\t"
- "slti %[temp0], %[temp3], 0x1 \n\t"
- "movz %[a], %[b], %[temp0] \n\t"
- : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp0]"=&r"(temp0),
- [a]"+&r"(a)
- : [b]"r"(b), [c]"r"(c)
- );
- return a;
-}
-
-static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
- __asm__ volatile (
- "adduh.qb %[a0], %[a0], %[a1] \n\t"
- : [a0]"+r"(a0)
- : [a1]"r"(a1)
- );
- return a0;
-}
-
-static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
- return Average2(Average2(a0, a2), a1);
-}
-
-static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
- uint32_t a2, uint32_t a3) {
- return Average2(Average2(a0, a1), Average2(a2, a3));
-}
-
-static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
- return Average3(left, top[0], top[1]);
-}
-
-static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
- return Average2(left, top[-1]);
-}
-
-static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
- return Average2(left, top[0]);
-}
-
-static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
- (void)left;
- return Average2(top[-1], top[0]);
-}
-
-static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
- (void)left;
- return Average2(top[0], top[1]);
-}
-
-static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
- return Average4(left, top[-1], top[0], top[1]);
-}
-
-static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
- return Select(top[0], left, top[-1]);
-}
-
-static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
- return ClampedAddSubtractFull(left, top[0], top[-1]);
-}
-
-static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
- return ClampedAddSubtractHalf(left, top[0], top[-1]);
-}
-
-// Add green to blue and red channels (i.e. perform the inverse transform of
-// 'subtract green').
-static void AddGreenToBlueAndRed(uint32_t* data, int num_pixels) {
- uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
- uint32_t* const p_loop1_end = data + (num_pixels & ~3);
- uint32_t* const p_loop2_end = data + num_pixels;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[data], %[p_loop1_end], 3f \n\t"
- " nop \n\t"
- "0: \n\t"
- "lw %[temp0], 0(%[data]) \n\t"
- "lw %[temp1], 4(%[data]) \n\t"
- "lw %[temp2], 8(%[data]) \n\t"
- "lw %[temp3], 12(%[data]) \n\t"
- "ext %[temp4], %[temp0], 8, 8 \n\t"
- "ext %[temp5], %[temp1], 8, 8 \n\t"
- "ext %[temp6], %[temp2], 8, 8 \n\t"
- "ext %[temp7], %[temp3], 8, 8 \n\t"
- "addiu %[data], %[data], 16 \n\t"
- "replv.ph %[temp4], %[temp4] \n\t"
- "replv.ph %[temp5], %[temp5] \n\t"
- "replv.ph %[temp6], %[temp6] \n\t"
- "replv.ph %[temp7], %[temp7] \n\t"
- "addu.qb %[temp0], %[temp0], %[temp4] \n\t"
- "addu.qb %[temp1], %[temp1], %[temp5] \n\t"
- "addu.qb %[temp2], %[temp2], %[temp6] \n\t"
- "addu.qb %[temp3], %[temp3], %[temp7] \n\t"
- "sw %[temp0], -16(%[data]) \n\t"
- "sw %[temp1], -12(%[data]) \n\t"
- "sw %[temp2], -8(%[data]) \n\t"
- "bne %[data], %[p_loop1_end], 0b \n\t"
- " sw %[temp3], -4(%[data]) \n\t"
- "3: \n\t"
- "beq %[data], %[p_loop2_end], 2f \n\t"
- " nop \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[data]) \n\t"
- "addiu %[data], %[data], 4 \n\t"
- "ext %[temp4], %[temp0], 8, 8 \n\t"
- "replv.ph %[temp4], %[temp4] \n\t"
- "addu.qb %[temp0], %[temp0], %[temp4] \n\t"
- "bne %[data], %[p_loop2_end], 1b \n\t"
- " sw %[temp0], -4(%[data]) \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [data]"+&r"(data), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
- [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), [temp7]"=&r"(temp7)
- : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
- : "memory"
- );
-}
-
-static void TransformColorInverse(const VP8LMultipliers* const m,
- uint32_t* data, int num_pixels) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- uint32_t argb, argb1, new_red;
- const uint32_t G_to_R = m->green_to_red_;
- const uint32_t G_to_B = m->green_to_blue_;
- const uint32_t R_to_B = m->red_to_blue_;
- uint32_t* const p_loop_end = data + (num_pixels & ~1);
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[data], %[p_loop_end], 1f \n\t"
- " nop \n\t"
- "replv.ph %[temp0], %[G_to_R] \n\t"
- "replv.ph %[temp1], %[G_to_B] \n\t"
- "replv.ph %[temp2], %[R_to_B] \n\t"
- "shll.ph %[temp0], %[temp0], 8 \n\t"
- "shll.ph %[temp1], %[temp1], 8 \n\t"
- "shll.ph %[temp2], %[temp2], 8 \n\t"
- "shra.ph %[temp0], %[temp0], 8 \n\t"
- "shra.ph %[temp1], %[temp1], 8 \n\t"
- "shra.ph %[temp2], %[temp2], 8 \n\t"
- "0: \n\t"
- "lw %[argb], 0(%[data]) \n\t"
- "lw %[argb1], 4(%[data]) \n\t"
- "addiu %[data], %[data], 8 \n\t"
- "precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t"
- "preceu.ph.qbra %[temp3], %[temp3] \n\t"
- "shll.ph %[temp3], %[temp3], 8 \n\t"
- "shra.ph %[temp3], %[temp3], 8 \n\t"
- "mul.ph %[temp5], %[temp3], %[temp0] \n\t"
- "mul.ph %[temp3], %[temp3], %[temp1] \n\t"
- "precrq.ph.w %[new_red], %[argb], %[argb1] \n\t"
- "ins %[argb1], %[argb], 16, 16 \n\t"
- "shra.ph %[temp5], %[temp5], 5 \n\t"
- "shra.ph %[temp3], %[temp3], 5 \n\t"
- "addu.ph %[new_red], %[new_red], %[temp5] \n\t"
- "addu.ph %[argb1], %[argb1], %[temp3] \n\t"
- "preceu.ph.qbra %[temp5], %[new_red] \n\t"
- "shll.ph %[temp4], %[temp5], 8 \n\t"
- "shra.ph %[temp4], %[temp4], 8 \n\t"
- "mul.ph %[temp4], %[temp4], %[temp2] \n\t"
- "sb %[temp5], -2(%[data]) \n\t"
- "sra %[temp5], %[temp5], 16 \n\t"
- "shra.ph %[temp4], %[temp4], 5 \n\t"
- "addu.ph %[argb1], %[argb1], %[temp4] \n\t"
- "preceu.ph.qbra %[temp3], %[argb1] \n\t"
- "sb %[temp5], -6(%[data]) \n\t"
- "sb %[temp3], -4(%[data]) \n\t"
- "sra %[temp3], %[temp3], 16 \n\t"
- "bne %[data], %[p_loop_end], 0b \n\t"
- " sb %[temp3], -8(%[data]) \n\t"
- "1: \n\t"
- ".set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [new_red]"=&r"(new_red), [argb]"=&r"(argb),
- [argb1]"=&r"(argb1), [data]"+&r"(data)
- : [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B),
- [G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end)
- : "memory", "hi", "lo"
- );
-
- // Fall-back to C-version for left-overs.
- if (num_pixels & 1) VP8LTransformColorInverse_C(m, data, 1);
-}
-
-static void ConvertBGRAToRGB(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- int temp0, temp1, temp2, temp3;
- const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
- const uint32_t* const p_loop2_end = src + num_pixels;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[src], %[p_loop1_end], 3f \n\t"
- " nop \n\t"
- "0: \n\t"
- "lw %[temp3], 12(%[src]) \n\t"
- "lw %[temp2], 8(%[src]) \n\t"
- "lw %[temp1], 4(%[src]) \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "ins %[temp3], %[temp2], 24, 8 \n\t"
- "sll %[temp2], %[temp2], 8 \n\t"
- "rotr %[temp3], %[temp3], 16 \n\t"
- "ins %[temp2], %[temp1], 0, 16 \n\t"
- "sll %[temp1], %[temp1], 8 \n\t"
- "wsbh %[temp3], %[temp3] \n\t"
- "balign %[temp0], %[temp1], 1 \n\t"
- "wsbh %[temp2], %[temp2] \n\t"
- "wsbh %[temp0], %[temp0] \n\t"
- "usw %[temp3], 8(%[dst]) \n\t"
- "rotr %[temp0], %[temp0], 16 \n\t"
- "usw %[temp2], 4(%[dst]) \n\t"
- "addiu %[src], %[src], 16 \n\t"
- "usw %[temp0], 0(%[dst]) \n\t"
- "bne %[src], %[p_loop1_end], 0b \n\t"
- " addiu %[dst], %[dst], 12 \n\t"
- "3: \n\t"
- "beq %[src], %[p_loop2_end], 2f \n\t"
- " nop \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "addiu %[src], %[src], 4 \n\t"
- "wsbh %[temp1], %[temp0] \n\t"
- "addiu %[dst], %[dst], 3 \n\t"
- "ush %[temp1], -2(%[dst]) \n\t"
- "sra %[temp0], %[temp0], 16 \n\t"
- "bne %[src], %[p_loop2_end], 1b \n\t"
- " sb %[temp0], -3(%[dst]) \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src)
- : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
- : "memory"
- );
-}
-
-static void ConvertBGRAToRGBA(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- int temp0, temp1, temp2, temp3;
- const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
- const uint32_t* const p_loop2_end = src + num_pixels;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[src], %[p_loop1_end], 3f \n\t"
- " nop \n\t"
- "0: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "lw %[temp1], 4(%[src]) \n\t"
- "lw %[temp2], 8(%[src]) \n\t"
- "lw %[temp3], 12(%[src]) \n\t"
- "wsbh %[temp0], %[temp0] \n\t"
- "wsbh %[temp1], %[temp1] \n\t"
- "wsbh %[temp2], %[temp2] \n\t"
- "wsbh %[temp3], %[temp3] \n\t"
- "addiu %[src], %[src], 16 \n\t"
- "balign %[temp0], %[temp0], 1 \n\t"
- "balign %[temp1], %[temp1], 1 \n\t"
- "balign %[temp2], %[temp2], 1 \n\t"
- "balign %[temp3], %[temp3], 1 \n\t"
- "usw %[temp0], 0(%[dst]) \n\t"
- "usw %[temp1], 4(%[dst]) \n\t"
- "usw %[temp2], 8(%[dst]) \n\t"
- "usw %[temp3], 12(%[dst]) \n\t"
- "bne %[src], %[p_loop1_end], 0b \n\t"
- " addiu %[dst], %[dst], 16 \n\t"
- "3: \n\t"
- "beq %[src], %[p_loop2_end], 2f \n\t"
- " nop \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "wsbh %[temp0], %[temp0] \n\t"
- "addiu %[src], %[src], 4 \n\t"
- "balign %[temp0], %[temp0], 1 \n\t"
- "usw %[temp0], 0(%[dst]) \n\t"
- "bne %[src], %[p_loop2_end], 1b \n\t"
- " addiu %[dst], %[dst], 4 \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src)
- : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
- : "memory"
- );
-}
-
-static void ConvertBGRAToRGBA4444(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
- const uint32_t* const p_loop2_end = src + num_pixels;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[src], %[p_loop1_end], 3f \n\t"
- " nop \n\t"
- "0: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "lw %[temp1], 4(%[src]) \n\t"
- "lw %[temp2], 8(%[src]) \n\t"
- "lw %[temp3], 12(%[src]) \n\t"
- "ext %[temp4], %[temp0], 28, 4 \n\t"
- "ext %[temp5], %[temp0], 12, 4 \n\t"
- "ins %[temp0], %[temp4], 0, 4 \n\t"
- "ext %[temp4], %[temp1], 28, 4 \n\t"
- "ins %[temp0], %[temp5], 16, 4 \n\t"
- "ext %[temp5], %[temp1], 12, 4 \n\t"
- "ins %[temp1], %[temp4], 0, 4 \n\t"
- "ext %[temp4], %[temp2], 28, 4 \n\t"
- "ins %[temp1], %[temp5], 16, 4 \n\t"
- "ext %[temp5], %[temp2], 12, 4 \n\t"
- "ins %[temp2], %[temp4], 0, 4 \n\t"
- "ext %[temp4], %[temp3], 28, 4 \n\t"
- "ins %[temp2], %[temp5], 16, 4 \n\t"
- "ext %[temp5], %[temp3], 12, 4 \n\t"
- "ins %[temp3], %[temp4], 0, 4 \n\t"
- "precr.qb.ph %[temp1], %[temp1], %[temp0] \n\t"
- "ins %[temp3], %[temp5], 16, 4 \n\t"
- "addiu %[src], %[src], 16 \n\t"
- "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t"
-#ifdef WEBP_SWAP_16BIT_CSP
- "usw %[temp1], 0(%[dst]) \n\t"
- "usw %[temp3], 4(%[dst]) \n\t"
-#else
- "wsbh %[temp1], %[temp1] \n\t"
- "wsbh %[temp3], %[temp3] \n\t"
- "usw %[temp1], 0(%[dst]) \n\t"
- "usw %[temp3], 4(%[dst]) \n\t"
-#endif
- "bne %[src], %[p_loop1_end], 0b \n\t"
- " addiu %[dst], %[dst], 8 \n\t"
- "3: \n\t"
- "beq %[src], %[p_loop2_end], 2f \n\t"
- " nop \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "ext %[temp4], %[temp0], 28, 4 \n\t"
- "ext %[temp5], %[temp0], 12, 4 \n\t"
- "ins %[temp0], %[temp4], 0, 4 \n\t"
- "ins %[temp0], %[temp5], 16, 4 \n\t"
- "addiu %[src], %[src], 4 \n\t"
- "precr.qb.ph %[temp0], %[temp0], %[temp0] \n\t"
-#ifdef WEBP_SWAP_16BIT_CSP
- "ush %[temp0], 0(%[dst]) \n\t"
-#else
- "wsbh %[temp0], %[temp0] \n\t"
- "ush %[temp0], 0(%[dst]) \n\t"
-#endif
- "bne %[src], %[p_loop2_end], 1b \n\t"
- " addiu %[dst], %[dst], 2 \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [dst]"+&r"(dst), [src]"+&r"(src)
- : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
- : "memory"
- );
-}
-
-static void ConvertBGRAToRGB565(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- int temp0, temp1, temp2, temp3, temp4, temp5;
- const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
- const uint32_t* const p_loop2_end = src + num_pixels;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[src], %[p_loop1_end], 3f \n\t"
- " nop \n\t"
- "0: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "lw %[temp1], 4(%[src]) \n\t"
- "lw %[temp2], 8(%[src]) \n\t"
- "lw %[temp3], 12(%[src]) \n\t"
- "ext %[temp4], %[temp0], 8, 16 \n\t"
- "ext %[temp5], %[temp0], 5, 11 \n\t"
- "ext %[temp0], %[temp0], 3, 5 \n\t"
- "ins %[temp4], %[temp5], 0, 11 \n\t"
- "ext %[temp5], %[temp1], 5, 11 \n\t"
- "ins %[temp4], %[temp0], 0, 5 \n\t"
- "ext %[temp0], %[temp1], 8, 16 \n\t"
- "ext %[temp1], %[temp1], 3, 5 \n\t"
- "ins %[temp0], %[temp5], 0, 11 \n\t"
- "ext %[temp5], %[temp2], 5, 11 \n\t"
- "ins %[temp0], %[temp1], 0, 5 \n\t"
- "ext %[temp1], %[temp2], 8, 16 \n\t"
- "ext %[temp2], %[temp2], 3, 5 \n\t"
- "ins %[temp1], %[temp5], 0, 11 \n\t"
- "ext %[temp5], %[temp3], 5, 11 \n\t"
- "ins %[temp1], %[temp2], 0, 5 \n\t"
- "ext %[temp2], %[temp3], 8, 16 \n\t"
- "ext %[temp3], %[temp3], 3, 5 \n\t"
- "ins %[temp2], %[temp5], 0, 11 \n\t"
- "append %[temp0], %[temp4], 16 \n\t"
- "ins %[temp2], %[temp3], 0, 5 \n\t"
- "addiu %[src], %[src], 16 \n\t"
- "append %[temp2], %[temp1], 16 \n\t"
-#ifdef WEBP_SWAP_16BIT_CSP
- "usw %[temp0], 0(%[dst]) \n\t"
- "usw %[temp2], 4(%[dst]) \n\t"
-#else
- "wsbh %[temp0], %[temp0] \n\t"
- "wsbh %[temp2], %[temp2] \n\t"
- "usw %[temp0], 0(%[dst]) \n\t"
- "usw %[temp2], 4(%[dst]) \n\t"
-#endif
- "bne %[src], %[p_loop1_end], 0b \n\t"
- " addiu %[dst], %[dst], 8 \n\t"
- "3: \n\t"
- "beq %[src], %[p_loop2_end], 2f \n\t"
- " nop \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "ext %[temp4], %[temp0], 8, 16 \n\t"
- "ext %[temp5], %[temp0], 5, 11 \n\t"
- "ext %[temp0], %[temp0], 3, 5 \n\t"
- "ins %[temp4], %[temp5], 0, 11 \n\t"
- "addiu %[src], %[src], 4 \n\t"
- "ins %[temp4], %[temp0], 0, 5 \n\t"
-#ifdef WEBP_SWAP_16BIT_CSP
- "ush %[temp4], 0(%[dst]) \n\t"
-#else
- "wsbh %[temp4], %[temp4] \n\t"
- "ush %[temp4], 0(%[dst]) \n\t"
-#endif
- "bne %[src], %[p_loop2_end], 1b \n\t"
- " addiu %[dst], %[dst], 2 \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [dst]"+&r"(dst), [src]"+&r"(src)
- : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
- : "memory"
- );
-}
-
-static void ConvertBGRAToBGR(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- int temp0, temp1, temp2, temp3;
- const uint32_t* const p_loop1_end = src + (num_pixels & ~3);
- const uint32_t* const p_loop2_end = src + num_pixels;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "beq %[src], %[p_loop1_end], 3f \n\t"
- " nop \n\t"
- "0: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "lw %[temp1], 4(%[src]) \n\t"
- "lw %[temp2], 8(%[src]) \n\t"
- "lw %[temp3], 12(%[src]) \n\t"
- "ins %[temp0], %[temp1], 24, 8 \n\t"
- "sra %[temp1], %[temp1], 8 \n\t"
- "ins %[temp1], %[temp2], 16, 16 \n\t"
- "sll %[temp2], %[temp2], 8 \n\t"
- "balign %[temp3], %[temp2], 1 \n\t"
- "addiu %[src], %[src], 16 \n\t"
- "usw %[temp0], 0(%[dst]) \n\t"
- "usw %[temp1], 4(%[dst]) \n\t"
- "usw %[temp3], 8(%[dst]) \n\t"
- "bne %[src], %[p_loop1_end], 0b \n\t"
- " addiu %[dst], %[dst], 12 \n\t"
- "3: \n\t"
- "beq %[src], %[p_loop2_end], 2f \n\t"
- " nop \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "addiu %[src], %[src], 4 \n\t"
- "addiu %[dst], %[dst], 3 \n\t"
- "ush %[temp0], -3(%[dst]) \n\t"
- "sra %[temp0], %[temp0], 16 \n\t"
- "bne %[src], %[p_loop2_end], 1b \n\t"
- " sb %[temp0], -1(%[dst]) \n\t"
- "2: \n\t"
- ".set pop \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [dst]"+&r"(dst), [src]"+&r"(src)
- : [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)
- : "memory"
- );
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8LDspInitMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMIPSdspR2(void) {
- VP8LMapColor32b = MapARGB;
- VP8LMapColor8b = MapAlpha;
- VP8LPredictors[5] = Predictor5;
- VP8LPredictors[6] = Predictor6;
- VP8LPredictors[7] = Predictor7;
- VP8LPredictors[8] = Predictor8;
- VP8LPredictors[9] = Predictor9;
- VP8LPredictors[10] = Predictor10;
- VP8LPredictors[11] = Predictor11;
- VP8LPredictors[12] = Predictor12;
- VP8LPredictors[13] = Predictor13;
- VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
- VP8LTransformColorInverse = TransformColorInverse;
- VP8LConvertBGRAToRGB = ConvertBGRAToRGB;
- VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
- VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444;
- VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565;
- VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(VP8LDspInitMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/lossless_neon.c b/drivers/webp/dsp/lossless_neon.c
deleted file mode 100644
index 6faccb8f97..0000000000
--- a/drivers/webp/dsp/lossless_neon.c
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// NEON variant of methods for lossless decoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_NEON)
-
-#include <arm_neon.h>
-
-#include "./lossless.h"
-#include "./neon.h"
-
-//------------------------------------------------------------------------------
-// Colorspace conversion functions
-
-#if !defined(WORK_AROUND_GCC)
-// gcc 4.6.0 had some trouble (NDK-r9) with this code. We only use it for
-// gcc-4.8.x at least.
-static void ConvertBGRAToRGBA(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const end = src + (num_pixels & ~15);
- for (; src < end; src += 16) {
- uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
- // swap B and R. (VSWP d0,d2 has no intrinsics equivalent!)
- const uint8x16_t tmp = pixel.val[0];
- pixel.val[0] = pixel.val[2];
- pixel.val[2] = tmp;
- vst4q_u8(dst, pixel);
- dst += 64;
- }
- VP8LConvertBGRAToRGBA_C(src, num_pixels & 15, dst); // left-overs
-}
-
-static void ConvertBGRAToBGR(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const end = src + (num_pixels & ~15);
- for (; src < end; src += 16) {
- const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
- const uint8x16x3_t tmp = { { pixel.val[0], pixel.val[1], pixel.val[2] } };
- vst3q_u8(dst, tmp);
- dst += 48;
- }
- VP8LConvertBGRAToBGR_C(src, num_pixels & 15, dst); // left-overs
-}
-
-static void ConvertBGRAToRGB(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const end = src + (num_pixels & ~15);
- for (; src < end; src += 16) {
- const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
- const uint8x16x3_t tmp = { { pixel.val[2], pixel.val[1], pixel.val[0] } };
- vst3q_u8(dst, tmp);
- dst += 48;
- }
- VP8LConvertBGRAToRGB_C(src, num_pixels & 15, dst); // left-overs
-}
-
-#else // WORK_AROUND_GCC
-
-// gcc-4.6.0 fallback
-
-static const uint8_t kRGBAShuffle[8] = { 2, 1, 0, 3, 6, 5, 4, 7 };
-
-static void ConvertBGRAToRGBA(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const end = src + (num_pixels & ~1);
- const uint8x8_t shuffle = vld1_u8(kRGBAShuffle);
- for (; src < end; src += 2) {
- const uint8x8_t pixels = vld1_u8((uint8_t*)src);
- vst1_u8(dst, vtbl1_u8(pixels, shuffle));
- dst += 8;
- }
- VP8LConvertBGRAToRGBA_C(src, num_pixels & 1, dst); // left-overs
-}
-
-static const uint8_t kBGRShuffle[3][8] = {
- { 0, 1, 2, 4, 5, 6, 8, 9 },
- { 10, 12, 13, 14, 16, 17, 18, 20 },
- { 21, 22, 24, 25, 26, 28, 29, 30 }
-};
-
-static void ConvertBGRAToBGR(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const end = src + (num_pixels & ~7);
- const uint8x8_t shuffle0 = vld1_u8(kBGRShuffle[0]);
- const uint8x8_t shuffle1 = vld1_u8(kBGRShuffle[1]);
- const uint8x8_t shuffle2 = vld1_u8(kBGRShuffle[2]);
- for (; src < end; src += 8) {
- uint8x8x4_t pixels;
- INIT_VECTOR4(pixels,
- vld1_u8((const uint8_t*)(src + 0)),
- vld1_u8((const uint8_t*)(src + 2)),
- vld1_u8((const uint8_t*)(src + 4)),
- vld1_u8((const uint8_t*)(src + 6)));
- vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0));
- vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1));
- vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2));
- dst += 8 * 3;
- }
- VP8LConvertBGRAToBGR_C(src, num_pixels & 7, dst); // left-overs
-}
-
-static const uint8_t kRGBShuffle[3][8] = {
- { 2, 1, 0, 6, 5, 4, 10, 9 },
- { 8, 14, 13, 12, 18, 17, 16, 22 },
- { 21, 20, 26, 25, 24, 30, 29, 28 }
-};
-
-static void ConvertBGRAToRGB(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const uint32_t* const end = src + (num_pixels & ~7);
- const uint8x8_t shuffle0 = vld1_u8(kRGBShuffle[0]);
- const uint8x8_t shuffle1 = vld1_u8(kRGBShuffle[1]);
- const uint8x8_t shuffle2 = vld1_u8(kRGBShuffle[2]);
- for (; src < end; src += 8) {
- uint8x8x4_t pixels;
- INIT_VECTOR4(pixels,
- vld1_u8((const uint8_t*)(src + 0)),
- vld1_u8((const uint8_t*)(src + 2)),
- vld1_u8((const uint8_t*)(src + 4)),
- vld1_u8((const uint8_t*)(src + 6)));
- vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0));
- vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1));
- vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2));
- dst += 8 * 3;
- }
- VP8LConvertBGRAToRGB_C(src, num_pixels & 7, dst); // left-overs
-}
-
-#endif // !WORK_AROUND_GCC
-
-//------------------------------------------------------------------------------
-// Subtract-Green Transform
-
-// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
-// non-standard versions there.
-#if defined(__APPLE__) && defined(__aarch64__) && \
- defined(__apple_build_version__) && (__apple_build_version__< 6020037)
-#define USE_VTBLQ
-#endif
-
-#ifdef USE_VTBLQ
-// 255 = byte will be zeroed
-static const uint8_t kGreenShuffle[16] = {
- 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255
-};
-
-static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
- const uint8x16_t shuffle) {
- return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)),
- vtbl1q_u8(argb, vget_high_u8(shuffle)));
-}
-#else // !USE_VTBLQ
-// 255 = byte will be zeroed
-static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 };
-
-static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
- const uint8x8_t shuffle) {
- return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
- vtbl1_u8(vget_high_u8(argb), shuffle));
-}
-#endif // USE_VTBLQ
-
-static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
- const uint32_t* const end = argb_data + (num_pixels & ~3);
-#ifdef USE_VTBLQ
- const uint8x16_t shuffle = vld1q_u8(kGreenShuffle);
-#else
- const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
-#endif
- for (; argb_data < end; argb_data += 4) {
- const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
- const uint8x16_t greens = DoGreenShuffle(argb, shuffle);
- vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens));
- }
- // fallthrough and finish off with plain-C
- VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3);
-}
-
-//------------------------------------------------------------------------------
-// Color Transform
-
-static void TransformColorInverse(const VP8LMultipliers* const m,
- uint32_t* argb_data, int num_pixels) {
- // sign-extended multiplying constants, pre-shifted by 6.
-#define CST(X) (((int16_t)(m->X << 8)) >> 6)
- const int16_t rb[8] = {
- CST(green_to_blue_), CST(green_to_red_),
- CST(green_to_blue_), CST(green_to_red_),
- CST(green_to_blue_), CST(green_to_red_),
- CST(green_to_blue_), CST(green_to_red_)
- };
- const int16x8_t mults_rb = vld1q_s16(rb);
- const int16_t b2[8] = {
- 0, CST(red_to_blue_), 0, CST(red_to_blue_),
- 0, CST(red_to_blue_), 0, CST(red_to_blue_),
- };
- const int16x8_t mults_b2 = vld1q_s16(b2);
-#undef CST
-#ifdef USE_VTBLQ
- static const uint8_t kg0g0[16] = {
- 255, 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13
- };
- const uint8x16_t shuffle = vld1q_u8(kg0g0);
-#else
- static const uint8_t k0g0g[8] = { 255, 1, 255, 1, 255, 5, 255, 5 };
- const uint8x8_t shuffle = vld1_u8(k0g0g);
-#endif
- const uint32x4_t mask_ag = vdupq_n_u32(0xff00ff00u);
- int i;
- for (i = 0; i + 4 <= num_pixels; i += 4) {
- const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i));
- const uint32x4_t a0g0 = vandq_u32(vreinterpretq_u32_u8(in), mask_ag);
- // 0 g 0 g
- const uint8x16_t greens = DoGreenShuffle(in, shuffle);
- // x dr x db1
- const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb);
- // x r' x b'
- const int8x16_t B = vaddq_s8(vreinterpretq_s8_u8(in),
- vreinterpretq_s8_s16(A));
- // r' 0 b' 0
- const int16x8_t C = vshlq_n_s16(vreinterpretq_s16_s8(B), 8);
- // x db2 0 0
- const int16x8_t D = vqdmulhq_s16(C, mults_b2);
- // 0 x db2 0
- const uint32x4_t E = vshrq_n_u32(vreinterpretq_u32_s16(D), 8);
- // r' x b'' 0
- const int8x16_t F = vaddq_s8(vreinterpretq_s8_u32(E),
- vreinterpretq_s8_s16(C));
- // 0 r' 0 b''
- const uint16x8_t G = vshrq_n_u16(vreinterpretq_u16_s8(F), 8);
- const uint32x4_t out = vorrq_u32(vreinterpretq_u32_u16(G), a0g0);
- vst1q_u32(argb_data + i, out);
- }
- // Fall-back to C-version for left-overs.
- VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i);
-}
-
-#undef USE_VTBLQ
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8LDspInitNEON(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitNEON(void) {
- VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
- VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
- VP8LConvertBGRAToRGB = ConvertBGRAToRGB;
-
- VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
- VP8LTransformColorInverse = TransformColorInverse;
-}
-
-#else // !WEBP_USE_NEON
-
-WEBP_DSP_INIT_STUB(VP8LDspInitNEON)
-
-#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/lossless_sse2.c b/drivers/webp/dsp/lossless_sse2.c
deleted file mode 100644
index 2d016c2911..0000000000
--- a/drivers/webp/dsp/lossless_sse2.c
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 variant of methods for lossless decoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-#include <assert.h>
-#include <emmintrin.h>
-#include "./lossless.h"
-
-//------------------------------------------------------------------------------
-// Predictor Transform
-
-static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
- uint32_t c2) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero);
- const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero);
- const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero);
- const __m128i V1 = _mm_add_epi16(C0, C1);
- const __m128i V2 = _mm_sub_epi16(V1, C2);
- const __m128i b = _mm_packus_epi16(V2, V2);
- const uint32_t output = _mm_cvtsi128_si32(b);
- return output;
-}
-
-static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
- uint32_t c2) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero);
- const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero);
- const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero);
- const __m128i avg = _mm_add_epi16(C1, C0);
- const __m128i A0 = _mm_srli_epi16(avg, 1);
- const __m128i A1 = _mm_sub_epi16(A0, B0);
- const __m128i BgtA = _mm_cmpgt_epi16(B0, A0);
- const __m128i A2 = _mm_sub_epi16(A1, BgtA);
- const __m128i A3 = _mm_srai_epi16(A2, 1);
- const __m128i A4 = _mm_add_epi16(A0, A3);
- const __m128i A5 = _mm_packus_epi16(A4, A4);
- const uint32_t output = _mm_cvtsi128_si32(A5);
- return output;
-}
-
-static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
- int pa_minus_pb;
- const __m128i zero = _mm_setzero_si128();
- const __m128i A0 = _mm_cvtsi32_si128(a);
- const __m128i B0 = _mm_cvtsi32_si128(b);
- const __m128i C0 = _mm_cvtsi32_si128(c);
- const __m128i AC0 = _mm_subs_epu8(A0, C0);
- const __m128i CA0 = _mm_subs_epu8(C0, A0);
- const __m128i BC0 = _mm_subs_epu8(B0, C0);
- const __m128i CB0 = _mm_subs_epu8(C0, B0);
- const __m128i AC = _mm_or_si128(AC0, CA0);
- const __m128i BC = _mm_or_si128(BC0, CB0);
- const __m128i pa = _mm_unpacklo_epi8(AC, zero); // |a - c|
- const __m128i pb = _mm_unpacklo_epi8(BC, zero); // |b - c|
- const __m128i diff = _mm_sub_epi16(pb, pa);
- {
- int16_t out[8];
- _mm_storeu_si128((__m128i*)out, diff);
- pa_minus_pb = out[0] + out[1] + out[2] + out[3];
- }
- return (pa_minus_pb <= 0) ? a : b;
-}
-
-static WEBP_INLINE __m128i Average2_128i(uint32_t a0, uint32_t a1) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a0), zero);
- const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero);
- const __m128i sum = _mm_add_epi16(A1, A0);
- const __m128i avg = _mm_srli_epi16(sum, 1);
- return avg;
-}
-
-static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
- const __m128i avg = Average2_128i(a0, a1);
- const __m128i A2 = _mm_packus_epi16(avg, avg);
- const uint32_t output = _mm_cvtsi128_si32(A2);
- return output;
-}
-
-static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i avg1 = Average2_128i(a0, a2);
- const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero);
- const __m128i sum = _mm_add_epi16(avg1, A1);
- const __m128i avg2 = _mm_srli_epi16(sum, 1);
- const __m128i A2 = _mm_packus_epi16(avg2, avg2);
- const uint32_t output = _mm_cvtsi128_si32(A2);
- return output;
-}
-
-static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
- uint32_t a2, uint32_t a3) {
- const __m128i avg1 = Average2_128i(a0, a1);
- const __m128i avg2 = Average2_128i(a2, a3);
- const __m128i sum = _mm_add_epi16(avg2, avg1);
- const __m128i avg3 = _mm_srli_epi16(sum, 1);
- const __m128i A0 = _mm_packus_epi16(avg3, avg3);
- const uint32_t output = _mm_cvtsi128_si32(A0);
- return output;
-}
-
-static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average3(left, top[0], top[1]);
- return pred;
-}
-static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average2(left, top[-1]);
- return pred;
-}
-static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average2(left, top[0]);
- return pred;
-}
-static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average2(top[-1], top[0]);
- (void)left;
- return pred;
-}
-static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average2(top[0], top[1]);
- (void)left;
- return pred;
-}
-static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
- return pred;
-}
-static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = Select(top[0], left, top[-1]);
- return pred;
-}
-static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
- return pred;
-}
-static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
- const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
- return pred;
-}
-
-//------------------------------------------------------------------------------
-// Subtract-Green Transform
-
-static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
- int i;
- for (i = 0; i + 4 <= num_pixels; i += 4) {
- const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
- const __m128i A = _mm_srli_epi16(in, 8); // 0 a 0 g
- const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0));
- const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // 0g0g
- const __m128i out = _mm_add_epi8(in, C);
- _mm_storeu_si128((__m128i*)&argb_data[i], out);
- }
- // fallthrough and finish off with plain-C
- VP8LAddGreenToBlueAndRed_C(argb_data + i, num_pixels - i);
-}
-
-//------------------------------------------------------------------------------
-// Color Transform
-
-static void TransformColorInverse(const VP8LMultipliers* const m,
- uint32_t* argb_data, int num_pixels) {
- // sign-extended multiplying constants, pre-shifted by 5.
-#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend
- const __m128i mults_rb = _mm_set_epi16(
- CST(green_to_red_), CST(green_to_blue_),
- CST(green_to_red_), CST(green_to_blue_),
- CST(green_to_red_), CST(green_to_blue_),
- CST(green_to_red_), CST(green_to_blue_));
- const __m128i mults_b2 = _mm_set_epi16(
- CST(red_to_blue_), 0, CST(red_to_blue_), 0,
- CST(red_to_blue_), 0, CST(red_to_blue_), 0);
-#undef CST
- const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks
- int i;
- for (i = 0; i + 4 <= num_pixels; i += 4) {
- const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
- const __m128i A = _mm_and_si128(in, mask_ag); // a 0 g 0
- const __m128i B = _mm_shufflelo_epi16(A, _MM_SHUFFLE(2, 2, 0, 0));
- const __m128i C = _mm_shufflehi_epi16(B, _MM_SHUFFLE(2, 2, 0, 0)); // g0g0
- const __m128i D = _mm_mulhi_epi16(C, mults_rb); // x dr x db1
- const __m128i E = _mm_add_epi8(in, D); // x r' x b'
- const __m128i F = _mm_slli_epi16(E, 8); // r' 0 b' 0
- const __m128i G = _mm_mulhi_epi16(F, mults_b2); // x db2 0 0
- const __m128i H = _mm_srli_epi32(G, 8); // 0 x db2 0
- const __m128i I = _mm_add_epi8(H, F); // r' x b'' 0
- const __m128i J = _mm_srli_epi16(I, 8); // 0 r' 0 b''
- const __m128i out = _mm_or_si128(J, A);
- _mm_storeu_si128((__m128i*)&argb_data[i], out);
- }
- // Fall-back to C-version for left-overs.
- VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i);
-}
-
-//------------------------------------------------------------------------------
-// Color-space conversion functions
-
-static void ConvertBGRAToRGBA(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const __m128i* in = (const __m128i*)src;
- __m128i* out = (__m128i*)dst;
- while (num_pixels >= 8) {
- const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
- const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
- const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
- const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
- const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
- const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
- const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
- const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
- const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
- const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
- const __m128i rg0 = _mm_unpacklo_epi8(rb0, ga0); // r0g0r1g1 ... r6g6r7g7
- const __m128i ba0 = _mm_unpackhi_epi8(rb0, ga0); // b0a0b1a1 ... b6a6b7a7
- const __m128i rgba0 = _mm_unpacklo_epi16(rg0, ba0); // rgba0|rgba1...
- const __m128i rgba4 = _mm_unpackhi_epi16(rg0, ba0); // rgba4|rgba5...
- _mm_storeu_si128(out++, rgba0);
- _mm_storeu_si128(out++, rgba4);
- num_pixels -= 8;
- }
- // left-overs
- VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
-}
-
-static void ConvertBGRAToRGBA4444(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const __m128i mask_0x0f = _mm_set1_epi8(0x0f);
- const __m128i mask_0xf0 = _mm_set1_epi8(0xf0);
- const __m128i* in = (const __m128i*)src;
- __m128i* out = (__m128i*)dst;
- while (num_pixels >= 8) {
- const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
- const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
- const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
- const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
- const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
- const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
- const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
- const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
- const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
- const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
- const __m128i ga1 = _mm_srli_epi16(ga0, 4); // g0-|g1-|...|a6-|a7-
- const __m128i rb1 = _mm_and_si128(rb0, mask_0xf0); // -r0|-r1|...|-b6|-a7
- const __m128i ga2 = _mm_and_si128(ga1, mask_0x0f); // g0-|g1-|...|a6-|a7-
- const __m128i rgba0 = _mm_or_si128(ga2, rb1); // rg0..rg7 | ba0..ba7
- const __m128i rgba1 = _mm_srli_si128(rgba0, 8); // ba0..ba7 | 0
-#ifdef WEBP_SWAP_16BIT_CSP
- const __m128i rgba = _mm_unpacklo_epi8(rgba1, rgba0); // barg0...barg7
-#else
- const __m128i rgba = _mm_unpacklo_epi8(rgba0, rgba1); // rgba0...rgba7
-#endif
- _mm_storeu_si128(out++, rgba);
- num_pixels -= 8;
- }
- // left-overs
- VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
-}
-
-static void ConvertBGRAToRGB565(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const __m128i mask_0xe0 = _mm_set1_epi8(0xe0);
- const __m128i mask_0xf8 = _mm_set1_epi8(0xf8);
- const __m128i mask_0x07 = _mm_set1_epi8(0x07);
- const __m128i* in = (const __m128i*)src;
- __m128i* out = (__m128i*)dst;
- while (num_pixels >= 8) {
- const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
- const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
- const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
- const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
- const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
- const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
- const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
- const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
- const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
- const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
- const __m128i rb1 = _mm_and_si128(rb0, mask_0xf8); // -r0..-r7|-b0..-b7
- const __m128i g_lo1 = _mm_srli_epi16(ga0, 5);
- const __m128i g_lo2 = _mm_and_si128(g_lo1, mask_0x07); // g0-...g7-|xx (3b)
- const __m128i g_hi1 = _mm_slli_epi16(ga0, 3);
- const __m128i g_hi2 = _mm_and_si128(g_hi1, mask_0xe0); // -g0...-g7|xx (3b)
- const __m128i b0 = _mm_srli_si128(rb1, 8); // -b0...-b7|0
- const __m128i rg1 = _mm_or_si128(rb1, g_lo2); // gr0...gr7|xx
- const __m128i b1 = _mm_srli_epi16(b0, 3);
- const __m128i gb1 = _mm_or_si128(b1, g_hi2); // bg0...bg7|xx
-#ifdef WEBP_SWAP_16BIT_CSP
- const __m128i rgba = _mm_unpacklo_epi8(gb1, rg1); // rggb0...rggb7
-#else
- const __m128i rgba = _mm_unpacklo_epi8(rg1, gb1); // bgrb0...bgrb7
-#endif
- _mm_storeu_si128(out++, rgba);
- num_pixels -= 8;
- }
- // left-overs
- VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
-}
-
-static void ConvertBGRAToBGR(const uint32_t* src,
- int num_pixels, uint8_t* dst) {
- const __m128i mask_l = _mm_set_epi32(0, 0x00ffffff, 0, 0x00ffffff);
- const __m128i mask_h = _mm_set_epi32(0x00ffffff, 0, 0x00ffffff, 0);
- const __m128i* in = (const __m128i*)src;
- const uint8_t* const end = dst + num_pixels * 3;
- // the last storel_epi64 below writes 8 bytes starting at offset 18
- while (dst + 26 <= end) {
- const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
- const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
- const __m128i a0l = _mm_and_si128(bgra0, mask_l); // bgr0|0|bgr0|0
- const __m128i a4l = _mm_and_si128(bgra4, mask_l); // bgr0|0|bgr0|0
- const __m128i a0h = _mm_and_si128(bgra0, mask_h); // 0|bgr0|0|bgr0
- const __m128i a4h = _mm_and_si128(bgra4, mask_h); // 0|bgr0|0|bgr0
- const __m128i b0h = _mm_srli_epi64(a0h, 8); // 000b|gr00|000b|gr00
- const __m128i b4h = _mm_srli_epi64(a4h, 8); // 000b|gr00|000b|gr00
- const __m128i c0 = _mm_or_si128(a0l, b0h); // rgbrgb00|rgbrgb00
- const __m128i c4 = _mm_or_si128(a4l, b4h); // rgbrgb00|rgbrgb00
- const __m128i c2 = _mm_srli_si128(c0, 8);
- const __m128i c6 = _mm_srli_si128(c4, 8);
- _mm_storel_epi64((__m128i*)(dst + 0), c0);
- _mm_storel_epi64((__m128i*)(dst + 6), c2);
- _mm_storel_epi64((__m128i*)(dst + 12), c4);
- _mm_storel_epi64((__m128i*)(dst + 18), c6);
- dst += 24;
- num_pixels -= 8;
- }
- // left-overs
- VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst);
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void VP8LDspInitSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE2(void) {
- VP8LPredictors[5] = Predictor5;
- VP8LPredictors[6] = Predictor6;
- VP8LPredictors[7] = Predictor7;
- VP8LPredictors[8] = Predictor8;
- VP8LPredictors[9] = Predictor9;
- VP8LPredictors[10] = Predictor10;
- VP8LPredictors[11] = Predictor11;
- VP8LPredictors[12] = Predictor12;
- VP8LPredictors[13] = Predictor13;
-
- VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
- VP8LTransformColorInverse = TransformColorInverse;
-
- VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
- VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444;
- VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565;
- VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(VP8LDspInitSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/mips_macro.h b/drivers/webp/dsp/mips_macro.h
deleted file mode 100644
index 44aba9b71d..0000000000
--- a/drivers/webp/dsp/mips_macro.h
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS common macros
-
-#ifndef WEBP_DSP_MIPS_MACRO_H_
-#define WEBP_DSP_MIPS_MACRO_H_
-
-#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409
-#define WORK_AROUND_GCC
-#endif
-
-#define STR(s) #s
-#define XSTR(s) STR(s)
-
-// O0[31..16 | 15..0] = I0[31..16 | 15..0] + I1[31..16 | 15..0]
-// O1[31..16 | 15..0] = I0[31..16 | 15..0] - I1[31..16 | 15..0]
-// O - output
-// I - input (macro doesn't change it)
-#define ADD_SUB_HALVES(O0, O1, \
- I0, I1) \
- "addq.ph %[" #O0 "], %[" #I0 "], %[" #I1 "] \n\t" \
- "subq.ph %[" #O1 "], %[" #I0 "], %[" #I1 "] \n\t"
-
-// O - output
-// I - input (macro doesn't change it)
-// I[0/1] - offset in bytes
-#define LOAD_IN_X2(O0, O1, \
- I0, I1) \
- "lh %[" #O0 "], " #I0 "(%[in]) \n\t" \
- "lh %[" #O1 "], " #I1 "(%[in]) \n\t"
-
-// I0 - location
-// I1..I9 - offsets in bytes
-#define LOAD_WITH_OFFSET_X4(O0, O1, O2, O3, \
- I0, I1, I2, I3, I4, I5, I6, I7, I8, I9) \
- "ulw %[" #O0 "], " #I1 "+" XSTR(I9) "*" #I5 "(%[" #I0 "]) \n\t" \
- "ulw %[" #O1 "], " #I2 "+" XSTR(I9) "*" #I6 "(%[" #I0 "]) \n\t" \
- "ulw %[" #O2 "], " #I3 "+" XSTR(I9) "*" #I7 "(%[" #I0 "]) \n\t" \
- "ulw %[" #O3 "], " #I4 "+" XSTR(I9) "*" #I8 "(%[" #I0 "]) \n\t"
-
-// O - output
-// IO - input/output
-// I - input (macro doesn't change it)
-#define MUL_SHIFT_SUM(O0, O1, O2, O3, O4, O5, O6, O7, \
- IO0, IO1, IO2, IO3, \
- I0, I1, I2, I3, I4, I5, I6, I7) \
- "mul %[" #O0 "], %[" #I0 "], %[kC2] \n\t" \
- "mul %[" #O1 "], %[" #I0 "], %[kC1] \n\t" \
- "mul %[" #O2 "], %[" #I1 "], %[kC2] \n\t" \
- "mul %[" #O3 "], %[" #I1 "], %[kC1] \n\t" \
- "mul %[" #O4 "], %[" #I2 "], %[kC2] \n\t" \
- "mul %[" #O5 "], %[" #I2 "], %[kC1] \n\t" \
- "mul %[" #O6 "], %[" #I3 "], %[kC2] \n\t" \
- "mul %[" #O7 "], %[" #I3 "], %[kC1] \n\t" \
- "sra %[" #O0 "], %[" #O0 "], 16 \n\t" \
- "sra %[" #O1 "], %[" #O1 "], 16 \n\t" \
- "sra %[" #O2 "], %[" #O2 "], 16 \n\t" \
- "sra %[" #O3 "], %[" #O3 "], 16 \n\t" \
- "sra %[" #O4 "], %[" #O4 "], 16 \n\t" \
- "sra %[" #O5 "], %[" #O5 "], 16 \n\t" \
- "sra %[" #O6 "], %[" #O6 "], 16 \n\t" \
- "sra %[" #O7 "], %[" #O7 "], 16 \n\t" \
- "addu %[" #IO0 "], %[" #IO0 "], %[" #I4 "] \n\t" \
- "addu %[" #IO1 "], %[" #IO1 "], %[" #I5 "] \n\t" \
- "subu %[" #IO2 "], %[" #IO2 "], %[" #I6 "] \n\t" \
- "subu %[" #IO3 "], %[" #IO3 "], %[" #I7 "] \n\t"
-
-// O - output
-// I - input (macro doesn't change it)
-#define INSERT_HALF_X2(O0, O1, \
- I0, I1) \
- "ins %[" #O0 "], %[" #I0 "], 16, 16 \n\t" \
- "ins %[" #O1 "], %[" #I1 "], 16, 16 \n\t"
-
-// O - output
-// I - input (macro doesn't change it)
-#define SRA_16(O0, O1, O2, O3, \
- I0, I1, I2, I3) \
- "sra %[" #O0 "], %[" #I0 "], 16 \n\t" \
- "sra %[" #O1 "], %[" #I1 "], 16 \n\t" \
- "sra %[" #O2 "], %[" #I2 "], 16 \n\t" \
- "sra %[" #O3 "], %[" #I3 "], 16 \n\t"
-
-// temp0[31..16 | 15..0] = temp8[31..16 | 15..0] + temp12[31..16 | 15..0]
-// temp1[31..16 | 15..0] = temp8[31..16 | 15..0] - temp12[31..16 | 15..0]
-// temp0[31..16 | 15..0] = temp0[31..16 >> 3 | 15..0 >> 3]
-// temp1[31..16 | 15..0] = temp1[31..16 >> 3 | 15..0 >> 3]
-// O - output
-// I - input (macro doesn't change it)
-#define SHIFT_R_SUM_X2(O0, O1, O2, O3, O4, O5, O6, O7, \
- I0, I1, I2, I3, I4, I5, I6, I7) \
- "addq.ph %[" #O0 "], %[" #I0 "], %[" #I4 "] \n\t" \
- "subq.ph %[" #O1 "], %[" #I0 "], %[" #I4 "] \n\t" \
- "addq.ph %[" #O2 "], %[" #I1 "], %[" #I5 "] \n\t" \
- "subq.ph %[" #O3 "], %[" #I1 "], %[" #I5 "] \n\t" \
- "addq.ph %[" #O4 "], %[" #I2 "], %[" #I6 "] \n\t" \
- "subq.ph %[" #O5 "], %[" #I2 "], %[" #I6 "] \n\t" \
- "addq.ph %[" #O6 "], %[" #I3 "], %[" #I7 "] \n\t" \
- "subq.ph %[" #O7 "], %[" #I3 "], %[" #I7 "] \n\t" \
- "shra.ph %[" #O0 "], %[" #O0 "], 3 \n\t" \
- "shra.ph %[" #O1 "], %[" #O1 "], 3 \n\t" \
- "shra.ph %[" #O2 "], %[" #O2 "], 3 \n\t" \
- "shra.ph %[" #O3 "], %[" #O3 "], 3 \n\t" \
- "shra.ph %[" #O4 "], %[" #O4 "], 3 \n\t" \
- "shra.ph %[" #O5 "], %[" #O5 "], 3 \n\t" \
- "shra.ph %[" #O6 "], %[" #O6 "], 3 \n\t" \
- "shra.ph %[" #O7 "], %[" #O7 "], 3 \n\t"
-
-// precrq.ph.w temp0, temp8, temp2
-// temp0 = temp8[31..16] | temp2[31..16]
-// ins temp2, temp8, 16, 16
-// temp2 = temp8[31..16] | temp2[15..0]
-// O - output
-// IO - input/output
-// I - input (macro doesn't change it)
-#define PACK_2_HALVES_TO_WORD(O0, O1, O2, O3, \
- IO0, IO1, IO2, IO3, \
- I0, I1, I2, I3) \
- "precrq.ph.w %[" #O0 "], %[" #I0 "], %[" #IO0 "] \n\t" \
- "precrq.ph.w %[" #O1 "], %[" #I1 "], %[" #IO1 "] \n\t" \
- "ins %[" #IO0 "], %[" #I0 "], 16, 16 \n\t" \
- "ins %[" #IO1 "], %[" #I1 "], 16, 16 \n\t" \
- "precrq.ph.w %[" #O2 "], %[" #I2 "], %[" #IO2 "] \n\t" \
- "precrq.ph.w %[" #O3 "], %[" #I3 "], %[" #IO3 "] \n\t" \
- "ins %[" #IO2 "], %[" #I2 "], 16, 16 \n\t" \
- "ins %[" #IO3 "], %[" #I3 "], 16, 16 \n\t"
-
-// preceu.ph.qbr temp0, temp8
-// temp0 = 0 | 0 | temp8[23..16] | temp8[7..0]
-// preceu.ph.qbl temp1, temp8
-// temp1 = temp8[23..16] | temp8[7..0] | 0 | 0
-// O - output
-// I - input (macro doesn't change it)
-#define CONVERT_2_BYTES_TO_HALF(O0, O1, O2, O3, O4, O5, O6, O7, \
- I0, I1, I2, I3) \
- "preceu.ph.qbr %[" #O0 "], %[" #I0 "] \n\t" \
- "preceu.ph.qbl %[" #O1 "], %[" #I0 "] \n\t" \
- "preceu.ph.qbr %[" #O2 "], %[" #I1 "] \n\t" \
- "preceu.ph.qbl %[" #O3 "], %[" #I1 "] \n\t" \
- "preceu.ph.qbr %[" #O4 "], %[" #I2 "] \n\t" \
- "preceu.ph.qbl %[" #O5 "], %[" #I2 "] \n\t" \
- "preceu.ph.qbr %[" #O6 "], %[" #I3 "] \n\t" \
- "preceu.ph.qbl %[" #O7 "], %[" #I3 "] \n\t"
-
-// temp0[31..16 | 15..0] = temp0[31..16 | 15..0] + temp8[31..16 | 15..0]
-// temp0[31..16 | 15..0] = temp0[31..16 <<(s) 7 | 15..0 <<(s) 7]
-// temp1..temp7 same as temp0
-// precrqu_s.qb.ph temp0, temp1, temp0:
-// temp0 = temp1[31..24] | temp1[15..8] | temp0[31..24] | temp0[15..8]
-// store temp0 to dst
-// IO - input/output
-// I - input (macro doesn't change it)
-#define STORE_SAT_SUM_X2(IO0, IO1, IO2, IO3, IO4, IO5, IO6, IO7, \
- I0, I1, I2, I3, I4, I5, I6, I7, \
- I8, I9, I10, I11, I12, I13) \
- "addq.ph %[" #IO0 "], %[" #IO0 "], %[" #I0 "] \n\t" \
- "addq.ph %[" #IO1 "], %[" #IO1 "], %[" #I1 "] \n\t" \
- "addq.ph %[" #IO2 "], %[" #IO2 "], %[" #I2 "] \n\t" \
- "addq.ph %[" #IO3 "], %[" #IO3 "], %[" #I3 "] \n\t" \
- "addq.ph %[" #IO4 "], %[" #IO4 "], %[" #I4 "] \n\t" \
- "addq.ph %[" #IO5 "], %[" #IO5 "], %[" #I5 "] \n\t" \
- "addq.ph %[" #IO6 "], %[" #IO6 "], %[" #I6 "] \n\t" \
- "addq.ph %[" #IO7 "], %[" #IO7 "], %[" #I7 "] \n\t" \
- "shll_s.ph %[" #IO0 "], %[" #IO0 "], 7 \n\t" \
- "shll_s.ph %[" #IO1 "], %[" #IO1 "], 7 \n\t" \
- "shll_s.ph %[" #IO2 "], %[" #IO2 "], 7 \n\t" \
- "shll_s.ph %[" #IO3 "], %[" #IO3 "], 7 \n\t" \
- "shll_s.ph %[" #IO4 "], %[" #IO4 "], 7 \n\t" \
- "shll_s.ph %[" #IO5 "], %[" #IO5 "], 7 \n\t" \
- "shll_s.ph %[" #IO6 "], %[" #IO6 "], 7 \n\t" \
- "shll_s.ph %[" #IO7 "], %[" #IO7 "], 7 \n\t" \
- "precrqu_s.qb.ph %[" #IO0 "], %[" #IO1 "], %[" #IO0 "] \n\t" \
- "precrqu_s.qb.ph %[" #IO2 "], %[" #IO3 "], %[" #IO2 "] \n\t" \
- "precrqu_s.qb.ph %[" #IO4 "], %[" #IO5 "], %[" #IO4 "] \n\t" \
- "precrqu_s.qb.ph %[" #IO6 "], %[" #IO7 "], %[" #IO6 "] \n\t" \
- "usw %[" #IO0 "], " XSTR(I13) "*" #I9 "(%[" #I8 "]) \n\t" \
- "usw %[" #IO2 "], " XSTR(I13) "*" #I10 "(%[" #I8 "]) \n\t" \
- "usw %[" #IO4 "], " XSTR(I13) "*" #I11 "(%[" #I8 "]) \n\t" \
- "usw %[" #IO6 "], " XSTR(I13) "*" #I12 "(%[" #I8 "]) \n\t"
-
-#define OUTPUT_EARLY_CLOBBER_REGS_10() \
- : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), \
- [temp7]"=&r"(temp7), [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), \
- [temp10]"=&r"(temp10)
-
-#define OUTPUT_EARLY_CLOBBER_REGS_18() \
- OUTPUT_EARLY_CLOBBER_REGS_10(), \
- [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), \
- [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), \
- [temp17]"=&r"(temp17), [temp18]"=&r"(temp18)
-
-#endif // WEBP_DSP_MIPS_MACRO_H_
diff --git a/drivers/webp/dsp/msa_macro.h b/drivers/webp/dsp/msa_macro.h
deleted file mode 100644
index 5c707f476a..0000000000
--- a/drivers/webp/dsp/msa_macro.h
+++ /dev/null
@@ -1,555 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MSA common macros
-//
-// Author(s): Prashant Patil (prashant.patil@imgtec.com)
-
-#ifndef WEBP_DSP_MSA_MACRO_H_
-#define WEBP_DSP_MSA_MACRO_H_
-
-#include <stdint.h>
-#include <msa.h>
-
-#if defined(__clang__)
- #define CLANG_BUILD
-#endif
-
-#ifdef CLANG_BUILD
- #define ADDVI_H(a, b) __msa_addvi_h((v8i16)a, b)
- #define SRAI_H(a, b) __msa_srai_h((v8i16)a, b)
- #define SRAI_W(a, b) __msa_srai_w((v4i32)a, b)
-#else
- #define ADDVI_H(a, b) (a + b)
- #define SRAI_H(a, b) (a >> b)
- #define SRAI_W(a, b) (a >> b)
-#endif
-
-#define LD_B(RTYPE, psrc) *((RTYPE*)(psrc))
-#define LD_UB(...) LD_B(v16u8, __VA_ARGS__)
-#define LD_SB(...) LD_B(v16i8, __VA_ARGS__)
-
-#define LD_H(RTYPE, psrc) *((RTYPE*)(psrc))
-#define LD_UH(...) LD_H(v8u16, __VA_ARGS__)
-#define LD_SH(...) LD_H(v8i16, __VA_ARGS__)
-
-#define LD_W(RTYPE, psrc) *((RTYPE*)(psrc))
-#define LD_UW(...) LD_W(v4u32, __VA_ARGS__)
-#define LD_SW(...) LD_W(v4i32, __VA_ARGS__)
-
-#define ST_B(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in
-#define ST_UB(...) ST_B(v16u8, __VA_ARGS__)
-#define ST_SB(...) ST_B(v16i8, __VA_ARGS__)
-
-#define ST_H(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in
-#define ST_UH(...) ST_H(v8u16, __VA_ARGS__)
-#define ST_SH(...) ST_H(v8i16, __VA_ARGS__)
-
-#define ST_W(RTYPE, in, pdst) *((RTYPE*)(pdst)) = in
-#define ST_UW(...) ST_W(v4u32, __VA_ARGS__)
-#define ST_SW(...) ST_W(v4i32, __VA_ARGS__)
-
-#define MSA_LOAD_FUNC(TYPE, INSTR, FUNC_NAME) \
- static inline TYPE FUNC_NAME(const void* const psrc) { \
- const uint8_t* const psrc_m = (const uint8_t*)psrc; \
- TYPE val_m; \
- asm volatile ( \
- "" #INSTR " %[val_m], %[psrc_m] \n\t" \
- : [val_m] "=r" (val_m) \
- : [psrc_m] "m" (*psrc_m)); \
- return val_m; \
- }
-
-#define MSA_LOAD(psrc, FUNC_NAME) FUNC_NAME(psrc)
-
-#define MSA_STORE_FUNC(TYPE, INSTR, FUNC_NAME) \
- static inline void FUNC_NAME(TYPE val, void* const pdst) { \
- uint8_t* const pdst_m = (uint8_t*)pdst; \
- TYPE val_m = val; \
- asm volatile ( \
- " " #INSTR " %[val_m], %[pdst_m] \n\t" \
- : [pdst_m] "=m" (*pdst_m) \
- : [val_m] "r" (val_m)); \
- }
-
-#define MSA_STORE(val, pdst, FUNC_NAME) FUNC_NAME(val, pdst)
-
-#if (__mips_isa_rev >= 6)
- MSA_LOAD_FUNC(uint16_t, lh, msa_lh);
- #define LH(psrc) MSA_LOAD(psrc, msa_lh)
- MSA_LOAD_FUNC(uint32_t, lw, msa_lw);
- #define LW(psrc) MSA_LOAD(psrc, msa_lw)
- #if (__mips == 64)
- MSA_LOAD_FUNC(uint64_t, ld, msa_ld);
- #define LD(psrc) MSA_LOAD(psrc, msa_ld)
- #else // !(__mips == 64)
- #define LD(psrc) ((((uint64_t)MSA_LOAD(psrc + 4, msa_lw)) << 32) | \
- MSA_LOAD(psrc, msa_lw))
- #endif // (__mips == 64)
-
- MSA_STORE_FUNC(uint16_t, sh, msa_sh);
- #define SH(val, pdst) MSA_STORE(val, pdst, msa_sh)
- MSA_STORE_FUNC(uint32_t, sw, msa_sw);
- #define SW(val, pdst) MSA_STORE(val, pdst, msa_sw)
- MSA_STORE_FUNC(uint64_t, sd, msa_sd);
- #define SD(val, pdst) MSA_STORE(val, pdst, msa_sd)
-#else // !(__mips_isa_rev >= 6)
- MSA_LOAD_FUNC(uint16_t, ulh, msa_ulh);
- #define LH(psrc) MSA_LOAD(psrc, msa_ulh)
- MSA_LOAD_FUNC(uint32_t, ulw, msa_ulw);
- #define LW(psrc) MSA_LOAD(psrc, msa_ulw)
- #if (__mips == 64)
- MSA_LOAD_FUNC(uint64_t, uld, msa_uld);
- #define LD(psrc) MSA_LOAD(psrc, msa_uld)
- #else // !(__mips == 64)
- #define LD(psrc) ((((uint64_t)MSA_LOAD(psrc + 4, msa_ulw)) << 32) | \
- MSA_LOAD(psrc, msa_ulw))
- #endif // (__mips == 64)
-
- MSA_STORE_FUNC(uint16_t, ush, msa_ush);
- #define SH(val, pdst) MSA_STORE(val, pdst, msa_ush)
- MSA_STORE_FUNC(uint32_t, usw, msa_usw);
- #define SW(val, pdst) MSA_STORE(val, pdst, msa_usw)
- #define SD(val, pdst) { \
- uint8_t* const pdst_sd_m = (uint8_t*)(pdst); \
- const uint32_t val0_m = (uint32_t)(val & 0x00000000FFFFFFFF); \
- const uint32_t val1_m = (uint32_t)((val >> 32) & 0x00000000FFFFFFFF); \
- SW(val0_m, pdst_sd_m); \
- SW(val1_m, pdst_sd_m + 4); \
- }
-#endif // (__mips_isa_rev >= 6)
-
-/* Description : Load 4 words with stride
- * Arguments : Inputs - psrc, stride
- * Outputs - out0, out1, out2, out3
- * Details : Load word in 'out0' from (psrc)
- * Load word in 'out1' from (psrc + stride)
- * Load word in 'out2' from (psrc + 2 * stride)
- * Load word in 'out3' from (psrc + 3 * stride)
- */
-#define LW4(psrc, stride, out0, out1, out2, out3) { \
- const uint8_t* ptmp = (const uint8_t*)psrc; \
- out0 = LW(ptmp); \
- ptmp += stride; \
- out1 = LW(ptmp); \
- ptmp += stride; \
- out2 = LW(ptmp); \
- ptmp += stride; \
- out3 = LW(ptmp); \
-}
-
-/* Description : Store 4 words with stride
- * Arguments : Inputs - in0, in1, in2, in3, pdst, stride
- * Details : Store word from 'in0' to (pdst)
- * Store word from 'in1' to (pdst + stride)
- * Store word from 'in2' to (pdst + 2 * stride)
- * Store word from 'in3' to (pdst + 3 * stride)
- */
-#define SW4(in0, in1, in2, in3, pdst, stride) { \
- uint8_t* ptmp = (uint8_t*)pdst; \
- SW(in0, ptmp); \
- ptmp += stride; \
- SW(in1, ptmp); \
- ptmp += stride; \
- SW(in2, ptmp); \
- ptmp += stride; \
- SW(in3, ptmp); \
-}
-
-/* Description : Load vectors with 16 byte elements with stride
- * Arguments : Inputs - psrc, stride
- * Outputs - out0, out1
- * Return Type - as per RTYPE
- * Details : Load 16 byte elements in 'out0' from (psrc)
- * Load 16 byte elements in 'out1' from (psrc + stride)
- */
-#define LD_B2(RTYPE, psrc, stride, out0, out1) { \
- out0 = LD_B(RTYPE, psrc); \
- out1 = LD_B(RTYPE, psrc + stride); \
-}
-#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__)
-#define LD_SB2(...) LD_B2(v16i8, __VA_ARGS__)
-
-#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) { \
- LD_B2(RTYPE, psrc, stride, out0, out1); \
- LD_B2(RTYPE, psrc + 2 * stride , stride, out2, out3); \
-}
-#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__)
-#define LD_SB4(...) LD_B4(v16i8, __VA_ARGS__)
-
-/* Description : Load vectors with 8 halfword elements with stride
- * Arguments : Inputs - psrc, stride
- * Outputs - out0, out1
- * Details : Load 8 halfword elements in 'out0' from (psrc)
- * Load 8 halfword elements in 'out1' from (psrc + stride)
- */
-#define LD_H2(RTYPE, psrc, stride, out0, out1) { \
- out0 = LD_H(RTYPE, psrc); \
- out1 = LD_H(RTYPE, psrc + stride); \
-}
-#define LD_UH2(...) LD_H2(v8u16, __VA_ARGS__)
-#define LD_SH2(...) LD_H2(v8i16, __VA_ARGS__)
-
-/* Description : Store 4x4 byte block to destination memory from input vector
- * Arguments : Inputs - in0, in1, pdst, stride
- * Details : 'Idx0' word element from input vector 'in0' is copied to the
- * GP register and stored to (pdst)
- * 'Idx1' word element from input vector 'in0' is copied to the
- * GP register and stored to (pdst + stride)
- * 'Idx2' word element from input vector 'in0' is copied to the
- * GP register and stored to (pdst + 2 * stride)
- * 'Idx3' word element from input vector 'in0' is copied to the
- * GP register and stored to (pdst + 3 * stride)
- */
-#define ST4x4_UB(in0, in1, idx0, idx1, idx2, idx3, pdst, stride) { \
- uint8_t* const pblk_4x4_m = (uint8_t*)pdst; \
- const uint32_t out0_m = __msa_copy_s_w((v4i32)in0, idx0); \
- const uint32_t out1_m = __msa_copy_s_w((v4i32)in0, idx1); \
- const uint32_t out2_m = __msa_copy_s_w((v4i32)in1, idx2); \
- const uint32_t out3_m = __msa_copy_s_w((v4i32)in1, idx3); \
- SW4(out0_m, out1_m, out2_m, out3_m, pblk_4x4_m, stride); \
-}
-
-/* Description : Immediate number of elements to slide
- * Arguments : Inputs - in0, in1, slide_val
- * Outputs - out
- * Return Type - as per RTYPE
- * Details : Byte elements from 'in1' vector are slid into 'in0' by
- * value specified in the 'slide_val'
- */
-#define SLDI_B(RTYPE, in0, in1, slide_val) \
- (RTYPE)__msa_sldi_b((v16i8)in0, (v16i8)in1, slide_val) \
-
-#define SLDI_UB(...) SLDI_B(v16u8, __VA_ARGS__)
-#define SLDI_SB(...) SLDI_B(v16i8, __VA_ARGS__)
-#define SLDI_SH(...) SLDI_B(v8i16, __VA_ARGS__)
-
-/* Description : Shuffle halfword vector elements as per mask vector
- * Arguments : Inputs - in0, in1, in2, in3, mask0, mask1
- * Outputs - out0, out1
- * Return Type - as per RTYPE
- * Details : halfword elements from 'in0' & 'in1' are copied selectively to
- * 'out0' as per control vector 'mask0'
- */
-#define VSHF_H2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) { \
- out0 = (RTYPE)__msa_vshf_h((v8i16)mask0, (v8i16)in1, (v8i16)in0); \
- out1 = (RTYPE)__msa_vshf_h((v8i16)mask1, (v8i16)in3, (v8i16)in2); \
-}
-#define VSHF_H2_UH(...) VSHF_H2(v8u16, __VA_ARGS__)
-#define VSHF_H2_SH(...) VSHF_H2(v8i16, __VA_ARGS__)
-
-/* Description : Clips all signed halfword elements of input vector
- * between 0 & 255
- * Arguments : Input/output - val
- * Return Type - signed halfword
- */
-#define CLIP_SH_0_255(val) { \
- const v8i16 max_m = __msa_ldi_h(255); \
- val = __msa_maxi_s_h((v8i16)val, 0); \
- val = __msa_min_s_h(max_m, (v8i16)val); \
-}
-#define CLIP_SH2_0_255(in0, in1) { \
- CLIP_SH_0_255(in0); \
- CLIP_SH_0_255(in1); \
-}
-
-/* Description : Clips all signed word elements of input vector
- * between 0 & 255
- * Arguments : Input/output - val
- * Return Type - signed word
- */
-#define CLIP_SW_0_255(val) { \
- const v4i32 max_m = __msa_ldi_w(255); \
- val = __msa_maxi_s_w((v4i32)val, 0); \
- val = __msa_min_s_w(max_m, (v4i32)val); \
-}
-#define CLIP_SW4_0_255(in0, in1, in2, in3) { \
- CLIP_SW_0_255(in0); \
- CLIP_SW_0_255(in1); \
- CLIP_SW_0_255(in2); \
- CLIP_SW_0_255(in3); \
-}
-
-/* Description : Set element n input vector to GPR value
- * Arguments : Inputs - in0, in1, in2, in3
- * Output - out
- * Return Type - as per RTYPE
- * Details : Set element 0 in vector 'out' to value specified in 'in0'
- */
-#define INSERT_W2(RTYPE, in0, in1, out) { \
- out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \
- out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \
-}
-#define INSERT_W2_UB(...) INSERT_W2(v16u8, __VA_ARGS__)
-#define INSERT_W2_SB(...) INSERT_W2(v16i8, __VA_ARGS__)
-
-#define INSERT_W4(RTYPE, in0, in1, in2, in3, out) { \
- out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \
- out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \
- out = (RTYPE)__msa_insert_w((v4i32)out, 2, in2); \
- out = (RTYPE)__msa_insert_w((v4i32)out, 3, in3); \
-}
-#define INSERT_W4_UB(...) INSERT_W4(v16u8, __VA_ARGS__)
-#define INSERT_W4_SB(...) INSERT_W4(v16i8, __VA_ARGS__)
-#define INSERT_W4_SW(...) INSERT_W4(v4i32, __VA_ARGS__)
-
-/* Description : Interleave right half of byte elements from vectors
- * Arguments : Inputs - in0, in1, in2, in3
- * Outputs - out0, out1
- * Return Type - as per RTYPE
- * Details : Right half of byte elements of 'in0' and 'in1' are interleaved
- * and written to out0.
- */
-#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \
- out1 = (RTYPE)__msa_ilvr_b((v16i8)in2, (v16i8)in3); \
-}
-#define ILVR_B2_UB(...) ILVR_B2(v16u8, __VA_ARGS__)
-#define ILVR_B2_SB(...) ILVR_B2(v16i8, __VA_ARGS__)
-#define ILVR_B2_UH(...) ILVR_B2(v8u16, __VA_ARGS__)
-#define ILVR_B2_SH(...) ILVR_B2(v8i16, __VA_ARGS__)
-#define ILVR_B2_SW(...) ILVR_B2(v4i32, __VA_ARGS__)
-
-#define ILVR_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \
- out0, out1, out2, out3) { \
- ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1); \
- ILVR_B2(RTYPE, in4, in5, in6, in7, out2, out3); \
-}
-#define ILVR_B4_UB(...) ILVR_B4(v16u8, __VA_ARGS__)
-#define ILVR_B4_SB(...) ILVR_B4(v16i8, __VA_ARGS__)
-#define ILVR_B4_UH(...) ILVR_B4(v8u16, __VA_ARGS__)
-#define ILVR_B4_SH(...) ILVR_B4(v8i16, __VA_ARGS__)
-#define ILVR_B4_SW(...) ILVR_B4(v4i32, __VA_ARGS__)
-
-/* Description : Interleave right half of halfword elements from vectors
- * Arguments : Inputs - in0, in1, in2, in3
- * Outputs - out0, out1
- * Return Type - as per RTYPE
- * Details : Right half of halfword elements of 'in0' and 'in1' are
- * interleaved and written to 'out0'.
- */
-#define ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \
- out1 = (RTYPE)__msa_ilvr_h((v8i16)in2, (v8i16)in3); \
-}
-#define ILVR_H2_UB(...) ILVR_H2(v16u8, __VA_ARGS__)
-#define ILVR_H2_SH(...) ILVR_H2(v8i16, __VA_ARGS__)
-#define ILVR_H2_SW(...) ILVR_H2(v4i32, __VA_ARGS__)
-
-#define ILVR_H4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \
- out0, out1, out2, out3) { \
- ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1); \
- ILVR_H2(RTYPE, in4, in5, in6, in7, out2, out3); \
-}
-#define ILVR_H4_UB(...) ILVR_H4(v16u8, __VA_ARGS__)
-#define ILVR_H4_SH(...) ILVR_H4(v8i16, __VA_ARGS__)
-#define ILVR_H4_SW(...) ILVR_H4(v4i32, __VA_ARGS__)
-
-/* Description : Interleave right half of double word elements from vectors
- * Arguments : Inputs - in0, in1, in2, in3
- * Outputs - out0, out1
- * Return Type - as per RTYPE
- * Details : Right half of double word elements of 'in0' and 'in1' are
- * interleaved and written to 'out0'.
- */
-#define ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)__msa_ilvr_d((v2i64)in0, (v2i64)in1); \
- out1 = (RTYPE)__msa_ilvr_d((v2i64)in2, (v2i64)in3); \
-}
-#define ILVR_D2_UB(...) ILVR_D2(v16u8, __VA_ARGS__)
-#define ILVR_D2_SB(...) ILVR_D2(v16i8, __VA_ARGS__)
-#define ILVR_D2_SH(...) ILVR_D2(v8i16, __VA_ARGS__)
-
-#define ILVRL_H2(RTYPE, in0, in1, out0, out1) { \
- out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \
- out1 = (RTYPE)__msa_ilvl_h((v8i16)in0, (v8i16)in1); \
-}
-#define ILVRL_H2_UB(...) ILVRL_H2(v16u8, __VA_ARGS__)
-#define ILVRL_H2_SB(...) ILVRL_H2(v16i8, __VA_ARGS__)
-#define ILVRL_H2_SH(...) ILVRL_H2(v8i16, __VA_ARGS__)
-#define ILVRL_H2_SW(...) ILVRL_H2(v4i32, __VA_ARGS__)
-#define ILVRL_H2_UW(...) ILVRL_H2(v4u32, __VA_ARGS__)
-
-#define ILVRL_W2(RTYPE, in0, in1, out0, out1) { \
- out0 = (RTYPE)__msa_ilvr_w((v4i32)in0, (v4i32)in1); \
- out1 = (RTYPE)__msa_ilvl_w((v4i32)in0, (v4i32)in1); \
-}
-#define ILVRL_W2_UB(...) ILVRL_W2(v16u8, __VA_ARGS__)
-#define ILVRL_W2_SH(...) ILVRL_W2(v8i16, __VA_ARGS__)
-#define ILVRL_W2_SW(...) ILVRL_W2(v4i32, __VA_ARGS__)
-
-/* Description : Pack even byte elements of vector pairs
- * Arguments : Inputs - in0, in1, in2, in3
- * Outputs - out0, out1
- * Return Type - as per RTYPE
- * Details : Even byte elements of 'in0' are copied to the left half of
- * 'out0' & even byte elements of 'in1' are copied to the right
- * half of 'out0'.
- */
-#define PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)__msa_pckev_b((v16i8)in0, (v16i8)in1); \
- out1 = (RTYPE)__msa_pckev_b((v16i8)in2, (v16i8)in3); \
-}
-#define PCKEV_B2_SB(...) PCKEV_B2(v16i8, __VA_ARGS__)
-#define PCKEV_B2_UB(...) PCKEV_B2(v16u8, __VA_ARGS__)
-#define PCKEV_B2_SH(...) PCKEV_B2(v8i16, __VA_ARGS__)
-#define PCKEV_B2_SW(...) PCKEV_B2(v4i32, __VA_ARGS__)
-
-/* Description : Arithmetic immediate shift right all elements of word vector
- * Arguments : Inputs - in0, in1, shift
- * Outputs - in place operation
- * Return Type - as per input vector RTYPE
- * Details : Each element of vector 'in0' is right shifted by 'shift' and
- * the result is written in-place. 'shift' is a GP variable.
- */
-#define SRAI_W2(RTYPE, in0, in1, shift_val) { \
- in0 = (RTYPE)SRAI_W(in0, shift_val); \
- in1 = (RTYPE)SRAI_W(in1, shift_val); \
-}
-#define SRAI_W2_SW(...) SRAI_W2(v4i32, __VA_ARGS__)
-#define SRAI_W2_UW(...) SRAI_W2(v4u32, __VA_ARGS__)
-
-#define SRAI_W4(RTYPE, in0, in1, in2, in3, shift_val) { \
- SRAI_W2(RTYPE, in0, in1, shift_val); \
- SRAI_W2(RTYPE, in2, in3, shift_val); \
-}
-#define SRAI_W4_SW(...) SRAI_W4(v4i32, __VA_ARGS__)
-#define SRAI_W4_UW(...) SRAI_W4(v4u32, __VA_ARGS__)
-
-/* Description : Arithmetic shift right all elements of half-word vector
- * Arguments : Inputs - in0, in1, shift
- * Outputs - in place operation
- * Return Type - as per input vector RTYPE
- * Details : Each element of vector 'in0' is right shifted by 'shift' and
- * the result is written in-place. 'shift' is a GP variable.
- */
-#define SRAI_H2(RTYPE, in0, in1, shift_val) { \
- in0 = (RTYPE)SRAI_H(in0, shift_val); \
- in1 = (RTYPE)SRAI_H(in1, shift_val); \
-}
-#define SRAI_H2_SH(...) SRAI_H2(v8i16, __VA_ARGS__)
-#define SRAI_H2_UH(...) SRAI_H2(v8u16, __VA_ARGS__)
-
-/* Description : Arithmetic rounded shift right all elements of word vector
- * Arguments : Inputs - in0, in1, shift
- * Outputs - in place operation
- * Return Type - as per input vector RTYPE
- * Details : Each element of vector 'in0' is right shifted by 'shift' and
- * the result is written in-place. 'shift' is a GP variable.
- */
-#define SRARI_W2(RTYPE, in0, in1, shift) { \
- in0 = (RTYPE)__msa_srari_w((v4i32)in0, shift); \
- in1 = (RTYPE)__msa_srari_w((v4i32)in1, shift); \
-}
-#define SRARI_W2_SW(...) SRARI_W2(v4i32, __VA_ARGS__)
-
-#define SRARI_W4(RTYPE, in0, in1, in2, in3, shift) { \
- SRARI_W2(RTYPE, in0, in1, shift); \
- SRARI_W2(RTYPE, in2, in3, shift); \
-}
-#define SRARI_W4_SH(...) SRARI_W4(v8i16, __VA_ARGS__)
-#define SRARI_W4_UW(...) SRARI_W4(v4u32, __VA_ARGS__)
-#define SRARI_W4_SW(...) SRARI_W4(v4i32, __VA_ARGS__)
-
-/* Description : Addition of 2 pairs of half-word vectors
- * Arguments : Inputs - in0, in1, in2, in3
- * Outputs - out0, out1
- * Details : Each element in 'in0' is added to 'in1' and result is written
- * to 'out0'.
- */
-#define ADDVI_H2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)ADDVI_H(in0, in1); \
- out1 = (RTYPE)ADDVI_H(in2, in3); \
-}
-#define ADDVI_H2_SH(...) ADDVI_H2(v8i16, __VA_ARGS__)
-#define ADDVI_H2_UH(...) ADDVI_H2(v8u16, __VA_ARGS__)
-
-/* Description : Addition of 2 pairs of vectors
- * Arguments : Inputs - in0, in1, in2, in3
- * Outputs - out0, out1
- * Details : Each element in 'in0' is added to 'in1' and result is written
- * to 'out0'.
- */
-#define ADD2(in0, in1, in2, in3, out0, out1) { \
- out0 = in0 + in1; \
- out1 = in2 + in3; \
-}
-#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, \
- out0, out1, out2, out3) { \
- ADD2(in0, in1, in2, in3, out0, out1); \
- ADD2(in4, in5, in6, in7, out2, out3); \
-}
-
-/* Description : Sign extend halfword elements from input vector and return
- * the result in pair of vectors
- * Arguments : Input - in (halfword vector)
- * Outputs - out0, out1 (sign extended word vectors)
- * Return Type - signed word
- * Details : Sign bit of halfword elements from input vector 'in' is
- * extracted and interleaved right with same vector 'in0' to
- * generate 4 signed word elements in 'out0'
- * Then interleaved left with same vector 'in0' to
- * generate 4 signed word elements in 'out1'
- */
-#define UNPCK_SH_SW(in, out0, out1) { \
- const v8i16 tmp_m = __msa_clti_s_h((v8i16)in, 0); \
- ILVRL_H2_SW(tmp_m, in, out0, out1); \
-}
-
-/* Description : Butterfly of 4 input vectors
- * Arguments : Inputs - in0, in1, in2, in3
- * Outputs - out0, out1, out2, out3
- * Details : Butterfly operation
- */
-#define BUTTERFLY_4(in0, in1, in2, in3, out0, out1, out2, out3) { \
- out0 = in0 + in3; \
- out1 = in1 + in2; \
- out2 = in1 - in2; \
- out3 = in0 - in3; \
-}
-
-/* Description : Transpose 4x4 block with word elements in vectors
- * Arguments : Inputs - in0, in1, in2, in3
- * Outputs - out0, out1, out2, out3
- * Return Type - as per RTYPE
- */
-#define TRANSPOSE4x4_W(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3) { \
- v4i32 s0_m, s1_m, s2_m, s3_m; \
- ILVRL_W2_SW(in1, in0, s0_m, s1_m); \
- ILVRL_W2_SW(in3, in2, s2_m, s3_m); \
- out0 = (RTYPE)__msa_ilvr_d((v2i64)s2_m, (v2i64)s0_m); \
- out1 = (RTYPE)__msa_ilvl_d((v2i64)s2_m, (v2i64)s0_m); \
- out2 = (RTYPE)__msa_ilvr_d((v2i64)s3_m, (v2i64)s1_m); \
- out3 = (RTYPE)__msa_ilvl_d((v2i64)s3_m, (v2i64)s1_m); \
-}
-#define TRANSPOSE4x4_SW_SW(...) TRANSPOSE4x4_W(v4i32, __VA_ARGS__)
-
-/* Description : Add block 4x4
- * Arguments : Inputs - in0, in1, in2, in3, pdst, stride
- * Details : Least significant 4 bytes from each input vector are added to
- * the destination bytes, clipped between 0-255 and stored.
- */
-#define ADDBLK_ST4x4_UB(in0, in1, in2, in3, pdst, stride) { \
- uint32_t src0_m, src1_m, src2_m, src3_m; \
- v8i16 inp0_m, inp1_m, res0_m, res1_m; \
- v16i8 dst0_m = { 0 }; \
- v16i8 dst1_m = { 0 }; \
- const v16i8 zero_m = { 0 }; \
- ILVR_D2_SH(in1, in0, in3, in2, inp0_m, inp1_m); \
- LW4(pdst, stride, src0_m, src1_m, src2_m, src3_m); \
- INSERT_W2_SB(src0_m, src1_m, dst0_m); \
- INSERT_W2_SB(src2_m, src3_m, dst1_m); \
- ILVR_B2_SH(zero_m, dst0_m, zero_m, dst1_m, res0_m, res1_m); \
- ADD2(res0_m, inp0_m, res1_m, inp1_m, res0_m, res1_m); \
- CLIP_SH2_0_255(res0_m, res1_m); \
- PCKEV_B2_SB(res0_m, res0_m, res1_m, res1_m, dst0_m, dst1_m); \
- ST4x4_UB(dst0_m, dst1_m, 0, 1, 0, 1, pdst, stride); \
-}
-
-#endif /* WEBP_DSP_MSA_MACRO_H_ */
diff --git a/drivers/webp/dsp/neon.h b/drivers/webp/dsp/neon.h
deleted file mode 100644
index 0a06266848..0000000000
--- a/drivers/webp/dsp/neon.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// NEON common code.
-
-#ifndef WEBP_DSP_NEON_H_
-#define WEBP_DSP_NEON_H_
-
-#include <arm_neon.h>
-
-#include "./dsp.h"
-
-// Right now, some intrinsics functions seem slower, so we disable them
-// everywhere except aarch64 where the inline assembly is incompatible.
-#if defined(__aarch64__)
-#define WEBP_USE_INTRINSICS // use intrinsics when possible
-#endif
-
-#define INIT_VECTOR2(v, a, b) do { \
- v.val[0] = a; \
- v.val[1] = b; \
-} while (0)
-
-#define INIT_VECTOR3(v, a, b, c) do { \
- v.val[0] = a; \
- v.val[1] = b; \
- v.val[2] = c; \
-} while (0)
-
-#define INIT_VECTOR4(v, a, b, c, d) do { \
- v.val[0] = a; \
- v.val[1] = b; \
- v.val[2] = c; \
- v.val[3] = d; \
-} while (0)
-
-// if using intrinsics, this flag avoids some functions that make gcc-4.6.3
-// crash ("internal compiler error: in immed_double_const, at emit-rtl.").
-// (probably similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=48183)
-#if !(LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__))
-#define WORK_AROUND_GCC
-#endif
-
-static WEBP_INLINE int32x4x4_t Transpose4x4(const int32x4x4_t rows) {
- uint64x2x2_t row01, row23;
-
- row01.val[0] = vreinterpretq_u64_s32(rows.val[0]);
- row01.val[1] = vreinterpretq_u64_s32(rows.val[1]);
- row23.val[0] = vreinterpretq_u64_s32(rows.val[2]);
- row23.val[1] = vreinterpretq_u64_s32(rows.val[3]);
- // Transpose 64-bit values (there's no vswp equivalent)
- {
- const uint64x1_t row0h = vget_high_u64(row01.val[0]);
- const uint64x1_t row2l = vget_low_u64(row23.val[0]);
- const uint64x1_t row1h = vget_high_u64(row01.val[1]);
- const uint64x1_t row3l = vget_low_u64(row23.val[1]);
- row01.val[0] = vcombine_u64(vget_low_u64(row01.val[0]), row2l);
- row23.val[0] = vcombine_u64(row0h, vget_high_u64(row23.val[0]));
- row01.val[1] = vcombine_u64(vget_low_u64(row01.val[1]), row3l);
- row23.val[1] = vcombine_u64(row1h, vget_high_u64(row23.val[1]));
- }
- {
- const int32x4x2_t out01 = vtrnq_s32(vreinterpretq_s32_u64(row01.val[0]),
- vreinterpretq_s32_u64(row01.val[1]));
- const int32x4x2_t out23 = vtrnq_s32(vreinterpretq_s32_u64(row23.val[0]),
- vreinterpretq_s32_u64(row23.val[1]));
- int32x4x4_t out;
- out.val[0] = out01.val[0];
- out.val[1] = out01.val[1];
- out.val[2] = out23.val[0];
- out.val[3] = out23.val[1];
- return out;
- }
-}
-
-#endif // WEBP_DSP_NEON_H_
diff --git a/drivers/webp/dsp/rescaler.c b/drivers/webp/dsp/rescaler.c
deleted file mode 100644
index bc743d5dc5..0000000000
--- a/drivers/webp/dsp/rescaler.c
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Rescaling functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-
-#include "./dsp.h"
-#include "../utils/rescaler.h"
-
-//------------------------------------------------------------------------------
-// Implementations of critical functions ImportRow / ExportRow
-
-#define ROUNDER (WEBP_RESCALER_ONE >> 1)
-#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
-
-//------------------------------------------------------------------------------
-// Row import
-
-void WebPRescalerImportRowExpandC(WebPRescaler* const wrk, const uint8_t* src) {
- const int x_stride = wrk->num_channels;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- int channel;
- assert(!WebPRescalerInputDone(wrk));
- assert(wrk->x_expand);
- for (channel = 0; channel < x_stride; ++channel) {
- int x_in = channel;
- int x_out = channel;
- // simple bilinear interpolation
- int accum = wrk->x_add;
- int left = src[x_in];
- int right = (wrk->src_width > 1) ? src[x_in + x_stride] : left;
- x_in += x_stride;
- while (1) {
- wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum;
- x_out += x_stride;
- if (x_out >= x_out_max) break;
- accum -= wrk->x_sub;
- if (accum < 0) {
- left = right;
- x_in += x_stride;
- assert(x_in < wrk->src_width * x_stride);
- right = src[x_in];
- accum += wrk->x_add;
- }
- }
- assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0);
- }
-}
-
-void WebPRescalerImportRowShrinkC(WebPRescaler* const wrk, const uint8_t* src) {
- const int x_stride = wrk->num_channels;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- int channel;
- assert(!WebPRescalerInputDone(wrk));
- assert(!wrk->x_expand);
- for (channel = 0; channel < x_stride; ++channel) {
- int x_in = channel;
- int x_out = channel;
- uint32_t sum = 0;
- int accum = 0;
- while (x_out < x_out_max) {
- uint32_t base = 0;
- accum += wrk->x_add;
- while (accum > 0) {
- accum -= wrk->x_sub;
- assert(x_in < wrk->src_width * x_stride);
- base = src[x_in];
- sum += base;
- x_in += x_stride;
- }
- { // Emit next horizontal pixel.
- const rescaler_t frac = base * (-accum);
- wrk->frow[x_out] = sum * wrk->x_sub - frac;
- // fresh fractional start for next pixel
- sum = (int)MULT_FIX(frac, wrk->fx_scale);
- }
- x_out += x_stride;
- }
- assert(accum == 0);
- }
-}
-
-//------------------------------------------------------------------------------
-// Row export
-
-void WebPRescalerExportRowExpandC(WebPRescaler* const wrk) {
- int x_out;
- uint8_t* const dst = wrk->dst;
- rescaler_t* const irow = wrk->irow;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const rescaler_t* const frow = wrk->frow;
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(wrk->y_expand);
- assert(wrk->y_sub != 0);
- if (wrk->y_accum == 0) {
- for (x_out = 0; x_out < x_out_max; ++x_out) {
- const uint32_t J = frow[x_out];
- const int v = (int)MULT_FIX(J, wrk->fy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- }
- } else {
- const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
- const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
- for (x_out = 0; x_out < x_out_max; ++x_out) {
- const uint64_t I = (uint64_t)A * frow[x_out]
- + (uint64_t)B * irow[x_out];
- const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
- const int v = (int)MULT_FIX(J, wrk->fy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- }
- }
-}
-
-void WebPRescalerExportRowShrinkC(WebPRescaler* const wrk) {
- int x_out;
- uint8_t* const dst = wrk->dst;
- rescaler_t* const irow = wrk->irow;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const rescaler_t* const frow = wrk->frow;
- const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(!wrk->y_expand);
- if (yscale) {
- for (x_out = 0; x_out < x_out_max; ++x_out) {
- const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- irow[x_out] = frac; // new fractional start
- }
- } else {
- for (x_out = 0; x_out < x_out_max; ++x_out) {
- const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- irow[x_out] = 0;
- }
- }
-}
-
-#undef MULT_FIX
-#undef ROUNDER
-
-//------------------------------------------------------------------------------
-// Main entry calls
-
-void WebPRescalerImportRow(WebPRescaler* const wrk, const uint8_t* src) {
- assert(!WebPRescalerInputDone(wrk));
- if (!wrk->x_expand) {
- WebPRescalerImportRowShrink(wrk, src);
- } else {
- WebPRescalerImportRowExpand(wrk, src);
- }
-}
-
-void WebPRescalerExportRow(WebPRescaler* const wrk) {
- if (wrk->y_accum <= 0) {
- assert(!WebPRescalerOutputDone(wrk));
- if (wrk->y_expand) {
- WebPRescalerExportRowExpand(wrk);
- } else if (wrk->fxy_scale) {
- WebPRescalerExportRowShrink(wrk);
- } else { // very special case for src = dst = 1x1
- int i;
- assert(wrk->src_width == 1 && wrk->dst_width <= 2);
- assert(wrk->src_height == 1 && wrk->dst_height == 1);
- for (i = 0; i < wrk->num_channels * wrk->dst_width; ++i) {
- wrk->dst[i] = wrk->irow[i];
- wrk->irow[i] = 0;
- }
- }
- wrk->y_accum += wrk->y_add;
- wrk->dst += wrk->dst_stride;
- ++wrk->dst_y;
- }
-}
-
-//------------------------------------------------------------------------------
-
-WebPRescalerImportRowFunc WebPRescalerImportRowExpand;
-WebPRescalerImportRowFunc WebPRescalerImportRowShrink;
-
-WebPRescalerExportRowFunc WebPRescalerExportRowExpand;
-WebPRescalerExportRowFunc WebPRescalerExportRowShrink;
-
-extern void WebPRescalerDspInitSSE2(void);
-extern void WebPRescalerDspInitMIPS32(void);
-extern void WebPRescalerDspInitMIPSdspR2(void);
-extern void WebPRescalerDspInitNEON(void);
-
-static volatile VP8CPUInfo rescaler_last_cpuinfo_used =
- (VP8CPUInfo)&rescaler_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) {
- if (rescaler_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- WebPRescalerImportRowExpand = WebPRescalerImportRowExpandC;
- WebPRescalerImportRowShrink = WebPRescalerImportRowShrinkC;
- WebPRescalerExportRowExpand = WebPRescalerExportRowExpandC;
- WebPRescalerExportRowShrink = WebPRescalerExportRowShrinkC;
-
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- WebPRescalerDspInitSSE2();
- }
-#endif
-#if defined(WEBP_USE_NEON)
- if (VP8GetCPUInfo(kNEON)) {
- WebPRescalerDspInitNEON();
- }
-#endif
-#if defined(WEBP_USE_MIPS32)
- if (VP8GetCPUInfo(kMIPS32)) {
- WebPRescalerDspInitMIPS32();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- WebPRescalerDspInitMIPSdspR2();
- }
-#endif
- }
- rescaler_last_cpuinfo_used = VP8GetCPUInfo;
-}
diff --git a/drivers/webp/dsp/rescaler_mips32.c b/drivers/webp/dsp/rescaler_mips32.c
deleted file mode 100644
index ddaa391336..0000000000
--- a/drivers/webp/dsp/rescaler_mips32.c
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS version of rescaling functions
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS32)
-
-#include <assert.h>
-#include "../utils/rescaler.h"
-
-//------------------------------------------------------------------------------
-// Row import
-
-static void ImportRowShrink(WebPRescaler* const wrk, const uint8_t* src) {
- const int x_stride = wrk->num_channels;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const int fx_scale = wrk->fx_scale;
- const int x_add = wrk->x_add;
- const int x_sub = wrk->x_sub;
- const int x_stride1 = x_stride << 2;
- int channel;
- assert(!wrk->x_expand);
- assert(!WebPRescalerInputDone(wrk));
-
- for (channel = 0; channel < x_stride; ++channel) {
- const uint8_t* src1 = src + channel;
- rescaler_t* frow = wrk->frow + channel;
- int temp1, temp2, temp3;
- int base, frac, sum;
- int accum, accum1;
- int loop_c = x_out_max - channel;
-
- __asm__ volatile (
- "li %[temp1], 0x8000 \n\t"
- "li %[temp2], 0x10000 \n\t"
- "li %[sum], 0 \n\t"
- "li %[accum], 0 \n\t"
- "1: \n\t"
- "addu %[accum], %[accum], %[x_add] \n\t"
- "li %[base], 0 \n\t"
- "blez %[accum], 3f \n\t"
- "2: \n\t"
- "lbu %[base], 0(%[src1]) \n\t"
- "subu %[accum], %[accum], %[x_sub] \n\t"
- "addu %[src1], %[src1], %[x_stride] \n\t"
- "addu %[sum], %[sum], %[base] \n\t"
- "bgtz %[accum], 2b \n\t"
- "3: \n\t"
- "negu %[accum1], %[accum] \n\t"
- "mul %[frac], %[base], %[accum1] \n\t"
- "mul %[temp3], %[sum], %[x_sub] \n\t"
- "subu %[loop_c], %[loop_c], %[x_stride] \n\t"
- "mult %[temp1], %[temp2] \n\t"
- "maddu %[frac], %[fx_scale] \n\t"
- "mfhi %[sum] \n\t"
- "subu %[temp3], %[temp3], %[frac] \n\t"
- "sw %[temp3], 0(%[frow]) \n\t"
- "addu %[frow], %[frow], %[x_stride1] \n\t"
- "bgtz %[loop_c], 1b \n\t"
- : [accum]"=&r"(accum), [src1]"+r"(src1), [temp3]"=&r"(temp3),
- [sum]"=&r"(sum), [base]"=&r"(base), [frac]"=&r"(frac),
- [frow]"+r"(frow), [accum1]"=&r"(accum1),
- [temp2]"=&r"(temp2), [temp1]"=&r"(temp1)
- : [x_stride]"r"(x_stride), [fx_scale]"r"(fx_scale),
- [x_sub]"r"(x_sub), [x_add]"r"(x_add),
- [loop_c]"r"(loop_c), [x_stride1]"r"(x_stride1)
- : "memory", "hi", "lo"
- );
- assert(accum == 0);
- }
-}
-
-static void ImportRowExpand(WebPRescaler* const wrk, const uint8_t* src) {
- const int x_stride = wrk->num_channels;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const int x_add = wrk->x_add;
- const int x_sub = wrk->x_sub;
- const int src_width = wrk->src_width;
- const int x_stride1 = x_stride << 2;
- int channel;
- assert(wrk->x_expand);
- assert(!WebPRescalerInputDone(wrk));
-
- for (channel = 0; channel < x_stride; ++channel) {
- const uint8_t* src1 = src + channel;
- rescaler_t* frow = wrk->frow + channel;
- int temp1, temp2, temp3, temp4;
- int frac;
- int accum;
- int x_out = channel;
-
- __asm__ volatile (
- "addiu %[temp3], %[src_width], -1 \n\t"
- "lbu %[temp2], 0(%[src1]) \n\t"
- "addu %[src1], %[src1], %[x_stride] \n\t"
- "bgtz %[temp3], 0f \n\t"
- "addiu %[temp1], %[temp2], 0 \n\t"
- "b 3f \n\t"
- "0: \n\t"
- "lbu %[temp1], 0(%[src1]) \n\t"
- "3: \n\t"
- "addiu %[accum], %[x_add], 0 \n\t"
- "1: \n\t"
- "subu %[temp3], %[temp2], %[temp1] \n\t"
- "mul %[temp3], %[temp3], %[accum] \n\t"
- "mul %[temp4], %[temp1], %[x_add] \n\t"
- "addu %[temp3], %[temp4], %[temp3] \n\t"
- "sw %[temp3], 0(%[frow]) \n\t"
- "addu %[frow], %[frow], %[x_stride1] \n\t"
- "addu %[x_out], %[x_out], %[x_stride] \n\t"
- "subu %[temp3], %[x_out], %[x_out_max] \n\t"
- "bgez %[temp3], 2f \n\t"
- "subu %[accum], %[accum], %[x_sub] \n\t"
- "bgez %[accum], 4f \n\t"
- "addiu %[temp2], %[temp1], 0 \n\t"
- "addu %[src1], %[src1], %[x_stride] \n\t"
- "lbu %[temp1], 0(%[src1]) \n\t"
- "addu %[accum], %[accum], %[x_add] \n\t"
- "4: \n\t"
- "b 1b \n\t"
- "2: \n\t"
- : [src1]"+r"(src1), [accum]"=&r"(accum), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
- [x_out]"+r"(x_out), [frac]"=&r"(frac), [frow]"+r"(frow)
- : [x_stride]"r"(x_stride), [x_add]"r"(x_add), [x_sub]"r"(x_sub),
- [x_stride1]"r"(x_stride1), [src_width]"r"(src_width),
- [x_out_max]"r"(x_out_max)
- : "memory", "hi", "lo"
- );
- assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0);
- }
-}
-
-//------------------------------------------------------------------------------
-// Row export
-
-static void ExportRowExpand(WebPRescaler* const wrk) {
- uint8_t* dst = wrk->dst;
- rescaler_t* irow = wrk->irow;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const rescaler_t* frow = wrk->frow;
- int temp0, temp1, temp3, temp4, temp5, loop_end;
- const int temp2 = (int)wrk->fy_scale;
- const int temp6 = x_out_max << 2;
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(wrk->y_expand);
- assert(wrk->y_sub != 0);
- if (wrk->y_accum == 0) {
- __asm__ volatile (
- "li %[temp3], 0x10000 \n\t"
- "li %[temp4], 0x8000 \n\t"
- "addu %[loop_end], %[frow], %[temp6] \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[frow]) \n\t"
- "addiu %[dst], %[dst], 1 \n\t"
- "addiu %[frow], %[frow], 4 \n\t"
- "mult %[temp3], %[temp4] \n\t"
- "maddu %[temp0], %[temp2] \n\t"
- "mfhi %[temp5] \n\t"
- "sb %[temp5], -1(%[dst]) \n\t"
- "bne %[frow], %[loop_end], 1b \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
- [dst]"+r"(dst), [loop_end]"=&r"(loop_end)
- : [temp2]"r"(temp2), [temp6]"r"(temp6)
- : "memory", "hi", "lo"
- );
- } else {
- const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
- const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
- __asm__ volatile (
- "li %[temp3], 0x10000 \n\t"
- "li %[temp4], 0x8000 \n\t"
- "addu %[loop_end], %[frow], %[temp6] \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[frow]) \n\t"
- "lw %[temp1], 0(%[irow]) \n\t"
- "addiu %[dst], %[dst], 1 \n\t"
- "mult %[temp3], %[temp4] \n\t"
- "maddu %[A], %[temp0] \n\t"
- "maddu %[B], %[temp1] \n\t"
- "addiu %[frow], %[frow], 4 \n\t"
- "addiu %[irow], %[irow], 4 \n\t"
- "mfhi %[temp5] \n\t"
- "mult %[temp3], %[temp4] \n\t"
- "maddu %[temp5], %[temp2] \n\t"
- "mfhi %[temp5] \n\t"
- "sb %[temp5], -1(%[dst]) \n\t"
- "bne %[frow], %[loop_end], 1b \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
- [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end)
- : [temp2]"r"(temp2), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B)
- : "memory", "hi", "lo"
- );
- }
-}
-
-static void ExportRowShrink(WebPRescaler* const wrk) {
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- uint8_t* dst = wrk->dst;
- rescaler_t* irow = wrk->irow;
- const rescaler_t* frow = wrk->frow;
- const int yscale = wrk->fy_scale * (-wrk->y_accum);
- int temp0, temp1, temp3, temp4, temp5, loop_end;
- const int temp2 = (int)wrk->fxy_scale;
- const int temp6 = x_out_max << 2;
-
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(!wrk->y_expand);
- assert(wrk->fxy_scale != 0);
- if (yscale) {
- __asm__ volatile (
- "li %[temp3], 0x10000 \n\t"
- "li %[temp4], 0x8000 \n\t"
- "addu %[loop_end], %[frow], %[temp6] \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[frow]) \n\t"
- "mult %[temp3], %[temp4] \n\t"
- "addiu %[frow], %[frow], 4 \n\t"
- "maddu %[temp0], %[yscale] \n\t"
- "mfhi %[temp1] \n\t"
- "lw %[temp0], 0(%[irow]) \n\t"
- "addiu %[dst], %[dst], 1 \n\t"
- "addiu %[irow], %[irow], 4 \n\t"
- "subu %[temp0], %[temp0], %[temp1] \n\t"
- "mult %[temp3], %[temp4] \n\t"
- "maddu %[temp0], %[temp2] \n\t"
- "mfhi %[temp5] \n\t"
- "sw %[temp1], -4(%[irow]) \n\t"
- "sb %[temp5], -1(%[dst]) \n\t"
- "bne %[frow], %[loop_end], 1b \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
- [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end)
- : [temp2]"r"(temp2), [yscale]"r"(yscale), [temp6]"r"(temp6)
- : "memory", "hi", "lo"
- );
- } else {
- __asm__ volatile (
- "li %[temp3], 0x10000 \n\t"
- "li %[temp4], 0x8000 \n\t"
- "addu %[loop_end], %[irow], %[temp6] \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[irow]) \n\t"
- "addiu %[dst], %[dst], 1 \n\t"
- "addiu %[irow], %[irow], 4 \n\t"
- "mult %[temp3], %[temp4] \n\t"
- "maddu %[temp0], %[temp2] \n\t"
- "mfhi %[temp5] \n\t"
- "sw $zero, -4(%[irow]) \n\t"
- "sb %[temp5], -1(%[dst]) \n\t"
- "bne %[irow], %[loop_end], 1b \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow),
- [dst]"+r"(dst), [loop_end]"=&r"(loop_end)
- : [temp2]"r"(temp2), [temp6]"r"(temp6)
- : "memory", "hi", "lo"
- );
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPRescalerDspInitMIPS32(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) {
- WebPRescalerImportRowExpand = ImportRowExpand;
- WebPRescalerImportRowShrink = ImportRowShrink;
- WebPRescalerExportRowExpand = ExportRowExpand;
- WebPRescalerExportRowShrink = ExportRowShrink;
-}
-
-#else // !WEBP_USE_MIPS32
-
-WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPS32)
-
-#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/rescaler_mips_dsp_r2.c b/drivers/webp/dsp/rescaler_mips_dsp_r2.c
deleted file mode 100644
index b457d0a30a..0000000000
--- a/drivers/webp/dsp/rescaler_mips_dsp_r2.c
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS version of rescaling functions
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include <assert.h>
-#include "../utils/rescaler.h"
-
-#define ROUNDER (WEBP_RESCALER_ONE >> 1)
-#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
-
-//------------------------------------------------------------------------------
-// Row export
-
-static void ExportRowShrink(WebPRescaler* const wrk) {
- int i;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- uint8_t* dst = wrk->dst;
- rescaler_t* irow = wrk->irow;
- const rescaler_t* frow = wrk->frow;
- const int yscale = wrk->fy_scale * (-wrk->y_accum);
- int temp0, temp1, temp2, temp3, temp4, temp5, loop_end;
- const int temp7 = (int)wrk->fxy_scale;
- const int temp6 = (x_out_max & ~0x3) << 2;
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(!wrk->y_expand);
- assert(wrk->fxy_scale != 0);
- if (yscale) {
- if (x_out_max >= 4) {
- int temp8, temp9, temp10, temp11;
- __asm__ volatile (
- "li %[temp3], 0x10000 \n\t"
- "li %[temp4], 0x8000 \n\t"
- "addu %[loop_end], %[frow], %[temp6] \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[frow]) \n\t"
- "lw %[temp1], 4(%[frow]) \n\t"
- "lw %[temp2], 8(%[frow]) \n\t"
- "lw %[temp5], 12(%[frow]) \n\t"
- "mult $ac0, %[temp3], %[temp4] \n\t"
- "maddu $ac0, %[temp0], %[yscale] \n\t"
- "mult $ac1, %[temp3], %[temp4] \n\t"
- "maddu $ac1, %[temp1], %[yscale] \n\t"
- "mult $ac2, %[temp3], %[temp4] \n\t"
- "maddu $ac2, %[temp2], %[yscale] \n\t"
- "mult $ac3, %[temp3], %[temp4] \n\t"
- "maddu $ac3, %[temp5], %[yscale] \n\t"
- "addiu %[frow], %[frow], 16 \n\t"
- "mfhi %[temp0], $ac0 \n\t"
- "mfhi %[temp1], $ac1 \n\t"
- "mfhi %[temp2], $ac2 \n\t"
- "mfhi %[temp5], $ac3 \n\t"
- "lw %[temp8], 0(%[irow]) \n\t"
- "lw %[temp9], 4(%[irow]) \n\t"
- "lw %[temp10], 8(%[irow]) \n\t"
- "lw %[temp11], 12(%[irow]) \n\t"
- "addiu %[dst], %[dst], 4 \n\t"
- "addiu %[irow], %[irow], 16 \n\t"
- "subu %[temp8], %[temp8], %[temp0] \n\t"
- "subu %[temp9], %[temp9], %[temp1] \n\t"
- "subu %[temp10], %[temp10], %[temp2] \n\t"
- "subu %[temp11], %[temp11], %[temp5] \n\t"
- "mult $ac0, %[temp3], %[temp4] \n\t"
- "maddu $ac0, %[temp8], %[temp7] \n\t"
- "mult $ac1, %[temp3], %[temp4] \n\t"
- "maddu $ac1, %[temp9], %[temp7] \n\t"
- "mult $ac2, %[temp3], %[temp4] \n\t"
- "maddu $ac2, %[temp10], %[temp7] \n\t"
- "mult $ac3, %[temp3], %[temp4] \n\t"
- "maddu $ac3, %[temp11], %[temp7] \n\t"
- "mfhi %[temp8], $ac0 \n\t"
- "mfhi %[temp9], $ac1 \n\t"
- "mfhi %[temp10], $ac2 \n\t"
- "mfhi %[temp11], $ac3 \n\t"
- "sw %[temp0], -16(%[irow]) \n\t"
- "sw %[temp1], -12(%[irow]) \n\t"
- "sw %[temp2], -8(%[irow]) \n\t"
- "sw %[temp5], -4(%[irow]) \n\t"
- "sb %[temp8], -4(%[dst]) \n\t"
- "sb %[temp9], -3(%[dst]) \n\t"
- "sb %[temp10], -2(%[dst]) \n\t"
- "sb %[temp11], -1(%[dst]) \n\t"
- "bne %[frow], %[loop_end], 1b \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
- [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end),
- [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10),
- [temp11]"=&r"(temp11), [temp2]"=&r"(temp2)
- : [temp7]"r"(temp7), [yscale]"r"(yscale), [temp6]"r"(temp6)
- : "memory", "hi", "lo", "$ac1hi", "$ac1lo",
- "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
- );
- }
- for (i = 0; i < (x_out_max & 0x3); ++i) {
- const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
- const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale);
- assert(v >= 0 && v <= 255);
- *dst++ = v;
- *irow++ = frac; // new fractional start
- }
- } else {
- if (x_out_max >= 4) {
- __asm__ volatile (
- "li %[temp3], 0x10000 \n\t"
- "li %[temp4], 0x8000 \n\t"
- "addu %[loop_end], %[irow], %[temp6] \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[irow]) \n\t"
- "lw %[temp1], 4(%[irow]) \n\t"
- "lw %[temp2], 8(%[irow]) \n\t"
- "lw %[temp5], 12(%[irow]) \n\t"
- "addiu %[dst], %[dst], 4 \n\t"
- "addiu %[irow], %[irow], 16 \n\t"
- "mult $ac0, %[temp3], %[temp4] \n\t"
- "maddu $ac0, %[temp0], %[temp7] \n\t"
- "mult $ac1, %[temp3], %[temp4] \n\t"
- "maddu $ac1, %[temp1], %[temp7] \n\t"
- "mult $ac2, %[temp3], %[temp4] \n\t"
- "maddu $ac2, %[temp2], %[temp7] \n\t"
- "mult $ac3, %[temp3], %[temp4] \n\t"
- "maddu $ac3, %[temp5], %[temp7] \n\t"
- "mfhi %[temp0], $ac0 \n\t"
- "mfhi %[temp1], $ac1 \n\t"
- "mfhi %[temp2], $ac2 \n\t"
- "mfhi %[temp5], $ac3 \n\t"
- "sw $zero, -16(%[irow]) \n\t"
- "sw $zero, -12(%[irow]) \n\t"
- "sw $zero, -8(%[irow]) \n\t"
- "sw $zero, -4(%[irow]) \n\t"
- "sb %[temp0], -4(%[dst]) \n\t"
- "sb %[temp1], -3(%[dst]) \n\t"
- "sb %[temp2], -2(%[dst]) \n\t"
- "sb %[temp5], -1(%[dst]) \n\t"
- "bne %[irow], %[loop_end], 1b \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [irow]"+r"(irow),
- [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2)
- : [temp7]"r"(temp7), [temp6]"r"(temp6)
- : "memory", "hi", "lo", "$ac1hi", "$ac1lo",
- "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
- );
- }
- for (i = 0; i < (x_out_max & 0x3); ++i) {
- const int v = (int)MULT_FIX(*irow, wrk->fxy_scale);
- assert(v >= 0 && v <= 255);
- *dst++ = v;
- *irow++ = 0;
- }
- }
-}
-
-static void ExportRowExpand(WebPRescaler* const wrk) {
- int i;
- uint8_t* dst = wrk->dst;
- rescaler_t* irow = wrk->irow;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const rescaler_t* frow = wrk->frow;
- int temp0, temp1, temp2, temp3, temp4, temp5, loop_end;
- const int temp6 = (x_out_max & ~0x3) << 2;
- const int temp7 = (int)wrk->fy_scale;
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(wrk->y_expand);
- assert(wrk->y_sub != 0);
- if (wrk->y_accum == 0) {
- if (x_out_max >= 4) {
- __asm__ volatile (
- "li %[temp4], 0x10000 \n\t"
- "li %[temp5], 0x8000 \n\t"
- "addu %[loop_end], %[frow], %[temp6] \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[frow]) \n\t"
- "lw %[temp1], 4(%[frow]) \n\t"
- "lw %[temp2], 8(%[frow]) \n\t"
- "lw %[temp3], 12(%[frow]) \n\t"
- "addiu %[dst], %[dst], 4 \n\t"
- "addiu %[frow], %[frow], 16 \n\t"
- "mult $ac0, %[temp4], %[temp5] \n\t"
- "maddu $ac0, %[temp0], %[temp7] \n\t"
- "mult $ac1, %[temp4], %[temp5] \n\t"
- "maddu $ac1, %[temp1], %[temp7] \n\t"
- "mult $ac2, %[temp4], %[temp5] \n\t"
- "maddu $ac2, %[temp2], %[temp7] \n\t"
- "mult $ac3, %[temp4], %[temp5] \n\t"
- "maddu $ac3, %[temp3], %[temp7] \n\t"
- "mfhi %[temp0], $ac0 \n\t"
- "mfhi %[temp1], $ac1 \n\t"
- "mfhi %[temp2], $ac2 \n\t"
- "mfhi %[temp3], $ac3 \n\t"
- "sb %[temp0], -4(%[dst]) \n\t"
- "sb %[temp1], -3(%[dst]) \n\t"
- "sb %[temp2], -2(%[dst]) \n\t"
- "sb %[temp3], -1(%[dst]) \n\t"
- "bne %[frow], %[loop_end], 1b \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
- [dst]"+r"(dst), [loop_end]"=&r"(loop_end), [temp2]"=&r"(temp2)
- : [temp7]"r"(temp7), [temp6]"r"(temp6)
- : "memory", "hi", "lo", "$ac1hi", "$ac1lo",
- "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
- );
- }
- for (i = 0; i < (x_out_max & 0x3); ++i) {
- const uint32_t J = *frow++;
- const int v = (int)MULT_FIX(J, wrk->fy_scale);
- assert(v >= 0 && v <= 255);
- *dst++ = v;
- }
- } else {
- const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
- const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
- if (x_out_max >= 4) {
- int temp8, temp9, temp10, temp11;
- __asm__ volatile (
- "li %[temp8], 0x10000 \n\t"
- "li %[temp9], 0x8000 \n\t"
- "addu %[loop_end], %[frow], %[temp6] \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[frow]) \n\t"
- "lw %[temp1], 4(%[frow]) \n\t"
- "lw %[temp2], 8(%[frow]) \n\t"
- "lw %[temp3], 12(%[frow]) \n\t"
- "lw %[temp4], 0(%[irow]) \n\t"
- "lw %[temp5], 4(%[irow]) \n\t"
- "lw %[temp10], 8(%[irow]) \n\t"
- "lw %[temp11], 12(%[irow]) \n\t"
- "addiu %[dst], %[dst], 4 \n\t"
- "mult $ac0, %[temp8], %[temp9] \n\t"
- "maddu $ac0, %[A], %[temp0] \n\t"
- "maddu $ac0, %[B], %[temp4] \n\t"
- "mult $ac1, %[temp8], %[temp9] \n\t"
- "maddu $ac1, %[A], %[temp1] \n\t"
- "maddu $ac1, %[B], %[temp5] \n\t"
- "mult $ac2, %[temp8], %[temp9] \n\t"
- "maddu $ac2, %[A], %[temp2] \n\t"
- "maddu $ac2, %[B], %[temp10] \n\t"
- "mult $ac3, %[temp8], %[temp9] \n\t"
- "maddu $ac3, %[A], %[temp3] \n\t"
- "maddu $ac3, %[B], %[temp11] \n\t"
- "addiu %[frow], %[frow], 16 \n\t"
- "addiu %[irow], %[irow], 16 \n\t"
- "mfhi %[temp0], $ac0 \n\t"
- "mfhi %[temp1], $ac1 \n\t"
- "mfhi %[temp2], $ac2 \n\t"
- "mfhi %[temp3], $ac3 \n\t"
- "mult $ac0, %[temp8], %[temp9] \n\t"
- "maddu $ac0, %[temp0], %[temp7] \n\t"
- "mult $ac1, %[temp8], %[temp9] \n\t"
- "maddu $ac1, %[temp1], %[temp7] \n\t"
- "mult $ac2, %[temp8], %[temp9] \n\t"
- "maddu $ac2, %[temp2], %[temp7] \n\t"
- "mult $ac3, %[temp8], %[temp9] \n\t"
- "maddu $ac3, %[temp3], %[temp7] \n\t"
- "mfhi %[temp0], $ac0 \n\t"
- "mfhi %[temp1], $ac1 \n\t"
- "mfhi %[temp2], $ac2 \n\t"
- "mfhi %[temp3], $ac3 \n\t"
- "sb %[temp0], -4(%[dst]) \n\t"
- "sb %[temp1], -3(%[dst]) \n\t"
- "sb %[temp2], -2(%[dst]) \n\t"
- "sb %[temp3], -1(%[dst]) \n\t"
- "bne %[frow], %[loop_end], 1b \n\t"
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [frow]"+r"(frow),
- [irow]"+r"(irow), [dst]"+r"(dst), [loop_end]"=&r"(loop_end),
- [temp8]"=&r"(temp8), [temp9]"=&r"(temp9), [temp10]"=&r"(temp10),
- [temp11]"=&r"(temp11), [temp2]"=&r"(temp2)
- : [temp7]"r"(temp7), [temp6]"r"(temp6), [A]"r"(A), [B]"r"(B)
- : "memory", "hi", "lo", "$ac1hi", "$ac1lo",
- "$ac2hi", "$ac2lo", "$ac3hi", "$ac3lo"
- );
- }
- for (i = 0; i < (x_out_max & 0x3); ++i) {
- const uint64_t I = (uint64_t)A * *frow++
- + (uint64_t)B * *irow++;
- const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
- const int v = (int)MULT_FIX(J, wrk->fy_scale);
- assert(v >= 0 && v <= 255);
- *dst++ = v;
- }
- }
-}
-
-#undef MULT_FIX
-#undef ROUNDER
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPRescalerDspInitMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) {
- WebPRescalerExportRowExpand = ExportRowExpand;
- WebPRescalerExportRowShrink = ExportRowShrink;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(WebPRescalerDspInitMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/rescaler_neon.c b/drivers/webp/dsp/rescaler_neon.c
deleted file mode 100644
index 16fd450ea3..0000000000
--- a/drivers/webp/dsp/rescaler_neon.c
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// NEON version of rescaling functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_NEON)
-
-#include <arm_neon.h>
-#include <assert.h>
-#include "./neon.h"
-#include "../utils/rescaler.h"
-
-#define ROUNDER (WEBP_RESCALER_ONE >> 1)
-#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
-
-#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC))
-#define LOAD_32x8(SRC, DST0, DST1) \
- LOAD_32x4(SRC + 0, DST0); \
- LOAD_32x4(SRC + 4, DST1)
-
-#define STORE_32x8(SRC0, SRC1, DST) do { \
- vst1q_u32((DST) + 0, SRC0); \
- vst1q_u32((DST) + 4, SRC1); \
-} while (0);
-
-#if (WEBP_RESCALER_RFIX == 32)
-#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1))
-#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \
- vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
-#else
-#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work"
-#endif
-
-static uint32x4_t Interpolate(const rescaler_t* const frow,
- const rescaler_t* const irow,
- uint32_t A, uint32_t B) {
- LOAD_32x4(frow, A0);
- LOAD_32x4(irow, B0);
- const uint64x2_t C0 = vmull_n_u32(vget_low_u32(A0), A);
- const uint64x2_t C1 = vmull_n_u32(vget_high_u32(A0), A);
- const uint64x2_t D0 = vmlal_n_u32(C0, vget_low_u32(B0), B);
- const uint64x2_t D1 = vmlal_n_u32(C1, vget_high_u32(B0), B);
- const uint32x4_t E = vcombine_u32(
- vrshrn_n_u64(D0, WEBP_RESCALER_RFIX),
- vrshrn_n_u64(D1, WEBP_RESCALER_RFIX));
- return E;
-}
-
-static void RescalerExportRowExpand(WebPRescaler* const wrk) {
- int x_out;
- uint8_t* const dst = wrk->dst;
- rescaler_t* const irow = wrk->irow;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const int max_span = x_out_max & ~7;
- const rescaler_t* const frow = wrk->frow;
- const uint32_t fy_scale = wrk->fy_scale;
- const int32x4_t fy_scale_half = MAKE_HALF_CST(fy_scale);
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(wrk->y_expand);
- assert(wrk->y_sub != 0);
- if (wrk->y_accum == 0) {
- for (x_out = 0; x_out < max_span; x_out += 8) {
- LOAD_32x4(frow + x_out + 0, A0);
- LOAD_32x4(frow + x_out + 4, A1);
- const uint32x4_t B0 = MULT_FIX(A0, fy_scale_half);
- const uint32x4_t B1 = MULT_FIX(A1, fy_scale_half);
- const uint16x4_t C0 = vmovn_u32(B0);
- const uint16x4_t C1 = vmovn_u32(B1);
- const uint8x8_t D = vmovn_u16(vcombine_u16(C0, C1));
- vst1_u8(dst + x_out, D);
- }
- for (; x_out < x_out_max; ++x_out) {
- const uint32_t J = frow[x_out];
- const int v = (int)MULT_FIX_C(J, fy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- }
- } else {
- const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
- const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
- for (x_out = 0; x_out < max_span; x_out += 8) {
- const uint32x4_t C0 =
- Interpolate(frow + x_out + 0, irow + x_out + 0, A, B);
- const uint32x4_t C1 =
- Interpolate(frow + x_out + 4, irow + x_out + 4, A, B);
- const uint32x4_t D0 = MULT_FIX(C0, fy_scale_half);
- const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half);
- const uint16x4_t E0 = vmovn_u32(D0);
- const uint16x4_t E1 = vmovn_u32(D1);
- const uint8x8_t F = vmovn_u16(vcombine_u16(E0, E1));
- vst1_u8(dst + x_out, F);
- }
- for (; x_out < x_out_max; ++x_out) {
- const uint64_t I = (uint64_t)A * frow[x_out]
- + (uint64_t)B * irow[x_out];
- const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
- const int v = (int)MULT_FIX_C(J, fy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- }
- }
-}
-
-static void RescalerExportRowShrink(WebPRescaler* const wrk) {
- int x_out;
- uint8_t* const dst = wrk->dst;
- rescaler_t* const irow = wrk->irow;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const int max_span = x_out_max & ~7;
- const rescaler_t* const frow = wrk->frow;
- const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
- const uint32_t fxy_scale = wrk->fxy_scale;
- const uint32x4_t zero = vdupq_n_u32(0);
- const int32x4_t yscale_half = MAKE_HALF_CST(yscale);
- const int32x4_t fxy_scale_half = MAKE_HALF_CST(fxy_scale);
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(!wrk->y_expand);
- if (yscale) {
- for (x_out = 0; x_out < max_span; x_out += 8) {
- LOAD_32x8(frow + x_out, in0, in1);
- LOAD_32x8(irow + x_out, in2, in3);
- const uint32x4_t A0 = MULT_FIX(in0, yscale_half);
- const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
- const uint32x4_t B0 = vqsubq_u32(in2, A0);
- const uint32x4_t B1 = vqsubq_u32(in3, A1);
- const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
- const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
- const uint16x4_t D0 = vmovn_u32(C0);
- const uint16x4_t D1 = vmovn_u32(C1);
- const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
- vst1_u8(dst + x_out, E);
- STORE_32x8(A0, A1, irow + x_out);
- }
- for (; x_out < x_out_max; ++x_out) {
- const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
- const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- irow[x_out] = frac; // new fractional start
- }
- } else {
- for (x_out = 0; x_out < max_span; x_out += 8) {
- LOAD_32x8(irow + x_out, in0, in1);
- const uint32x4_t A0 = MULT_FIX(in0, fxy_scale_half);
- const uint32x4_t A1 = MULT_FIX(in1, fxy_scale_half);
- const uint16x4_t B0 = vmovn_u32(A0);
- const uint16x4_t B1 = vmovn_u32(A1);
- const uint8x8_t C = vmovn_u16(vcombine_u16(B0, B1));
- vst1_u8(dst + x_out, C);
- STORE_32x8(zero, zero, irow + x_out);
- }
- for (; x_out < x_out_max; ++x_out) {
- const int v = (int)MULT_FIX_C(irow[x_out], fxy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- irow[x_out] = 0;
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
-extern void WebPRescalerDspInitNEON(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitNEON(void) {
- WebPRescalerExportRowExpand = RescalerExportRowExpand;
- WebPRescalerExportRowShrink = RescalerExportRowShrink;
-}
-
-#else // !WEBP_USE_NEON
-
-WEBP_DSP_INIT_STUB(WebPRescalerDspInitNEON)
-
-#endif // WEBP_USE_NEON
diff --git a/drivers/webp/dsp/rescaler_sse2.c b/drivers/webp/dsp/rescaler_sse2.c
deleted file mode 100644
index 5b9702817c..0000000000
--- a/drivers/webp/dsp/rescaler_sse2.c
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 Rescaling functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-#include <emmintrin.h>
-
-#include <assert.h>
-#include "../utils/rescaler.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// Implementations of critical functions ImportRow / ExportRow
-
-#define ROUNDER (WEBP_RESCALER_ONE >> 1)
-#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
-
-// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0
-static void LoadTwoPixels(const uint8_t* const src, __m128i* out) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH
- const __m128i B = _mm_unpacklo_epi8(A, zero); // A0B0C0D0E0F0G0H0
- const __m128i C = _mm_srli_si128(B, 8); // E0F0G0H0
- *out = _mm_unpacklo_epi16(B, C);
-}
-
-// input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0
-static void LoadHeightPixels(const uint8_t* const src, __m128i* out) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH
- *out = _mm_unpacklo_epi8(A, zero);
-}
-
-static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk,
- const uint8_t* src) {
- rescaler_t* frow = wrk->frow;
- const rescaler_t* const frow_end = frow + wrk->dst_width * wrk->num_channels;
- const int x_add = wrk->x_add;
- int accum = x_add;
- __m128i cur_pixels;
-
- assert(!WebPRescalerInputDone(wrk));
- assert(wrk->x_expand);
- if (wrk->num_channels == 4) {
- if (wrk->src_width < 2) {
- WebPRescalerImportRowExpandC(wrk, src);
- return;
- }
- LoadTwoPixels(src, &cur_pixels);
- src += 4;
- while (1) {
- const __m128i mult = _mm_set1_epi32(((x_add - accum) << 16) | accum);
- const __m128i out = _mm_madd_epi16(cur_pixels, mult);
- _mm_storeu_si128((__m128i*)frow, out);
- frow += 4;
- if (frow >= frow_end) break;
- accum -= wrk->x_sub;
- if (accum < 0) {
- LoadTwoPixels(src, &cur_pixels);
- src += 4;
- accum += x_add;
- }
- }
- } else {
- int left;
- const uint8_t* const src_limit = src + wrk->src_width - 8;
- if (wrk->src_width < 8) {
- WebPRescalerImportRowExpandC(wrk, src);
- return;
- }
- LoadHeightPixels(src, &cur_pixels);
- src += 7;
- left = 7;
- while (1) {
- const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum);
- const __m128i out = _mm_madd_epi16(cur_pixels, mult);
- assert(sizeof(*frow) == sizeof(uint32_t));
- WebPUint32ToMem((uint8_t*)frow, _mm_cvtsi128_si32(out));
- frow += 1;
- if (frow >= frow_end) break;
- accum -= wrk->x_sub;
- if (accum < 0) {
- if (--left) {
- cur_pixels = _mm_srli_si128(cur_pixels, 2);
- } else if (src <= src_limit) {
- LoadHeightPixels(src, &cur_pixels);
- src += 7;
- left = 7;
- } else { // tail
- cur_pixels = _mm_srli_si128(cur_pixels, 2);
- cur_pixels = _mm_insert_epi16(cur_pixels, src[1], 1);
- src += 1;
- left = 1;
- }
- accum += x_add;
- }
- }
- }
- assert(accum == 0);
-}
-
-static void RescalerImportRowShrinkSSE2(WebPRescaler* const wrk,
- const uint8_t* src) {
- const int x_sub = wrk->x_sub;
- int accum = 0;
- const __m128i zero = _mm_setzero_si128();
- const __m128i mult0 = _mm_set1_epi16(x_sub);
- const __m128i mult1 = _mm_set1_epi32(wrk->fx_scale);
- const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
- __m128i sum = zero;
- rescaler_t* frow = wrk->frow;
- const rescaler_t* const frow_end = wrk->frow + 4 * wrk->dst_width;
-
- if (wrk->num_channels != 4 || wrk->x_add > (x_sub << 7)) {
- WebPRescalerImportRowShrinkC(wrk, src);
- return;
- }
- assert(!WebPRescalerInputDone(wrk));
- assert(!wrk->x_expand);
-
- for (; frow < frow_end; frow += 4) {
- __m128i base = zero;
- accum += wrk->x_add;
- while (accum > 0) {
- const __m128i A = _mm_cvtsi32_si128(WebPMemToUint32(src));
- src += 4;
- base = _mm_unpacklo_epi8(A, zero);
- // To avoid overflow, we need: base * x_add / x_sub < 32768
- // => x_add < x_sub << 7. That's a 1/128 reduction ratio limit.
- sum = _mm_add_epi16(sum, base);
- accum -= x_sub;
- }
- { // Emit next horizontal pixel.
- const __m128i mult = _mm_set1_epi16(-accum);
- const __m128i frac0 = _mm_mullo_epi16(base, mult); // 16b x 16b -> 32b
- const __m128i frac1 = _mm_mulhi_epu16(base, mult);
- const __m128i frac = _mm_unpacklo_epi16(frac0, frac1); // frac is 32b
- const __m128i A0 = _mm_mullo_epi16(sum, mult0);
- const __m128i A1 = _mm_mulhi_epu16(sum, mult0);
- const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // sum * x_sub
- const __m128i frow_out = _mm_sub_epi32(B0, frac); // sum * x_sub - frac
- const __m128i D0 = _mm_srli_epi64(frac, 32);
- const __m128i D1 = _mm_mul_epu32(frac, mult1); // 32b x 16b -> 64b
- const __m128i D2 = _mm_mul_epu32(D0, mult1);
- const __m128i E1 = _mm_add_epi64(D1, rounder);
- const __m128i E2 = _mm_add_epi64(D2, rounder);
- const __m128i F1 = _mm_shuffle_epi32(E1, 1 | (3 << 2));
- const __m128i F2 = _mm_shuffle_epi32(E2, 1 | (3 << 2));
- const __m128i G = _mm_unpacklo_epi32(F1, F2);
- sum = _mm_packs_epi32(G, zero);
- _mm_storeu_si128((__m128i*)frow, frow_out);
- }
- }
- assert(accum == 0);
-}
-
-//------------------------------------------------------------------------------
-// Row export
-
-// load *src as epi64, multiply by mult and store result in [out0 ... out3]
-static WEBP_INLINE void LoadDispatchAndMult(const rescaler_t* const src,
- const __m128i* const mult,
- __m128i* const out0,
- __m128i* const out1,
- __m128i* const out2,
- __m128i* const out3) {
- const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + 0));
- const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + 4));
- const __m128i A2 = _mm_srli_epi64(A0, 32);
- const __m128i A3 = _mm_srli_epi64(A1, 32);
- if (mult != NULL) {
- *out0 = _mm_mul_epu32(A0, *mult);
- *out1 = _mm_mul_epu32(A1, *mult);
- *out2 = _mm_mul_epu32(A2, *mult);
- *out3 = _mm_mul_epu32(A3, *mult);
- } else {
- *out0 = A0;
- *out1 = A1;
- *out2 = A2;
- *out3 = A3;
- }
-}
-
-static WEBP_INLINE void ProcessRow(const __m128i* const A0,
- const __m128i* const A1,
- const __m128i* const A2,
- const __m128i* const A3,
- const __m128i* const mult,
- uint8_t* const dst) {
- const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
- const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
- const __m128i B0 = _mm_mul_epu32(*A0, *mult);
- const __m128i B1 = _mm_mul_epu32(*A1, *mult);
- const __m128i B2 = _mm_mul_epu32(*A2, *mult);
- const __m128i B3 = _mm_mul_epu32(*A3, *mult);
- const __m128i C0 = _mm_add_epi64(B0, rounder);
- const __m128i C1 = _mm_add_epi64(B1, rounder);
- const __m128i C2 = _mm_add_epi64(B2, rounder);
- const __m128i C3 = _mm_add_epi64(B3, rounder);
- const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX);
- const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX);
-#if (WEBP_RESCALER_FIX < 32)
- const __m128i D2 =
- _mm_and_si128(_mm_slli_epi64(C2, 32 - WEBP_RESCALER_RFIX), mask);
- const __m128i D3 =
- _mm_and_si128(_mm_slli_epi64(C3, 32 - WEBP_RESCALER_RFIX), mask);
-#else
- const __m128i D2 = _mm_and_si128(C2, mask);
- const __m128i D3 = _mm_and_si128(C3, mask);
-#endif
- const __m128i E0 = _mm_or_si128(D0, D2);
- const __m128i E1 = _mm_or_si128(D1, D3);
- const __m128i F = _mm_packs_epi32(E0, E1);
- const __m128i G = _mm_packus_epi16(F, F);
- _mm_storel_epi64((__m128i*)dst, G);
-}
-
-static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) {
- int x_out;
- uint8_t* const dst = wrk->dst;
- rescaler_t* const irow = wrk->irow;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const rescaler_t* const frow = wrk->frow;
- const __m128i mult = _mm_set_epi32(0, wrk->fy_scale, 0, wrk->fy_scale);
-
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0 && wrk->y_sub + wrk->y_accum >= 0);
- assert(wrk->y_expand);
- if (wrk->y_accum == 0) {
- for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
- __m128i A0, A1, A2, A3;
- LoadDispatchAndMult(frow + x_out, NULL, &A0, &A1, &A2, &A3);
- ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out);
- }
- for (; x_out < x_out_max; ++x_out) {
- const uint32_t J = frow[x_out];
- const int v = (int)MULT_FIX(J, wrk->fy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- }
- } else {
- const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
- const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
- const __m128i mA = _mm_set_epi32(0, A, 0, A);
- const __m128i mB = _mm_set_epi32(0, B, 0, B);
- const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
- for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
- __m128i A0, A1, A2, A3, B0, B1, B2, B3;
- LoadDispatchAndMult(frow + x_out, &mA, &A0, &A1, &A2, &A3);
- LoadDispatchAndMult(irow + x_out, &mB, &B0, &B1, &B2, &B3);
- {
- const __m128i C0 = _mm_add_epi64(A0, B0);
- const __m128i C1 = _mm_add_epi64(A1, B1);
- const __m128i C2 = _mm_add_epi64(A2, B2);
- const __m128i C3 = _mm_add_epi64(A3, B3);
- const __m128i D0 = _mm_add_epi64(C0, rounder);
- const __m128i D1 = _mm_add_epi64(C1, rounder);
- const __m128i D2 = _mm_add_epi64(C2, rounder);
- const __m128i D3 = _mm_add_epi64(C3, rounder);
- const __m128i E0 = _mm_srli_epi64(D0, WEBP_RESCALER_RFIX);
- const __m128i E1 = _mm_srli_epi64(D1, WEBP_RESCALER_RFIX);
- const __m128i E2 = _mm_srli_epi64(D2, WEBP_RESCALER_RFIX);
- const __m128i E3 = _mm_srli_epi64(D3, WEBP_RESCALER_RFIX);
- ProcessRow(&E0, &E1, &E2, &E3, &mult, dst + x_out);
- }
- }
- for (; x_out < x_out_max; ++x_out) {
- const uint64_t I = (uint64_t)A * frow[x_out]
- + (uint64_t)B * irow[x_out];
- const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
- const int v = (int)MULT_FIX(J, wrk->fy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- }
- }
-}
-
-static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) {
- int x_out;
- uint8_t* const dst = wrk->dst;
- rescaler_t* const irow = wrk->irow;
- const int x_out_max = wrk->dst_width * wrk->num_channels;
- const rescaler_t* const frow = wrk->frow;
- const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
- assert(!WebPRescalerOutputDone(wrk));
- assert(wrk->y_accum <= 0);
- assert(!wrk->y_expand);
- if (yscale) {
- const int scale_xy = wrk->fxy_scale;
- const __m128i mult_xy = _mm_set_epi32(0, scale_xy, 0, scale_xy);
- const __m128i mult_y = _mm_set_epi32(0, yscale, 0, yscale);
- const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
- for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
- __m128i A0, A1, A2, A3, B0, B1, B2, B3;
- LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3);
- LoadDispatchAndMult(frow + x_out, &mult_y, &B0, &B1, &B2, &B3);
- {
- const __m128i C0 = _mm_add_epi64(B0, rounder);
- const __m128i C1 = _mm_add_epi64(B1, rounder);
- const __m128i C2 = _mm_add_epi64(B2, rounder);
- const __m128i C3 = _mm_add_epi64(B3, rounder);
- const __m128i D0 = _mm_srli_epi64(C0, WEBP_RESCALER_RFIX); // = frac
- const __m128i D1 = _mm_srli_epi64(C1, WEBP_RESCALER_RFIX);
- const __m128i D2 = _mm_srli_epi64(C2, WEBP_RESCALER_RFIX);
- const __m128i D3 = _mm_srli_epi64(C3, WEBP_RESCALER_RFIX);
- const __m128i E0 = _mm_sub_epi64(A0, D0); // irow[x] - frac
- const __m128i E1 = _mm_sub_epi64(A1, D1);
- const __m128i E2 = _mm_sub_epi64(A2, D2);
- const __m128i E3 = _mm_sub_epi64(A3, D3);
- const __m128i F2 = _mm_slli_epi64(D2, 32);
- const __m128i F3 = _mm_slli_epi64(D3, 32);
- const __m128i G0 = _mm_or_si128(D0, F2);
- const __m128i G1 = _mm_or_si128(D1, F3);
- _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
- _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
- ProcessRow(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
- }
- }
- for (; x_out < x_out_max; ++x_out) {
- const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- irow[x_out] = frac; // new fractional start
- }
- } else {
- const uint32_t scale = wrk->fxy_scale;
- const __m128i mult = _mm_set_epi32(0, scale, 0, scale);
- const __m128i zero = _mm_setzero_si128();
- for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) {
- __m128i A0, A1, A2, A3;
- LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3);
- _mm_storeu_si128((__m128i*)(irow + x_out + 0), zero);
- _mm_storeu_si128((__m128i*)(irow + x_out + 4), zero);
- ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out);
- }
- for (; x_out < x_out_max; ++x_out) {
- const int v = (int)MULT_FIX(irow[x_out], scale);
- assert(v >= 0 && v <= 255);
- dst[x_out] = v;
- irow[x_out] = 0;
- }
- }
-}
-
-#undef MULT_FIX
-#undef ROUNDER
-
-//------------------------------------------------------------------------------
-
-extern void WebPRescalerDspInitSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitSSE2(void) {
- WebPRescalerImportRowExpand = RescalerImportRowExpandSSE2;
- WebPRescalerImportRowShrink = RescalerImportRowShrinkSSE2;
- WebPRescalerExportRowExpand = RescalerExportRowExpandSSE2;
- WebPRescalerExportRowShrink = RescalerExportRowShrinkSSE2;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(WebPRescalerDspInitSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/upsampling.c b/drivers/webp/dsp/upsampling.c
deleted file mode 100644
index 651274fcee..0000000000
--- a/drivers/webp/dsp/upsampling.c
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// YUV to RGB upsampling functions.
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#include "./dsp.h"
-#include "./yuv.h"
-
-#include <assert.h>
-
-//------------------------------------------------------------------------------
-// Fancy upsampler
-
-#ifdef FANCY_UPSAMPLING
-
-// Fancy upsampling functions to convert YUV to RGB
-WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST];
-
-// Given samples laid out in a square as:
-// [a b]
-// [c d]
-// we interpolate u/v as:
-// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16
-// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16
-
-// We process u and v together stashed into 32bit (16bit each).
-#define LOAD_UV(u, v) ((u) | ((v) << 16))
-
-#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
-static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
- const uint8_t* top_u, const uint8_t* top_v, \
- const uint8_t* cur_u, const uint8_t* cur_v, \
- uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
- int x; \
- const int last_pixel_pair = (len - 1) >> 1; \
- uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \
- uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \
- assert(top_y != NULL); \
- { \
- const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
- FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
- } \
- if (bottom_y != NULL) { \
- const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
- FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \
- } \
- for (x = 1; x <= last_pixel_pair; ++x) { \
- const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \
- const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \
- /* precompute invariant values associated with first and second diagonals*/\
- const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \
- const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \
- const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \
- { \
- const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \
- const uint32_t uv1 = (diag_03 + t_uv) >> 1; \
- FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
- top_dst + (2 * x - 1) * XSTEP); \
- FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \
- top_dst + (2 * x - 0) * XSTEP); \
- } \
- if (bottom_y != NULL) { \
- const uint32_t uv0 = (diag_03 + l_uv) >> 1; \
- const uint32_t uv1 = (diag_12 + uv) >> 1; \
- FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
- bottom_dst + (2 * x - 1) * XSTEP); \
- FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \
- bottom_dst + (2 * x + 0) * XSTEP); \
- } \
- tl_uv = t_uv; \
- l_uv = uv; \
- } \
- if (!(len & 1)) { \
- { \
- const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
- FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
- top_dst + (len - 1) * XSTEP); \
- } \
- if (bottom_y != NULL) { \
- const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
- FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
- bottom_dst + (len - 1) * XSTEP); \
- } \
- } \
-}
-
-// All variants implemented.
-UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3)
-UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3)
-UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4)
-UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4)
-UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4)
-UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2)
-UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2)
-
-#undef LOAD_UV
-#undef UPSAMPLE_FUNC
-
-#endif // FANCY_UPSAMPLING
-
-//------------------------------------------------------------------------------
-
-#if !defined(FANCY_UPSAMPLING)
-#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \
-static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
- const uint8_t* top_u, const uint8_t* top_v, \
- const uint8_t* bot_u, const uint8_t* bot_v, \
- uint8_t* top_dst, uint8_t* bot_dst, int len) { \
- const int half_len = len >> 1; \
- int x; \
- assert(top_dst != NULL); \
- { \
- for (x = 0; x < half_len; ++x) { \
- FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \
- FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \
- } \
- if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \
- } \
- if (bot_dst != NULL) { \
- for (x = 0; x < half_len; ++x) { \
- FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \
- FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \
- } \
- if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \
- } \
-}
-
-DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra)
-DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb)
-#undef DUAL_SAMPLE_FUNC
-
-#endif // !FANCY_UPSAMPLING
-
-WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) {
- WebPInitUpsamplers();
- VP8YUVInit();
-#ifdef FANCY_UPSAMPLING
- return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB];
-#else
- return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB);
-#endif
-}
-
-//------------------------------------------------------------------------------
-// YUV444 converter
-
-#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \
-extern void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
- uint8_t* dst, int len); \
-void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
- uint8_t* dst, int len) { \
- int i; \
- for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \
-}
-
-YUV444_FUNC(WebPYuv444ToRgbC, VP8YuvToRgb, 3)
-YUV444_FUNC(WebPYuv444ToBgrC, VP8YuvToBgr, 3)
-YUV444_FUNC(WebPYuv444ToRgbaC, VP8YuvToRgba, 4)
-YUV444_FUNC(WebPYuv444ToBgraC, VP8YuvToBgra, 4)
-YUV444_FUNC(WebPYuv444ToArgbC, VP8YuvToArgb, 4)
-YUV444_FUNC(WebPYuv444ToRgba4444C, VP8YuvToRgba4444, 2)
-YUV444_FUNC(WebPYuv444ToRgb565C, VP8YuvToRgb565, 2)
-
-#undef YUV444_FUNC
-
-WebPYUV444Converter WebPYUV444Converters[MODE_LAST];
-
-extern void WebPInitYUV444ConvertersMIPSdspR2(void);
-extern void WebPInitYUV444ConvertersSSE2(void);
-
-static volatile VP8CPUInfo upsampling_last_cpuinfo_used1 =
- (VP8CPUInfo)&upsampling_last_cpuinfo_used1;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) {
- if (upsampling_last_cpuinfo_used1 == VP8GetCPUInfo) return;
-
- WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgbC;
- WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgbaC;
- WebPYUV444Converters[MODE_BGR] = WebPYuv444ToBgrC;
- WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgraC;
- WebPYUV444Converters[MODE_ARGB] = WebPYuv444ToArgbC;
- WebPYUV444Converters[MODE_RGBA_4444] = WebPYuv444ToRgba4444C;
- WebPYUV444Converters[MODE_RGB_565] = WebPYuv444ToRgb565C;
- WebPYUV444Converters[MODE_rgbA] = WebPYuv444ToRgbaC;
- WebPYUV444Converters[MODE_bgrA] = WebPYuv444ToBgraC;
- WebPYUV444Converters[MODE_Argb] = WebPYuv444ToArgbC;
- WebPYUV444Converters[MODE_rgbA_4444] = WebPYuv444ToRgba4444C;
-
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- WebPInitYUV444ConvertersSSE2();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- WebPInitYUV444ConvertersMIPSdspR2();
- }
-#endif
- }
- upsampling_last_cpuinfo_used1 = VP8GetCPUInfo;
-}
-
-//------------------------------------------------------------------------------
-// Main calls
-
-extern void WebPInitUpsamplersSSE2(void);
-extern void WebPInitUpsamplersNEON(void);
-extern void WebPInitUpsamplersMIPSdspR2(void);
-
-static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 =
- (VP8CPUInfo)&upsampling_last_cpuinfo_used2;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
- if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return;
-
-#ifdef FANCY_UPSAMPLING
- WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
- WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
- WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
- WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
- WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
- WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
- WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
- WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
- WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
- WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
- WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- WebPInitUpsamplersSSE2();
- }
-#endif
-#if defined(WEBP_USE_NEON)
- if (VP8GetCPUInfo(kNEON)) {
- WebPInitUpsamplersNEON();
- }
-#endif
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- WebPInitUpsamplersMIPSdspR2();
- }
-#endif
- }
-#endif // FANCY_UPSAMPLING
- upsampling_last_cpuinfo_used2 = VP8GetCPUInfo;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/dsp/upsampling_mips_dsp_r2.c b/drivers/webp/dsp/upsampling_mips_dsp_r2.c
deleted file mode 100644
index ed2eb74825..0000000000
--- a/drivers/webp/dsp/upsampling_mips_dsp_r2.c
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// YUV to RGB upsampling functions.
-//
-// Author(s): Branimir Vasic (branimir.vasic@imgtec.com)
-// Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include <assert.h>
-#include "./yuv.h"
-
-#if !defined(WEBP_YUV_USE_TABLE)
-
-#define YUV_TO_RGB(Y, U, V, R, G, B) do { \
- const int t1 = MultHi(Y, 19077); \
- const int t2 = MultHi(V, 13320); \
- R = MultHi(V, 26149); \
- G = MultHi(U, 6419); \
- B = MultHi(U, 33050); \
- R = t1 + R; \
- G = t1 - G; \
- B = t1 + B; \
- R = R - 14234; \
- G = G - t2 + 8708; \
- B = B - 17685; \
- __asm__ volatile ( \
- "shll_s.w %[" #R "], %[" #R "], 17 \n\t" \
- "shll_s.w %[" #G "], %[" #G "], 17 \n\t" \
- "shll_s.w %[" #B "], %[" #B "], 17 \n\t" \
- "precrqu_s.qb.ph %[" #R "], %[" #R "], $zero \n\t" \
- "precrqu_s.qb.ph %[" #G "], %[" #G "], $zero \n\t" \
- "precrqu_s.qb.ph %[" #B "], %[" #B "], $zero \n\t" \
- "srl %[" #R "], %[" #R "], 24 \n\t" \
- "srl %[" #G "], %[" #G "], 24 \n\t" \
- "srl %[" #B "], %[" #B "], 24 \n\t" \
- : [R]"+r"(R), [G]"+r"(G), [B]"+r"(B) \
- : \
- ); \
- } while (0)
-
-static WEBP_INLINE void YuvToRgb(int y, int u, int v, uint8_t* const rgb) {
- int r, g, b;
- YUV_TO_RGB(y, u, v, r, g, b);
- rgb[0] = r;
- rgb[1] = g;
- rgb[2] = b;
-}
-static WEBP_INLINE void YuvToBgr(int y, int u, int v, uint8_t* const bgr) {
- int r, g, b;
- YUV_TO_RGB(y, u, v, r, g, b);
- bgr[0] = b;
- bgr[1] = g;
- bgr[2] = r;
-}
-static WEBP_INLINE void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) {
- int r, g, b;
- YUV_TO_RGB(y, u, v, r, g, b);
- {
- const int rg = (r & 0xf8) | (g >> 5);
- const int gb = ((g << 3) & 0xe0) | (b >> 3);
-#ifdef WEBP_SWAP_16BIT_CSP
- rgb[0] = gb;
- rgb[1] = rg;
-#else
- rgb[0] = rg;
- rgb[1] = gb;
-#endif
- }
-}
-static WEBP_INLINE void YuvToRgba4444(int y, int u, int v,
- uint8_t* const argb) {
- int r, g, b;
- YUV_TO_RGB(y, u, v, r, g, b);
- {
- const int rg = (r & 0xf0) | (g >> 4);
- const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits
-#ifdef WEBP_SWAP_16BIT_CSP
- argb[0] = ba;
- argb[1] = rg;
-#else
- argb[0] = rg;
- argb[1] = ba;
-#endif
- }
-}
-#endif // WEBP_YUV_USE_TABLE
-
-//-----------------------------------------------------------------------------
-// Alpha handling variants
-
-static WEBP_INLINE void YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const argb) {
- int r, g, b;
- YUV_TO_RGB(y, u, v, r, g, b);
- argb[0] = 0xff;
- argb[1] = r;
- argb[2] = g;
- argb[3] = b;
-}
-static WEBP_INLINE void YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const bgra) {
- int r, g, b;
- YUV_TO_RGB(y, u, v, r, g, b);
- bgra[0] = b;
- bgra[1] = g;
- bgra[2] = r;
- bgra[3] = 0xff;
-}
-static WEBP_INLINE void YuvToRgba(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const rgba) {
- int r, g, b;
- YUV_TO_RGB(y, u, v, r, g, b);
- rgba[0] = r;
- rgba[1] = g;
- rgba[2] = b;
- rgba[3] = 0xff;
-}
-
-//------------------------------------------------------------------------------
-// Fancy upsampler
-
-#ifdef FANCY_UPSAMPLING
-
-// Given samples laid out in a square as:
-// [a b]
-// [c d]
-// we interpolate u/v as:
-// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16
-// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16
-
-// We process u and v together stashed into 32bit (16bit each).
-#define LOAD_UV(u, v) ((u) | ((v) << 16))
-
-#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
-static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
- const uint8_t* top_u, const uint8_t* top_v, \
- const uint8_t* cur_u, const uint8_t* cur_v, \
- uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
- int x; \
- const int last_pixel_pair = (len - 1) >> 1; \
- uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \
- uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \
- assert(top_y != NULL); \
- { \
- const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
- FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
- } \
- if (bottom_y != NULL) { \
- const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
- FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \
- } \
- for (x = 1; x <= last_pixel_pair; ++x) { \
- const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \
- const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \
- /* precompute invariant values associated with first and second diagonals*/\
- const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \
- const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \
- const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \
- { \
- const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \
- const uint32_t uv1 = (diag_03 + t_uv) >> 1; \
- FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
- top_dst + (2 * x - 1) * XSTEP); \
- FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \
- top_dst + (2 * x - 0) * XSTEP); \
- } \
- if (bottom_y != NULL) { \
- const uint32_t uv0 = (diag_03 + l_uv) >> 1; \
- const uint32_t uv1 = (diag_12 + uv) >> 1; \
- FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
- bottom_dst + (2 * x - 1) * XSTEP); \
- FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \
- bottom_dst + (2 * x + 0) * XSTEP); \
- } \
- tl_uv = t_uv; \
- l_uv = uv; \
- } \
- if (!(len & 1)) { \
- { \
- const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
- FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
- top_dst + (len - 1) * XSTEP); \
- } \
- if (bottom_y != NULL) { \
- const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
- FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
- bottom_dst + (len - 1) * XSTEP); \
- } \
- } \
-}
-
-// All variants implemented.
-UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3)
-UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3)
-UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4)
-UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4)
-UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4)
-UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2)
-UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2)
-
-#undef LOAD_UV
-#undef UPSAMPLE_FUNC
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPInitUpsamplersMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMIPSdspR2(void) {
- WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
- WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
- WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
- WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
- WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
- WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
- WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
- WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
- WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
- WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
- WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
-}
-
-#endif // FANCY_UPSAMPLING
-
-//------------------------------------------------------------------------------
-// YUV444 converter
-
-#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \
-static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
- uint8_t* dst, int len) { \
- int i; \
- for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \
-}
-
-YUV444_FUNC(Yuv444ToRgb, YuvToRgb, 3)
-YUV444_FUNC(Yuv444ToBgr, YuvToBgr, 3)
-YUV444_FUNC(Yuv444ToRgba, YuvToRgba, 4)
-YUV444_FUNC(Yuv444ToBgra, YuvToBgra, 4)
-YUV444_FUNC(Yuv444ToArgb, YuvToArgb, 4)
-YUV444_FUNC(Yuv444ToRgba4444, YuvToRgba4444, 2)
-YUV444_FUNC(Yuv444ToRgb565, YuvToRgb565, 2)
-
-#undef YUV444_FUNC
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPInitYUV444ConvertersMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersMIPSdspR2(void) {
- WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb;
- WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba;
- WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr;
- WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra;
- WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb;
- WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444;
- WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565;
- WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba;
- WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra;
- WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb;
- WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
-
-#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MIPS_DSP_R2))
-WEBP_DSP_INIT_STUB(WebPInitUpsamplersMIPSdspR2)
-#endif
diff --git a/drivers/webp/dsp/upsampling_neon.c b/drivers/webp/dsp/upsampling_neon.c
deleted file mode 100644
index 2b0c99bddb..0000000000
--- a/drivers/webp/dsp/upsampling_neon.c
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// NEON version of YUV to RGB upsampling functions.
-//
-// Author: mans@mansr.com (Mans Rullgard)
-// Based on SSE code by: somnath@google.com (Somnath Banerjee)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_NEON)
-
-#include <assert.h>
-#include <arm_neon.h>
-#include <string.h>
-#include "./neon.h"
-#include "./yuv.h"
-
-#ifdef FANCY_UPSAMPLING
-
-//-----------------------------------------------------------------------------
-// U/V upsampling
-
-// Loads 9 pixels each from rows r1 and r2 and generates 16 pixels.
-#define UPSAMPLE_16PIXELS(r1, r2, out) { \
- uint8x8_t a = vld1_u8(r1); \
- uint8x8_t b = vld1_u8(r1 + 1); \
- uint8x8_t c = vld1_u8(r2); \
- uint8x8_t d = vld1_u8(r2 + 1); \
- \
- uint16x8_t al = vshll_n_u8(a, 1); \
- uint16x8_t bl = vshll_n_u8(b, 1); \
- uint16x8_t cl = vshll_n_u8(c, 1); \
- uint16x8_t dl = vshll_n_u8(d, 1); \
- \
- uint8x8_t diag1, diag2; \
- uint16x8_t sl; \
- \
- /* a + b + c + d */ \
- sl = vaddl_u8(a, b); \
- sl = vaddw_u8(sl, c); \
- sl = vaddw_u8(sl, d); \
- \
- al = vaddq_u16(sl, al); /* 3a + b + c + d */ \
- bl = vaddq_u16(sl, bl); /* a + 3b + c + d */ \
- \
- al = vaddq_u16(al, dl); /* 3a + b + c + 3d */ \
- bl = vaddq_u16(bl, cl); /* a + 3b + 3c + d */ \
- \
- diag2 = vshrn_n_u16(al, 3); \
- diag1 = vshrn_n_u16(bl, 3); \
- \
- a = vrhadd_u8(a, diag1); \
- b = vrhadd_u8(b, diag2); \
- c = vrhadd_u8(c, diag2); \
- d = vrhadd_u8(d, diag1); \
- \
- { \
- uint8x8x2_t a_b, c_d; \
- INIT_VECTOR2(a_b, a, b); \
- INIT_VECTOR2(c_d, c, d); \
- vst2_u8(out, a_b); \
- vst2_u8(out + 32, c_d); \
- } \
-}
-
-// Turn the macro into a function for reducing code-size when non-critical
-static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2,
- uint8_t *out) {
- UPSAMPLE_16PIXELS(r1, r2, out);
-}
-
-#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \
- uint8_t r1[9], r2[9]; \
- memcpy(r1, (tb), (num_pixels)); \
- memcpy(r2, (bb), (num_pixels)); \
- /* replicate last byte */ \
- memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \
- memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \
- Upsample16Pixels(r1, r2, out); \
-}
-
-//-----------------------------------------------------------------------------
-// YUV->RGB conversion
-
-// note: we represent the 33050 large constant as 32768 + 282
-static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 };
-
-#define v255 vdup_n_u8(255)
-#define v_0x0f vdup_n_u8(15)
-
-#define STORE_Rgb(out, r, g, b) do { \
- uint8x8x3_t r_g_b; \
- INIT_VECTOR3(r_g_b, r, g, b); \
- vst3_u8(out, r_g_b); \
-} while (0)
-
-#define STORE_Bgr(out, r, g, b) do { \
- uint8x8x3_t b_g_r; \
- INIT_VECTOR3(b_g_r, b, g, r); \
- vst3_u8(out, b_g_r); \
-} while (0)
-
-#define STORE_Rgba(out, r, g, b) do { \
- uint8x8x4_t r_g_b_v255; \
- INIT_VECTOR4(r_g_b_v255, r, g, b, v255); \
- vst4_u8(out, r_g_b_v255); \
-} while (0)
-
-#define STORE_Bgra(out, r, g, b) do { \
- uint8x8x4_t b_g_r_v255; \
- INIT_VECTOR4(b_g_r_v255, b, g, r, v255); \
- vst4_u8(out, b_g_r_v255); \
-} while (0)
-
-#define STORE_Argb(out, r, g, b) do { \
- uint8x8x4_t v255_r_g_b; \
- INIT_VECTOR4(v255_r_g_b, v255, r, g, b); \
- vst4_u8(out, v255_r_g_b); \
-} while (0)
-
-#if !defined(WEBP_SWAP_16BIT_CSP)
-#define ZIP_U8(lo, hi) vzip_u8((lo), (hi))
-#else
-#define ZIP_U8(lo, hi) vzip_u8((hi), (lo))
-#endif
-
-#define STORE_Rgba4444(out, r, g, b) do { \
- const uint8x8_t r1 = vshl_n_u8(vshr_n_u8(r, 4), 4); /* 4bits */ \
- const uint8x8_t g1 = vshr_n_u8(g, 4); \
- const uint8x8_t ba = vorr_u8(b, v_0x0f); \
- const uint8x8_t rg = vorr_u8(r1, g1); \
- const uint8x8x2_t rgba4444 = ZIP_U8(rg, ba); \
- vst1q_u8(out, vcombine_u8(rgba4444.val[0], rgba4444.val[1])); \
-} while (0)
-
-#define STORE_Rgb565(out, r, g, b) do { \
- const uint8x8_t r1 = vshl_n_u8(vshr_n_u8(r, 3), 3); /* 5bits */ \
- const uint8x8_t g1 = vshr_n_u8(g, 5); /* upper 3bits */\
- const uint8x8_t g2 = vshl_n_u8(vshr_n_u8(g, 2), 5); /* lower 3bits */\
- const uint8x8_t b1 = vshr_n_u8(b, 3); /* 5bits */ \
- const uint8x8_t rg = vorr_u8(r1, g1); \
- const uint8x8_t gb = vorr_u8(g2, b1); \
- const uint8x8x2_t rgb565 = ZIP_U8(rg, gb); \
- vst1q_u8(out, vcombine_u8(rgb565.val[0], rgb565.val[1])); \
-} while (0)
-
-#define CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) do { \
- int i; \
- for (i = 0; i < N; i += 8) { \
- const int off = ((cur_x) + i) * XSTEP; \
- const uint8x8_t y = vld1_u8((src_y) + (cur_x) + i); \
- const uint8x8_t u = vld1_u8((src_uv) + i + 0); \
- const uint8x8_t v = vld1_u8((src_uv) + i + 16); \
- const int16x8_t Y0 = vreinterpretq_s16_u16(vshll_n_u8(y, 7)); \
- const int16x8_t U0 = vreinterpretq_s16_u16(vshll_n_u8(u, 7)); \
- const int16x8_t V0 = vreinterpretq_s16_u16(vshll_n_u8(v, 7)); \
- const int16x8_t Y1 = vqdmulhq_lane_s16(Y0, coeff1, 0); \
- const int16x8_t R0 = vqdmulhq_lane_s16(V0, coeff1, 1); \
- const int16x8_t G0 = vqdmulhq_lane_s16(U0, coeff1, 2); \
- const int16x8_t G1 = vqdmulhq_lane_s16(V0, coeff1, 3); \
- const int16x8_t B0 = vqdmulhq_n_s16(U0, 282); \
- const int16x8_t R1 = vqaddq_s16(Y1, R_Rounder); \
- const int16x8_t G2 = vqaddq_s16(Y1, G_Rounder); \
- const int16x8_t B1 = vqaddq_s16(Y1, B_Rounder); \
- const int16x8_t R2 = vqaddq_s16(R0, R1); \
- const int16x8_t G3 = vqaddq_s16(G0, G1); \
- const int16x8_t B2 = vqaddq_s16(B0, B1); \
- const int16x8_t G4 = vqsubq_s16(G2, G3); \
- const int16x8_t B3 = vqaddq_s16(B2, U0); \
- const uint8x8_t R = vqshrun_n_s16(R2, YUV_FIX2); \
- const uint8x8_t G = vqshrun_n_s16(G4, YUV_FIX2); \
- const uint8x8_t B = vqshrun_n_s16(B3, YUV_FIX2); \
- STORE_ ## FMT(out + off, R, G, B); \
- } \
-} while (0)
-
-#define CONVERT1(FUNC, XSTEP, N, src_y, src_uv, rgb, cur_x) { \
- int i; \
- for (i = 0; i < N; i++) { \
- const int off = ((cur_x) + i) * XSTEP; \
- const int y = src_y[(cur_x) + i]; \
- const int u = (src_uv)[i]; \
- const int v = (src_uv)[i + 16]; \
- FUNC(y, u, v, rgb + off); \
- } \
-}
-
-#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \
- top_dst, bottom_dst, cur_x, len) { \
- CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x); \
- if (bottom_y != NULL) { \
- CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \
- } \
-}
-
-#define CONVERT2RGB_1(FUNC, XSTEP, top_y, bottom_y, uv, \
- top_dst, bottom_dst, cur_x, len) { \
- CONVERT1(FUNC, XSTEP, len, top_y, uv, top_dst, cur_x); \
- if (bottom_y != NULL) { \
- CONVERT1(FUNC, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \
- } \
-}
-
-#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \
-static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \
- const uint8_t *top_u, const uint8_t *top_v, \
- const uint8_t *cur_u, const uint8_t *cur_v, \
- uint8_t *top_dst, uint8_t *bottom_dst, int len) { \
- int block; \
- /* 16 byte aligned array to cache reconstructed u and v */ \
- uint8_t uv_buf[2 * 32 + 15]; \
- uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
- const int uv_len = (len + 1) >> 1; \
- /* 9 pixels must be read-able for each block */ \
- const int num_blocks = (uv_len - 1) >> 3; \
- const int leftover = uv_len - num_blocks * 8; \
- const int last_pos = 1 + 16 * num_blocks; \
- \
- const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
- const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
- \
- const int16x4_t coeff1 = vld1_s16(kCoeffs1); \
- const int16x8_t R_Rounder = vdupq_n_s16(-14234); \
- const int16x8_t G_Rounder = vdupq_n_s16(8708); \
- const int16x8_t B_Rounder = vdupq_n_s16(-17685); \
- \
- /* Treat the first pixel in regular way */ \
- assert(top_y != NULL); \
- { \
- const int u0 = (top_u[0] + u_diag) >> 1; \
- const int v0 = (top_v[0] + v_diag) >> 1; \
- VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \
- } \
- if (bottom_y != NULL) { \
- const int u0 = (cur_u[0] + u_diag) >> 1; \
- const int v0 = (cur_v[0] + v_diag) >> 1; \
- VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \
- } \
- \
- for (block = 0; block < num_blocks; ++block) { \
- UPSAMPLE_16PIXELS(top_u, cur_u, r_uv); \
- UPSAMPLE_16PIXELS(top_v, cur_v, r_uv + 16); \
- CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, r_uv, \
- top_dst, bottom_dst, 16 * block + 1, 16); \
- top_u += 8; \
- cur_u += 8; \
- top_v += 8; \
- cur_v += 8; \
- } \
- \
- UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv); \
- UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 16); \
- CONVERT2RGB_1(VP8YuvTo ## FMT, XSTEP, top_y, bottom_y, r_uv, \
- top_dst, bottom_dst, last_pos, len - last_pos); \
-}
-
-// NEON variants of the fancy upsampler.
-NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair, Rgb, 3)
-NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair, Bgr, 3)
-NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair, Rgba, 4)
-NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair, Bgra, 4)
-NEON_UPSAMPLE_FUNC(UpsampleArgbLinePair, Argb, 4)
-NEON_UPSAMPLE_FUNC(UpsampleRgba4444LinePair, Rgba4444, 2)
-NEON_UPSAMPLE_FUNC(UpsampleRgb565LinePair, Rgb565, 2)
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
-
-extern void WebPInitUpsamplersNEON(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersNEON(void) {
- WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
- WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
- WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
- WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
- WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
- WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
- WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
- WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
- WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
- WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
- WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
-}
-
-#endif // FANCY_UPSAMPLING
-
-#endif // WEBP_USE_NEON
-
-#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_NEON))
-WEBP_DSP_INIT_STUB(WebPInitUpsamplersNEON)
-#endif
diff --git a/drivers/webp/dsp/upsampling_sse2.c b/drivers/webp/dsp/upsampling_sse2.c
deleted file mode 100644
index b5b668900f..0000000000
--- a/drivers/webp/dsp/upsampling_sse2.c
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 version of YUV to RGB upsampling functions.
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_SSE2)
-
-#include <assert.h>
-#include <emmintrin.h>
-#include <string.h>
-#include "./yuv.h"
-
-#ifdef FANCY_UPSAMPLING
-
-// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows
-// u = (9*a + 3*b + 3*c + d + 8) / 16
-// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2
-// = (a + m + 1) / 2
-// where m = (a + 3*b + 3*c + d) / 8
-// = ((a + b + c + d) / 2 + b + c) / 4
-//
-// Let's say k = (a + b + c + d) / 4.
-// We can compute k as
-// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1
-// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2
-//
-// Then m can be written as
-// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1
-
-// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1
-#define GET_M(ij, in, out) do { \
- const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \
- const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \
- const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \
- const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\
- const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \
- (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \
-} while (0)
-
-// pack and store two alternating pixel rows
-#define PACK_AND_STORE(a, b, da, db, out) do { \
- const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \
- const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \
- const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \
- const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \
- _mm_store_si128(((__m128i*)(out)) + 0, t_1); \
- _mm_store_si128(((__m128i*)(out)) + 1, t_2); \
-} while (0)
-
-// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels.
-#define UPSAMPLE_32PIXELS(r1, r2, out) { \
- const __m128i one = _mm_set1_epi8(1); \
- const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \
- const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \
- const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \
- const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \
- \
- const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \
- const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \
- const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \
- \
- const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \
- const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \
- \
- const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \
- const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \
- const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \
- const __m128i t4 = _mm_avg_epu8(s, t); \
- const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \
- __m128i diag1, diag2; \
- \
- GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \
- GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \
- \
- /* pack the alternate pixels */ \
- PACK_AND_STORE(a, b, diag1, diag2, out + 0); /* store top */ \
- PACK_AND_STORE(c, d, diag2, diag1, out + 2 * 32); /* store bottom */ \
-}
-
-// Turn the macro into a function for reducing code-size when non-critical
-static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[],
- uint8_t* const out) {
- UPSAMPLE_32PIXELS(r1, r2, out);
-}
-
-#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \
- uint8_t r1[17], r2[17]; \
- memcpy(r1, (tb), (num_pixels)); \
- memcpy(r2, (bb), (num_pixels)); \
- /* replicate last byte */ \
- memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \
- memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \
- /* using the shared function instead of the macro saves ~3k code size */ \
- Upsample32Pixels(r1, r2, out); \
-}
-
-#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, \
- top_dst, bottom_dst, cur_x, num_pixels) { \
- int n; \
- for (n = 0; n < (num_pixels); ++n) { \
- FUNC(top_y[(cur_x) + n], r_u[n], r_v[n], \
- top_dst + ((cur_x) + n) * XSTEP); \
- } \
- if (bottom_y != NULL) { \
- for (n = 0; n < (num_pixels); ++n) { \
- FUNC(bottom_y[(cur_x) + n], r_u[64 + n], r_v[64 + n], \
- bottom_dst + ((cur_x) + n) * XSTEP); \
- } \
- } \
-}
-
-#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \
- top_dst, bottom_dst, cur_x) do { \
- FUNC##32(top_y + (cur_x), r_u, r_v, top_dst + (cur_x) * XSTEP); \
- if (bottom_y != NULL) { \
- FUNC##32(bottom_y + (cur_x), r_u + 64, r_v + 64, \
- bottom_dst + (cur_x) * XSTEP); \
- } \
-} while (0)
-
-#define SSE2_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
-static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
- const uint8_t* top_u, const uint8_t* top_v, \
- const uint8_t* cur_u, const uint8_t* cur_v, \
- uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
- int uv_pos, pos; \
- /* 16byte-aligned array to cache reconstructed u and v */ \
- uint8_t uv_buf[4 * 32 + 15]; \
- uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
- uint8_t* const r_v = r_u + 32; \
- \
- assert(top_y != NULL); \
- { /* Treat the first pixel in regular way */ \
- const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
- const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
- const int u0_t = (top_u[0] + u_diag) >> 1; \
- const int v0_t = (top_v[0] + v_diag) >> 1; \
- FUNC(top_y[0], u0_t, v0_t, top_dst); \
- if (bottom_y != NULL) { \
- const int u0_b = (cur_u[0] + u_diag) >> 1; \
- const int v0_b = (cur_v[0] + v_diag) >> 1; \
- FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \
- } \
- } \
- /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \
- for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \
- UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \
- UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \
- CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \
- } \
- if (len > 1) { \
- const int left_over = ((len + 1) >> 1) - (pos >> 1); \
- assert(left_over > 0); \
- UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \
- UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \
- CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, \
- pos, len - pos); \
- } \
-}
-
-// SSE2 variants of the fancy upsampler.
-SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3)
-SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3)
-SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4)
-SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4)
-SSE2_UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4)
-SSE2_UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2)
-SSE2_UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2)
-
-#undef GET_M
-#undef PACK_AND_STORE
-#undef UPSAMPLE_32PIXELS
-#undef UPSAMPLE_LAST_BLOCK
-#undef CONVERT2RGB
-#undef CONVERT2RGB_32
-#undef SSE2_UPSAMPLE_FUNC
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
-
-extern void WebPInitUpsamplersSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE2(void) {
- WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
- WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
- WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
- WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
- WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
- WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
- WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
- WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
- WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
- WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
- WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
-}
-
-#endif // FANCY_UPSAMPLING
-
-//------------------------------------------------------------------------------
-
-extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
-extern void WebPInitYUV444ConvertersSSE2(void);
-
-#define YUV444_FUNC(FUNC_NAME, CALL, XSTEP) \
-extern void WebP##FUNC_NAME##C(const uint8_t* y, const uint8_t* u, \
- const uint8_t* v, uint8_t* dst, int len); \
-static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
- uint8_t* dst, int len) { \
- int i; \
- const int max_len = len & ~31; \
- for (i = 0; i < max_len; i += 32) CALL(y + i, u + i, v + i, dst + i * XSTEP);\
- if (i < len) { /* C-fallback */ \
- WebP##FUNC_NAME##C(y + i, u + i, v + i, dst + i * XSTEP, len - i); \
- } \
-}
-
-YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba32, 4);
-YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra32, 4);
-YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb32, 3);
-YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr32, 3);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE2(void) {
- WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba;
- WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra;
- WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb;
- WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr;
-}
-
-#else
-
-WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE2)
-
-#endif // WEBP_USE_SSE2
-
-#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE2))
-WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE2)
-#endif
diff --git a/drivers/webp/dsp/yuv.c b/drivers/webp/dsp/yuv.c
deleted file mode 100644
index f50a253168..0000000000
--- a/drivers/webp/dsp/yuv.c
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// YUV->RGB conversion functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./yuv.h"
-
-#if defined(WEBP_YUV_USE_TABLE)
-
-static int done = 0;
-
-static WEBP_INLINE uint8_t clip(int v, int max_value) {
- return v < 0 ? 0 : v > max_value ? max_value : v;
-}
-
-int16_t VP8kVToR[256], VP8kUToB[256];
-int32_t VP8kVToG[256], VP8kUToG[256];
-uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
-uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {
- int i;
- if (done) {
- return;
- }
-#ifndef USE_YUVj
- for (i = 0; i < 256; ++i) {
- VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX;
- VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF;
- VP8kVToG[i] = -45773 * (i - 128);
- VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX;
- }
- for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) {
- const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX;
- VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
- VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
- }
-#else
- for (i = 0; i < 256; ++i) {
- VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX;
- VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF;
- VP8kVToG[i] = -46802 * (i - 128);
- VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX;
- }
- for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) {
- const int k = i;
- VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
- VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
- }
-#endif
-
- done = 1;
-}
-
-#else
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {}
-
-#endif // WEBP_YUV_USE_TABLE
-
-//-----------------------------------------------------------------------------
-// Plain-C version
-
-#define ROW_FUNC(FUNC_NAME, FUNC, XSTEP) \
-static void FUNC_NAME(const uint8_t* y, \
- const uint8_t* u, const uint8_t* v, \
- uint8_t* dst, int len) { \
- const uint8_t* const end = dst + (len & ~1) * XSTEP; \
- while (dst != end) { \
- FUNC(y[0], u[0], v[0], dst); \
- FUNC(y[1], u[0], v[0], dst + XSTEP); \
- y += 2; \
- ++u; \
- ++v; \
- dst += 2 * XSTEP; \
- } \
- if (len & 1) { \
- FUNC(y[0], u[0], v[0], dst); \
- } \
-} \
-
-// All variants implemented.
-ROW_FUNC(YuvToRgbRow, VP8YuvToRgb, 3)
-ROW_FUNC(YuvToBgrRow, VP8YuvToBgr, 3)
-ROW_FUNC(YuvToRgbaRow, VP8YuvToRgba, 4)
-ROW_FUNC(YuvToBgraRow, VP8YuvToBgra, 4)
-ROW_FUNC(YuvToArgbRow, VP8YuvToArgb, 4)
-ROW_FUNC(YuvToRgba4444Row, VP8YuvToRgba4444, 2)
-ROW_FUNC(YuvToRgb565Row, VP8YuvToRgb565, 2)
-
-#undef ROW_FUNC
-
-// Main call for processing a plane with a WebPSamplerRowFunc function:
-void WebPSamplerProcessPlane(const uint8_t* y, int y_stride,
- const uint8_t* u, const uint8_t* v, int uv_stride,
- uint8_t* dst, int dst_stride,
- int width, int height, WebPSamplerRowFunc func) {
- int j;
- for (j = 0; j < height; ++j) {
- func(y, u, v, dst, width);
- y += y_stride;
- if (j & 1) {
- u += uv_stride;
- v += uv_stride;
- }
- dst += dst_stride;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Main call
-
-WebPSamplerRowFunc WebPSamplers[MODE_LAST];
-
-extern void WebPInitSamplersSSE2(void);
-extern void WebPInitSamplersMIPS32(void);
-extern void WebPInitSamplersMIPSdspR2(void);
-
-static volatile VP8CPUInfo yuv_last_cpuinfo_used =
- (VP8CPUInfo)&yuv_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) {
- if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- WebPSamplers[MODE_RGB] = YuvToRgbRow;
- WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
- WebPSamplers[MODE_BGR] = YuvToBgrRow;
- WebPSamplers[MODE_BGRA] = YuvToBgraRow;
- WebPSamplers[MODE_ARGB] = YuvToArgbRow;
- WebPSamplers[MODE_RGBA_4444] = YuvToRgba4444Row;
- WebPSamplers[MODE_RGB_565] = YuvToRgb565Row;
- WebPSamplers[MODE_rgbA] = YuvToRgbaRow;
- WebPSamplers[MODE_bgrA] = YuvToBgraRow;
- WebPSamplers[MODE_Argb] = YuvToArgbRow;
- WebPSamplers[MODE_rgbA_4444] = YuvToRgba4444Row;
-
- // If defined, use CPUInfo() to overwrite some pointers with faster versions.
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- WebPInitSamplersSSE2();
- }
-#endif // WEBP_USE_SSE2
-#if defined(WEBP_USE_MIPS32)
- if (VP8GetCPUInfo(kMIPS32)) {
- WebPInitSamplersMIPS32();
- }
-#endif // WEBP_USE_MIPS32
-#if defined(WEBP_USE_MIPS_DSP_R2)
- if (VP8GetCPUInfo(kMIPSdspR2)) {
- WebPInitSamplersMIPSdspR2();
- }
-#endif // WEBP_USE_MIPS_DSP_R2
- }
- yuv_last_cpuinfo_used = VP8GetCPUInfo;
-}
-
-//-----------------------------------------------------------------------------
-// ARGB -> YUV converters
-
-static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) {
- int i;
- for (i = 0; i < width; ++i) {
- const uint32_t p = argb[i];
- y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
- YUV_HALF);
- }
-}
-
-void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v,
- int src_width, int do_store) {
- // No rounding. Last pixel is dealt with separately.
- const int uv_width = src_width >> 1;
- int i;
- for (i = 0; i < uv_width; ++i) {
- const uint32_t v0 = argb[2 * i + 0];
- const uint32_t v1 = argb[2 * i + 1];
- // VP8RGBToU/V expects four accumulated pixels. Hence we need to
- // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
- const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
- const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe);
- const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe);
- const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
- const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
- if (do_store) {
- u[i] = tmp_u;
- v[i] = tmp_v;
- } else {
- // Approximated average-of-four. But it's an acceptable diff.
- u[i] = (u[i] + tmp_u + 1) >> 1;
- v[i] = (v[i] + tmp_v + 1) >> 1;
- }
- }
- if (src_width & 1) { // last pixel
- const uint32_t v0 = argb[2 * i + 0];
- const int r = (v0 >> 14) & 0x3fc;
- const int g = (v0 >> 6) & 0x3fc;
- const int b = (v0 << 2) & 0x3fc;
- const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
- const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
- if (do_store) {
- u[i] = tmp_u;
- v[i] = tmp_v;
- } else {
- u[i] = (u[i] + tmp_u + 1) >> 1;
- v[i] = (v[i] + tmp_v + 1) >> 1;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-
-static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) {
- int i;
- for (i = 0; i < width; ++i, rgb += 3) {
- y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF);
- }
-}
-
-static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) {
- int i;
- for (i = 0; i < width; ++i, bgr += 3) {
- y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF);
- }
-}
-
-void WebPConvertRGBA32ToUV_C(const uint16_t* rgb,
- uint8_t* u, uint8_t* v, int width) {
- int i;
- for (i = 0; i < width; i += 1, rgb += 4) {
- const int r = rgb[0], g = rgb[1], b = rgb[2];
- u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
- v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
- }
-}
-
-//-----------------------------------------------------------------------------
-
-void (*WebPConvertRGB24ToY)(const uint8_t* rgb, uint8_t* y, int width);
-void (*WebPConvertBGR24ToY)(const uint8_t* bgr, uint8_t* y, int width);
-void (*WebPConvertRGBA32ToUV)(const uint16_t* rgb,
- uint8_t* u, uint8_t* v, int width);
-
-void (*WebPConvertARGBToY)(const uint32_t* argb, uint8_t* y, int width);
-void (*WebPConvertARGBToUV)(const uint32_t* argb, uint8_t* u, uint8_t* v,
- int src_width, int do_store);
-
-static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used =
- (VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used;
-
-extern void WebPInitConvertARGBToYUVSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
- if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
-
- WebPConvertARGBToY = ConvertARGBToY;
- WebPConvertARGBToUV = WebPConvertARGBToUV_C;
-
- WebPConvertRGB24ToY = ConvertRGB24ToY;
- WebPConvertBGR24ToY = ConvertBGR24ToY;
-
- WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C;
-
- if (VP8GetCPUInfo != NULL) {
-#if defined(WEBP_USE_SSE2)
- if (VP8GetCPUInfo(kSSE2)) {
- WebPInitConvertARGBToYUVSSE2();
- }
-#endif // WEBP_USE_SSE2
- }
- rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo;
-}
diff --git a/drivers/webp/dsp/yuv.h b/drivers/webp/dsp/yuv.h
deleted file mode 100644
index 01c40fcb84..0000000000
--- a/drivers/webp/dsp/yuv.h
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// inline YUV<->RGB conversion function
-//
-// The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
-// More information at: http://en.wikipedia.org/wiki/YCbCr
-// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
-// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
-// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
-// We use 16bit fixed point operations for RGB->YUV conversion (YUV_FIX).
-//
-// For the Y'CbCr to RGB conversion, the BT.601 specification reads:
-// R = 1.164 * (Y-16) + 1.596 * (V-128)
-// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128)
-// B = 1.164 * (Y-16) + 2.018 * (U-128)
-// where Y is in the [16,235] range, and U/V in the [16,240] range.
-//
-// The fixed-point implementation used here is:
-// R = (19077 . y + 26149 . v - 14234) >> 6
-// G = (19077 . y - 6419 . u - 13320 . v + 8708) >> 6
-// B = (19077 . y + 33050 . u - 17685) >> 6
-// where the '.' operator is the mulhi_epu16 variant:
-// a . b = ((a << 8) * b) >> 16
-// that preserves 8 bits of fractional precision before final descaling.
-
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_DSP_YUV_H_
-#define WEBP_DSP_YUV_H_
-
-#include "./dsp.h"
-#include "../dec/decode_vp8.h"
-
-#if defined(WEBP_EXPERIMENTAL_FEATURES)
-// Do NOT activate this feature for real compression. This is only experimental!
-// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace.
-// This colorspace is close to Rec.601's Y'CbCr model with the notable
-// difference of allowing larger range for luma/chroma.
-// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its
-// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
-// #define USE_YUVj
-#endif
-
-//------------------------------------------------------------------------------
-// YUV -> RGB conversion
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
- YUV_FIX = 16, // fixed-point precision for RGB->YUV
- YUV_HALF = 1 << (YUV_FIX - 1),
- YUV_MASK = (256 << YUV_FIX) - 1,
- YUV_RANGE_MIN = -227, // min value of r/g/b output
- YUV_RANGE_MAX = 256 + 226, // max value of r/g/b output
-
- YUV_FIX2 = 6, // fixed-point precision for YUV->RGB
- YUV_HALF2 = 1 << YUV_FIX2 >> 1,
- YUV_MASK2 = (256 << YUV_FIX2) - 1
-};
-
-//------------------------------------------------------------------------------
-// slower on x86 by ~7-8%, but bit-exact with the SSE2/NEON version
-
-static WEBP_INLINE int MultHi(int v, int coeff) { // _mm_mulhi_epu16 emulation
- return (v * coeff) >> 8;
-}
-
-static WEBP_INLINE int VP8Clip8(int v) {
- return ((v & ~YUV_MASK2) == 0) ? (v >> YUV_FIX2) : (v < 0) ? 0 : 255;
-}
-
-static WEBP_INLINE int VP8YUVToR(int y, int v) {
- return VP8Clip8(MultHi(y, 19077) + MultHi(v, 26149) - 14234);
-}
-
-static WEBP_INLINE int VP8YUVToG(int y, int u, int v) {
- return VP8Clip8(MultHi(y, 19077) - MultHi(u, 6419) - MultHi(v, 13320) + 8708);
-}
-
-static WEBP_INLINE int VP8YUVToB(int y, int u) {
- return VP8Clip8(MultHi(y, 19077) + MultHi(u, 33050) - 17685);
-}
-
-static WEBP_INLINE void VP8YuvToRgb(int y, int u, int v,
- uint8_t* const rgb) {
- rgb[0] = VP8YUVToR(y, v);
- rgb[1] = VP8YUVToG(y, u, v);
- rgb[2] = VP8YUVToB(y, u);
-}
-
-static WEBP_INLINE void VP8YuvToBgr(int y, int u, int v,
- uint8_t* const bgr) {
- bgr[0] = VP8YUVToB(y, u);
- bgr[1] = VP8YUVToG(y, u, v);
- bgr[2] = VP8YUVToR(y, v);
-}
-
-static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v,
- uint8_t* const rgb) {
- const int r = VP8YUVToR(y, v); // 5 usable bits
- const int g = VP8YUVToG(y, u, v); // 6 usable bits
- const int b = VP8YUVToB(y, u); // 5 usable bits
- const int rg = (r & 0xf8) | (g >> 5);
- const int gb = ((g << 3) & 0xe0) | (b >> 3);
-#ifdef WEBP_SWAP_16BIT_CSP
- rgb[0] = gb;
- rgb[1] = rg;
-#else
- rgb[0] = rg;
- rgb[1] = gb;
-#endif
-}
-
-static WEBP_INLINE void VP8YuvToRgba4444(int y, int u, int v,
- uint8_t* const argb) {
- const int r = VP8YUVToR(y, v); // 4 usable bits
- const int g = VP8YUVToG(y, u, v); // 4 usable bits
- const int b = VP8YUVToB(y, u); // 4 usable bits
- const int rg = (r & 0xf0) | (g >> 4);
- const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits
-#ifdef WEBP_SWAP_16BIT_CSP
- argb[0] = ba;
- argb[1] = rg;
-#else
- argb[0] = rg;
- argb[1] = ba;
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Alpha handling variants
-
-static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const argb) {
- argb[0] = 0xff;
- VP8YuvToRgb(y, u, v, argb + 1);
-}
-
-static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const bgra) {
- VP8YuvToBgr(y, u, v, bgra);
- bgra[3] = 0xff;
-}
-
-static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v,
- uint8_t* const rgba) {
- VP8YuvToRgb(y, u, v, rgba);
- rgba[3] = 0xff;
-}
-
-// Must be called before everything, to initialize the tables.
-void VP8YUVInit(void);
-
-//-----------------------------------------------------------------------------
-// SSE2 extra functions (mostly for upsampling_sse2.c)
-
-#if defined(WEBP_USE_SSE2)
-
-// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst.
-void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst);
-void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst);
-void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst);
-void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst);
-void VP8YuvToArgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst);
-void VP8YuvToRgba444432(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst);
-void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst);
-
-#endif // WEBP_USE_SSE2
-
-//------------------------------------------------------------------------------
-// RGB -> YUV conversion
-
-// Stub functions that can be called with various rounding values:
-static WEBP_INLINE int VP8ClipUV(int uv, int rounding) {
- uv = (uv + rounding + (128 << (YUV_FIX + 2))) >> (YUV_FIX + 2);
- return ((uv & ~0xff) == 0) ? uv : (uv < 0) ? 0 : 255;
-}
-
-#ifndef USE_YUVj
-
-static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) {
- const int luma = 16839 * r + 33059 * g + 6420 * b;
- return (luma + rounding + (16 << YUV_FIX)) >> YUV_FIX; // no need to clip
-}
-
-static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) {
- const int u = -9719 * r - 19081 * g + 28800 * b;
- return VP8ClipUV(u, rounding);
-}
-
-static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
- const int v = +28800 * r - 24116 * g - 4684 * b;
- return VP8ClipUV(v, rounding);
-}
-
-#else
-
-// This JPEG-YUV colorspace, only for comparison!
-// These are also 16bit precision coefficients from Rec.601, but with full
-// [0..255] output range.
-static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) {
- const int luma = 19595 * r + 38470 * g + 7471 * b;
- return (luma + rounding) >> YUV_FIX; // no need to clip
-}
-
-static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) {
- const int u = -11058 * r - 21710 * g + 32768 * b;
- return VP8ClipUV(u, rounding);
-}
-
-static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
- const int v = 32768 * r - 27439 * g - 5329 * b;
- return VP8ClipUV(v, rounding);
-}
-
-#endif // USE_YUVj
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DSP_YUV_H_ */
diff --git a/drivers/webp/dsp/yuv_mips32.c b/drivers/webp/dsp/yuv_mips32.c
deleted file mode 100644
index e61aac571f..0000000000
--- a/drivers/webp/dsp/yuv_mips32.c
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS version of YUV to RGB upsampling functions.
-//
-// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
-// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS32)
-
-#include "./yuv.h"
-
-//------------------------------------------------------------------------------
-// simple point-sampling
-
-#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \
-static void FUNC_NAME(const uint8_t* y, \
- const uint8_t* u, const uint8_t* v, \
- uint8_t* dst, int len) { \
- int i, r, g, b; \
- int temp0, temp1, temp2, temp3, temp4; \
- for (i = 0; i < (len >> 1); i++) { \
- temp1 = MultHi(v[0], 26149); \
- temp3 = MultHi(v[0], 13320); \
- temp2 = MultHi(u[0], 6419); \
- temp4 = MultHi(u[0], 33050); \
- temp0 = MultHi(y[0], 19077); \
- temp1 -= 14234; \
- temp3 -= 8708; \
- temp2 += temp3; \
- temp4 -= 17685; \
- r = VP8Clip8(temp0 + temp1); \
- g = VP8Clip8(temp0 - temp2); \
- b = VP8Clip8(temp0 + temp4); \
- temp0 = MultHi(y[1], 19077); \
- dst[R] = r; \
- dst[G] = g; \
- dst[B] = b; \
- if (A) dst[A] = 0xff; \
- r = VP8Clip8(temp0 + temp1); \
- g = VP8Clip8(temp0 - temp2); \
- b = VP8Clip8(temp0 + temp4); \
- dst[R + XSTEP] = r; \
- dst[G + XSTEP] = g; \
- dst[B + XSTEP] = b; \
- if (A) dst[A + XSTEP] = 0xff; \
- y += 2; \
- ++u; \
- ++v; \
- dst += 2 * XSTEP; \
- } \
- if (len & 1) { \
- temp1 = MultHi(v[0], 26149); \
- temp3 = MultHi(v[0], 13320); \
- temp2 = MultHi(u[0], 6419); \
- temp4 = MultHi(u[0], 33050); \
- temp0 = MultHi(y[0], 19077); \
- temp1 -= 14234; \
- temp3 -= 8708; \
- temp2 += temp3; \
- temp4 -= 17685; \
- r = VP8Clip8(temp0 + temp1); \
- g = VP8Clip8(temp0 - temp2); \
- b = VP8Clip8(temp0 + temp4); \
- dst[R] = r; \
- dst[G] = g; \
- dst[B] = b; \
- if (A) dst[A] = 0xff; \
- } \
-}
-
-ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0)
-ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3)
-ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0)
-ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3)
-
-#undef ROW_FUNC
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPInitSamplersMIPS32(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPS32(void) {
- WebPSamplers[MODE_RGB] = YuvToRgbRow;
- WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
- WebPSamplers[MODE_BGR] = YuvToBgrRow;
- WebPSamplers[MODE_BGRA] = YuvToBgraRow;
-}
-
-#else // !WEBP_USE_MIPS32
-
-WEBP_DSP_INIT_STUB(WebPInitSamplersMIPS32)
-
-#endif // WEBP_USE_MIPS32
diff --git a/drivers/webp/dsp/yuv_mips_dsp_r2.c b/drivers/webp/dsp/yuv_mips_dsp_r2.c
deleted file mode 100644
index 1720d4190f..0000000000
--- a/drivers/webp/dsp/yuv_mips_dsp_r2.c
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// MIPS DSPr2 version of YUV to RGB upsampling functions.
-//
-// Author(s): Branimir Vasic (branimir.vasic@imgtec.com)
-// Djordje Pesut (djordje.pesut@imgtec.com)
-
-#include "./dsp.h"
-
-#if defined(WEBP_USE_MIPS_DSP_R2)
-
-#include "./yuv.h"
-
-//------------------------------------------------------------------------------
-// simple point-sampling
-
-#define ROW_FUNC_PART_1() \
- "lbu %[temp3], 0(%[v]) \n\t" \
- "lbu %[temp4], 0(%[u]) \n\t" \
- "lbu %[temp0], 0(%[y]) \n\t" \
- "mul %[temp1], %[t_con_1], %[temp3] \n\t" \
- "mul %[temp3], %[t_con_2], %[temp3] \n\t" \
- "mul %[temp2], %[t_con_3], %[temp4] \n\t" \
- "mul %[temp4], %[t_con_4], %[temp4] \n\t" \
- "mul %[temp0], %[t_con_5], %[temp0] \n\t" \
- "subu %[temp1], %[temp1], %[t_con_6] \n\t" \
- "subu %[temp3], %[temp3], %[t_con_7] \n\t" \
- "addu %[temp2], %[temp2], %[temp3] \n\t" \
- "subu %[temp4], %[temp4], %[t_con_8] \n\t" \
-
-#define ROW_FUNC_PART_2(R, G, B, K) \
- "addu %[temp5], %[temp0], %[temp1] \n\t" \
- "subu %[temp6], %[temp0], %[temp2] \n\t" \
- "addu %[temp7], %[temp0], %[temp4] \n\t" \
-".if " #K " \n\t" \
- "lbu %[temp0], 1(%[y]) \n\t" \
-".endif \n\t" \
- "shll_s.w %[temp5], %[temp5], 17 \n\t" \
- "shll_s.w %[temp6], %[temp6], 17 \n\t" \
-".if " #K " \n\t" \
- "mul %[temp0], %[t_con_5], %[temp0] \n\t" \
-".endif \n\t" \
- "shll_s.w %[temp7], %[temp7], 17 \n\t" \
- "precrqu_s.qb.ph %[temp5], %[temp5], $zero \n\t" \
- "precrqu_s.qb.ph %[temp6], %[temp6], $zero \n\t" \
- "precrqu_s.qb.ph %[temp7], %[temp7], $zero \n\t" \
- "srl %[temp5], %[temp5], 24 \n\t" \
- "srl %[temp6], %[temp6], 24 \n\t" \
- "srl %[temp7], %[temp7], 24 \n\t" \
- "sb %[temp5], " #R "(%[dst]) \n\t" \
- "sb %[temp6], " #G "(%[dst]) \n\t" \
- "sb %[temp7], " #B "(%[dst]) \n\t" \
-
-#define ASM_CLOBBER_LIST() \
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) \
- : [t_con_1]"r"(t_con_1), [t_con_2]"r"(t_con_2), [t_con_3]"r"(t_con_3), \
- [t_con_4]"r"(t_con_4), [t_con_5]"r"(t_con_5), [t_con_6]"r"(t_con_6), \
- [u]"r"(u), [v]"r"(v), [y]"r"(y), [dst]"r"(dst), \
- [t_con_7]"r"(t_con_7), [t_con_8]"r"(t_con_8) \
- : "memory", "hi", "lo" \
-
-#define ROW_FUNC(FUNC_NAME, XSTEP, R, G, B, A) \
-static void FUNC_NAME(const uint8_t* y, \
- const uint8_t* u, const uint8_t* v, \
- uint8_t* dst, int len) { \
- int i; \
- uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; \
- const int t_con_1 = 26149; \
- const int t_con_2 = 13320; \
- const int t_con_3 = 6419; \
- const int t_con_4 = 33050; \
- const int t_con_5 = 19077; \
- const int t_con_6 = 14234; \
- const int t_con_7 = 8708; \
- const int t_con_8 = 17685; \
- for (i = 0; i < (len >> 1); i++) { \
- __asm__ volatile ( \
- ROW_FUNC_PART_1() \
- ROW_FUNC_PART_2(R, G, B, 1) \
- ROW_FUNC_PART_2(R + XSTEP, G + XSTEP, B + XSTEP, 0) \
- ASM_CLOBBER_LIST() \
- ); \
- if (A) dst[A] = dst[A + XSTEP] = 0xff; \
- y += 2; \
- ++u; \
- ++v; \
- dst += 2 * XSTEP; \
- } \
- if (len & 1) { \
- __asm__ volatile ( \
- ROW_FUNC_PART_1() \
- ROW_FUNC_PART_2(R, G, B, 0) \
- ASM_CLOBBER_LIST() \
- ); \
- if (A) dst[A] = 0xff; \
- } \
-}
-
-ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0)
-ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3)
-ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0)
-ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3)
-
-#undef ROW_FUNC
-#undef ASM_CLOBBER_LIST
-#undef ROW_FUNC_PART_2
-#undef ROW_FUNC_PART_1
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPInitSamplersMIPSdspR2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPSdspR2(void) {
- WebPSamplers[MODE_RGB] = YuvToRgbRow;
- WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
- WebPSamplers[MODE_BGR] = YuvToBgrRow;
- WebPSamplers[MODE_BGRA] = YuvToBgraRow;
-}
-
-#else // !WEBP_USE_MIPS_DSP_R2
-
-WEBP_DSP_INIT_STUB(WebPInitSamplersMIPSdspR2)
-
-#endif // WEBP_USE_MIPS_DSP_R2
diff --git a/drivers/webp/dsp/yuv_sse2.c b/drivers/webp/dsp/yuv_sse2.c
deleted file mode 100644
index e19bddff6c..0000000000
--- a/drivers/webp/dsp/yuv_sse2.c
+++ /dev/null
@@ -1,775 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// YUV->RGB conversion functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./yuv.h"
-
-#if defined(WEBP_USE_SSE2)
-
-#include <emmintrin.h>
-
-//-----------------------------------------------------------------------------
-// Convert spans of 32 pixels to various RGB formats for the fancy upsampler.
-
-// These constants are 14b fixed-point version of ITU-R BT.601 constants.
-// R = (19077 * y + 26149 * v - 14234) >> 6
-// G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6
-// B = (19077 * y + 33050 * u - 17685) >> 6
-static void ConvertYUV444ToRGB(const __m128i* const Y0,
- const __m128i* const U0,
- const __m128i* const V0,
- __m128i* const R,
- __m128i* const G,
- __m128i* const B) {
- const __m128i k19077 = _mm_set1_epi16(19077);
- const __m128i k26149 = _mm_set1_epi16(26149);
- const __m128i k14234 = _mm_set1_epi16(14234);
- // 33050 doesn't fit in a signed short: only use this with unsigned arithmetic
- const __m128i k33050 = _mm_set1_epi16((short)33050);
- const __m128i k17685 = _mm_set1_epi16(17685);
- const __m128i k6419 = _mm_set1_epi16(6419);
- const __m128i k13320 = _mm_set1_epi16(13320);
- const __m128i k8708 = _mm_set1_epi16(8708);
-
- const __m128i Y1 = _mm_mulhi_epu16(*Y0, k19077);
-
- const __m128i R0 = _mm_mulhi_epu16(*V0, k26149);
- const __m128i R1 = _mm_sub_epi16(Y1, k14234);
- const __m128i R2 = _mm_add_epi16(R1, R0);
-
- const __m128i G0 = _mm_mulhi_epu16(*U0, k6419);
- const __m128i G1 = _mm_mulhi_epu16(*V0, k13320);
- const __m128i G2 = _mm_add_epi16(Y1, k8708);
- const __m128i G3 = _mm_add_epi16(G0, G1);
- const __m128i G4 = _mm_sub_epi16(G2, G3);
-
- // be careful with the saturated *unsigned* arithmetic here!
- const __m128i B0 = _mm_mulhi_epu16(*U0, k33050);
- const __m128i B1 = _mm_adds_epu16(B0, Y1);
- const __m128i B2 = _mm_subs_epu16(B1, k17685);
-
- // use logical shift for B2, which can be larger than 32767
- *R = _mm_srai_epi16(R2, 6); // range: [-14234, 30815]
- *G = _mm_srai_epi16(G4, 6); // range: [-10953, 27710]
- *B = _mm_srli_epi16(B2, 6); // range: [0, 34238]
-}
-
-// Load the bytes into the *upper* part of 16b words. That's "<< 8", basically.
-static WEBP_INLINE __m128i Load_HI_16(const uint8_t* src) {
- const __m128i zero = _mm_setzero_si128();
- return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src));
-}
-
-// Load and replicate the U/V samples
-static WEBP_INLINE __m128i Load_UV_HI_8(const uint8_t* src) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i tmp0 = _mm_cvtsi32_si128(*(const uint32_t*)src);
- const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0);
- return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples
-}
-
-// Convert 32 samples of YUV444 to R/G/B
-static void YUV444ToRGB(const uint8_t* const y,
- const uint8_t* const u,
- const uint8_t* const v,
- __m128i* const R, __m128i* const G, __m128i* const B) {
- const __m128i Y0 = Load_HI_16(y), U0 = Load_HI_16(u), V0 = Load_HI_16(v);
- ConvertYUV444ToRGB(&Y0, &U0, &V0, R, G, B);
-}
-
-// Convert 32 samples of YUV420 to R/G/B
-static void YUV420ToRGB(const uint8_t* const y,
- const uint8_t* const u,
- const uint8_t* const v,
- __m128i* const R, __m128i* const G, __m128i* const B) {
- const __m128i Y0 = Load_HI_16(y), U0 = Load_UV_HI_8(u), V0 = Load_UV_HI_8(v);
- ConvertYUV444ToRGB(&Y0, &U0, &V0, R, G, B);
-}
-
-// Pack R/G/B/A results into 32b output.
-static WEBP_INLINE void PackAndStore4(const __m128i* const R,
- const __m128i* const G,
- const __m128i* const B,
- const __m128i* const A,
- uint8_t* const dst) {
- const __m128i rb = _mm_packus_epi16(*R, *B);
- const __m128i ga = _mm_packus_epi16(*G, *A);
- const __m128i rg = _mm_unpacklo_epi8(rb, ga);
- const __m128i ba = _mm_unpackhi_epi8(rb, ga);
- const __m128i RGBA_lo = _mm_unpacklo_epi16(rg, ba);
- const __m128i RGBA_hi = _mm_unpackhi_epi16(rg, ba);
- _mm_storeu_si128((__m128i*)(dst + 0), RGBA_lo);
- _mm_storeu_si128((__m128i*)(dst + 16), RGBA_hi);
-}
-
-// Pack R/G/B/A results into 16b output.
-static WEBP_INLINE void PackAndStore4444(const __m128i* const R,
- const __m128i* const G,
- const __m128i* const B,
- const __m128i* const A,
- uint8_t* const dst) {
-#if !defined(WEBP_SWAP_16BIT_CSP)
- const __m128i rg0 = _mm_packus_epi16(*R, *G);
- const __m128i ba0 = _mm_packus_epi16(*B, *A);
-#else
- const __m128i rg0 = _mm_packus_epi16(*B, *A);
- const __m128i ba0 = _mm_packus_epi16(*R, *G);
-#endif
- const __m128i mask_0xf0 = _mm_set1_epi8(0xf0);
- const __m128i rb1 = _mm_unpacklo_epi8(rg0, ba0); // rbrbrbrbrb...
- const __m128i ga1 = _mm_unpackhi_epi8(rg0, ba0); // gagagagaga...
- const __m128i rb2 = _mm_and_si128(rb1, mask_0xf0);
- const __m128i ga2 = _mm_srli_epi16(_mm_and_si128(ga1, mask_0xf0), 4);
- const __m128i rgba4444 = _mm_or_si128(rb2, ga2);
- _mm_storeu_si128((__m128i*)dst, rgba4444);
-}
-
-// Pack R/G/B results into 16b output.
-static WEBP_INLINE void PackAndStore565(const __m128i* const R,
- const __m128i* const G,
- const __m128i* const B,
- uint8_t* const dst) {
- const __m128i r0 = _mm_packus_epi16(*R, *R);
- const __m128i g0 = _mm_packus_epi16(*G, *G);
- const __m128i b0 = _mm_packus_epi16(*B, *B);
- const __m128i r1 = _mm_and_si128(r0, _mm_set1_epi8(0xf8));
- const __m128i b1 = _mm_and_si128(_mm_srli_epi16(b0, 3), _mm_set1_epi8(0x1f));
- const __m128i g1 = _mm_srli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0xe0)), 5);
- const __m128i g2 = _mm_slli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0x1c)), 3);
- const __m128i rg = _mm_or_si128(r1, g1);
- const __m128i gb = _mm_or_si128(g2, b1);
-#if !defined(WEBP_SWAP_16BIT_CSP)
- const __m128i rgb565 = _mm_unpacklo_epi8(rg, gb);
-#else
- const __m128i rgb565 = _mm_unpacklo_epi8(gb, rg);
-#endif
- _mm_storeu_si128((__m128i*)dst, rgb565);
-}
-
-// Function used several times in PlanarTo24b.
-// It samples the in buffer as follows: one every two unsigned char is stored
-// at the beginning of the buffer, while the other half is stored at the end.
-static WEBP_INLINE void PlanarTo24bHelper(const __m128i* const in /*in[6]*/,
- __m128i* const out /*out[6]*/) {
- const __m128i v_mask = _mm_set1_epi16(0x00ff);
-
- // Take one every two upper 8b values.
- out[0] = _mm_packus_epi16(_mm_and_si128(in[0], v_mask),
- _mm_and_si128(in[1], v_mask));
- out[1] = _mm_packus_epi16(_mm_and_si128(in[2], v_mask),
- _mm_and_si128(in[3], v_mask));
- out[2] = _mm_packus_epi16(_mm_and_si128(in[4], v_mask),
- _mm_and_si128(in[5], v_mask));
- // Take one every two lower 8b values.
- out[3] = _mm_packus_epi16(_mm_srli_epi16(in[0], 8), _mm_srli_epi16(in[1], 8));
- out[4] = _mm_packus_epi16(_mm_srli_epi16(in[2], 8), _mm_srli_epi16(in[3], 8));
- out[5] = _mm_packus_epi16(_mm_srli_epi16(in[4], 8), _mm_srli_epi16(in[5], 8));
-}
-
-// Pack the planar buffers
-// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
-// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
-static WEBP_INLINE void PlanarTo24b(__m128i* const in /*in[6]*/, uint8_t* rgb) {
- // The input is 6 registers of sixteen 8b but for the sake of explanation,
- // let's take 6 registers of four 8b values.
- // To pack, we will keep taking one every two 8b integer and move it
- // around as follows:
- // Input:
- // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7
- // Split the 6 registers in two sets of 3 registers: the first set as the even
- // 8b bytes, the second the odd ones:
- // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7
- // Repeat the same permutations twice more:
- // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7
- // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7
- __m128i tmp[6];
- PlanarTo24bHelper(in, tmp);
- PlanarTo24bHelper(tmp, in);
- PlanarTo24bHelper(in, tmp);
- // We need to do it two more times than the example as we have sixteen bytes.
- PlanarTo24bHelper(tmp, in);
- PlanarTo24bHelper(in, tmp);
-
- _mm_storeu_si128((__m128i*)(rgb + 0), tmp[0]);
- _mm_storeu_si128((__m128i*)(rgb + 16), tmp[1]);
- _mm_storeu_si128((__m128i*)(rgb + 32), tmp[2]);
- _mm_storeu_si128((__m128i*)(rgb + 48), tmp[3]);
- _mm_storeu_si128((__m128i*)(rgb + 64), tmp[4]);
- _mm_storeu_si128((__m128i*)(rgb + 80), tmp[5]);
-}
-#undef MK_UINT32
-
-void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst) {
- const __m128i kAlpha = _mm_set1_epi16(255);
- int n;
- for (n = 0; n < 32; n += 8, dst += 32) {
- __m128i R, G, B;
- YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B);
- PackAndStore4(&R, &G, &B, &kAlpha, dst);
- }
-}
-
-void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst) {
- const __m128i kAlpha = _mm_set1_epi16(255);
- int n;
- for (n = 0; n < 32; n += 8, dst += 32) {
- __m128i R, G, B;
- YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B);
- PackAndStore4(&B, &G, &R, &kAlpha, dst);
- }
-}
-
-void VP8YuvToArgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst) {
- const __m128i kAlpha = _mm_set1_epi16(255);
- int n;
- for (n = 0; n < 32; n += 8, dst += 32) {
- __m128i R, G, B;
- YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B);
- PackAndStore4(&kAlpha, &R, &G, &B, dst);
- }
-}
-
-void VP8YuvToRgba444432(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst) {
- const __m128i kAlpha = _mm_set1_epi16(255);
- int n;
- for (n = 0; n < 32; n += 8, dst += 16) {
- __m128i R, G, B;
- YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B);
- PackAndStore4444(&R, &G, &B, &kAlpha, dst);
- }
-}
-
-void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst) {
- int n;
- for (n = 0; n < 32; n += 8, dst += 16) {
- __m128i R, G, B;
- YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B);
- PackAndStore565(&R, &G, &B, dst);
- }
-}
-
-void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst) {
- __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
- __m128i rgb[6];
-
- YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
- YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1);
- YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2);
- YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3);
-
- // Cast to 8b and store as RRRRGGGGBBBB.
- rgb[0] = _mm_packus_epi16(R0, R1);
- rgb[1] = _mm_packus_epi16(R2, R3);
- rgb[2] = _mm_packus_epi16(G0, G1);
- rgb[3] = _mm_packus_epi16(G2, G3);
- rgb[4] = _mm_packus_epi16(B0, B1);
- rgb[5] = _mm_packus_epi16(B2, B3);
-
- // Pack as RGBRGBRGBRGB.
- PlanarTo24b(rgb, dst);
-}
-
-void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst) {
- __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
- __m128i bgr[6];
-
- YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
- YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1);
- YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2);
- YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3);
-
- // Cast to 8b and store as BBBBGGGGRRRR.
- bgr[0] = _mm_packus_epi16(B0, B1);
- bgr[1] = _mm_packus_epi16(B2, B3);
- bgr[2] = _mm_packus_epi16(G0, G1);
- bgr[3] = _mm_packus_epi16(G2, G3);
- bgr[4] = _mm_packus_epi16(R0, R1);
- bgr[5] = _mm_packus_epi16(R2, R3);
-
- // Pack as BGRBGRBGRBGR.
- PlanarTo24b(bgr, dst);
-}
-
-//-----------------------------------------------------------------------------
-// Arbitrary-length row conversion functions
-
-static void YuvToRgbaRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst, int len) {
- const __m128i kAlpha = _mm_set1_epi16(255);
- int n;
- for (n = 0; n + 8 <= len; n += 8, dst += 32) {
- __m128i R, G, B;
- YUV420ToRGB(y, u, v, &R, &G, &B);
- PackAndStore4(&R, &G, &B, &kAlpha, dst);
- y += 8;
- u += 4;
- v += 4;
- }
- for (; n < len; ++n) { // Finish off
- VP8YuvToRgba(y[0], u[0], v[0], dst);
- dst += 4;
- y += 1;
- u += (n & 1);
- v += (n & 1);
- }
-}
-
-static void YuvToBgraRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst, int len) {
- const __m128i kAlpha = _mm_set1_epi16(255);
- int n;
- for (n = 0; n + 8 <= len; n += 8, dst += 32) {
- __m128i R, G, B;
- YUV420ToRGB(y, u, v, &R, &G, &B);
- PackAndStore4(&B, &G, &R, &kAlpha, dst);
- y += 8;
- u += 4;
- v += 4;
- }
- for (; n < len; ++n) { // Finish off
- VP8YuvToBgra(y[0], u[0], v[0], dst);
- dst += 4;
- y += 1;
- u += (n & 1);
- v += (n & 1);
- }
-}
-
-static void YuvToArgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst, int len) {
- const __m128i kAlpha = _mm_set1_epi16(255);
- int n;
- for (n = 0; n + 8 <= len; n += 8, dst += 32) {
- __m128i R, G, B;
- YUV420ToRGB(y, u, v, &R, &G, &B);
- PackAndStore4(&kAlpha, &R, &G, &B, dst);
- y += 8;
- u += 4;
- v += 4;
- }
- for (; n < len; ++n) { // Finish off
- VP8YuvToArgb(y[0], u[0], v[0], dst);
- dst += 4;
- y += 1;
- u += (n & 1);
- v += (n & 1);
- }
-}
-
-static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst, int len) {
- int n;
- for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
- __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
- __m128i rgb[6];
-
- YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
- YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1);
- YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2);
- YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3);
-
- // Cast to 8b and store as RRRRGGGGBBBB.
- rgb[0] = _mm_packus_epi16(R0, R1);
- rgb[1] = _mm_packus_epi16(R2, R3);
- rgb[2] = _mm_packus_epi16(G0, G1);
- rgb[3] = _mm_packus_epi16(G2, G3);
- rgb[4] = _mm_packus_epi16(B0, B1);
- rgb[5] = _mm_packus_epi16(B2, B3);
-
- // Pack as RGBRGBRGBRGB.
- PlanarTo24b(rgb, dst);
-
- y += 32;
- u += 16;
- v += 16;
- }
- for (; n < len; ++n) { // Finish off
- VP8YuvToRgb(y[0], u[0], v[0], dst);
- dst += 3;
- y += 1;
- u += (n & 1);
- v += (n & 1);
- }
-}
-
-static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
- uint8_t* dst, int len) {
- int n;
- for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
- __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
- __m128i bgr[6];
-
- YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
- YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1);
- YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2);
- YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3);
-
- // Cast to 8b and store as BBBBGGGGRRRR.
- bgr[0] = _mm_packus_epi16(B0, B1);
- bgr[1] = _mm_packus_epi16(B2, B3);
- bgr[2] = _mm_packus_epi16(G0, G1);
- bgr[3] = _mm_packus_epi16(G2, G3);
- bgr[4] = _mm_packus_epi16(R0, R1);
- bgr[5] = _mm_packus_epi16(R2, R3);
-
- // Pack as BGRBGRBGRBGR.
- PlanarTo24b(bgr, dst);
-
- y += 32;
- u += 16;
- v += 16;
- }
- for (; n < len; ++n) { // Finish off
- VP8YuvToBgr(y[0], u[0], v[0], dst);
- dst += 3;
- y += 1;
- u += (n & 1);
- v += (n & 1);
- }
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-extern void WebPInitSamplersSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) {
- WebPSamplers[MODE_RGB] = YuvToRgbRow;
- WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
- WebPSamplers[MODE_BGR] = YuvToBgrRow;
- WebPSamplers[MODE_BGRA] = YuvToBgraRow;
- WebPSamplers[MODE_ARGB] = YuvToArgbRow;
-}
-
-//------------------------------------------------------------------------------
-// RGB24/32 -> YUV converters
-
-// Load eight 16b-words from *src.
-#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src))
-// Store either 16b-words into *dst
-#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V))
-
-// Function that inserts a value of the second half of the in buffer in between
-// every two char of the first half.
-static WEBP_INLINE void RGB24PackedToPlanarHelper(
- const __m128i* const in /*in[6]*/, __m128i* const out /*out[6]*/) {
- out[0] = _mm_unpacklo_epi8(in[0], in[3]);
- out[1] = _mm_unpackhi_epi8(in[0], in[3]);
- out[2] = _mm_unpacklo_epi8(in[1], in[4]);
- out[3] = _mm_unpackhi_epi8(in[1], in[4]);
- out[4] = _mm_unpacklo_epi8(in[2], in[5]);
- out[5] = _mm_unpackhi_epi8(in[2], in[5]);
-}
-
-// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers:
-// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
-// Similar to PlanarTo24bHelper(), but in reverse order.
-static WEBP_INLINE void RGB24PackedToPlanar(const uint8_t* const rgb,
- __m128i* const out /*out[6]*/) {
- __m128i tmp[6];
- tmp[0] = _mm_loadu_si128((const __m128i*)(rgb + 0));
- tmp[1] = _mm_loadu_si128((const __m128i*)(rgb + 16));
- tmp[2] = _mm_loadu_si128((const __m128i*)(rgb + 32));
- tmp[3] = _mm_loadu_si128((const __m128i*)(rgb + 48));
- tmp[4] = _mm_loadu_si128((const __m128i*)(rgb + 64));
- tmp[5] = _mm_loadu_si128((const __m128i*)(rgb + 80));
-
- RGB24PackedToPlanarHelper(tmp, out);
- RGB24PackedToPlanarHelper(out, tmp);
- RGB24PackedToPlanarHelper(tmp, out);
- RGB24PackedToPlanarHelper(out, tmp);
- RGB24PackedToPlanarHelper(tmp, out);
-}
-
-// Convert 8 packed ARGB to r[], g[], b[]
-static WEBP_INLINE void RGB32PackedToPlanar(const uint32_t* const argb,
- __m128i* const r,
- __m128i* const g,
- __m128i* const b) {
- const __m128i zero = _mm_setzero_si128();
- const __m128i in0 = LOAD_16(argb + 0); // argb3 | argb2 | argb1 | argb0
- const __m128i in1 = LOAD_16(argb + 4); // argb7 | argb6 | argb5 | argb4
- // column-wise transpose
- const __m128i A0 = _mm_unpacklo_epi8(in0, in1);
- const __m128i A1 = _mm_unpackhi_epi8(in0, in1);
- const __m128i B0 = _mm_unpacklo_epi8(A0, A1);
- const __m128i B1 = _mm_unpackhi_epi8(A0, A1);
- // C0 = g7 g6 ... g1 g0 | b7 b6 ... b1 b0
- // C1 = a7 a6 ... a1 a0 | r7 r6 ... r1 r0
- const __m128i C0 = _mm_unpacklo_epi8(B0, B1);
- const __m128i C1 = _mm_unpackhi_epi8(B0, B1);
- // store 16b
- *r = _mm_unpacklo_epi8(C1, zero);
- *g = _mm_unpackhi_epi8(C0, zero);
- *b = _mm_unpacklo_epi8(C0, zero);
-}
-
-// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX
-// It's a macro and not a function because we need to use immediate values with
-// srai_epi32, e.g.
-#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \
- ROUNDER, DESCALE_FIX, OUT) do { \
- const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \
- const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \
- const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \
- const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \
- const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \
- const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \
- const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \
- const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \
- const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \
- const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \
- (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \
-} while (0)
-
-#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A))
-static WEBP_INLINE void ConvertRGBToY(const __m128i* const R,
- const __m128i* const G,
- const __m128i* const B,
- __m128i* const Y) {
- const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384);
- const __m128i kGB_y = MK_CST_16(16384, 6420);
- const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF);
-
- const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G);
- const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G);
- const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B);
- const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B);
- TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y);
-}
-
-static WEBP_INLINE void ConvertRGBToUV(const __m128i* const R,
- const __m128i* const G,
- const __m128i* const B,
- __m128i* const U, __m128i* const V) {
- const __m128i kRG_u = MK_CST_16(-9719, -19081);
- const __m128i kGB_u = MK_CST_16(0, 28800);
- const __m128i kRG_v = MK_CST_16(28800, 0);
- const __m128i kGB_v = MK_CST_16(-24116, -4684);
- const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2);
-
- const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G);
- const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G);
- const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B);
- const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B);
- TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u,
- kHALF_UV, YUV_FIX + 2, *U);
- TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v,
- kHALF_UV, YUV_FIX + 2, *V);
-}
-
-#undef MK_CST_16
-#undef TRANSFORM
-
-static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) {
- const int max_width = width & ~31;
- int i;
- for (i = 0; i < max_width; rgb += 3 * 16 * 2) {
- __m128i rgb_plane[6];
- int j;
-
- RGB24PackedToPlanar(rgb, rgb_plane);
-
- for (j = 0; j < 2; ++j, i += 16) {
- const __m128i zero = _mm_setzero_si128();
- __m128i r, g, b, Y0, Y1;
-
- // Convert to 16-bit Y.
- r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero);
- g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero);
- b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero);
- ConvertRGBToY(&r, &g, &b, &Y0);
-
- // Convert to 16-bit Y.
- r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero);
- g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero);
- b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero);
- ConvertRGBToY(&r, &g, &b, &Y1);
-
- // Cast to 8-bit and store.
- STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
- }
- }
- for (; i < width; ++i, rgb += 3) { // left-over
- y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF);
- }
-}
-
-static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) {
- const int max_width = width & ~31;
- int i;
- for (i = 0; i < max_width; bgr += 3 * 16 * 2) {
- __m128i bgr_plane[6];
- int j;
-
- RGB24PackedToPlanar(bgr, bgr_plane);
-
- for (j = 0; j < 2; ++j, i += 16) {
- const __m128i zero = _mm_setzero_si128();
- __m128i r, g, b, Y0, Y1;
-
- // Convert to 16-bit Y.
- b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero);
- g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero);
- r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero);
- ConvertRGBToY(&r, &g, &b, &Y0);
-
- // Convert to 16-bit Y.
- b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero);
- g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero);
- r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero);
- ConvertRGBToY(&r, &g, &b, &Y1);
-
- // Cast to 8-bit and store.
- STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
- }
- }
- for (; i < width; ++i, bgr += 3) { // left-over
- y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF);
- }
-}
-
-static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) {
- const int max_width = width & ~15;
- int i;
- for (i = 0; i < max_width; i += 16) {
- __m128i r, g, b, Y0, Y1;
- RGB32PackedToPlanar(&argb[i + 0], &r, &g, &b);
- ConvertRGBToY(&r, &g, &b, &Y0);
- RGB32PackedToPlanar(&argb[i + 8], &r, &g, &b);
- ConvertRGBToY(&r, &g, &b, &Y1);
- STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
- }
- for (; i < width; ++i) { // left-over
- const uint32_t p = argb[i];
- y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
- YUV_HALF);
- }
-}
-
-// Horizontal add (doubled) of two 16b values, result is 16b.
-// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ...
-static void HorizontalAddPack(const __m128i* const A, const __m128i* const B,
- __m128i* const out) {
- const __m128i k2 = _mm_set1_epi16(2);
- const __m128i C = _mm_madd_epi16(*A, k2);
- const __m128i D = _mm_madd_epi16(*B, k2);
- *out = _mm_packs_epi32(C, D);
-}
-
-static void ConvertARGBToUV(const uint32_t* argb, uint8_t* u, uint8_t* v,
- int src_width, int do_store) {
- const int max_width = src_width & ~31;
- int i;
- for (i = 0; i < max_width; i += 32, u += 16, v += 16) {
- __m128i r0, g0, b0, r1, g1, b1, U0, V0, U1, V1;
- RGB32PackedToPlanar(&argb[i + 0], &r0, &g0, &b0);
- RGB32PackedToPlanar(&argb[i + 8], &r1, &g1, &b1);
- HorizontalAddPack(&r0, &r1, &r0);
- HorizontalAddPack(&g0, &g1, &g0);
- HorizontalAddPack(&b0, &b1, &b0);
- ConvertRGBToUV(&r0, &g0, &b0, &U0, &V0);
-
- RGB32PackedToPlanar(&argb[i + 16], &r0, &g0, &b0);
- RGB32PackedToPlanar(&argb[i + 24], &r1, &g1, &b1);
- HorizontalAddPack(&r0, &r1, &r0);
- HorizontalAddPack(&g0, &g1, &g0);
- HorizontalAddPack(&b0, &b1, &b0);
- ConvertRGBToUV(&r0, &g0, &b0, &U1, &V1);
-
- U0 = _mm_packus_epi16(U0, U1);
- V0 = _mm_packus_epi16(V0, V1);
- if (!do_store) {
- const __m128i prev_u = LOAD_16(u);
- const __m128i prev_v = LOAD_16(v);
- U0 = _mm_avg_epu8(U0, prev_u);
- V0 = _mm_avg_epu8(V0, prev_v);
- }
- STORE_16(U0, u);
- STORE_16(V0, v);
- }
- if (i < src_width) { // left-over
- WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store);
- }
-}
-
-// Convert 16 packed ARGB 16b-values to r[], g[], b[]
-static WEBP_INLINE void RGBA32PackedToPlanar_16b(const uint16_t* const rgbx,
- __m128i* const r,
- __m128i* const g,
- __m128i* const b) {
- const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x
- const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x
- const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ...
- const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ...
- // column-wise transpose
- const __m128i A0 = _mm_unpacklo_epi16(in0, in1);
- const __m128i A1 = _mm_unpackhi_epi16(in0, in1);
- const __m128i A2 = _mm_unpacklo_epi16(in2, in3);
- const __m128i A3 = _mm_unpackhi_epi16(in2, in3);
- const __m128i B0 = _mm_unpacklo_epi16(A0, A1); // r0 r1 r2 r3 | g0 g1 ..
- const __m128i B1 = _mm_unpackhi_epi16(A0, A1); // b0 b1 b2 b3 | x x x x
- const __m128i B2 = _mm_unpacklo_epi16(A2, A3); // r4 r5 r6 r7 | g4 g5 ..
- const __m128i B3 = _mm_unpackhi_epi16(A2, A3); // b4 b5 b6 b7 | x x x x
- *r = _mm_unpacklo_epi64(B0, B2);
- *g = _mm_unpackhi_epi64(B0, B2);
- *b = _mm_unpacklo_epi64(B1, B3);
-}
-
-static void ConvertRGBA32ToUV(const uint16_t* rgb,
- uint8_t* u, uint8_t* v, int width) {
- const int max_width = width & ~15;
- const uint16_t* const last_rgb = rgb + 4 * max_width;
- while (rgb < last_rgb) {
- __m128i r, g, b, U0, V0, U1, V1;
- RGBA32PackedToPlanar_16b(rgb + 0, &r, &g, &b);
- ConvertRGBToUV(&r, &g, &b, &U0, &V0);
- RGBA32PackedToPlanar_16b(rgb + 32, &r, &g, &b);
- ConvertRGBToUV(&r, &g, &b, &U1, &V1);
- STORE_16(_mm_packus_epi16(U0, U1), u);
- STORE_16(_mm_packus_epi16(V0, V1), v);
- u += 16;
- v += 16;
- rgb += 2 * 32;
- }
- if (max_width < width) { // left-over
- WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width);
- }
-}
-
-//------------------------------------------------------------------------------
-
-extern void WebPInitConvertARGBToYUVSSE2(void);
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE2(void) {
- WebPConvertARGBToY = ConvertARGBToY;
- WebPConvertARGBToUV = ConvertARGBToUV;
-
- WebPConvertRGB24ToY = ConvertRGB24ToY;
- WebPConvertBGR24ToY = ConvertBGR24ToY;
-
- WebPConvertRGBA32ToUV = ConvertRGBA32ToUV;
-}
-
-#else // !WEBP_USE_SSE2
-
-WEBP_DSP_INIT_STUB(WebPInitSamplersSSE2)
-WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE2)
-
-#endif // WEBP_USE_SSE2
diff --git a/drivers/webp/dsp/yuv_tables_sse2.h b/drivers/webp/dsp/yuv_tables_sse2.h
deleted file mode 100644
index 2b0f057518..0000000000
--- a/drivers/webp/dsp/yuv_tables_sse2.h
+++ /dev/null
@@ -1,536 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// SSE2 tables for YUV->RGB conversion (12kB overall)
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-// This file is not compiled, but #include'd directly from yuv.c
-// Only used if WEBP_YUV_USE_SSE2_TABLES is defined.
-
-static const VP8kCstSSE2 VP8kYtoRGBA[256] = {
- {{0xfffb77b0, 0xfffb77b0, 0xfffb77b0, 0x003fc000}},
- {{0xfffbc235, 0xfffbc235, 0xfffbc235, 0x003fc000}},
- {{0xfffc0cba, 0xfffc0cba, 0xfffc0cba, 0x003fc000}},
- {{0xfffc573f, 0xfffc573f, 0xfffc573f, 0x003fc000}},
- {{0xfffca1c4, 0xfffca1c4, 0xfffca1c4, 0x003fc000}},
- {{0xfffcec49, 0xfffcec49, 0xfffcec49, 0x003fc000}},
- {{0xfffd36ce, 0xfffd36ce, 0xfffd36ce, 0x003fc000}},
- {{0xfffd8153, 0xfffd8153, 0xfffd8153, 0x003fc000}},
- {{0xfffdcbd8, 0xfffdcbd8, 0xfffdcbd8, 0x003fc000}},
- {{0xfffe165d, 0xfffe165d, 0xfffe165d, 0x003fc000}},
- {{0xfffe60e2, 0xfffe60e2, 0xfffe60e2, 0x003fc000}},
- {{0xfffeab67, 0xfffeab67, 0xfffeab67, 0x003fc000}},
- {{0xfffef5ec, 0xfffef5ec, 0xfffef5ec, 0x003fc000}},
- {{0xffff4071, 0xffff4071, 0xffff4071, 0x003fc000}},
- {{0xffff8af6, 0xffff8af6, 0xffff8af6, 0x003fc000}},
- {{0xffffd57b, 0xffffd57b, 0xffffd57b, 0x003fc000}},
- {{0x00002000, 0x00002000, 0x00002000, 0x003fc000}},
- {{0x00006a85, 0x00006a85, 0x00006a85, 0x003fc000}},
- {{0x0000b50a, 0x0000b50a, 0x0000b50a, 0x003fc000}},
- {{0x0000ff8f, 0x0000ff8f, 0x0000ff8f, 0x003fc000}},
- {{0x00014a14, 0x00014a14, 0x00014a14, 0x003fc000}},
- {{0x00019499, 0x00019499, 0x00019499, 0x003fc000}},
- {{0x0001df1e, 0x0001df1e, 0x0001df1e, 0x003fc000}},
- {{0x000229a3, 0x000229a3, 0x000229a3, 0x003fc000}},
- {{0x00027428, 0x00027428, 0x00027428, 0x003fc000}},
- {{0x0002bead, 0x0002bead, 0x0002bead, 0x003fc000}},
- {{0x00030932, 0x00030932, 0x00030932, 0x003fc000}},
- {{0x000353b7, 0x000353b7, 0x000353b7, 0x003fc000}},
- {{0x00039e3c, 0x00039e3c, 0x00039e3c, 0x003fc000}},
- {{0x0003e8c1, 0x0003e8c1, 0x0003e8c1, 0x003fc000}},
- {{0x00043346, 0x00043346, 0x00043346, 0x003fc000}},
- {{0x00047dcb, 0x00047dcb, 0x00047dcb, 0x003fc000}},
- {{0x0004c850, 0x0004c850, 0x0004c850, 0x003fc000}},
- {{0x000512d5, 0x000512d5, 0x000512d5, 0x003fc000}},
- {{0x00055d5a, 0x00055d5a, 0x00055d5a, 0x003fc000}},
- {{0x0005a7df, 0x0005a7df, 0x0005a7df, 0x003fc000}},
- {{0x0005f264, 0x0005f264, 0x0005f264, 0x003fc000}},
- {{0x00063ce9, 0x00063ce9, 0x00063ce9, 0x003fc000}},
- {{0x0006876e, 0x0006876e, 0x0006876e, 0x003fc000}},
- {{0x0006d1f3, 0x0006d1f3, 0x0006d1f3, 0x003fc000}},
- {{0x00071c78, 0x00071c78, 0x00071c78, 0x003fc000}},
- {{0x000766fd, 0x000766fd, 0x000766fd, 0x003fc000}},
- {{0x0007b182, 0x0007b182, 0x0007b182, 0x003fc000}},
- {{0x0007fc07, 0x0007fc07, 0x0007fc07, 0x003fc000}},
- {{0x0008468c, 0x0008468c, 0x0008468c, 0x003fc000}},
- {{0x00089111, 0x00089111, 0x00089111, 0x003fc000}},
- {{0x0008db96, 0x0008db96, 0x0008db96, 0x003fc000}},
- {{0x0009261b, 0x0009261b, 0x0009261b, 0x003fc000}},
- {{0x000970a0, 0x000970a0, 0x000970a0, 0x003fc000}},
- {{0x0009bb25, 0x0009bb25, 0x0009bb25, 0x003fc000}},
- {{0x000a05aa, 0x000a05aa, 0x000a05aa, 0x003fc000}},
- {{0x000a502f, 0x000a502f, 0x000a502f, 0x003fc000}},
- {{0x000a9ab4, 0x000a9ab4, 0x000a9ab4, 0x003fc000}},
- {{0x000ae539, 0x000ae539, 0x000ae539, 0x003fc000}},
- {{0x000b2fbe, 0x000b2fbe, 0x000b2fbe, 0x003fc000}},
- {{0x000b7a43, 0x000b7a43, 0x000b7a43, 0x003fc000}},
- {{0x000bc4c8, 0x000bc4c8, 0x000bc4c8, 0x003fc000}},
- {{0x000c0f4d, 0x000c0f4d, 0x000c0f4d, 0x003fc000}},
- {{0x000c59d2, 0x000c59d2, 0x000c59d2, 0x003fc000}},
- {{0x000ca457, 0x000ca457, 0x000ca457, 0x003fc000}},
- {{0x000ceedc, 0x000ceedc, 0x000ceedc, 0x003fc000}},
- {{0x000d3961, 0x000d3961, 0x000d3961, 0x003fc000}},
- {{0x000d83e6, 0x000d83e6, 0x000d83e6, 0x003fc000}},
- {{0x000dce6b, 0x000dce6b, 0x000dce6b, 0x003fc000}},
- {{0x000e18f0, 0x000e18f0, 0x000e18f0, 0x003fc000}},
- {{0x000e6375, 0x000e6375, 0x000e6375, 0x003fc000}},
- {{0x000eadfa, 0x000eadfa, 0x000eadfa, 0x003fc000}},
- {{0x000ef87f, 0x000ef87f, 0x000ef87f, 0x003fc000}},
- {{0x000f4304, 0x000f4304, 0x000f4304, 0x003fc000}},
- {{0x000f8d89, 0x000f8d89, 0x000f8d89, 0x003fc000}},
- {{0x000fd80e, 0x000fd80e, 0x000fd80e, 0x003fc000}},
- {{0x00102293, 0x00102293, 0x00102293, 0x003fc000}},
- {{0x00106d18, 0x00106d18, 0x00106d18, 0x003fc000}},
- {{0x0010b79d, 0x0010b79d, 0x0010b79d, 0x003fc000}},
- {{0x00110222, 0x00110222, 0x00110222, 0x003fc000}},
- {{0x00114ca7, 0x00114ca7, 0x00114ca7, 0x003fc000}},
- {{0x0011972c, 0x0011972c, 0x0011972c, 0x003fc000}},
- {{0x0011e1b1, 0x0011e1b1, 0x0011e1b1, 0x003fc000}},
- {{0x00122c36, 0x00122c36, 0x00122c36, 0x003fc000}},
- {{0x001276bb, 0x001276bb, 0x001276bb, 0x003fc000}},
- {{0x0012c140, 0x0012c140, 0x0012c140, 0x003fc000}},
- {{0x00130bc5, 0x00130bc5, 0x00130bc5, 0x003fc000}},
- {{0x0013564a, 0x0013564a, 0x0013564a, 0x003fc000}},
- {{0x0013a0cf, 0x0013a0cf, 0x0013a0cf, 0x003fc000}},
- {{0x0013eb54, 0x0013eb54, 0x0013eb54, 0x003fc000}},
- {{0x001435d9, 0x001435d9, 0x001435d9, 0x003fc000}},
- {{0x0014805e, 0x0014805e, 0x0014805e, 0x003fc000}},
- {{0x0014cae3, 0x0014cae3, 0x0014cae3, 0x003fc000}},
- {{0x00151568, 0x00151568, 0x00151568, 0x003fc000}},
- {{0x00155fed, 0x00155fed, 0x00155fed, 0x003fc000}},
- {{0x0015aa72, 0x0015aa72, 0x0015aa72, 0x003fc000}},
- {{0x0015f4f7, 0x0015f4f7, 0x0015f4f7, 0x003fc000}},
- {{0x00163f7c, 0x00163f7c, 0x00163f7c, 0x003fc000}},
- {{0x00168a01, 0x00168a01, 0x00168a01, 0x003fc000}},
- {{0x0016d486, 0x0016d486, 0x0016d486, 0x003fc000}},
- {{0x00171f0b, 0x00171f0b, 0x00171f0b, 0x003fc000}},
- {{0x00176990, 0x00176990, 0x00176990, 0x003fc000}},
- {{0x0017b415, 0x0017b415, 0x0017b415, 0x003fc000}},
- {{0x0017fe9a, 0x0017fe9a, 0x0017fe9a, 0x003fc000}},
- {{0x0018491f, 0x0018491f, 0x0018491f, 0x003fc000}},
- {{0x001893a4, 0x001893a4, 0x001893a4, 0x003fc000}},
- {{0x0018de29, 0x0018de29, 0x0018de29, 0x003fc000}},
- {{0x001928ae, 0x001928ae, 0x001928ae, 0x003fc000}},
- {{0x00197333, 0x00197333, 0x00197333, 0x003fc000}},
- {{0x0019bdb8, 0x0019bdb8, 0x0019bdb8, 0x003fc000}},
- {{0x001a083d, 0x001a083d, 0x001a083d, 0x003fc000}},
- {{0x001a52c2, 0x001a52c2, 0x001a52c2, 0x003fc000}},
- {{0x001a9d47, 0x001a9d47, 0x001a9d47, 0x003fc000}},
- {{0x001ae7cc, 0x001ae7cc, 0x001ae7cc, 0x003fc000}},
- {{0x001b3251, 0x001b3251, 0x001b3251, 0x003fc000}},
- {{0x001b7cd6, 0x001b7cd6, 0x001b7cd6, 0x003fc000}},
- {{0x001bc75b, 0x001bc75b, 0x001bc75b, 0x003fc000}},
- {{0x001c11e0, 0x001c11e0, 0x001c11e0, 0x003fc000}},
- {{0x001c5c65, 0x001c5c65, 0x001c5c65, 0x003fc000}},
- {{0x001ca6ea, 0x001ca6ea, 0x001ca6ea, 0x003fc000}},
- {{0x001cf16f, 0x001cf16f, 0x001cf16f, 0x003fc000}},
- {{0x001d3bf4, 0x001d3bf4, 0x001d3bf4, 0x003fc000}},
- {{0x001d8679, 0x001d8679, 0x001d8679, 0x003fc000}},
- {{0x001dd0fe, 0x001dd0fe, 0x001dd0fe, 0x003fc000}},
- {{0x001e1b83, 0x001e1b83, 0x001e1b83, 0x003fc000}},
- {{0x001e6608, 0x001e6608, 0x001e6608, 0x003fc000}},
- {{0x001eb08d, 0x001eb08d, 0x001eb08d, 0x003fc000}},
- {{0x001efb12, 0x001efb12, 0x001efb12, 0x003fc000}},
- {{0x001f4597, 0x001f4597, 0x001f4597, 0x003fc000}},
- {{0x001f901c, 0x001f901c, 0x001f901c, 0x003fc000}},
- {{0x001fdaa1, 0x001fdaa1, 0x001fdaa1, 0x003fc000}},
- {{0x00202526, 0x00202526, 0x00202526, 0x003fc000}},
- {{0x00206fab, 0x00206fab, 0x00206fab, 0x003fc000}},
- {{0x0020ba30, 0x0020ba30, 0x0020ba30, 0x003fc000}},
- {{0x002104b5, 0x002104b5, 0x002104b5, 0x003fc000}},
- {{0x00214f3a, 0x00214f3a, 0x00214f3a, 0x003fc000}},
- {{0x002199bf, 0x002199bf, 0x002199bf, 0x003fc000}},
- {{0x0021e444, 0x0021e444, 0x0021e444, 0x003fc000}},
- {{0x00222ec9, 0x00222ec9, 0x00222ec9, 0x003fc000}},
- {{0x0022794e, 0x0022794e, 0x0022794e, 0x003fc000}},
- {{0x0022c3d3, 0x0022c3d3, 0x0022c3d3, 0x003fc000}},
- {{0x00230e58, 0x00230e58, 0x00230e58, 0x003fc000}},
- {{0x002358dd, 0x002358dd, 0x002358dd, 0x003fc000}},
- {{0x0023a362, 0x0023a362, 0x0023a362, 0x003fc000}},
- {{0x0023ede7, 0x0023ede7, 0x0023ede7, 0x003fc000}},
- {{0x0024386c, 0x0024386c, 0x0024386c, 0x003fc000}},
- {{0x002482f1, 0x002482f1, 0x002482f1, 0x003fc000}},
- {{0x0024cd76, 0x0024cd76, 0x0024cd76, 0x003fc000}},
- {{0x002517fb, 0x002517fb, 0x002517fb, 0x003fc000}},
- {{0x00256280, 0x00256280, 0x00256280, 0x003fc000}},
- {{0x0025ad05, 0x0025ad05, 0x0025ad05, 0x003fc000}},
- {{0x0025f78a, 0x0025f78a, 0x0025f78a, 0x003fc000}},
- {{0x0026420f, 0x0026420f, 0x0026420f, 0x003fc000}},
- {{0x00268c94, 0x00268c94, 0x00268c94, 0x003fc000}},
- {{0x0026d719, 0x0026d719, 0x0026d719, 0x003fc000}},
- {{0x0027219e, 0x0027219e, 0x0027219e, 0x003fc000}},
- {{0x00276c23, 0x00276c23, 0x00276c23, 0x003fc000}},
- {{0x0027b6a8, 0x0027b6a8, 0x0027b6a8, 0x003fc000}},
- {{0x0028012d, 0x0028012d, 0x0028012d, 0x003fc000}},
- {{0x00284bb2, 0x00284bb2, 0x00284bb2, 0x003fc000}},
- {{0x00289637, 0x00289637, 0x00289637, 0x003fc000}},
- {{0x0028e0bc, 0x0028e0bc, 0x0028e0bc, 0x003fc000}},
- {{0x00292b41, 0x00292b41, 0x00292b41, 0x003fc000}},
- {{0x002975c6, 0x002975c6, 0x002975c6, 0x003fc000}},
- {{0x0029c04b, 0x0029c04b, 0x0029c04b, 0x003fc000}},
- {{0x002a0ad0, 0x002a0ad0, 0x002a0ad0, 0x003fc000}},
- {{0x002a5555, 0x002a5555, 0x002a5555, 0x003fc000}},
- {{0x002a9fda, 0x002a9fda, 0x002a9fda, 0x003fc000}},
- {{0x002aea5f, 0x002aea5f, 0x002aea5f, 0x003fc000}},
- {{0x002b34e4, 0x002b34e4, 0x002b34e4, 0x003fc000}},
- {{0x002b7f69, 0x002b7f69, 0x002b7f69, 0x003fc000}},
- {{0x002bc9ee, 0x002bc9ee, 0x002bc9ee, 0x003fc000}},
- {{0x002c1473, 0x002c1473, 0x002c1473, 0x003fc000}},
- {{0x002c5ef8, 0x002c5ef8, 0x002c5ef8, 0x003fc000}},
- {{0x002ca97d, 0x002ca97d, 0x002ca97d, 0x003fc000}},
- {{0x002cf402, 0x002cf402, 0x002cf402, 0x003fc000}},
- {{0x002d3e87, 0x002d3e87, 0x002d3e87, 0x003fc000}},
- {{0x002d890c, 0x002d890c, 0x002d890c, 0x003fc000}},
- {{0x002dd391, 0x002dd391, 0x002dd391, 0x003fc000}},
- {{0x002e1e16, 0x002e1e16, 0x002e1e16, 0x003fc000}},
- {{0x002e689b, 0x002e689b, 0x002e689b, 0x003fc000}},
- {{0x002eb320, 0x002eb320, 0x002eb320, 0x003fc000}},
- {{0x002efda5, 0x002efda5, 0x002efda5, 0x003fc000}},
- {{0x002f482a, 0x002f482a, 0x002f482a, 0x003fc000}},
- {{0x002f92af, 0x002f92af, 0x002f92af, 0x003fc000}},
- {{0x002fdd34, 0x002fdd34, 0x002fdd34, 0x003fc000}},
- {{0x003027b9, 0x003027b9, 0x003027b9, 0x003fc000}},
- {{0x0030723e, 0x0030723e, 0x0030723e, 0x003fc000}},
- {{0x0030bcc3, 0x0030bcc3, 0x0030bcc3, 0x003fc000}},
- {{0x00310748, 0x00310748, 0x00310748, 0x003fc000}},
- {{0x003151cd, 0x003151cd, 0x003151cd, 0x003fc000}},
- {{0x00319c52, 0x00319c52, 0x00319c52, 0x003fc000}},
- {{0x0031e6d7, 0x0031e6d7, 0x0031e6d7, 0x003fc000}},
- {{0x0032315c, 0x0032315c, 0x0032315c, 0x003fc000}},
- {{0x00327be1, 0x00327be1, 0x00327be1, 0x003fc000}},
- {{0x0032c666, 0x0032c666, 0x0032c666, 0x003fc000}},
- {{0x003310eb, 0x003310eb, 0x003310eb, 0x003fc000}},
- {{0x00335b70, 0x00335b70, 0x00335b70, 0x003fc000}},
- {{0x0033a5f5, 0x0033a5f5, 0x0033a5f5, 0x003fc000}},
- {{0x0033f07a, 0x0033f07a, 0x0033f07a, 0x003fc000}},
- {{0x00343aff, 0x00343aff, 0x00343aff, 0x003fc000}},
- {{0x00348584, 0x00348584, 0x00348584, 0x003fc000}},
- {{0x0034d009, 0x0034d009, 0x0034d009, 0x003fc000}},
- {{0x00351a8e, 0x00351a8e, 0x00351a8e, 0x003fc000}},
- {{0x00356513, 0x00356513, 0x00356513, 0x003fc000}},
- {{0x0035af98, 0x0035af98, 0x0035af98, 0x003fc000}},
- {{0x0035fa1d, 0x0035fa1d, 0x0035fa1d, 0x003fc000}},
- {{0x003644a2, 0x003644a2, 0x003644a2, 0x003fc000}},
- {{0x00368f27, 0x00368f27, 0x00368f27, 0x003fc000}},
- {{0x0036d9ac, 0x0036d9ac, 0x0036d9ac, 0x003fc000}},
- {{0x00372431, 0x00372431, 0x00372431, 0x003fc000}},
- {{0x00376eb6, 0x00376eb6, 0x00376eb6, 0x003fc000}},
- {{0x0037b93b, 0x0037b93b, 0x0037b93b, 0x003fc000}},
- {{0x003803c0, 0x003803c0, 0x003803c0, 0x003fc000}},
- {{0x00384e45, 0x00384e45, 0x00384e45, 0x003fc000}},
- {{0x003898ca, 0x003898ca, 0x003898ca, 0x003fc000}},
- {{0x0038e34f, 0x0038e34f, 0x0038e34f, 0x003fc000}},
- {{0x00392dd4, 0x00392dd4, 0x00392dd4, 0x003fc000}},
- {{0x00397859, 0x00397859, 0x00397859, 0x003fc000}},
- {{0x0039c2de, 0x0039c2de, 0x0039c2de, 0x003fc000}},
- {{0x003a0d63, 0x003a0d63, 0x003a0d63, 0x003fc000}},
- {{0x003a57e8, 0x003a57e8, 0x003a57e8, 0x003fc000}},
- {{0x003aa26d, 0x003aa26d, 0x003aa26d, 0x003fc000}},
- {{0x003aecf2, 0x003aecf2, 0x003aecf2, 0x003fc000}},
- {{0x003b3777, 0x003b3777, 0x003b3777, 0x003fc000}},
- {{0x003b81fc, 0x003b81fc, 0x003b81fc, 0x003fc000}},
- {{0x003bcc81, 0x003bcc81, 0x003bcc81, 0x003fc000}},
- {{0x003c1706, 0x003c1706, 0x003c1706, 0x003fc000}},
- {{0x003c618b, 0x003c618b, 0x003c618b, 0x003fc000}},
- {{0x003cac10, 0x003cac10, 0x003cac10, 0x003fc000}},
- {{0x003cf695, 0x003cf695, 0x003cf695, 0x003fc000}},
- {{0x003d411a, 0x003d411a, 0x003d411a, 0x003fc000}},
- {{0x003d8b9f, 0x003d8b9f, 0x003d8b9f, 0x003fc000}},
- {{0x003dd624, 0x003dd624, 0x003dd624, 0x003fc000}},
- {{0x003e20a9, 0x003e20a9, 0x003e20a9, 0x003fc000}},
- {{0x003e6b2e, 0x003e6b2e, 0x003e6b2e, 0x003fc000}},
- {{0x003eb5b3, 0x003eb5b3, 0x003eb5b3, 0x003fc000}},
- {{0x003f0038, 0x003f0038, 0x003f0038, 0x003fc000}},
- {{0x003f4abd, 0x003f4abd, 0x003f4abd, 0x003fc000}},
- {{0x003f9542, 0x003f9542, 0x003f9542, 0x003fc000}},
- {{0x003fdfc7, 0x003fdfc7, 0x003fdfc7, 0x003fc000}},
- {{0x00402a4c, 0x00402a4c, 0x00402a4c, 0x003fc000}},
- {{0x004074d1, 0x004074d1, 0x004074d1, 0x003fc000}},
- {{0x0040bf56, 0x0040bf56, 0x0040bf56, 0x003fc000}},
- {{0x004109db, 0x004109db, 0x004109db, 0x003fc000}},
- {{0x00415460, 0x00415460, 0x00415460, 0x003fc000}},
- {{0x00419ee5, 0x00419ee5, 0x00419ee5, 0x003fc000}},
- {{0x0041e96a, 0x0041e96a, 0x0041e96a, 0x003fc000}},
- {{0x004233ef, 0x004233ef, 0x004233ef, 0x003fc000}},
- {{0x00427e74, 0x00427e74, 0x00427e74, 0x003fc000}},
- {{0x0042c8f9, 0x0042c8f9, 0x0042c8f9, 0x003fc000}},
- {{0x0043137e, 0x0043137e, 0x0043137e, 0x003fc000}},
- {{0x00435e03, 0x00435e03, 0x00435e03, 0x003fc000}},
- {{0x0043a888, 0x0043a888, 0x0043a888, 0x003fc000}},
- {{0x0043f30d, 0x0043f30d, 0x0043f30d, 0x003fc000}},
- {{0x00443d92, 0x00443d92, 0x00443d92, 0x003fc000}},
- {{0x00448817, 0x00448817, 0x00448817, 0x003fc000}},
- {{0x0044d29c, 0x0044d29c, 0x0044d29c, 0x003fc000}},
- {{0x00451d21, 0x00451d21, 0x00451d21, 0x003fc000}},
- {{0x004567a6, 0x004567a6, 0x004567a6, 0x003fc000}},
- {{0x0045b22b, 0x0045b22b, 0x0045b22b, 0x003fc000}}
-};
-
-static const VP8kCstSSE2 VP8kUtoRGBA[256] = {
- {{0, 0x000c8980, 0xffbf7300, 0}}, {{0, 0x000c706d, 0xffbff41a, 0}},
- {{0, 0x000c575a, 0xffc07534, 0}}, {{0, 0x000c3e47, 0xffc0f64e, 0}},
- {{0, 0x000c2534, 0xffc17768, 0}}, {{0, 0x000c0c21, 0xffc1f882, 0}},
- {{0, 0x000bf30e, 0xffc2799c, 0}}, {{0, 0x000bd9fb, 0xffc2fab6, 0}},
- {{0, 0x000bc0e8, 0xffc37bd0, 0}}, {{0, 0x000ba7d5, 0xffc3fcea, 0}},
- {{0, 0x000b8ec2, 0xffc47e04, 0}}, {{0, 0x000b75af, 0xffc4ff1e, 0}},
- {{0, 0x000b5c9c, 0xffc58038, 0}}, {{0, 0x000b4389, 0xffc60152, 0}},
- {{0, 0x000b2a76, 0xffc6826c, 0}}, {{0, 0x000b1163, 0xffc70386, 0}},
- {{0, 0x000af850, 0xffc784a0, 0}}, {{0, 0x000adf3d, 0xffc805ba, 0}},
- {{0, 0x000ac62a, 0xffc886d4, 0}}, {{0, 0x000aad17, 0xffc907ee, 0}},
- {{0, 0x000a9404, 0xffc98908, 0}}, {{0, 0x000a7af1, 0xffca0a22, 0}},
- {{0, 0x000a61de, 0xffca8b3c, 0}}, {{0, 0x000a48cb, 0xffcb0c56, 0}},
- {{0, 0x000a2fb8, 0xffcb8d70, 0}}, {{0, 0x000a16a5, 0xffcc0e8a, 0}},
- {{0, 0x0009fd92, 0xffcc8fa4, 0}}, {{0, 0x0009e47f, 0xffcd10be, 0}},
- {{0, 0x0009cb6c, 0xffcd91d8, 0}}, {{0, 0x0009b259, 0xffce12f2, 0}},
- {{0, 0x00099946, 0xffce940c, 0}}, {{0, 0x00098033, 0xffcf1526, 0}},
- {{0, 0x00096720, 0xffcf9640, 0}}, {{0, 0x00094e0d, 0xffd0175a, 0}},
- {{0, 0x000934fa, 0xffd09874, 0}}, {{0, 0x00091be7, 0xffd1198e, 0}},
- {{0, 0x000902d4, 0xffd19aa8, 0}}, {{0, 0x0008e9c1, 0xffd21bc2, 0}},
- {{0, 0x0008d0ae, 0xffd29cdc, 0}}, {{0, 0x0008b79b, 0xffd31df6, 0}},
- {{0, 0x00089e88, 0xffd39f10, 0}}, {{0, 0x00088575, 0xffd4202a, 0}},
- {{0, 0x00086c62, 0xffd4a144, 0}}, {{0, 0x0008534f, 0xffd5225e, 0}},
- {{0, 0x00083a3c, 0xffd5a378, 0}}, {{0, 0x00082129, 0xffd62492, 0}},
- {{0, 0x00080816, 0xffd6a5ac, 0}}, {{0, 0x0007ef03, 0xffd726c6, 0}},
- {{0, 0x0007d5f0, 0xffd7a7e0, 0}}, {{0, 0x0007bcdd, 0xffd828fa, 0}},
- {{0, 0x0007a3ca, 0xffd8aa14, 0}}, {{0, 0x00078ab7, 0xffd92b2e, 0}},
- {{0, 0x000771a4, 0xffd9ac48, 0}}, {{0, 0x00075891, 0xffda2d62, 0}},
- {{0, 0x00073f7e, 0xffdaae7c, 0}}, {{0, 0x0007266b, 0xffdb2f96, 0}},
- {{0, 0x00070d58, 0xffdbb0b0, 0}}, {{0, 0x0006f445, 0xffdc31ca, 0}},
- {{0, 0x0006db32, 0xffdcb2e4, 0}}, {{0, 0x0006c21f, 0xffdd33fe, 0}},
- {{0, 0x0006a90c, 0xffddb518, 0}}, {{0, 0x00068ff9, 0xffde3632, 0}},
- {{0, 0x000676e6, 0xffdeb74c, 0}}, {{0, 0x00065dd3, 0xffdf3866, 0}},
- {{0, 0x000644c0, 0xffdfb980, 0}}, {{0, 0x00062bad, 0xffe03a9a, 0}},
- {{0, 0x0006129a, 0xffe0bbb4, 0}}, {{0, 0x0005f987, 0xffe13cce, 0}},
- {{0, 0x0005e074, 0xffe1bde8, 0}}, {{0, 0x0005c761, 0xffe23f02, 0}},
- {{0, 0x0005ae4e, 0xffe2c01c, 0}}, {{0, 0x0005953b, 0xffe34136, 0}},
- {{0, 0x00057c28, 0xffe3c250, 0}}, {{0, 0x00056315, 0xffe4436a, 0}},
- {{0, 0x00054a02, 0xffe4c484, 0}}, {{0, 0x000530ef, 0xffe5459e, 0}},
- {{0, 0x000517dc, 0xffe5c6b8, 0}}, {{0, 0x0004fec9, 0xffe647d2, 0}},
- {{0, 0x0004e5b6, 0xffe6c8ec, 0}}, {{0, 0x0004cca3, 0xffe74a06, 0}},
- {{0, 0x0004b390, 0xffe7cb20, 0}}, {{0, 0x00049a7d, 0xffe84c3a, 0}},
- {{0, 0x0004816a, 0xffe8cd54, 0}}, {{0, 0x00046857, 0xffe94e6e, 0}},
- {{0, 0x00044f44, 0xffe9cf88, 0}}, {{0, 0x00043631, 0xffea50a2, 0}},
- {{0, 0x00041d1e, 0xffead1bc, 0}}, {{0, 0x0004040b, 0xffeb52d6, 0}},
- {{0, 0x0003eaf8, 0xffebd3f0, 0}}, {{0, 0x0003d1e5, 0xffec550a, 0}},
- {{0, 0x0003b8d2, 0xffecd624, 0}}, {{0, 0x00039fbf, 0xffed573e, 0}},
- {{0, 0x000386ac, 0xffedd858, 0}}, {{0, 0x00036d99, 0xffee5972, 0}},
- {{0, 0x00035486, 0xffeeda8c, 0}}, {{0, 0x00033b73, 0xffef5ba6, 0}},
- {{0, 0x00032260, 0xffefdcc0, 0}}, {{0, 0x0003094d, 0xfff05dda, 0}},
- {{0, 0x0002f03a, 0xfff0def4, 0}}, {{0, 0x0002d727, 0xfff1600e, 0}},
- {{0, 0x0002be14, 0xfff1e128, 0}}, {{0, 0x0002a501, 0xfff26242, 0}},
- {{0, 0x00028bee, 0xfff2e35c, 0}}, {{0, 0x000272db, 0xfff36476, 0}},
- {{0, 0x000259c8, 0xfff3e590, 0}}, {{0, 0x000240b5, 0xfff466aa, 0}},
- {{0, 0x000227a2, 0xfff4e7c4, 0}}, {{0, 0x00020e8f, 0xfff568de, 0}},
- {{0, 0x0001f57c, 0xfff5e9f8, 0}}, {{0, 0x0001dc69, 0xfff66b12, 0}},
- {{0, 0x0001c356, 0xfff6ec2c, 0}}, {{0, 0x0001aa43, 0xfff76d46, 0}},
- {{0, 0x00019130, 0xfff7ee60, 0}}, {{0, 0x0001781d, 0xfff86f7a, 0}},
- {{0, 0x00015f0a, 0xfff8f094, 0}}, {{0, 0x000145f7, 0xfff971ae, 0}},
- {{0, 0x00012ce4, 0xfff9f2c8, 0}}, {{0, 0x000113d1, 0xfffa73e2, 0}},
- {{0, 0x0000fabe, 0xfffaf4fc, 0}}, {{0, 0x0000e1ab, 0xfffb7616, 0}},
- {{0, 0x0000c898, 0xfffbf730, 0}}, {{0, 0x0000af85, 0xfffc784a, 0}},
- {{0, 0x00009672, 0xfffcf964, 0}}, {{0, 0x00007d5f, 0xfffd7a7e, 0}},
- {{0, 0x0000644c, 0xfffdfb98, 0}}, {{0, 0x00004b39, 0xfffe7cb2, 0}},
- {{0, 0x00003226, 0xfffefdcc, 0}}, {{0, 0x00001913, 0xffff7ee6, 0}},
- {{0, 0x00000000, 0x00000000, 0}}, {{0, 0xffffe6ed, 0x0000811a, 0}},
- {{0, 0xffffcdda, 0x00010234, 0}}, {{0, 0xffffb4c7, 0x0001834e, 0}},
- {{0, 0xffff9bb4, 0x00020468, 0}}, {{0, 0xffff82a1, 0x00028582, 0}},
- {{0, 0xffff698e, 0x0003069c, 0}}, {{0, 0xffff507b, 0x000387b6, 0}},
- {{0, 0xffff3768, 0x000408d0, 0}}, {{0, 0xffff1e55, 0x000489ea, 0}},
- {{0, 0xffff0542, 0x00050b04, 0}}, {{0, 0xfffeec2f, 0x00058c1e, 0}},
- {{0, 0xfffed31c, 0x00060d38, 0}}, {{0, 0xfffeba09, 0x00068e52, 0}},
- {{0, 0xfffea0f6, 0x00070f6c, 0}}, {{0, 0xfffe87e3, 0x00079086, 0}},
- {{0, 0xfffe6ed0, 0x000811a0, 0}}, {{0, 0xfffe55bd, 0x000892ba, 0}},
- {{0, 0xfffe3caa, 0x000913d4, 0}}, {{0, 0xfffe2397, 0x000994ee, 0}},
- {{0, 0xfffe0a84, 0x000a1608, 0}}, {{0, 0xfffdf171, 0x000a9722, 0}},
- {{0, 0xfffdd85e, 0x000b183c, 0}}, {{0, 0xfffdbf4b, 0x000b9956, 0}},
- {{0, 0xfffda638, 0x000c1a70, 0}}, {{0, 0xfffd8d25, 0x000c9b8a, 0}},
- {{0, 0xfffd7412, 0x000d1ca4, 0}}, {{0, 0xfffd5aff, 0x000d9dbe, 0}},
- {{0, 0xfffd41ec, 0x000e1ed8, 0}}, {{0, 0xfffd28d9, 0x000e9ff2, 0}},
- {{0, 0xfffd0fc6, 0x000f210c, 0}}, {{0, 0xfffcf6b3, 0x000fa226, 0}},
- {{0, 0xfffcdda0, 0x00102340, 0}}, {{0, 0xfffcc48d, 0x0010a45a, 0}},
- {{0, 0xfffcab7a, 0x00112574, 0}}, {{0, 0xfffc9267, 0x0011a68e, 0}},
- {{0, 0xfffc7954, 0x001227a8, 0}}, {{0, 0xfffc6041, 0x0012a8c2, 0}},
- {{0, 0xfffc472e, 0x001329dc, 0}}, {{0, 0xfffc2e1b, 0x0013aaf6, 0}},
- {{0, 0xfffc1508, 0x00142c10, 0}}, {{0, 0xfffbfbf5, 0x0014ad2a, 0}},
- {{0, 0xfffbe2e2, 0x00152e44, 0}}, {{0, 0xfffbc9cf, 0x0015af5e, 0}},
- {{0, 0xfffbb0bc, 0x00163078, 0}}, {{0, 0xfffb97a9, 0x0016b192, 0}},
- {{0, 0xfffb7e96, 0x001732ac, 0}}, {{0, 0xfffb6583, 0x0017b3c6, 0}},
- {{0, 0xfffb4c70, 0x001834e0, 0}}, {{0, 0xfffb335d, 0x0018b5fa, 0}},
- {{0, 0xfffb1a4a, 0x00193714, 0}}, {{0, 0xfffb0137, 0x0019b82e, 0}},
- {{0, 0xfffae824, 0x001a3948, 0}}, {{0, 0xfffacf11, 0x001aba62, 0}},
- {{0, 0xfffab5fe, 0x001b3b7c, 0}}, {{0, 0xfffa9ceb, 0x001bbc96, 0}},
- {{0, 0xfffa83d8, 0x001c3db0, 0}}, {{0, 0xfffa6ac5, 0x001cbeca, 0}},
- {{0, 0xfffa51b2, 0x001d3fe4, 0}}, {{0, 0xfffa389f, 0x001dc0fe, 0}},
- {{0, 0xfffa1f8c, 0x001e4218, 0}}, {{0, 0xfffa0679, 0x001ec332, 0}},
- {{0, 0xfff9ed66, 0x001f444c, 0}}, {{0, 0xfff9d453, 0x001fc566, 0}},
- {{0, 0xfff9bb40, 0x00204680, 0}}, {{0, 0xfff9a22d, 0x0020c79a, 0}},
- {{0, 0xfff9891a, 0x002148b4, 0}}, {{0, 0xfff97007, 0x0021c9ce, 0}},
- {{0, 0xfff956f4, 0x00224ae8, 0}}, {{0, 0xfff93de1, 0x0022cc02, 0}},
- {{0, 0xfff924ce, 0x00234d1c, 0}}, {{0, 0xfff90bbb, 0x0023ce36, 0}},
- {{0, 0xfff8f2a8, 0x00244f50, 0}}, {{0, 0xfff8d995, 0x0024d06a, 0}},
- {{0, 0xfff8c082, 0x00255184, 0}}, {{0, 0xfff8a76f, 0x0025d29e, 0}},
- {{0, 0xfff88e5c, 0x002653b8, 0}}, {{0, 0xfff87549, 0x0026d4d2, 0}},
- {{0, 0xfff85c36, 0x002755ec, 0}}, {{0, 0xfff84323, 0x0027d706, 0}},
- {{0, 0xfff82a10, 0x00285820, 0}}, {{0, 0xfff810fd, 0x0028d93a, 0}},
- {{0, 0xfff7f7ea, 0x00295a54, 0}}, {{0, 0xfff7ded7, 0x0029db6e, 0}},
- {{0, 0xfff7c5c4, 0x002a5c88, 0}}, {{0, 0xfff7acb1, 0x002adda2, 0}},
- {{0, 0xfff7939e, 0x002b5ebc, 0}}, {{0, 0xfff77a8b, 0x002bdfd6, 0}},
- {{0, 0xfff76178, 0x002c60f0, 0}}, {{0, 0xfff74865, 0x002ce20a, 0}},
- {{0, 0xfff72f52, 0x002d6324, 0}}, {{0, 0xfff7163f, 0x002de43e, 0}},
- {{0, 0xfff6fd2c, 0x002e6558, 0}}, {{0, 0xfff6e419, 0x002ee672, 0}},
- {{0, 0xfff6cb06, 0x002f678c, 0}}, {{0, 0xfff6b1f3, 0x002fe8a6, 0}},
- {{0, 0xfff698e0, 0x003069c0, 0}}, {{0, 0xfff67fcd, 0x0030eada, 0}},
- {{0, 0xfff666ba, 0x00316bf4, 0}}, {{0, 0xfff64da7, 0x0031ed0e, 0}},
- {{0, 0xfff63494, 0x00326e28, 0}}, {{0, 0xfff61b81, 0x0032ef42, 0}},
- {{0, 0xfff6026e, 0x0033705c, 0}}, {{0, 0xfff5e95b, 0x0033f176, 0}},
- {{0, 0xfff5d048, 0x00347290, 0}}, {{0, 0xfff5b735, 0x0034f3aa, 0}},
- {{0, 0xfff59e22, 0x003574c4, 0}}, {{0, 0xfff5850f, 0x0035f5de, 0}},
- {{0, 0xfff56bfc, 0x003676f8, 0}}, {{0, 0xfff552e9, 0x0036f812, 0}},
- {{0, 0xfff539d6, 0x0037792c, 0}}, {{0, 0xfff520c3, 0x0037fa46, 0}},
- {{0, 0xfff507b0, 0x00387b60, 0}}, {{0, 0xfff4ee9d, 0x0038fc7a, 0}},
- {{0, 0xfff4d58a, 0x00397d94, 0}}, {{0, 0xfff4bc77, 0x0039feae, 0}},
- {{0, 0xfff4a364, 0x003a7fc8, 0}}, {{0, 0xfff48a51, 0x003b00e2, 0}},
- {{0, 0xfff4713e, 0x003b81fc, 0}}, {{0, 0xfff4582b, 0x003c0316, 0}},
- {{0, 0xfff43f18, 0x003c8430, 0}}, {{0, 0xfff42605, 0x003d054a, 0}},
- {{0, 0xfff40cf2, 0x003d8664, 0}}, {{0, 0xfff3f3df, 0x003e077e, 0}},
- {{0, 0xfff3dacc, 0x003e8898, 0}}, {{0, 0xfff3c1b9, 0x003f09b2, 0}},
- {{0, 0xfff3a8a6, 0x003f8acc, 0}}, {{0, 0xfff38f93, 0x00400be6, 0}}
-};
-
-static VP8kCstSSE2 VP8kVtoRGBA[256] = {
- {{0xffcced80, 0x001a0400, 0, 0}}, {{0xffcd53a5, 0x0019cff8, 0, 0}},
- {{0xffcdb9ca, 0x00199bf0, 0, 0}}, {{0xffce1fef, 0x001967e8, 0, 0}},
- {{0xffce8614, 0x001933e0, 0, 0}}, {{0xffceec39, 0x0018ffd8, 0, 0}},
- {{0xffcf525e, 0x0018cbd0, 0, 0}}, {{0xffcfb883, 0x001897c8, 0, 0}},
- {{0xffd01ea8, 0x001863c0, 0, 0}}, {{0xffd084cd, 0x00182fb8, 0, 0}},
- {{0xffd0eaf2, 0x0017fbb0, 0, 0}}, {{0xffd15117, 0x0017c7a8, 0, 0}},
- {{0xffd1b73c, 0x001793a0, 0, 0}}, {{0xffd21d61, 0x00175f98, 0, 0}},
- {{0xffd28386, 0x00172b90, 0, 0}}, {{0xffd2e9ab, 0x0016f788, 0, 0}},
- {{0xffd34fd0, 0x0016c380, 0, 0}}, {{0xffd3b5f5, 0x00168f78, 0, 0}},
- {{0xffd41c1a, 0x00165b70, 0, 0}}, {{0xffd4823f, 0x00162768, 0, 0}},
- {{0xffd4e864, 0x0015f360, 0, 0}}, {{0xffd54e89, 0x0015bf58, 0, 0}},
- {{0xffd5b4ae, 0x00158b50, 0, 0}}, {{0xffd61ad3, 0x00155748, 0, 0}},
- {{0xffd680f8, 0x00152340, 0, 0}}, {{0xffd6e71d, 0x0014ef38, 0, 0}},
- {{0xffd74d42, 0x0014bb30, 0, 0}}, {{0xffd7b367, 0x00148728, 0, 0}},
- {{0xffd8198c, 0x00145320, 0, 0}}, {{0xffd87fb1, 0x00141f18, 0, 0}},
- {{0xffd8e5d6, 0x0013eb10, 0, 0}}, {{0xffd94bfb, 0x0013b708, 0, 0}},
- {{0xffd9b220, 0x00138300, 0, 0}}, {{0xffda1845, 0x00134ef8, 0, 0}},
- {{0xffda7e6a, 0x00131af0, 0, 0}}, {{0xffdae48f, 0x0012e6e8, 0, 0}},
- {{0xffdb4ab4, 0x0012b2e0, 0, 0}}, {{0xffdbb0d9, 0x00127ed8, 0, 0}},
- {{0xffdc16fe, 0x00124ad0, 0, 0}}, {{0xffdc7d23, 0x001216c8, 0, 0}},
- {{0xffdce348, 0x0011e2c0, 0, 0}}, {{0xffdd496d, 0x0011aeb8, 0, 0}},
- {{0xffddaf92, 0x00117ab0, 0, 0}}, {{0xffde15b7, 0x001146a8, 0, 0}},
- {{0xffde7bdc, 0x001112a0, 0, 0}}, {{0xffdee201, 0x0010de98, 0, 0}},
- {{0xffdf4826, 0x0010aa90, 0, 0}}, {{0xffdfae4b, 0x00107688, 0, 0}},
- {{0xffe01470, 0x00104280, 0, 0}}, {{0xffe07a95, 0x00100e78, 0, 0}},
- {{0xffe0e0ba, 0x000fda70, 0, 0}}, {{0xffe146df, 0x000fa668, 0, 0}},
- {{0xffe1ad04, 0x000f7260, 0, 0}}, {{0xffe21329, 0x000f3e58, 0, 0}},
- {{0xffe2794e, 0x000f0a50, 0, 0}}, {{0xffe2df73, 0x000ed648, 0, 0}},
- {{0xffe34598, 0x000ea240, 0, 0}}, {{0xffe3abbd, 0x000e6e38, 0, 0}},
- {{0xffe411e2, 0x000e3a30, 0, 0}}, {{0xffe47807, 0x000e0628, 0, 0}},
- {{0xffe4de2c, 0x000dd220, 0, 0}}, {{0xffe54451, 0x000d9e18, 0, 0}},
- {{0xffe5aa76, 0x000d6a10, 0, 0}}, {{0xffe6109b, 0x000d3608, 0, 0}},
- {{0xffe676c0, 0x000d0200, 0, 0}}, {{0xffe6dce5, 0x000ccdf8, 0, 0}},
- {{0xffe7430a, 0x000c99f0, 0, 0}}, {{0xffe7a92f, 0x000c65e8, 0, 0}},
- {{0xffe80f54, 0x000c31e0, 0, 0}}, {{0xffe87579, 0x000bfdd8, 0, 0}},
- {{0xffe8db9e, 0x000bc9d0, 0, 0}}, {{0xffe941c3, 0x000b95c8, 0, 0}},
- {{0xffe9a7e8, 0x000b61c0, 0, 0}}, {{0xffea0e0d, 0x000b2db8, 0, 0}},
- {{0xffea7432, 0x000af9b0, 0, 0}}, {{0xffeada57, 0x000ac5a8, 0, 0}},
- {{0xffeb407c, 0x000a91a0, 0, 0}}, {{0xffeba6a1, 0x000a5d98, 0, 0}},
- {{0xffec0cc6, 0x000a2990, 0, 0}}, {{0xffec72eb, 0x0009f588, 0, 0}},
- {{0xffecd910, 0x0009c180, 0, 0}}, {{0xffed3f35, 0x00098d78, 0, 0}},
- {{0xffeda55a, 0x00095970, 0, 0}}, {{0xffee0b7f, 0x00092568, 0, 0}},
- {{0xffee71a4, 0x0008f160, 0, 0}}, {{0xffeed7c9, 0x0008bd58, 0, 0}},
- {{0xffef3dee, 0x00088950, 0, 0}}, {{0xffefa413, 0x00085548, 0, 0}},
- {{0xfff00a38, 0x00082140, 0, 0}}, {{0xfff0705d, 0x0007ed38, 0, 0}},
- {{0xfff0d682, 0x0007b930, 0, 0}}, {{0xfff13ca7, 0x00078528, 0, 0}},
- {{0xfff1a2cc, 0x00075120, 0, 0}}, {{0xfff208f1, 0x00071d18, 0, 0}},
- {{0xfff26f16, 0x0006e910, 0, 0}}, {{0xfff2d53b, 0x0006b508, 0, 0}},
- {{0xfff33b60, 0x00068100, 0, 0}}, {{0xfff3a185, 0x00064cf8, 0, 0}},
- {{0xfff407aa, 0x000618f0, 0, 0}}, {{0xfff46dcf, 0x0005e4e8, 0, 0}},
- {{0xfff4d3f4, 0x0005b0e0, 0, 0}}, {{0xfff53a19, 0x00057cd8, 0, 0}},
- {{0xfff5a03e, 0x000548d0, 0, 0}}, {{0xfff60663, 0x000514c8, 0, 0}},
- {{0xfff66c88, 0x0004e0c0, 0, 0}}, {{0xfff6d2ad, 0x0004acb8, 0, 0}},
- {{0xfff738d2, 0x000478b0, 0, 0}}, {{0xfff79ef7, 0x000444a8, 0, 0}},
- {{0xfff8051c, 0x000410a0, 0, 0}}, {{0xfff86b41, 0x0003dc98, 0, 0}},
- {{0xfff8d166, 0x0003a890, 0, 0}}, {{0xfff9378b, 0x00037488, 0, 0}},
- {{0xfff99db0, 0x00034080, 0, 0}}, {{0xfffa03d5, 0x00030c78, 0, 0}},
- {{0xfffa69fa, 0x0002d870, 0, 0}}, {{0xfffad01f, 0x0002a468, 0, 0}},
- {{0xfffb3644, 0x00027060, 0, 0}}, {{0xfffb9c69, 0x00023c58, 0, 0}},
- {{0xfffc028e, 0x00020850, 0, 0}}, {{0xfffc68b3, 0x0001d448, 0, 0}},
- {{0xfffcced8, 0x0001a040, 0, 0}}, {{0xfffd34fd, 0x00016c38, 0, 0}},
- {{0xfffd9b22, 0x00013830, 0, 0}}, {{0xfffe0147, 0x00010428, 0, 0}},
- {{0xfffe676c, 0x0000d020, 0, 0}}, {{0xfffecd91, 0x00009c18, 0, 0}},
- {{0xffff33b6, 0x00006810, 0, 0}}, {{0xffff99db, 0x00003408, 0, 0}},
- {{0x00000000, 0x00000000, 0, 0}}, {{0x00006625, 0xffffcbf8, 0, 0}},
- {{0x0000cc4a, 0xffff97f0, 0, 0}}, {{0x0001326f, 0xffff63e8, 0, 0}},
- {{0x00019894, 0xffff2fe0, 0, 0}}, {{0x0001feb9, 0xfffefbd8, 0, 0}},
- {{0x000264de, 0xfffec7d0, 0, 0}}, {{0x0002cb03, 0xfffe93c8, 0, 0}},
- {{0x00033128, 0xfffe5fc0, 0, 0}}, {{0x0003974d, 0xfffe2bb8, 0, 0}},
- {{0x0003fd72, 0xfffdf7b0, 0, 0}}, {{0x00046397, 0xfffdc3a8, 0, 0}},
- {{0x0004c9bc, 0xfffd8fa0, 0, 0}}, {{0x00052fe1, 0xfffd5b98, 0, 0}},
- {{0x00059606, 0xfffd2790, 0, 0}}, {{0x0005fc2b, 0xfffcf388, 0, 0}},
- {{0x00066250, 0xfffcbf80, 0, 0}}, {{0x0006c875, 0xfffc8b78, 0, 0}},
- {{0x00072e9a, 0xfffc5770, 0, 0}}, {{0x000794bf, 0xfffc2368, 0, 0}},
- {{0x0007fae4, 0xfffbef60, 0, 0}}, {{0x00086109, 0xfffbbb58, 0, 0}},
- {{0x0008c72e, 0xfffb8750, 0, 0}}, {{0x00092d53, 0xfffb5348, 0, 0}},
- {{0x00099378, 0xfffb1f40, 0, 0}}, {{0x0009f99d, 0xfffaeb38, 0, 0}},
- {{0x000a5fc2, 0xfffab730, 0, 0}}, {{0x000ac5e7, 0xfffa8328, 0, 0}},
- {{0x000b2c0c, 0xfffa4f20, 0, 0}}, {{0x000b9231, 0xfffa1b18, 0, 0}},
- {{0x000bf856, 0xfff9e710, 0, 0}}, {{0x000c5e7b, 0xfff9b308, 0, 0}},
- {{0x000cc4a0, 0xfff97f00, 0, 0}}, {{0x000d2ac5, 0xfff94af8, 0, 0}},
- {{0x000d90ea, 0xfff916f0, 0, 0}}, {{0x000df70f, 0xfff8e2e8, 0, 0}},
- {{0x000e5d34, 0xfff8aee0, 0, 0}}, {{0x000ec359, 0xfff87ad8, 0, 0}},
- {{0x000f297e, 0xfff846d0, 0, 0}}, {{0x000f8fa3, 0xfff812c8, 0, 0}},
- {{0x000ff5c8, 0xfff7dec0, 0, 0}}, {{0x00105bed, 0xfff7aab8, 0, 0}},
- {{0x0010c212, 0xfff776b0, 0, 0}}, {{0x00112837, 0xfff742a8, 0, 0}},
- {{0x00118e5c, 0xfff70ea0, 0, 0}}, {{0x0011f481, 0xfff6da98, 0, 0}},
- {{0x00125aa6, 0xfff6a690, 0, 0}}, {{0x0012c0cb, 0xfff67288, 0, 0}},
- {{0x001326f0, 0xfff63e80, 0, 0}}, {{0x00138d15, 0xfff60a78, 0, 0}},
- {{0x0013f33a, 0xfff5d670, 0, 0}}, {{0x0014595f, 0xfff5a268, 0, 0}},
- {{0x0014bf84, 0xfff56e60, 0, 0}}, {{0x001525a9, 0xfff53a58, 0, 0}},
- {{0x00158bce, 0xfff50650, 0, 0}}, {{0x0015f1f3, 0xfff4d248, 0, 0}},
- {{0x00165818, 0xfff49e40, 0, 0}}, {{0x0016be3d, 0xfff46a38, 0, 0}},
- {{0x00172462, 0xfff43630, 0, 0}}, {{0x00178a87, 0xfff40228, 0, 0}},
- {{0x0017f0ac, 0xfff3ce20, 0, 0}}, {{0x001856d1, 0xfff39a18, 0, 0}},
- {{0x0018bcf6, 0xfff36610, 0, 0}}, {{0x0019231b, 0xfff33208, 0, 0}},
- {{0x00198940, 0xfff2fe00, 0, 0}}, {{0x0019ef65, 0xfff2c9f8, 0, 0}},
- {{0x001a558a, 0xfff295f0, 0, 0}}, {{0x001abbaf, 0xfff261e8, 0, 0}},
- {{0x001b21d4, 0xfff22de0, 0, 0}}, {{0x001b87f9, 0xfff1f9d8, 0, 0}},
- {{0x001bee1e, 0xfff1c5d0, 0, 0}}, {{0x001c5443, 0xfff191c8, 0, 0}},
- {{0x001cba68, 0xfff15dc0, 0, 0}}, {{0x001d208d, 0xfff129b8, 0, 0}},
- {{0x001d86b2, 0xfff0f5b0, 0, 0}}, {{0x001decd7, 0xfff0c1a8, 0, 0}},
- {{0x001e52fc, 0xfff08da0, 0, 0}}, {{0x001eb921, 0xfff05998, 0, 0}},
- {{0x001f1f46, 0xfff02590, 0, 0}}, {{0x001f856b, 0xffeff188, 0, 0}},
- {{0x001feb90, 0xffefbd80, 0, 0}}, {{0x002051b5, 0xffef8978, 0, 0}},
- {{0x0020b7da, 0xffef5570, 0, 0}}, {{0x00211dff, 0xffef2168, 0, 0}},
- {{0x00218424, 0xffeeed60, 0, 0}}, {{0x0021ea49, 0xffeeb958, 0, 0}},
- {{0x0022506e, 0xffee8550, 0, 0}}, {{0x0022b693, 0xffee5148, 0, 0}},
- {{0x00231cb8, 0xffee1d40, 0, 0}}, {{0x002382dd, 0xffede938, 0, 0}},
- {{0x0023e902, 0xffedb530, 0, 0}}, {{0x00244f27, 0xffed8128, 0, 0}},
- {{0x0024b54c, 0xffed4d20, 0, 0}}, {{0x00251b71, 0xffed1918, 0, 0}},
- {{0x00258196, 0xffece510, 0, 0}}, {{0x0025e7bb, 0xffecb108, 0, 0}},
- {{0x00264de0, 0xffec7d00, 0, 0}}, {{0x0026b405, 0xffec48f8, 0, 0}},
- {{0x00271a2a, 0xffec14f0, 0, 0}}, {{0x0027804f, 0xffebe0e8, 0, 0}},
- {{0x0027e674, 0xffebace0, 0, 0}}, {{0x00284c99, 0xffeb78d8, 0, 0}},
- {{0x0028b2be, 0xffeb44d0, 0, 0}}, {{0x002918e3, 0xffeb10c8, 0, 0}},
- {{0x00297f08, 0xffeadcc0, 0, 0}}, {{0x0029e52d, 0xffeaa8b8, 0, 0}},
- {{0x002a4b52, 0xffea74b0, 0, 0}}, {{0x002ab177, 0xffea40a8, 0, 0}},
- {{0x002b179c, 0xffea0ca0, 0, 0}}, {{0x002b7dc1, 0xffe9d898, 0, 0}},
- {{0x002be3e6, 0xffe9a490, 0, 0}}, {{0x002c4a0b, 0xffe97088, 0, 0}},
- {{0x002cb030, 0xffe93c80, 0, 0}}, {{0x002d1655, 0xffe90878, 0, 0}},
- {{0x002d7c7a, 0xffe8d470, 0, 0}}, {{0x002de29f, 0xffe8a068, 0, 0}},
- {{0x002e48c4, 0xffe86c60, 0, 0}}, {{0x002eaee9, 0xffe83858, 0, 0}},
- {{0x002f150e, 0xffe80450, 0, 0}}, {{0x002f7b33, 0xffe7d048, 0, 0}},
- {{0x002fe158, 0xffe79c40, 0, 0}}, {{0x0030477d, 0xffe76838, 0, 0}},
- {{0x0030ada2, 0xffe73430, 0, 0}}, {{0x003113c7, 0xffe70028, 0, 0}},
- {{0x003179ec, 0xffe6cc20, 0, 0}}, {{0x0031e011, 0xffe69818, 0, 0}},
- {{0x00324636, 0xffe66410, 0, 0}}, {{0x0032ac5b, 0xffe63008, 0, 0}}
-};
diff --git a/drivers/webp/enc/alpha.c b/drivers/webp/enc/alpha.c
deleted file mode 100644
index 464df4db09..0000000000
--- a/drivers/webp/enc/alpha.c
+++ /dev/null
@@ -1,433 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Alpha-plane compression.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "./vp8enci.h"
-#include "../dsp/dsp.h"
-#include "../utils/filters.h"
-#include "../utils/quant_levels.h"
-#include "../utils/utils.h"
-#include "webp/format_constants.h"
-
-// -----------------------------------------------------------------------------
-// Encodes the given alpha data via specified compression method 'method'.
-// The pre-processing (quantization) is performed if 'quality' is less than 100.
-// For such cases, the encoding is lossy. The valid range is [0, 100] for
-// 'quality' and [0, 1] for 'method':
-// 'method = 0' - No compression;
-// 'method = 1' - Use lossless coder on the alpha plane only
-// 'filter' values [0, 4] correspond to prediction modes none, horizontal,
-// vertical & gradient filters. The prediction mode 4 will try all the
-// prediction modes 0 to 3 and pick the best one.
-// 'effort_level': specifies how much effort must be spent to try and reduce
-// the compressed output size. In range 0 (quick) to 6 (slow).
-//
-// 'output' corresponds to the buffer containing compressed alpha data.
-// This buffer is allocated by this method and caller should call
-// WebPSafeFree(*output) when done.
-// 'output_size' corresponds to size of this compressed alpha buffer.
-//
-// Returns 1 on successfully encoding the alpha and
-// 0 if either:
-// invalid quality or method, or
-// memory allocation for the compressed data fails.
-
-#include "../enc/vp8li.h"
-
-static int EncodeLossless(const uint8_t* const data, int width, int height,
- int effort_level, // in [0..6] range
- VP8LBitWriter* const bw,
- WebPAuxStats* const stats) {
- int ok = 0;
- WebPConfig config;
- WebPPicture picture;
-
- WebPPictureInit(&picture);
- picture.width = width;
- picture.height = height;
- picture.use_argb = 1;
- picture.stats = stats;
- if (!WebPPictureAlloc(&picture)) return 0;
-
- // Transfer the alpha values to the green channel.
- WebPDispatchAlphaToGreen(data, width, picture.width, picture.height,
- picture.argb, picture.argb_stride);
-
- WebPConfigInit(&config);
- config.lossless = 1;
- // Enable exact, or it would alter RGB values of transparent alpha, which is
- // normally OK but not here since we are not encoding the input image but an
- // internal encoding-related image containing necessary exact information in
- // RGB channels.
- config.exact = 1;
- config.method = effort_level; // impact is very small
- // Set a low default quality for encoding alpha. Ensure that Alpha quality at
- // lower methods (3 and below) is less than the threshold for triggering
- // costly 'BackwardReferencesTraceBackwards'.
- config.quality = 8.f * effort_level;
- assert(config.quality >= 0 && config.quality <= 100.f);
-
- // TODO(urvang): Temporary fix to avoid generating images that trigger
- // a decoder bug related to alpha with color cache.
- // See: https://code.google.com/p/webp/issues/detail?id=239
- // Need to re-enable this later.
- ok = (VP8LEncodeStream(&config, &picture, bw, 0 /*use_cache*/) == VP8_ENC_OK);
- WebPPictureFree(&picture);
- ok = ok && !bw->error_;
- if (!ok) {
- VP8LBitWriterWipeOut(bw);
- return 0;
- }
- return 1;
-}
-
-// -----------------------------------------------------------------------------
-
-// Small struct to hold the result of a filter mode compression attempt.
-typedef struct {
- size_t score;
- VP8BitWriter bw;
- WebPAuxStats stats;
-} FilterTrial;
-
-// This function always returns an initialized 'bw' object, even upon error.
-static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
- int method, int filter, int reduce_levels,
- int effort_level, // in [0..6] range
- uint8_t* const tmp_alpha,
- FilterTrial* result) {
- int ok = 0;
- const uint8_t* alpha_src;
- WebPFilterFunc filter_func;
- uint8_t header;
- const size_t data_size = width * height;
- const uint8_t* output = NULL;
- size_t output_size = 0;
- VP8LBitWriter tmp_bw;
-
- assert((uint64_t)data_size == (uint64_t)width * height); // as per spec
- assert(filter >= 0 && filter < WEBP_FILTER_LAST);
- assert(method >= ALPHA_NO_COMPRESSION);
- assert(method <= ALPHA_LOSSLESS_COMPRESSION);
- assert(sizeof(header) == ALPHA_HEADER_LEN);
-
- filter_func = WebPFilters[filter];
- if (filter_func != NULL) {
- filter_func(data, width, height, width, tmp_alpha);
- alpha_src = tmp_alpha;
- } else {
- alpha_src = data;
- }
-
- if (method != ALPHA_NO_COMPRESSION) {
- ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3);
- ok = ok && EncodeLossless(alpha_src, width, height, effort_level,
- &tmp_bw, &result->stats);
- if (ok) {
- output = VP8LBitWriterFinish(&tmp_bw);
- output_size = VP8LBitWriterNumBytes(&tmp_bw);
- if (output_size > data_size) {
- // compressed size is larger than source! Revert to uncompressed mode.
- method = ALPHA_NO_COMPRESSION;
- VP8LBitWriterWipeOut(&tmp_bw);
- }
- } else {
- VP8LBitWriterWipeOut(&tmp_bw);
- return 0;
- }
- }
-
- if (method == ALPHA_NO_COMPRESSION) {
- output = alpha_src;
- output_size = data_size;
- ok = 1;
- }
-
- // Emit final result.
- header = method | (filter << 2);
- if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
-
- VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size);
- ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN);
- ok = ok && VP8BitWriterAppend(&result->bw, output, output_size);
-
- if (method != ALPHA_NO_COMPRESSION) {
- VP8LBitWriterWipeOut(&tmp_bw);
- }
- ok = ok && !result->bw.error_;
- result->score = VP8BitWriterSize(&result->bw);
- return ok;
-}
-
-// -----------------------------------------------------------------------------
-
-static int GetNumColors(const uint8_t* data, int width, int height,
- int stride) {
- int j;
- int colors = 0;
- uint8_t color[256] = { 0 };
-
- for (j = 0; j < height; ++j) {
- int i;
- const uint8_t* const p = data + j * stride;
- for (i = 0; i < width; ++i) {
- color[p[i]] = 1;
- }
- }
- for (j = 0; j < 256; ++j) {
- if (color[j] > 0) ++colors;
- }
- return colors;
-}
-
-#define FILTER_TRY_NONE (1 << WEBP_FILTER_NONE)
-#define FILTER_TRY_ALL ((1 << WEBP_FILTER_LAST) - 1)
-
-// Given the input 'filter' option, return an OR'd bit-set of filters to try.
-static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height,
- int filter, int effort_level) {
- uint32_t bit_map = 0U;
- if (filter == WEBP_FILTER_FAST) {
- // Quick estimate of the best candidate.
- int try_filter_none = (effort_level > 3);
- const int kMinColorsForFilterNone = 16;
- const int kMaxColorsForFilterNone = 192;
- const int num_colors = GetNumColors(alpha, width, height, width);
- // For low number of colors, NONE yields better compression.
- filter = (num_colors <= kMinColorsForFilterNone)
- ? WEBP_FILTER_NONE
- : WebPEstimateBestFilter(alpha, width, height, width);
- bit_map |= 1 << filter;
- // For large number of colors, try FILTER_NONE in addition to the best
- // filter as well.
- if (try_filter_none || num_colors > kMaxColorsForFilterNone) {
- bit_map |= FILTER_TRY_NONE;
- }
- } else if (filter == WEBP_FILTER_NONE) {
- bit_map = FILTER_TRY_NONE;
- } else { // WEBP_FILTER_BEST -> try all
- bit_map = FILTER_TRY_ALL;
- }
- return bit_map;
-}
-
-static void InitFilterTrial(FilterTrial* const score) {
- score->score = (size_t)~0U;
- VP8BitWriterInit(&score->bw, 0);
-}
-
-static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height,
- size_t data_size, int method, int filter,
- int reduce_levels, int effort_level,
- uint8_t** const output,
- size_t* const output_size,
- WebPAuxStats* const stats) {
- int ok = 1;
- FilterTrial best;
- uint32_t try_map =
- GetFilterMap(alpha, width, height, filter, effort_level);
- InitFilterTrial(&best);
-
- if (try_map != FILTER_TRY_NONE) {
- uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size);
- if (filtered_alpha == NULL) return 0;
-
- for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) {
- if (try_map & 1) {
- FilterTrial trial;
- ok = EncodeAlphaInternal(alpha, width, height, method, filter,
- reduce_levels, effort_level, filtered_alpha,
- &trial);
- if (ok && trial.score < best.score) {
- VP8BitWriterWipeOut(&best.bw);
- best = trial;
- } else {
- VP8BitWriterWipeOut(&trial.bw);
- }
- }
- }
- WebPSafeFree(filtered_alpha);
- } else {
- ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE,
- reduce_levels, effort_level, NULL, &best);
- }
- if (ok) {
- if (stats != NULL) {
- stats->lossless_features = best.stats.lossless_features;
- stats->histogram_bits = best.stats.histogram_bits;
- stats->transform_bits = best.stats.transform_bits;
- stats->cache_bits = best.stats.cache_bits;
- stats->palette_size = best.stats.palette_size;
- stats->lossless_size = best.stats.lossless_size;
- stats->lossless_hdr_size = best.stats.lossless_hdr_size;
- stats->lossless_data_size = best.stats.lossless_data_size;
- }
- *output_size = VP8BitWriterSize(&best.bw);
- *output = VP8BitWriterBuf(&best.bw);
- } else {
- VP8BitWriterWipeOut(&best.bw);
- }
- return ok;
-}
-
-static int EncodeAlpha(VP8Encoder* const enc,
- int quality, int method, int filter,
- int effort_level,
- uint8_t** const output, size_t* const output_size) {
- const WebPPicture* const pic = enc->pic_;
- const int width = pic->width;
- const int height = pic->height;
-
- uint8_t* quant_alpha = NULL;
- const size_t data_size = width * height;
- uint64_t sse = 0;
- int ok = 1;
- const int reduce_levels = (quality < 100);
-
- // quick sanity checks
- assert((uint64_t)data_size == (uint64_t)width * height); // as per spec
- assert(enc != NULL && pic != NULL && pic->a != NULL);
- assert(output != NULL && output_size != NULL);
- assert(width > 0 && height > 0);
- assert(pic->a_stride >= width);
- assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST);
-
- if (quality < 0 || quality > 100) {
- return 0;
- }
-
- if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) {
- return 0;
- }
-
- if (method == ALPHA_NO_COMPRESSION) {
- // Don't filter, as filtering will make no impact on compressed size.
- filter = WEBP_FILTER_NONE;
- }
-
- quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size);
- if (quant_alpha == NULL) {
- return 0;
- }
-
- // Extract alpha data (width x height) from raw_data (stride x height).
- WebPCopyPlane(pic->a, pic->a_stride, quant_alpha, width, width, height);
-
- if (reduce_levels) { // No Quantization required for 'quality = 100'.
- // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence
- // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16]
- // and Quality:]70, 100] -> Levels:]16, 256].
- const int alpha_levels = (quality <= 70) ? (2 + quality / 5)
- : (16 + (quality - 70) * 8);
- ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse);
- }
-
- if (ok) {
- VP8FiltersInit();
- ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method,
- filter, reduce_levels, effort_level, output,
- output_size, pic->stats);
- if (pic->stats != NULL) { // need stats?
- pic->stats->coded_size += (int)(*output_size);
- enc->sse_[3] = sse;
- }
- }
-
- WebPSafeFree(quant_alpha);
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// Main calls
-
-static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) {
- const WebPConfig* config = enc->config_;
- uint8_t* alpha_data = NULL;
- size_t alpha_size = 0;
- const int effort_level = config->method; // maps to [0..6]
- const WEBP_FILTER_TYPE filter =
- (config->alpha_filtering == 0) ? WEBP_FILTER_NONE :
- (config->alpha_filtering == 1) ? WEBP_FILTER_FAST :
- WEBP_FILTER_BEST;
- if (!EncodeAlpha(enc, config->alpha_quality, config->alpha_compression,
- filter, effort_level, &alpha_data, &alpha_size)) {
- return 0;
- }
- if (alpha_size != (uint32_t)alpha_size) { // Sanity check.
- WebPSafeFree(alpha_data);
- return 0;
- }
- enc->alpha_data_size_ = (uint32_t)alpha_size;
- enc->alpha_data_ = alpha_data;
- (void)dummy;
- return 1;
-}
-
-void VP8EncInitAlpha(VP8Encoder* const enc) {
- WebPInitAlphaProcessing();
- enc->has_alpha_ = WebPPictureHasTransparency(enc->pic_);
- enc->alpha_data_ = NULL;
- enc->alpha_data_size_ = 0;
- if (enc->thread_level_ > 0) {
- WebPWorker* const worker = &enc->alpha_worker_;
- WebPGetWorkerInterface()->Init(worker);
- worker->data1 = enc;
- worker->data2 = NULL;
- worker->hook = (WebPWorkerHook)CompressAlphaJob;
- }
-}
-
-int VP8EncStartAlpha(VP8Encoder* const enc) {
- if (enc->has_alpha_) {
- if (enc->thread_level_ > 0) {
- WebPWorker* const worker = &enc->alpha_worker_;
- // Makes sure worker is good to go.
- if (!WebPGetWorkerInterface()->Reset(worker)) {
- return 0;
- }
- WebPGetWorkerInterface()->Launch(worker);
- return 1;
- } else {
- return CompressAlphaJob(enc, NULL); // just do the job right away
- }
- }
- return 1;
-}
-
-int VP8EncFinishAlpha(VP8Encoder* const enc) {
- if (enc->has_alpha_) {
- if (enc->thread_level_ > 0) {
- WebPWorker* const worker = &enc->alpha_worker_;
- if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error
- }
- }
- return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
-}
-
-int VP8EncDeleteAlpha(VP8Encoder* const enc) {
- int ok = 1;
- if (enc->thread_level_ > 0) {
- WebPWorker* const worker = &enc->alpha_worker_;
- // finish anything left in flight
- ok = WebPGetWorkerInterface()->Sync(worker);
- // still need to end the worker, even if !ok
- WebPGetWorkerInterface()->End(worker);
- }
- WebPSafeFree(enc->alpha_data_);
- enc->alpha_data_ = NULL;
- enc->alpha_data_size_ = 0;
- enc->has_alpha_ = 0;
- return ok;
-}
diff --git a/drivers/webp/enc/analysis.c b/drivers/webp/enc/analysis.c
deleted file mode 100644
index b55128fd48..0000000000
--- a/drivers/webp/enc/analysis.c
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Macroblock analysis
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "./vp8enci.h"
-#include "./cost.h"
-#include "../utils/utils.h"
-
-#define MAX_ITERS_K_MEANS 6
-
-//------------------------------------------------------------------------------
-// Smooth the segment map by replacing isolated block by the majority of its
-// neighbours.
-
-static void SmoothSegmentMap(VP8Encoder* const enc) {
- int n, x, y;
- const int w = enc->mb_w_;
- const int h = enc->mb_h_;
- const int majority_cnt_3_x_3_grid = 5;
- uint8_t* const tmp = (uint8_t*)WebPSafeMalloc(w * h, sizeof(*tmp));
- assert((uint64_t)(w * h) == (uint64_t)w * h); // no overflow, as per spec
-
- if (tmp == NULL) return;
- for (y = 1; y < h - 1; ++y) {
- for (x = 1; x < w - 1; ++x) {
- int cnt[NUM_MB_SEGMENTS] = { 0 };
- const VP8MBInfo* const mb = &enc->mb_info_[x + w * y];
- int majority_seg = mb->segment_;
- // Check the 8 neighbouring segment values.
- cnt[mb[-w - 1].segment_]++; // top-left
- cnt[mb[-w + 0].segment_]++; // top
- cnt[mb[-w + 1].segment_]++; // top-right
- cnt[mb[ - 1].segment_]++; // left
- cnt[mb[ + 1].segment_]++; // right
- cnt[mb[ w - 1].segment_]++; // bottom-left
- cnt[mb[ w + 0].segment_]++; // bottom
- cnt[mb[ w + 1].segment_]++; // bottom-right
- for (n = 0; n < NUM_MB_SEGMENTS; ++n) {
- if (cnt[n] >= majority_cnt_3_x_3_grid) {
- majority_seg = n;
- break;
- }
- }
- tmp[x + y * w] = majority_seg;
- }
- }
- for (y = 1; y < h - 1; ++y) {
- for (x = 1; x < w - 1; ++x) {
- VP8MBInfo* const mb = &enc->mb_info_[x + w * y];
- mb->segment_ = tmp[x + y * w];
- }
- }
- WebPSafeFree(tmp);
-}
-
-//------------------------------------------------------------------------------
-// set segment susceptibility alpha_ / beta_
-
-static WEBP_INLINE int clip(int v, int m, int M) {
- return (v < m) ? m : (v > M) ? M : v;
-}
-
-static void SetSegmentAlphas(VP8Encoder* const enc,
- const int centers[NUM_MB_SEGMENTS],
- int mid) {
- const int nb = enc->segment_hdr_.num_segments_;
- int min = centers[0], max = centers[0];
- int n;
-
- if (nb > 1) {
- for (n = 0; n < nb; ++n) {
- if (min > centers[n]) min = centers[n];
- if (max < centers[n]) max = centers[n];
- }
- }
- if (max == min) max = min + 1;
- assert(mid <= max && mid >= min);
- for (n = 0; n < nb; ++n) {
- const int alpha = 255 * (centers[n] - mid) / (max - min);
- const int beta = 255 * (centers[n] - min) / (max - min);
- enc->dqm_[n].alpha_ = clip(alpha, -127, 127);
- enc->dqm_[n].beta_ = clip(beta, 0, 255);
- }
-}
-
-//------------------------------------------------------------------------------
-// Compute susceptibility based on DCT-coeff histograms:
-// the higher, the "easier" the macroblock is to compress.
-
-#define MAX_ALPHA 255 // 8b of precision for susceptibilities.
-#define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha.
-#define DEFAULT_ALPHA (-1)
-#define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha))
-
-static int FinalAlphaValue(int alpha) {
- alpha = MAX_ALPHA - alpha;
- return clip(alpha, 0, MAX_ALPHA);
-}
-
-static int GetAlpha(const VP8Histogram* const histo) {
- // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer
- // values which happen to be mostly noise. This leaves the maximum precision
- // for handling the useful small values which contribute most.
- const int max_value = histo->max_value;
- const int last_non_zero = histo->last_non_zero;
- const int alpha =
- (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0;
- return alpha;
-}
-
-static void InitHistogram(VP8Histogram* const histo) {
- histo->max_value = 0;
- histo->last_non_zero = 1;
-}
-
-static void MergeHistograms(const VP8Histogram* const in,
- VP8Histogram* const out) {
- if (in->max_value > out->max_value) {
- out->max_value = in->max_value;
- }
- if (in->last_non_zero > out->last_non_zero) {
- out->last_non_zero = in->last_non_zero;
- }
-}
-
-//------------------------------------------------------------------------------
-// Simplified k-Means, to assign Nb segments based on alpha-histogram
-
-static void AssignSegments(VP8Encoder* const enc,
- const int alphas[MAX_ALPHA + 1]) {
- // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an
- // explicit check is needed to avoid spurious warning about 'n + 1' exceeding
- // array bounds of 'centers' with some compilers (noticed with gcc-4.9).
- const int nb = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) ?
- enc->segment_hdr_.num_segments_ : NUM_MB_SEGMENTS;
- int centers[NUM_MB_SEGMENTS];
- int weighted_average = 0;
- int map[MAX_ALPHA + 1];
- int a, n, k;
- int min_a = 0, max_a = MAX_ALPHA, range_a;
- // 'int' type is ok for histo, and won't overflow
- int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS];
-
- assert(nb >= 1);
- assert(nb <= NUM_MB_SEGMENTS);
-
- // bracket the input
- for (n = 0; n <= MAX_ALPHA && alphas[n] == 0; ++n) {}
- min_a = n;
- for (n = MAX_ALPHA; n > min_a && alphas[n] == 0; --n) {}
- max_a = n;
- range_a = max_a - min_a;
-
- // Spread initial centers evenly
- for (k = 0, n = 1; k < nb; ++k, n += 2) {
- assert(n < 2 * nb);
- centers[k] = min_a + (n * range_a) / (2 * nb);
- }
-
- for (k = 0; k < MAX_ITERS_K_MEANS; ++k) { // few iters are enough
- int total_weight;
- int displaced;
- // Reset stats
- for (n = 0; n < nb; ++n) {
- accum[n] = 0;
- dist_accum[n] = 0;
- }
- // Assign nearest center for each 'a'
- n = 0; // track the nearest center for current 'a'
- for (a = min_a; a <= max_a; ++a) {
- if (alphas[a]) {
- while (n + 1 < nb && abs(a - centers[n + 1]) < abs(a - centers[n])) {
- n++;
- }
- map[a] = n;
- // accumulate contribution into best centroid
- dist_accum[n] += a * alphas[a];
- accum[n] += alphas[a];
- }
- }
- // All point are classified. Move the centroids to the
- // center of their respective cloud.
- displaced = 0;
- weighted_average = 0;
- total_weight = 0;
- for (n = 0; n < nb; ++n) {
- if (accum[n]) {
- const int new_center = (dist_accum[n] + accum[n] / 2) / accum[n];
- displaced += abs(centers[n] - new_center);
- centers[n] = new_center;
- weighted_average += new_center * accum[n];
- total_weight += accum[n];
- }
- }
- weighted_average = (weighted_average + total_weight / 2) / total_weight;
- if (displaced < 5) break; // no need to keep on looping...
- }
-
- // Map each original value to the closest centroid
- for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
- VP8MBInfo* const mb = &enc->mb_info_[n];
- const int alpha = mb->alpha_;
- mb->segment_ = map[alpha];
- mb->alpha_ = centers[map[alpha]]; // for the record.
- }
-
- if (nb > 1) {
- const int smooth = (enc->config_->preprocessing & 1);
- if (smooth) SmoothSegmentMap(enc);
- }
-
- SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas.
-}
-
-//------------------------------------------------------------------------------
-// Macroblock analysis: collect histogram for each mode, deduce the maximal
-// susceptibility and set best modes for this macroblock.
-// Segment assignment is done later.
-
-// Number of modes to inspect for alpha_ evaluation. We don't need to test all
-// the possible modes during the analysis phase: we risk falling into a local
-// optimum, or be subject to boundary effect
-#define MAX_INTRA16_MODE 2
-#define MAX_INTRA4_MODE 2
-#define MAX_UV_MODE 2
-
-static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) {
- const int max_mode = MAX_INTRA16_MODE;
- int mode;
- int best_alpha = DEFAULT_ALPHA;
- int best_mode = 0;
-
- VP8MakeLuma16Preds(it);
- for (mode = 0; mode < max_mode; ++mode) {
- VP8Histogram histo;
- int alpha;
-
- InitHistogram(&histo);
- VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC,
- it->yuv_p_ + VP8I16ModeOffsets[mode],
- 0, 16, &histo);
- alpha = GetAlpha(&histo);
- if (IS_BETTER_ALPHA(alpha, best_alpha)) {
- best_alpha = alpha;
- best_mode = mode;
- }
- }
- VP8SetIntra16Mode(it, best_mode);
- return best_alpha;
-}
-
-static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
- int best_alpha) {
- uint8_t modes[16];
- const int max_mode = MAX_INTRA4_MODE;
- int i4_alpha;
- VP8Histogram total_histo;
- int cur_histo = 0;
- InitHistogram(&total_histo);
-
- VP8IteratorStartI4(it);
- do {
- int mode;
- int best_mode_alpha = DEFAULT_ALPHA;
- VP8Histogram histos[2];
- const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
-
- VP8MakeIntra4Preds(it);
- for (mode = 0; mode < max_mode; ++mode) {
- int alpha;
-
- InitHistogram(&histos[cur_histo]);
- VP8CollectHistogram(src, it->yuv_p_ + VP8I4ModeOffsets[mode],
- 0, 1, &histos[cur_histo]);
- alpha = GetAlpha(&histos[cur_histo]);
- if (IS_BETTER_ALPHA(alpha, best_mode_alpha)) {
- best_mode_alpha = alpha;
- modes[it->i4_] = mode;
- cur_histo ^= 1; // keep track of best histo so far.
- }
- }
- // accumulate best histogram
- MergeHistograms(&histos[cur_histo ^ 1], &total_histo);
- // Note: we reuse the original samples for predictors
- } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF_ENC));
-
- i4_alpha = GetAlpha(&total_histo);
- if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) {
- VP8SetIntra4Mode(it, modes);
- best_alpha = i4_alpha;
- }
- return best_alpha;
-}
-
-static int MBAnalyzeBestUVMode(VP8EncIterator* const it) {
- int best_alpha = DEFAULT_ALPHA;
- int best_mode = 0;
- const int max_mode = MAX_UV_MODE;
- int mode;
-
- VP8MakeChroma8Preds(it);
- for (mode = 0; mode < max_mode; ++mode) {
- VP8Histogram histo;
- int alpha;
- InitHistogram(&histo);
- VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC,
- it->yuv_p_ + VP8UVModeOffsets[mode],
- 16, 16 + 4 + 4, &histo);
- alpha = GetAlpha(&histo);
- if (IS_BETTER_ALPHA(alpha, best_alpha)) {
- best_alpha = alpha;
- best_mode = mode;
- }
- }
- VP8SetIntraUVMode(it, best_mode);
- return best_alpha;
-}
-
-static void MBAnalyze(VP8EncIterator* const it,
- int alphas[MAX_ALPHA + 1],
- int* const alpha, int* const uv_alpha) {
- const VP8Encoder* const enc = it->enc_;
- int best_alpha, best_uv_alpha;
-
- VP8SetIntra16Mode(it, 0); // default: Intra16, DC_PRED
- VP8SetSkip(it, 0); // not skipped
- VP8SetSegment(it, 0); // default segment, spec-wise.
-
- best_alpha = MBAnalyzeBestIntra16Mode(it);
- if (enc->method_ >= 5) {
- // We go and make a fast decision for intra4/intra16.
- // It's usually not a good and definitive pick, but helps seeding the stats
- // about level bit-cost.
- // TODO(skal): improve criterion.
- best_alpha = MBAnalyzeBestIntra4Mode(it, best_alpha);
- }
- best_uv_alpha = MBAnalyzeBestUVMode(it);
-
- // Final susceptibility mix
- best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2;
- best_alpha = FinalAlphaValue(best_alpha);
- alphas[best_alpha]++;
- it->mb_->alpha_ = best_alpha; // for later remapping.
-
- // Accumulate for later complexity analysis.
- *alpha += best_alpha; // mixed susceptibility (not just luma)
- *uv_alpha += best_uv_alpha;
-}
-
-static void DefaultMBInfo(VP8MBInfo* const mb) {
- mb->type_ = 1; // I16x16
- mb->uv_mode_ = 0;
- mb->skip_ = 0; // not skipped
- mb->segment_ = 0; // default segment
- mb->alpha_ = 0;
-}
-
-//------------------------------------------------------------------------------
-// Main analysis loop:
-// Collect all susceptibilities for each macroblock and record their
-// distribution in alphas[]. Segments is assigned a-posteriori, based on
-// this histogram.
-// We also pick an intra16 prediction mode, which shouldn't be considered
-// final except for fast-encode settings. We can also pick some intra4 modes
-// and decide intra4/intra16, but that's usually almost always a bad choice at
-// this stage.
-
-static void ResetAllMBInfo(VP8Encoder* const enc) {
- int n;
- for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
- DefaultMBInfo(&enc->mb_info_[n]);
- }
- // Default susceptibilities.
- enc->dqm_[0].alpha_ = 0;
- enc->dqm_[0].beta_ = 0;
- // Note: we can't compute this alpha_ / uv_alpha_ -> set to default value.
- enc->alpha_ = 0;
- enc->uv_alpha_ = 0;
- WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
-}
-
-// struct used to collect job result
-typedef struct {
- WebPWorker worker;
- int alphas[MAX_ALPHA + 1];
- int alpha, uv_alpha;
- VP8EncIterator it;
- int delta_progress;
-} SegmentJob;
-
-// main work call
-static int DoSegmentsJob(SegmentJob* const job, VP8EncIterator* const it) {
- int ok = 1;
- if (!VP8IteratorIsDone(it)) {
- uint8_t tmp[32 + WEBP_ALIGN_CST];
- uint8_t* const scratch = (uint8_t*)WEBP_ALIGN(tmp);
- do {
- // Let's pretend we have perfect lossless reconstruction.
- VP8IteratorImport(it, scratch);
- MBAnalyze(it, job->alphas, &job->alpha, &job->uv_alpha);
- ok = VP8IteratorProgress(it, job->delta_progress);
- } while (ok && VP8IteratorNext(it));
- }
- return ok;
-}
-
-static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) {
- int i;
- for (i = 0; i <= MAX_ALPHA; ++i) dst->alphas[i] += src->alphas[i];
- dst->alpha += src->alpha;
- dst->uv_alpha += src->uv_alpha;
-}
-
-// initialize the job struct with some TODOs
-static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job,
- int start_row, int end_row) {
- WebPGetWorkerInterface()->Init(&job->worker);
- job->worker.data1 = job;
- job->worker.data2 = &job->it;
- job->worker.hook = (WebPWorkerHook)DoSegmentsJob;
- VP8IteratorInit(enc, &job->it);
- VP8IteratorSetRow(&job->it, start_row);
- VP8IteratorSetCountDown(&job->it, (end_row - start_row) * enc->mb_w_);
- memset(job->alphas, 0, sizeof(job->alphas));
- job->alpha = 0;
- job->uv_alpha = 0;
- // only one of both jobs can record the progress, since we don't
- // expect the user's hook to be multi-thread safe
- job->delta_progress = (start_row == 0) ? 20 : 0;
-}
-
-// main entry point
-int VP8EncAnalyze(VP8Encoder* const enc) {
- int ok = 1;
- const int do_segments =
- enc->config_->emulate_jpeg_size || // We need the complexity evaluation.
- (enc->segment_hdr_.num_segments_ > 1) ||
- (enc->method_ == 0); // for method 0, we need preds_[] to be filled.
- if (do_segments) {
- const int last_row = enc->mb_h_;
- // We give a little more than a half work to the main thread.
- const int split_row = (9 * last_row + 15) >> 4;
- const int total_mb = last_row * enc->mb_w_;
-#ifdef WEBP_USE_THREAD
- const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it
- const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow);
-#else
- const int do_mt = 0;
-#endif
- const WebPWorkerInterface* const worker_interface =
- WebPGetWorkerInterface();
- SegmentJob main_job;
- if (do_mt) {
- SegmentJob side_job;
- // Note the use of '&' instead of '&&' because we must call the functions
- // no matter what.
- InitSegmentJob(enc, &main_job, 0, split_row);
- InitSegmentJob(enc, &side_job, split_row, last_row);
- // we don't need to call Reset() on main_job.worker, since we're calling
- // WebPWorkerExecute() on it
- ok &= worker_interface->Reset(&side_job.worker);
- // launch the two jobs in parallel
- if (ok) {
- worker_interface->Launch(&side_job.worker);
- worker_interface->Execute(&main_job.worker);
- ok &= worker_interface->Sync(&side_job.worker);
- ok &= worker_interface->Sync(&main_job.worker);
- }
- worker_interface->End(&side_job.worker);
- if (ok) MergeJobs(&side_job, &main_job); // merge results together
- } else {
- // Even for single-thread case, we use the generic Worker tools.
- InitSegmentJob(enc, &main_job, 0, last_row);
- worker_interface->Execute(&main_job.worker);
- ok &= worker_interface->Sync(&main_job.worker);
- }
- worker_interface->End(&main_job.worker);
- if (ok) {
- enc->alpha_ = main_job.alpha / total_mb;
- enc->uv_alpha_ = main_job.uv_alpha / total_mb;
- AssignSegments(enc, main_job.alphas);
- }
- } else { // Use only one default segment.
- ResetAllMBInfo(enc);
- }
- return ok;
-}
-
diff --git a/drivers/webp/enc/backward_references.c b/drivers/webp/enc/backward_references.c
deleted file mode 100644
index 136a24a8c3..0000000000
--- a/drivers/webp/enc/backward_references.c
+++ /dev/null
@@ -1,1715 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-//
-
-#include <assert.h>
-#include <math.h>
-
-#include "./backward_references.h"
-#include "./histogram.h"
-#include "../dsp/lossless.h"
-#include "../dsp/dsp.h"
-#include "../utils/color_cache.h"
-#include "../utils/utils.h"
-
-#define VALUES_IN_BYTE 256
-
-#define MIN_BLOCK_SIZE 256 // minimum block size for backward references
-
-#define MAX_ENTROPY (1e30f)
-
-// 1M window (4M bytes) minus 120 special codes for short distances.
-#define WINDOW_SIZE_BITS 20
-#define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120)
-
-// Bounds for the match length.
-#define MIN_LENGTH 2
-// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it
-// is used in VP8LHashChain.
-#define MAX_LENGTH_BITS 12
-// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits.
-#define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1)
-#if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32
-#error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32"
-#endif
-
-// -----------------------------------------------------------------------------
-
-static const uint8_t plane_to_code_lut[128] = {
- 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255,
- 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79,
- 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87,
- 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91,
- 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100,
- 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109,
- 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114,
- 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117
-};
-
-static int DistanceToPlaneCode(int xsize, int dist) {
- const int yoffset = dist / xsize;
- const int xoffset = dist - yoffset * xsize;
- if (xoffset <= 8 && yoffset < 8) {
- return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1;
- } else if (xoffset > xsize - 8 && yoffset < 7) {
- return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1;
- }
- return dist + 120;
-}
-
-// Returns the exact index where array1 and array2 are different. For an index
-// inferior or equal to best_len_match, the return value just has to be strictly
-// inferior to best_len_match. The current behavior is to return 0 if this index
-// is best_len_match, and the index itself otherwise.
-// If no two elements are the same, it returns max_limit.
-static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
- const uint32_t* const array2,
- int best_len_match, int max_limit) {
- // Before 'expensive' linear match, check if the two arrays match at the
- // current best length index.
- if (array1[best_len_match] != array2[best_len_match]) return 0;
-
- return VP8LVectorMismatch(array1, array2, max_limit);
-}
-
-// -----------------------------------------------------------------------------
-// VP8LBackwardRefs
-
-struct PixOrCopyBlock {
- PixOrCopyBlock* next_; // next block (or NULL)
- PixOrCopy* start_; // data start
- int size_; // currently used size
-};
-
-static void ClearBackwardRefs(VP8LBackwardRefs* const refs) {
- assert(refs != NULL);
- if (refs->tail_ != NULL) {
- *refs->tail_ = refs->free_blocks_; // recycle all blocks at once
- }
- refs->free_blocks_ = refs->refs_;
- refs->tail_ = &refs->refs_;
- refs->last_block_ = NULL;
- refs->refs_ = NULL;
-}
-
-void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) {
- assert(refs != NULL);
- ClearBackwardRefs(refs);
- while (refs->free_blocks_ != NULL) {
- PixOrCopyBlock* const next = refs->free_blocks_->next_;
- WebPSafeFree(refs->free_blocks_);
- refs->free_blocks_ = next;
- }
-}
-
-void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) {
- assert(refs != NULL);
- memset(refs, 0, sizeof(*refs));
- refs->tail_ = &refs->refs_;
- refs->block_size_ =
- (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size;
-}
-
-VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) {
- VP8LRefsCursor c;
- c.cur_block_ = refs->refs_;
- if (refs->refs_ != NULL) {
- c.cur_pos = c.cur_block_->start_;
- c.last_pos_ = c.cur_pos + c.cur_block_->size_;
- } else {
- c.cur_pos = NULL;
- c.last_pos_ = NULL;
- }
- return c;
-}
-
-void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) {
- PixOrCopyBlock* const b = c->cur_block_->next_;
- c->cur_pos = (b == NULL) ? NULL : b->start_;
- c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_;
- c->cur_block_ = b;
-}
-
-// Create a new block, either from the free list or allocated
-static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) {
- PixOrCopyBlock* b = refs->free_blocks_;
- if (b == NULL) { // allocate new memory chunk
- const size_t total_size =
- sizeof(*b) + refs->block_size_ * sizeof(*b->start_);
- b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size);
- if (b == NULL) {
- refs->error_ |= 1;
- return NULL;
- }
- b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned
- } else { // recycle from free-list
- refs->free_blocks_ = b->next_;
- }
- *refs->tail_ = b;
- refs->tail_ = &b->next_;
- refs->last_block_ = b;
- b->next_ = NULL;
- b->size_ = 0;
- return b;
-}
-
-static WEBP_INLINE void BackwardRefsCursorAdd(VP8LBackwardRefs* const refs,
- const PixOrCopy v) {
- PixOrCopyBlock* b = refs->last_block_;
- if (b == NULL || b->size_ == refs->block_size_) {
- b = BackwardRefsNewBlock(refs);
- if (b == NULL) return; // refs->error_ is set
- }
- b->start_[b->size_++] = v;
-}
-
-int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src,
- VP8LBackwardRefs* const dst) {
- const PixOrCopyBlock* b = src->refs_;
- ClearBackwardRefs(dst);
- assert(src->block_size_ == dst->block_size_);
- while (b != NULL) {
- PixOrCopyBlock* const new_b = BackwardRefsNewBlock(dst);
- if (new_b == NULL) return 0; // dst->error_ is set
- memcpy(new_b->start_, b->start_, b->size_ * sizeof(*b->start_));
- new_b->size_ = b->size_;
- b = b->next_;
- }
- return 1;
-}
-
-// -----------------------------------------------------------------------------
-// Hash chains
-
-int VP8LHashChainInit(VP8LHashChain* const p, int size) {
- assert(p->size_ == 0);
- assert(p->offset_length_ == NULL);
- assert(size > 0);
- p->offset_length_ =
- (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_));
- if (p->offset_length_ == NULL) return 0;
- p->size_ = size;
-
- return 1;
-}
-
-void VP8LHashChainClear(VP8LHashChain* const p) {
- assert(p != NULL);
- WebPSafeFree(p->offset_length_);
-
- p->size_ = 0;
- p->offset_length_ = NULL;
-}
-
-// -----------------------------------------------------------------------------
-
-#define HASH_MULTIPLIER_HI (0xc6a4a793U)
-#define HASH_MULTIPLIER_LO (0x5bd1e996U)
-
-static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) {
- uint32_t key;
- key = argb[1] * HASH_MULTIPLIER_HI;
- key += argb[0] * HASH_MULTIPLIER_LO;
- key = key >> (32 - HASH_BITS);
- return key;
-}
-
-// Returns the maximum number of hash chain lookups to do for a
-// given compression quality. Return value in range [8, 86].
-static int GetMaxItersForQuality(int quality) {
- return 8 + (quality * quality) / 128;
-}
-
-static int GetWindowSizeForHashChain(int quality, int xsize) {
- const int max_window_size = (quality > 75) ? WINDOW_SIZE
- : (quality > 50) ? (xsize << 8)
- : (quality > 25) ? (xsize << 6)
- : (xsize << 4);
- assert(xsize > 0);
- return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size;
-}
-
-static WEBP_INLINE int MaxFindCopyLength(int len) {
- return (len < MAX_LENGTH) ? len : MAX_LENGTH;
-}
-
-int VP8LHashChainFill(VP8LHashChain* const p, int quality,
- const uint32_t* const argb, int xsize, int ysize) {
- const int size = xsize * ysize;
- const int iter_max = GetMaxItersForQuality(quality);
- const int iter_min = iter_max - quality / 10;
- const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize);
- int pos;
- uint32_t base_position;
- int32_t* hash_to_first_index;
- // Temporarily use the p->offset_length_ as a hash chain.
- int32_t* chain = (int32_t*)p->offset_length_;
- assert(p->size_ != 0);
- assert(p->offset_length_ != NULL);
-
- hash_to_first_index =
- (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index));
- if (hash_to_first_index == NULL) return 0;
-
- // Set the int32_t array to -1.
- memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index));
- // Fill the chain linking pixels with the same hash.
- for (pos = 0; pos < size - 1; ++pos) {
- const uint32_t hash_code = GetPixPairHash64(argb + pos);
- chain[pos] = hash_to_first_index[hash_code];
- hash_to_first_index[hash_code] = pos;
- }
- WebPSafeFree(hash_to_first_index);
-
- // Find the best match interval at each pixel, defined by an offset to the
- // pixel and a length. The right-most pixel cannot match anything to the right
- // (hence a best length of 0) and the left-most pixel nothing to the left
- // (hence an offset of 0).
- p->offset_length_[0] = p->offset_length_[size - 1] = 0;
- for (base_position = size - 2 < 0 ? 0 : size - 2; base_position > 0;) {
- const int max_len = MaxFindCopyLength(size - 1 - base_position);
- const uint32_t* const argb_start = argb + base_position;
- int iter = iter_max;
- int best_length = 0;
- uint32_t best_distance = 0;
- const int min_pos =
- (base_position > window_size) ? base_position - window_size : 0;
- const int length_max = (max_len < 256) ? max_len : 256;
- uint32_t max_base_position;
-
- for (pos = chain[base_position]; pos >= min_pos; pos = chain[pos]) {
- int curr_length;
- if (--iter < 0) {
- break;
- }
- assert(base_position > (uint32_t)pos);
-
- curr_length =
- FindMatchLength(argb + pos, argb_start, best_length, max_len);
- if (best_length < curr_length) {
- best_length = curr_length;
- best_distance = base_position - pos;
- // Stop if we have reached the maximum length. Otherwise, make sure
- // we have executed a minimum number of iterations depending on the
- // quality.
- if ((best_length == MAX_LENGTH) ||
- (curr_length >= length_max && iter < iter_min)) {
- break;
- }
- }
- }
- // We have the best match but in case the two intervals continue matching
- // to the left, we have the best matches for the left-extended pixels.
- max_base_position = base_position;
- while (1) {
- assert(best_length <= MAX_LENGTH);
- assert(best_distance <= WINDOW_SIZE);
- p->offset_length_[base_position] =
- (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length;
- --base_position;
- // Stop if we don't have a match or if we are out of bounds.
- if (best_distance == 0 || base_position == 0) break;
- // Stop if we cannot extend the matching intervals to the left.
- if (base_position < best_distance ||
- argb[base_position - best_distance] != argb[base_position]) {
- break;
- }
- // Stop if we are matching at its limit because there could be a closer
- // matching interval with the same maximum length. Then again, if the
- // matching interval is as close as possible (best_distance == 1), we will
- // never find anything better so let's continue.
- if (best_length == MAX_LENGTH && best_distance != 1 &&
- base_position + MAX_LENGTH < max_base_position) {
- break;
- }
- if (best_length < MAX_LENGTH) {
- ++best_length;
- max_base_position = base_position;
- }
- }
- }
- return 1;
-}
-
-static WEBP_INLINE int HashChainFindOffset(const VP8LHashChain* const p,
- const int base_position) {
- return p->offset_length_[base_position] >> MAX_LENGTH_BITS;
-}
-
-static WEBP_INLINE int HashChainFindLength(const VP8LHashChain* const p,
- const int base_position) {
- return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1);
-}
-
-static WEBP_INLINE void HashChainFindCopy(const VP8LHashChain* const p,
- int base_position,
- int* const offset_ptr,
- int* const length_ptr) {
- *offset_ptr = HashChainFindOffset(p, base_position);
- *length_ptr = HashChainFindLength(p, base_position);
-}
-
-static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache,
- VP8LColorCache* const hashers,
- VP8LBackwardRefs* const refs) {
- PixOrCopy v;
- if (use_color_cache) {
- const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel);
- if (VP8LColorCacheLookup(hashers, key) == pixel) {
- v = PixOrCopyCreateCacheIdx(key);
- } else {
- v = PixOrCopyCreateLiteral(pixel);
- VP8LColorCacheSet(hashers, key, pixel);
- }
- } else {
- v = PixOrCopyCreateLiteral(pixel);
- }
- BackwardRefsCursorAdd(refs, v);
-}
-
-static int BackwardReferencesRle(int xsize, int ysize,
- const uint32_t* const argb,
- int cache_bits, VP8LBackwardRefs* const refs) {
- const int pix_count = xsize * ysize;
- int i, k;
- const int use_color_cache = (cache_bits > 0);
- VP8LColorCache hashers;
-
- if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) {
- return 0;
- }
- ClearBackwardRefs(refs);
- // Add first pixel as literal.
- AddSingleLiteral(argb[0], use_color_cache, &hashers, refs);
- i = 1;
- while (i < pix_count) {
- const int max_len = MaxFindCopyLength(pix_count - i);
- const int kMinLength = 4;
- const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len);
- const int prev_row_len = (i < xsize) ? 0 :
- FindMatchLength(argb + i, argb + i - xsize, 0, max_len);
- if (rle_len >= prev_row_len && rle_len >= kMinLength) {
- BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len));
- // We don't need to update the color cache here since it is always the
- // same pixel being copied, and that does not change the color cache
- // state.
- i += rle_len;
- } else if (prev_row_len >= kMinLength) {
- BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len));
- if (use_color_cache) {
- for (k = 0; k < prev_row_len; ++k) {
- VP8LColorCacheInsert(&hashers, argb[i + k]);
- }
- }
- i += prev_row_len;
- } else {
- AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
- i++;
- }
- }
- if (use_color_cache) VP8LColorCacheClear(&hashers);
- return !refs->error_;
-}
-
-static int BackwardReferencesLz77(int xsize, int ysize,
- const uint32_t* const argb, int cache_bits,
- const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs) {
- int i;
- int i_last_check = -1;
- int ok = 0;
- int cc_init = 0;
- const int use_color_cache = (cache_bits > 0);
- const int pix_count = xsize * ysize;
- VP8LColorCache hashers;
-
- if (use_color_cache) {
- cc_init = VP8LColorCacheInit(&hashers, cache_bits);
- if (!cc_init) goto Error;
- }
- ClearBackwardRefs(refs);
- for (i = 0; i < pix_count;) {
- // Alternative#1: Code the pixels starting at 'i' using backward reference.
- int offset = 0;
- int len = 0;
- int j;
- HashChainFindCopy(hash_chain, i, &offset, &len);
- if (len > MIN_LENGTH + 1) {
- const int len_ini = len;
- int max_reach = 0;
- assert(i + len < pix_count);
- // Only start from what we have not checked already.
- i_last_check = (i > i_last_check) ? i : i_last_check;
- // We know the best match for the current pixel but we try to find the
- // best matches for the current pixel AND the next one combined.
- // The naive method would use the intervals:
- // [i,i+len) + [i+len, length of best match at i+len)
- // while we check if we can use:
- // [i,j) (where j<=i+len) + [j, length of best match at j)
- for (j = i_last_check + 1; j <= i + len_ini; ++j) {
- const int len_j = HashChainFindLength(hash_chain, j);
- const int reach =
- j + (len_j > MIN_LENGTH + 1 ? len_j : 1); // 1 for single literal.
- if (reach > max_reach) {
- len = j - i;
- max_reach = reach;
- }
- }
- } else {
- len = 1;
- }
- // Go with literal or backward reference.
- assert(len > 0);
- if (len == 1) {
- AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
- } else {
- BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
- if (use_color_cache) {
- for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]);
- }
- }
- i += len;
- }
-
- ok = !refs->error_;
- Error:
- if (cc_init) VP8LColorCacheClear(&hashers);
- return ok;
-}
-
-// -----------------------------------------------------------------------------
-
-typedef struct {
- double alpha_[VALUES_IN_BYTE];
- double red_[VALUES_IN_BYTE];
- double blue_[VALUES_IN_BYTE];
- double distance_[NUM_DISTANCE_CODES];
- double* literal_;
-} CostModel;
-
-static int BackwardReferencesTraceBackwards(
- int xsize, int ysize, const uint32_t* const argb, int quality,
- int cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs);
-
-static void ConvertPopulationCountTableToBitEstimates(
- int num_symbols, const uint32_t population_counts[], double output[]) {
- uint32_t sum = 0;
- int nonzeros = 0;
- int i;
- for (i = 0; i < num_symbols; ++i) {
- sum += population_counts[i];
- if (population_counts[i] > 0) {
- ++nonzeros;
- }
- }
- if (nonzeros <= 1) {
- memset(output, 0, num_symbols * sizeof(*output));
- } else {
- const double logsum = VP8LFastLog2(sum);
- for (i = 0; i < num_symbols; ++i) {
- output[i] = logsum - VP8LFastLog2(population_counts[i]);
- }
- }
-}
-
-static int CostModelBuild(CostModel* const m, int cache_bits,
- VP8LBackwardRefs* const refs) {
- int ok = 0;
- VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits);
- if (histo == NULL) goto Error;
-
- VP8LHistogramCreate(histo, refs, cache_bits);
-
- ConvertPopulationCountTableToBitEstimates(
- VP8LHistogramNumCodes(histo->palette_code_bits_),
- histo->literal_, m->literal_);
- ConvertPopulationCountTableToBitEstimates(
- VALUES_IN_BYTE, histo->red_, m->red_);
- ConvertPopulationCountTableToBitEstimates(
- VALUES_IN_BYTE, histo->blue_, m->blue_);
- ConvertPopulationCountTableToBitEstimates(
- VALUES_IN_BYTE, histo->alpha_, m->alpha_);
- ConvertPopulationCountTableToBitEstimates(
- NUM_DISTANCE_CODES, histo->distance_, m->distance_);
- ok = 1;
-
- Error:
- VP8LFreeHistogram(histo);
- return ok;
-}
-
-static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) {
- return m->alpha_[v >> 24] +
- m->red_[(v >> 16) & 0xff] +
- m->literal_[(v >> 8) & 0xff] +
- m->blue_[v & 0xff];
-}
-
-static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) {
- const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx;
- return m->literal_[literal_idx];
-}
-
-static WEBP_INLINE double GetLengthCost(const CostModel* const m,
- uint32_t length) {
- int code, extra_bits;
- VP8LPrefixEncodeBits(length, &code, &extra_bits);
- return m->literal_[VALUES_IN_BYTE + code] + extra_bits;
-}
-
-static WEBP_INLINE double GetDistanceCost(const CostModel* const m,
- uint32_t distance) {
- int code, extra_bits;
- VP8LPrefixEncodeBits(distance, &code, &extra_bits);
- return m->distance_[code] + extra_bits;
-}
-
-static void AddSingleLiteralWithCostModel(const uint32_t* const argb,
- VP8LColorCache* const hashers,
- const CostModel* const cost_model,
- int idx, int use_color_cache,
- double prev_cost, float* const cost,
- uint16_t* const dist_array) {
- double cost_val = prev_cost;
- const uint32_t color = argb[0];
- if (use_color_cache && VP8LColorCacheContains(hashers, color)) {
- const double mul0 = 0.68;
- const int ix = VP8LColorCacheGetIndex(hashers, color);
- cost_val += GetCacheCost(cost_model, ix) * mul0;
- } else {
- const double mul1 = 0.82;
- if (use_color_cache) VP8LColorCacheInsert(hashers, color);
- cost_val += GetLiteralCost(cost_model, color) * mul1;
- }
- if (cost[idx] > cost_val) {
- cost[idx] = (float)cost_val;
- dist_array[idx] = 1; // only one is inserted.
- }
-}
-
-// -----------------------------------------------------------------------------
-// CostManager and interval handling
-
-// Empirical value to avoid high memory consumption but good for performance.
-#define COST_CACHE_INTERVAL_SIZE_MAX 100
-
-// To perform backward reference every pixel at index index_ is considered and
-// the cost for the MAX_LENGTH following pixels computed. Those following pixels
-// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of:
-// distance_cost_ at index_ + GetLengthCost(cost_model, k)
-// (named cost) (named cached cost)
-// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an
-// array of size MAX_LENGTH.
-// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the
-// minimal values using intervals, for which lower_ and upper_ bounds are kept.
-// An interval is defined by the index_ of the pixel that generated it and
-// is only useful in a range of indices from start_ to end_ (exclusive), i.e.
-// it contains the minimum value for pixels between start_ and end_.
-// Intervals are stored in a linked list and ordered by start_. When a new
-// interval has a better minimum, old intervals are split or removed.
-typedef struct CostInterval CostInterval;
-struct CostInterval {
- double lower_;
- double upper_;
- int start_;
- int end_;
- double distance_cost_;
- int index_;
- CostInterval* previous_;
- CostInterval* next_;
-};
-
-// The GetLengthCost(cost_model, k) part of the costs is also bounded for
-// efficiency in a set of intervals of a different type.
-// If those intervals are small enough, they are not used for comparison and
-// written into the costs right away.
-typedef struct {
- double lower_; // Lower bound of the interval.
- double upper_; // Upper bound of the interval.
- int start_;
- int end_; // Exclusive.
- int do_write_; // If !=0, the interval is saved to cost instead of being kept
- // for comparison.
-} CostCacheInterval;
-
-// This structure is in charge of managing intervals and costs.
-// It caches the different CostCacheInterval, caches the different
-// GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose
-// count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX).
-#define COST_MANAGER_MAX_FREE_LIST 10
-typedef struct {
- CostInterval* head_;
- int count_; // The number of stored intervals.
- CostCacheInterval* cache_intervals_;
- size_t cache_intervals_size_;
- double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k).
- double min_cost_cache_; // The minimum value in cost_cache_[1:].
- double max_cost_cache_; // The maximum value in cost_cache_[1:].
- float* costs_;
- uint16_t* dist_array_;
- // Most of the time, we only need few intervals -> use a free-list, to avoid
- // fragmentation with small allocs in most common cases.
- CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST];
- CostInterval* free_intervals_;
- // These are regularly malloc'd remains. This list can't grow larger than than
- // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note.
- CostInterval* recycled_intervals_;
- // Buffer used in BackwardReferencesHashChainDistanceOnly to store the ends
- // of the intervals that can have impacted the cost at a pixel.
- int* interval_ends_;
- int interval_ends_size_;
-} CostManager;
-
-static int IsCostCacheIntervalWritable(int start, int end) {
- // 100 is the length for which we consider an interval for comparison, and not
- // for writing.
- // The first intervals are very small and go in increasing size. This constant
- // helps merging them into one big interval (up to index 150/200 usually from
- // which intervals start getting much bigger).
- // This value is empirical.
- return (end - start + 1 < 100);
-}
-
-static void CostIntervalAddToFreeList(CostManager* const manager,
- CostInterval* const interval) {
- interval->next_ = manager->free_intervals_;
- manager->free_intervals_ = interval;
-}
-
-static int CostIntervalIsInFreeList(const CostManager* const manager,
- const CostInterval* const interval) {
- return (interval >= &manager->intervals_[0] &&
- interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]);
-}
-
-static void CostManagerInitFreeList(CostManager* const manager) {
- int i;
- manager->free_intervals_ = NULL;
- for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) {
- CostIntervalAddToFreeList(manager, &manager->intervals_[i]);
- }
-}
-
-static void DeleteIntervalList(CostManager* const manager,
- const CostInterval* interval) {
- while (interval != NULL) {
- const CostInterval* const next = interval->next_;
- if (!CostIntervalIsInFreeList(manager, interval)) {
- WebPSafeFree((void*)interval);
- } // else: do nothing
- interval = next;
- }
-}
-
-static void CostManagerClear(CostManager* const manager) {
- if (manager == NULL) return;
-
- WebPSafeFree(manager->costs_);
- WebPSafeFree(manager->cache_intervals_);
- WebPSafeFree(manager->interval_ends_);
-
- // Clear the interval lists.
- DeleteIntervalList(manager, manager->head_);
- manager->head_ = NULL;
- DeleteIntervalList(manager, manager->recycled_intervals_);
- manager->recycled_intervals_ = NULL;
-
- // Reset pointers, count_ and cache_intervals_size_.
- memset(manager, 0, sizeof(*manager));
- CostManagerInitFreeList(manager);
-}
-
-static int CostManagerInit(CostManager* const manager,
- uint16_t* const dist_array, int pix_count,
- const CostModel* const cost_model) {
- int i;
- const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count;
- // This constant is tied to the cost_model we use.
- // Empirically, differences between intervals is usually of more than 1.
- const double min_cost_diff = 0.1;
-
- manager->costs_ = NULL;
- manager->cache_intervals_ = NULL;
- manager->interval_ends_ = NULL;
- manager->head_ = NULL;
- manager->recycled_intervals_ = NULL;
- manager->count_ = 0;
- manager->dist_array_ = dist_array;
- CostManagerInitFreeList(manager);
-
- // Fill in the cost_cache_.
- manager->cache_intervals_size_ = 1;
- manager->cost_cache_[0] = 0;
- for (i = 1; i < cost_cache_size; ++i) {
- manager->cost_cache_[i] = GetLengthCost(cost_model, i);
- // Get an approximation of the number of bound intervals.
- if (fabs(manager->cost_cache_[i] - manager->cost_cache_[i - 1]) >
- min_cost_diff) {
- ++manager->cache_intervals_size_;
- }
- // Compute the minimum of cost_cache_.
- if (i == 1) {
- manager->min_cost_cache_ = manager->cost_cache_[1];
- manager->max_cost_cache_ = manager->cost_cache_[1];
- } else if (manager->cost_cache_[i] < manager->min_cost_cache_) {
- manager->min_cost_cache_ = manager->cost_cache_[i];
- } else if (manager->cost_cache_[i] > manager->max_cost_cache_) {
- manager->max_cost_cache_ = manager->cost_cache_[i];
- }
- }
-
- // With the current cost models, we have 15 intervals, so we are safe by
- // setting a maximum of COST_CACHE_INTERVAL_SIZE_MAX.
- if (manager->cache_intervals_size_ > COST_CACHE_INTERVAL_SIZE_MAX) {
- manager->cache_intervals_size_ = COST_CACHE_INTERVAL_SIZE_MAX;
- }
- manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc(
- manager->cache_intervals_size_, sizeof(*manager->cache_intervals_));
- if (manager->cache_intervals_ == NULL) {
- CostManagerClear(manager);
- return 0;
- }
-
- // Fill in the cache_intervals_.
- {
- double cost_prev = -1e38f; // unprobably low initial value
- CostCacheInterval* prev = NULL;
- CostCacheInterval* cur = manager->cache_intervals_;
- const CostCacheInterval* const end =
- manager->cache_intervals_ + manager->cache_intervals_size_;
-
- // Consecutive values in cost_cache_ are compared and if a big enough
- // difference is found, a new interval is created and bounded.
- for (i = 0; i < cost_cache_size; ++i) {
- const double cost_val = manager->cost_cache_[i];
- if (i == 0 ||
- (fabs(cost_val - cost_prev) > min_cost_diff && cur + 1 < end)) {
- if (i > 1) {
- const int is_writable =
- IsCostCacheIntervalWritable(cur->start_, cur->end_);
- // Merge with the previous interval if both are writable.
- if (is_writable && cur != manager->cache_intervals_ &&
- prev->do_write_) {
- // Update the previous interval.
- prev->end_ = cur->end_;
- if (cur->lower_ < prev->lower_) {
- prev->lower_ = cur->lower_;
- } else if (cur->upper_ > prev->upper_) {
- prev->upper_ = cur->upper_;
- }
- } else {
- cur->do_write_ = is_writable;
- prev = cur;
- ++cur;
- }
- }
- // Initialize an interval.
- cur->start_ = i;
- cur->do_write_ = 0;
- cur->lower_ = cost_val;
- cur->upper_ = cost_val;
- } else {
- // Update the current interval bounds.
- if (cost_val < cur->lower_) {
- cur->lower_ = cost_val;
- } else if (cost_val > cur->upper_) {
- cur->upper_ = cost_val;
- }
- }
- cur->end_ = i + 1;
- cost_prev = cost_val;
- }
- manager->cache_intervals_size_ = cur + 1 - manager->cache_intervals_;
- }
-
- manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_));
- if (manager->costs_ == NULL) {
- CostManagerClear(manager);
- return 0;
- }
- // Set the initial costs_ high for every pixel as we will keep the minimum.
- for (i = 0; i < pix_count; ++i) manager->costs_[i] = 1e38f;
-
- // The cost at pixel is influenced by the cost intervals from previous pixels.
- // Let us take the specific case where the offset is the same (which actually
- // happens a lot in case of uniform regions).
- // pixel i contributes to j>i a cost of: offset cost + cost_cache_[j-i]
- // pixel i+1 contributes to j>i a cost of: 2*offset cost + cost_cache_[j-i-1]
- // pixel i+2 contributes to j>i a cost of: 3*offset cost + cost_cache_[j-i-2]
- // and so on.
- // A pixel i influences the following length(j) < MAX_LENGTH pixels. What is
- // the value of j such that pixel i + j cannot influence any of those pixels?
- // This value is such that:
- // max of cost_cache_ < j*offset cost + min of cost_cache_
- // (pixel i + j 's cost cannot beat the worst cost given by pixel i).
- // This value will be used to optimize the cost computation in
- // BackwardReferencesHashChainDistanceOnly.
- {
- // The offset cost is computed in GetDistanceCost and has a minimum value of
- // the minimum in cost_model->distance_. The case where the offset cost is 0
- // will be dealt with differently later so we are only interested in the
- // minimum non-zero offset cost.
- double offset_cost_min = 0.;
- int size;
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- if (cost_model->distance_[i] != 0) {
- if (offset_cost_min == 0.) {
- offset_cost_min = cost_model->distance_[i];
- } else if (cost_model->distance_[i] < offset_cost_min) {
- offset_cost_min = cost_model->distance_[i];
- }
- }
- }
- // In case all the cost_model->distance_ is 0, the next non-zero cost we
- // can have is from the extra bit in GetDistanceCost, hence 1.
- if (offset_cost_min < 1.) offset_cost_min = 1.;
-
- size = 1 + (int)ceil((manager->max_cost_cache_ - manager->min_cost_cache_) /
- offset_cost_min);
- // Empirically, we usually end up with a value below 100.
- if (size > MAX_LENGTH) size = MAX_LENGTH;
-
- manager->interval_ends_ =
- (int*)WebPSafeMalloc(size, sizeof(*manager->interval_ends_));
- if (manager->interval_ends_ == NULL) {
- CostManagerClear(manager);
- return 0;
- }
- manager->interval_ends_size_ = size;
- }
-
- return 1;
-}
-
-// Given the distance_cost for pixel 'index', update the cost at pixel 'i' if it
-// is smaller than the previously computed value.
-static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, int index,
- double distance_cost) {
- int k = i - index;
- double cost_tmp;
- assert(k >= 0 && k < MAX_LENGTH);
- cost_tmp = distance_cost + manager->cost_cache_[k];
-
- if (manager->costs_[i] > cost_tmp) {
- manager->costs_[i] = (float)cost_tmp;
- manager->dist_array_[i] = k + 1;
- }
-}
-
-// Given the distance_cost for pixel 'index', update the cost for all the pixels
-// between 'start' and 'end' excluded.
-static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager,
- int start, int end, int index,
- double distance_cost) {
- int i;
- for (i = start; i < end; ++i) UpdateCost(manager, i, index, distance_cost);
-}
-
-// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'.
-static WEBP_INLINE void ConnectIntervals(CostManager* const manager,
- CostInterval* const prev,
- CostInterval* const next) {
- if (prev != NULL) {
- prev->next_ = next;
- } else {
- manager->head_ = next;
- }
-
- if (next != NULL) next->previous_ = prev;
-}
-
-// Pop an interval in the manager.
-static WEBP_INLINE void PopInterval(CostManager* const manager,
- CostInterval* const interval) {
- CostInterval* const next = interval->next_;
-
- if (interval == NULL) return;
-
- ConnectIntervals(manager, interval->previous_, next);
- if (CostIntervalIsInFreeList(manager, interval)) {
- CostIntervalAddToFreeList(manager, interval);
- } else { // recycle regularly malloc'd intervals too
- interval->next_ = manager->recycled_intervals_;
- manager->recycled_intervals_ = interval;
- }
- --manager->count_;
- assert(manager->count_ >= 0);
-}
-
-// Update the cost at index i by going over all the stored intervals that
-// overlap with i.
-static WEBP_INLINE void UpdateCostPerIndex(CostManager* const manager, int i) {
- CostInterval* current = manager->head_;
-
- while (current != NULL && current->start_ <= i) {
- if (current->end_ <= i) {
- // We have an outdated interval, remove it.
- CostInterval* next = current->next_;
- PopInterval(manager, current);
- current = next;
- } else {
- UpdateCost(manager, i, current->index_, current->distance_cost_);
- current = current->next_;
- }
- }
-}
-
-// Given a current orphan interval and its previous interval, before
-// it was orphaned (which can be NULL), set it at the right place in the list
-// of intervals using the start_ ordering and the previous interval as a hint.
-static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager,
- CostInterval* const current,
- CostInterval* previous) {
- assert(current != NULL);
-
- if (previous == NULL) previous = manager->head_;
- while (previous != NULL && current->start_ < previous->start_) {
- previous = previous->previous_;
- }
- while (previous != NULL && previous->next_ != NULL &&
- previous->next_->start_ < current->start_) {
- previous = previous->next_;
- }
-
- if (previous != NULL) {
- ConnectIntervals(manager, current, previous->next_);
- } else {
- ConnectIntervals(manager, current, manager->head_);
- }
- ConnectIntervals(manager, previous, current);
-}
-
-// Insert an interval in the list contained in the manager by starting at
-// interval_in as a hint. The intervals are sorted by start_ value.
-static WEBP_INLINE void InsertInterval(CostManager* const manager,
- CostInterval* const interval_in,
- double distance_cost, double lower,
- double upper, int index, int start,
- int end) {
- CostInterval* interval_new;
-
- if (IsCostCacheIntervalWritable(start, end) ||
- manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) {
- // Write down the interval if it is too small.
- UpdateCostPerInterval(manager, start, end, index, distance_cost);
- return;
- }
- if (manager->free_intervals_ != NULL) {
- interval_new = manager->free_intervals_;
- manager->free_intervals_ = interval_new->next_;
- } else if (manager->recycled_intervals_ != NULL) {
- interval_new = manager->recycled_intervals_;
- manager->recycled_intervals_ = interval_new->next_;
- } else { // malloc for good
- interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new));
- if (interval_new == NULL) {
- // Write down the interval if we cannot create it.
- UpdateCostPerInterval(manager, start, end, index, distance_cost);
- return;
- }
- }
-
- interval_new->distance_cost_ = distance_cost;
- interval_new->lower_ = lower;
- interval_new->upper_ = upper;
- interval_new->index_ = index;
- interval_new->start_ = start;
- interval_new->end_ = end;
- PositionOrphanInterval(manager, interval_new, interval_in);
-
- ++manager->count_;
-}
-
-// When an interval has its start_ or end_ modified, it needs to be
-// repositioned in the linked list.
-static WEBP_INLINE void RepositionInterval(CostManager* const manager,
- CostInterval* const interval) {
- if (IsCostCacheIntervalWritable(interval->start_, interval->end_)) {
- // Maybe interval has been resized and is small enough to be removed.
- UpdateCostPerInterval(manager, interval->start_, interval->end_,
- interval->index_, interval->distance_cost_);
- PopInterval(manager, interval);
- return;
- }
-
- // Early exit if interval is at the right spot.
- if ((interval->previous_ == NULL ||
- interval->previous_->start_ <= interval->start_) &&
- (interval->next_ == NULL ||
- interval->start_ <= interval->next_->start_)) {
- return;
- }
-
- ConnectIntervals(manager, interval->previous_, interval->next_);
- PositionOrphanInterval(manager, interval, interval->previous_);
-}
-
-// Given a new cost interval defined by its start at index, its last value and
-// distance_cost, add its contributions to the previous intervals and costs.
-// If handling the interval or one of its subintervals becomes to heavy, its
-// contribution is added to the costs right away.
-static WEBP_INLINE void PushInterval(CostManager* const manager,
- double distance_cost, int index,
- int last) {
- size_t i;
- CostInterval* interval = manager->head_;
- CostInterval* interval_next;
- const CostCacheInterval* const cost_cache_intervals =
- manager->cache_intervals_;
-
- for (i = 0; i < manager->cache_intervals_size_ &&
- cost_cache_intervals[i].start_ < last;
- ++i) {
- // Define the intersection of the ith interval with the new one.
- int start = index + cost_cache_intervals[i].start_;
- const int end = index + (cost_cache_intervals[i].end_ > last
- ? last
- : cost_cache_intervals[i].end_);
- const double lower_in = cost_cache_intervals[i].lower_;
- const double upper_in = cost_cache_intervals[i].upper_;
- const double lower_full_in = distance_cost + lower_in;
- const double upper_full_in = distance_cost + upper_in;
-
- if (cost_cache_intervals[i].do_write_) {
- UpdateCostPerInterval(manager, start, end, index, distance_cost);
- continue;
- }
-
- for (; interval != NULL && interval->start_ < end && start < end;
- interval = interval_next) {
- const double lower_full_interval =
- interval->distance_cost_ + interval->lower_;
- const double upper_full_interval =
- interval->distance_cost_ + interval->upper_;
-
- interval_next = interval->next_;
-
- // Make sure we have some overlap
- if (start >= interval->end_) continue;
-
- if (lower_full_in >= upper_full_interval) {
- // When intervals are represented, the lower, the better.
- // [**********************************************************]
- // start end
- // [----------------------------------]
- // interval->start_ interval->end_
- // If we are worse than what we already have, add whatever we have so
- // far up to interval.
- const int start_new = interval->end_;
- InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
- index, start, interval->start_);
- start = start_new;
- continue;
- }
-
- // We know the two intervals intersect.
- if (upper_full_in >= lower_full_interval) {
- // There is no clear cut on which is best, so let's keep both.
- // [*********[*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*]***********]
- // start interval->start_ interval->end_ end
- // OR
- // [*********[*-*-*-*-*-*-*-*-*-*-*-]----------------------]
- // start interval->start_ end interval->end_
- const int end_new = (interval->end_ <= end) ? interval->end_ : end;
- InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
- index, start, end_new);
- start = end_new;
- } else if (start <= interval->start_ && interval->end_ <= end) {
- // [----------------------------------]
- // interval->start_ interval->end_
- // [**************************************************************]
- // start end
- // We can safely remove the old interval as it is fully included.
- PopInterval(manager, interval);
- } else {
- if (interval->start_ <= start && end <= interval->end_) {
- // [--------------------------------------------------------------]
- // interval->start_ interval->end_
- // [*****************************]
- // start end
- // We have to split the old interval as it fully contains the new one.
- const int end_original = interval->end_;
- interval->end_ = start;
- InsertInterval(manager, interval, interval->distance_cost_,
- interval->lower_, interval->upper_, interval->index_,
- end, end_original);
- } else if (interval->start_ < start) {
- // [------------------------------------]
- // interval->start_ interval->end_
- // [*****************************]
- // start end
- interval->end_ = start;
- } else {
- // [------------------------------------]
- // interval->start_ interval->end_
- // [*****************************]
- // start end
- interval->start_ = end;
- }
-
- // The interval has been modified, we need to reposition it or write it.
- RepositionInterval(manager, interval);
- }
- }
- // Insert the remaining interval from start to end.
- InsertInterval(manager, interval, distance_cost, lower_in, upper_in, index,
- start, end);
- }
-}
-
-static int BackwardReferencesHashChainDistanceOnly(
- int xsize, int ysize, const uint32_t* const argb, int quality,
- int cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs, uint16_t* const dist_array) {
- int i;
- int ok = 0;
- int cc_init = 0;
- const int pix_count = xsize * ysize;
- const int use_color_cache = (cache_bits > 0);
- const size_t literal_array_size = sizeof(double) *
- (NUM_LITERAL_CODES + NUM_LENGTH_CODES +
- ((cache_bits > 0) ? (1 << cache_bits) : 0));
- const size_t cost_model_size = sizeof(CostModel) + literal_array_size;
- CostModel* const cost_model =
- (CostModel*)WebPSafeCalloc(1ULL, cost_model_size);
- VP8LColorCache hashers;
- const int skip_length = 32 + quality;
- const int skip_min_distance_code = 2;
- CostManager* cost_manager =
- (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager));
-
- if (cost_model == NULL || cost_manager == NULL) goto Error;
-
- cost_model->literal_ = (double*)(cost_model + 1);
- if (use_color_cache) {
- cc_init = VP8LColorCacheInit(&hashers, cache_bits);
- if (!cc_init) goto Error;
- }
-
- if (!CostModelBuild(cost_model, cache_bits, refs)) {
- goto Error;
- }
-
- if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) {
- goto Error;
- }
-
- // We loop one pixel at a time, but store all currently best points to
- // non-processed locations from this point.
- dist_array[0] = 0;
- // Add first pixel as literal.
- AddSingleLiteralWithCostModel(argb + 0, &hashers, cost_model, 0,
- use_color_cache, 0.0, cost_manager->costs_,
- dist_array);
-
- for (i = 1; i < pix_count - 1; ++i) {
- int offset = 0, len = 0;
- double prev_cost = cost_manager->costs_[i - 1];
- HashChainFindCopy(hash_chain, i, &offset, &len);
- if (len >= MIN_LENGTH) {
- const int code = DistanceToPlaneCode(xsize, offset);
- const double offset_cost = GetDistanceCost(cost_model, code);
- const int first_i = i;
- int j_max = 0, interval_ends_index = 0;
- const int is_offset_zero = (offset_cost == 0.);
-
- if (!is_offset_zero) {
- j_max = (int)ceil(
- (cost_manager->max_cost_cache_ - cost_manager->min_cost_cache_) /
- offset_cost);
- if (j_max < 1) {
- j_max = 1;
- } else if (j_max > cost_manager->interval_ends_size_ - 1) {
- // This could only happen in the case of MAX_LENGTH.
- j_max = cost_manager->interval_ends_size_ - 1;
- }
- } // else j_max is unused anyway.
-
- // Instead of considering all contributions from a pixel i by calling:
- // PushInterval(cost_manager, prev_cost + offset_cost, i, len);
- // we optimize these contributions in case offset_cost stays the same for
- // consecutive pixels. This describes a set of pixels similar to a
- // previous set (e.g. constant color regions).
- for (; i < pix_count - 1; ++i) {
- int offset_next, len_next;
- prev_cost = cost_manager->costs_[i - 1];
-
- if (is_offset_zero) {
- // No optimization can be made so we just push all of the
- // contributions from i.
- PushInterval(cost_manager, prev_cost, i, len);
- } else {
- // j_max is chosen as the smallest j such that:
- // max of cost_cache_ < j*offset cost + min of cost_cache_
- // Therefore, the pixel influenced by i-j_max, cannot be influenced
- // by i. Only the costs after the end of what i contributed need to be
- // updated. cost_manager->interval_ends_ is a circular buffer that
- // stores those ends.
- const double distance_cost = prev_cost + offset_cost;
- int j = cost_manager->interval_ends_[interval_ends_index];
- if (i - first_i <= j_max ||
- !IsCostCacheIntervalWritable(j, i + len)) {
- PushInterval(cost_manager, distance_cost, i, len);
- } else {
- for (; j < i + len; ++j) {
- UpdateCost(cost_manager, j, i, distance_cost);
- }
- }
- // Store the new end in the circular buffer.
- assert(interval_ends_index < cost_manager->interval_ends_size_);
- cost_manager->interval_ends_[interval_ends_index] = i + len;
- if (++interval_ends_index > j_max) interval_ends_index = 0;
- }
-
- // Check whether i is the last pixel to consider, as it is handled
- // differently.
- if (i + 1 >= pix_count - 1) break;
- HashChainFindCopy(hash_chain, i + 1, &offset_next, &len_next);
- if (offset_next != offset) break;
- len = len_next;
- UpdateCostPerIndex(cost_manager, i);
- AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
- use_color_cache, prev_cost,
- cost_manager->costs_, dist_array);
- }
- // Submit the last pixel.
- UpdateCostPerIndex(cost_manager, i + 1);
-
- // This if is for speedup only. It roughly doubles the speed, and
- // makes compression worse by .1 %.
- if (len >= skip_length && code <= skip_min_distance_code) {
- // Long copy for short distances, let's skip the middle
- // lookups for better copies.
- // 1) insert the hashes.
- if (use_color_cache) {
- int k;
- for (k = 0; k < len; ++k) {
- VP8LColorCacheInsert(&hashers, argb[i + k]);
- }
- }
- // 2) jump.
- {
- const int i_next = i + len - 1; // for loop does ++i, thus -1 here.
- for (; i <= i_next; ++i) UpdateCostPerIndex(cost_manager, i + 1);
- i = i_next;
- }
- goto next_symbol;
- }
- if (len > MIN_LENGTH) {
- int code_min_length;
- double cost_total;
- offset = HashChainFindOffset(hash_chain, i);
- code_min_length = DistanceToPlaneCode(xsize, offset);
- cost_total = prev_cost +
- GetDistanceCost(cost_model, code_min_length) +
- GetLengthCost(cost_model, 1);
- if (cost_manager->costs_[i + 1] > cost_total) {
- cost_manager->costs_[i + 1] = (float)cost_total;
- dist_array[i + 1] = 2;
- }
- }
- } else { // len < MIN_LENGTH
- UpdateCostPerIndex(cost_manager, i + 1);
- }
-
- AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
- use_color_cache, prev_cost,
- cost_manager->costs_, dist_array);
-
- next_symbol: ;
- }
- // Handle the last pixel.
- if (i == (pix_count - 1)) {
- AddSingleLiteralWithCostModel(
- argb + i, &hashers, cost_model, i, use_color_cache,
- cost_manager->costs_[pix_count - 2], cost_manager->costs_, dist_array);
- }
-
- ok = !refs->error_;
- Error:
- if (cc_init) VP8LColorCacheClear(&hashers);
- CostManagerClear(cost_manager);
- WebPSafeFree(cost_model);
- WebPSafeFree(cost_manager);
- return ok;
-}
-
-// We pack the path at the end of *dist_array and return
-// a pointer to this part of the array. Example:
-// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232]
-static void TraceBackwards(uint16_t* const dist_array,
- int dist_array_size,
- uint16_t** const chosen_path,
- int* const chosen_path_size) {
- uint16_t* path = dist_array + dist_array_size;
- uint16_t* cur = dist_array + dist_array_size - 1;
- while (cur >= dist_array) {
- const int k = *cur;
- --path;
- *path = k;
- cur -= k;
- }
- *chosen_path = path;
- *chosen_path_size = (int)(dist_array + dist_array_size - path);
-}
-
-static int BackwardReferencesHashChainFollowChosenPath(
- const uint32_t* const argb, int cache_bits,
- const uint16_t* const chosen_path, int chosen_path_size,
- const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) {
- const int use_color_cache = (cache_bits > 0);
- int ix;
- int i = 0;
- int ok = 0;
- int cc_init = 0;
- VP8LColorCache hashers;
-
- if (use_color_cache) {
- cc_init = VP8LColorCacheInit(&hashers, cache_bits);
- if (!cc_init) goto Error;
- }
-
- ClearBackwardRefs(refs);
- for (ix = 0; ix < chosen_path_size; ++ix) {
- const int len = chosen_path[ix];
- if (len != 1) {
- int k;
- const int offset = HashChainFindOffset(hash_chain, i);
- BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
- if (use_color_cache) {
- for (k = 0; k < len; ++k) {
- VP8LColorCacheInsert(&hashers, argb[i + k]);
- }
- }
- i += len;
- } else {
- PixOrCopy v;
- if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) {
- // push pixel as a color cache index
- const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]);
- v = PixOrCopyCreateCacheIdx(idx);
- } else {
- if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
- v = PixOrCopyCreateLiteral(argb[i]);
- }
- BackwardRefsCursorAdd(refs, v);
- ++i;
- }
- }
- ok = !refs->error_;
- Error:
- if (cc_init) VP8LColorCacheClear(&hashers);
- return ok;
-}
-
-// Returns 1 on success.
-static int BackwardReferencesTraceBackwards(
- int xsize, int ysize, const uint32_t* const argb, int quality,
- int cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs) {
- int ok = 0;
- const int dist_array_size = xsize * ysize;
- uint16_t* chosen_path = NULL;
- int chosen_path_size = 0;
- uint16_t* dist_array =
- (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array));
-
- if (dist_array == NULL) goto Error;
-
- if (!BackwardReferencesHashChainDistanceOnly(
- xsize, ysize, argb, quality, cache_bits, hash_chain,
- refs, dist_array)) {
- goto Error;
- }
- TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size);
- if (!BackwardReferencesHashChainFollowChosenPath(
- argb, cache_bits, chosen_path, chosen_path_size, hash_chain, refs)) {
- goto Error;
- }
- ok = 1;
- Error:
- WebPSafeFree(dist_array);
- return ok;
-}
-
-static void BackwardReferences2DLocality(int xsize,
- const VP8LBackwardRefs* const refs) {
- VP8LRefsCursor c = VP8LRefsCursorInit(refs);
- while (VP8LRefsCursorOk(&c)) {
- if (PixOrCopyIsCopy(c.cur_pos)) {
- const int dist = c.cur_pos->argb_or_distance;
- const int transformed_dist = DistanceToPlaneCode(xsize, dist);
- c.cur_pos->argb_or_distance = transformed_dist;
- }
- VP8LRefsCursorNext(&c);
- }
-}
-
-// Returns entropy for the given cache bits.
-static double ComputeCacheEntropy(const uint32_t* argb,
- const VP8LBackwardRefs* const refs,
- int cache_bits) {
- const int use_color_cache = (cache_bits > 0);
- int cc_init = 0;
- double entropy = MAX_ENTROPY;
- const double kSmallPenaltyForLargeCache = 4.0;
- VP8LColorCache hashers;
- VP8LRefsCursor c = VP8LRefsCursorInit(refs);
- VP8LHistogram* histo = VP8LAllocateHistogram(cache_bits);
- if (histo == NULL) goto Error;
-
- if (use_color_cache) {
- cc_init = VP8LColorCacheInit(&hashers, cache_bits);
- if (!cc_init) goto Error;
- }
- if (!use_color_cache) {
- while (VP8LRefsCursorOk(&c)) {
- VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos);
- VP8LRefsCursorNext(&c);
- }
- } else {
- while (VP8LRefsCursorOk(&c)) {
- const PixOrCopy* const v = c.cur_pos;
- if (PixOrCopyIsLiteral(v)) {
- const uint32_t pix = *argb++;
- const uint32_t key = VP8LColorCacheGetIndex(&hashers, pix);
- if (VP8LColorCacheLookup(&hashers, key) == pix) {
- ++histo->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key];
- } else {
- VP8LColorCacheSet(&hashers, key, pix);
- ++histo->blue_[pix & 0xff];
- ++histo->literal_[(pix >> 8) & 0xff];
- ++histo->red_[(pix >> 16) & 0xff];
- ++histo->alpha_[pix >> 24];
- }
- } else {
- int len = PixOrCopyLength(v);
- int code, extra_bits;
- VP8LPrefixEncodeBits(len, &code, &extra_bits);
- ++histo->literal_[NUM_LITERAL_CODES + code];
- VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits);
- ++histo->distance_[code];
- do {
- VP8LColorCacheInsert(&hashers, *argb++);
- } while(--len != 0);
- }
- VP8LRefsCursorNext(&c);
- }
- }
- entropy = VP8LHistogramEstimateBits(histo) +
- kSmallPenaltyForLargeCache * cache_bits;
- Error:
- if (cc_init) VP8LColorCacheClear(&hashers);
- VP8LFreeHistogram(histo);
- return entropy;
-}
-
-// Evaluate optimal cache bits for the local color cache.
-// The input *best_cache_bits sets the maximum cache bits to use (passing 0
-// implies disabling the local color cache). The local color cache is also
-// disabled for the lower (<= 25) quality.
-// Returns 0 in case of memory error.
-static int CalculateBestCacheSize(const uint32_t* const argb,
- int xsize, int ysize, int quality,
- const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs,
- int* const lz77_computed,
- int* const best_cache_bits) {
- int eval_low = 1;
- int eval_high = 1;
- double entropy_low = MAX_ENTROPY;
- double entropy_high = MAX_ENTROPY;
- const double cost_mul = 5e-4;
- int cache_bits_low = 0;
- int cache_bits_high = (quality <= 25) ? 0 : *best_cache_bits;
-
- assert(cache_bits_high <= MAX_COLOR_CACHE_BITS);
-
- *lz77_computed = 0;
- if (cache_bits_high == 0) {
- *best_cache_bits = 0;
- // Local color cache is disabled.
- return 1;
- }
- if (!BackwardReferencesLz77(xsize, ysize, argb, cache_bits_low, hash_chain,
- refs)) {
- return 0;
- }
- // Do a binary search to find the optimal entropy for cache_bits.
- while (eval_low || eval_high) {
- if (eval_low) {
- entropy_low = ComputeCacheEntropy(argb, refs, cache_bits_low);
- entropy_low += entropy_low * cache_bits_low * cost_mul;
- eval_low = 0;
- }
- if (eval_high) {
- entropy_high = ComputeCacheEntropy(argb, refs, cache_bits_high);
- entropy_high += entropy_high * cache_bits_high * cost_mul;
- eval_high = 0;
- }
- if (entropy_high < entropy_low) {
- const int prev_cache_bits_low = cache_bits_low;
- *best_cache_bits = cache_bits_high;
- cache_bits_low = (cache_bits_low + cache_bits_high) / 2;
- if (cache_bits_low != prev_cache_bits_low) eval_low = 1;
- } else {
- *best_cache_bits = cache_bits_low;
- cache_bits_high = (cache_bits_low + cache_bits_high) / 2;
- if (cache_bits_high != cache_bits_low) eval_high = 1;
- }
- }
- *lz77_computed = 1;
- return 1;
-}
-
-// Update (in-place) backward references for specified cache_bits.
-static int BackwardRefsWithLocalCache(const uint32_t* const argb,
- int cache_bits,
- VP8LBackwardRefs* const refs) {
- int pixel_index = 0;
- VP8LColorCache hashers;
- VP8LRefsCursor c = VP8LRefsCursorInit(refs);
- if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0;
-
- while (VP8LRefsCursorOk(&c)) {
- PixOrCopy* const v = c.cur_pos;
- if (PixOrCopyIsLiteral(v)) {
- const uint32_t argb_literal = v->argb_or_distance;
- if (VP8LColorCacheContains(&hashers, argb_literal)) {
- const int ix = VP8LColorCacheGetIndex(&hashers, argb_literal);
- *v = PixOrCopyCreateCacheIdx(ix);
- } else {
- VP8LColorCacheInsert(&hashers, argb_literal);
- }
- ++pixel_index;
- } else {
- // refs was created without local cache, so it can not have cache indexes.
- int k;
- assert(PixOrCopyIsCopy(v));
- for (k = 0; k < v->len; ++k) {
- VP8LColorCacheInsert(&hashers, argb[pixel_index++]);
- }
- }
- VP8LRefsCursorNext(&c);
- }
- VP8LColorCacheClear(&hashers);
- return 1;
-}
-
-static VP8LBackwardRefs* GetBackwardReferencesLowEffort(
- int width, int height, const uint32_t* const argb,
- int* const cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs refs_array[2]) {
- VP8LBackwardRefs* refs_lz77 = &refs_array[0];
- *cache_bits = 0;
- if (!BackwardReferencesLz77(width, height, argb, 0, hash_chain, refs_lz77)) {
- return NULL;
- }
- BackwardReferences2DLocality(width, refs_lz77);
- return refs_lz77;
-}
-
-static VP8LBackwardRefs* GetBackwardReferences(
- int width, int height, const uint32_t* const argb, int quality,
- int* const cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs refs_array[2]) {
- int lz77_is_useful;
- int lz77_computed;
- double bit_cost_lz77, bit_cost_rle;
- VP8LBackwardRefs* best = NULL;
- VP8LBackwardRefs* refs_lz77 = &refs_array[0];
- VP8LBackwardRefs* refs_rle = &refs_array[1];
- VP8LHistogram* histo = NULL;
-
- if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain,
- refs_lz77, &lz77_computed, cache_bits)) {
- goto Error;
- }
-
- if (lz77_computed) {
- // Transform refs_lz77 for the optimized cache_bits.
- if (*cache_bits > 0) {
- if (!BackwardRefsWithLocalCache(argb, *cache_bits, refs_lz77)) {
- goto Error;
- }
- }
- } else {
- if (!BackwardReferencesLz77(width, height, argb, *cache_bits, hash_chain,
- refs_lz77)) {
- goto Error;
- }
- }
-
- if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) {
- goto Error;
- }
-
- histo = VP8LAllocateHistogram(*cache_bits);
- if (histo == NULL) goto Error;
-
- {
- // Evaluate LZ77 coding.
- VP8LHistogramCreate(histo, refs_lz77, *cache_bits);
- bit_cost_lz77 = VP8LHistogramEstimateBits(histo);
- // Evaluate RLE coding.
- VP8LHistogramCreate(histo, refs_rle, *cache_bits);
- bit_cost_rle = VP8LHistogramEstimateBits(histo);
- // Decide if LZ77 is useful.
- lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
- }
-
- // Choose appropriate backward reference.
- if (lz77_is_useful) {
- // TraceBackwards is costly. Don't execute it at lower quality.
- const int try_lz77_trace_backwards = (quality >= 25);
- best = refs_lz77; // default guess: lz77 is better
- if (try_lz77_trace_backwards) {
- VP8LBackwardRefs* const refs_trace = refs_rle;
- if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) {
- best = NULL;
- goto Error;
- }
- if (BackwardReferencesTraceBackwards(width, height, argb, quality,
- *cache_bits, hash_chain,
- refs_trace)) {
- double bit_cost_trace;
- // Evaluate LZ77 coding.
- VP8LHistogramCreate(histo, refs_trace, *cache_bits);
- bit_cost_trace = VP8LHistogramEstimateBits(histo);
- if (bit_cost_trace < bit_cost_lz77) {
- best = refs_trace;
- }
- }
- }
- } else {
- best = refs_rle;
- }
-
- BackwardReferences2DLocality(width, best);
-
- Error:
- VP8LFreeHistogram(histo);
- return best;
-}
-
-VP8LBackwardRefs* VP8LGetBackwardReferences(
- int width, int height, const uint32_t* const argb, int quality,
- int low_effort, int* const cache_bits,
- const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[2]) {
- if (low_effort) {
- return GetBackwardReferencesLowEffort(width, height, argb, cache_bits,
- hash_chain, refs_array);
- } else {
- return GetBackwardReferences(width, height, argb, quality, cache_bits,
- hash_chain, refs_array);
- }
-}
diff --git a/drivers/webp/enc/backward_references.h b/drivers/webp/enc/backward_references.h
deleted file mode 100644
index b72a01fb0e..0000000000
--- a/drivers/webp/enc/backward_references.h
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-//
-
-#ifndef WEBP_ENC_BACKWARD_REFERENCES_H_
-#define WEBP_ENC_BACKWARD_REFERENCES_H_
-
-#include <assert.h>
-#include <stdlib.h>
-#include "webp/types.h"
-#include "webp/format_constants.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// The maximum allowed limit is 11.
-#define MAX_COLOR_CACHE_BITS 10
-
-// -----------------------------------------------------------------------------
-// PixOrCopy
-
-enum Mode {
- kLiteral,
- kCacheIdx,
- kCopy,
- kNone
-};
-
-typedef struct {
- // mode as uint8_t to make the memory layout to be exactly 8 bytes.
- uint8_t mode;
- uint16_t len;
- uint32_t argb_or_distance;
-} PixOrCopy;
-
-static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance,
- uint16_t len) {
- PixOrCopy retval;
- retval.mode = kCopy;
- retval.argb_or_distance = distance;
- retval.len = len;
- return retval;
-}
-
-static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) {
- PixOrCopy retval;
- assert(idx >= 0);
- assert(idx < (1 << MAX_COLOR_CACHE_BITS));
- retval.mode = kCacheIdx;
- retval.argb_or_distance = idx;
- retval.len = 1;
- return retval;
-}
-
-static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) {
- PixOrCopy retval;
- retval.mode = kLiteral;
- retval.argb_or_distance = argb;
- retval.len = 1;
- return retval;
-}
-
-static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) {
- return (p->mode == kLiteral);
-}
-
-static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) {
- return (p->mode == kCacheIdx);
-}
-
-static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) {
- return (p->mode == kCopy);
-}
-
-static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p,
- int component) {
- assert(p->mode == kLiteral);
- return (p->argb_or_distance >> (component * 8)) & 0xff;
-}
-
-static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) {
- return p->len;
-}
-
-static WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) {
- assert(p->mode == kLiteral);
- return p->argb_or_distance;
-}
-
-static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) {
- assert(p->mode == kCacheIdx);
- assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS));
- return p->argb_or_distance;
-}
-
-static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) {
- assert(p->mode == kCopy);
- return p->argb_or_distance;
-}
-
-// -----------------------------------------------------------------------------
-// VP8LHashChain
-
-#define HASH_BITS 18
-#define HASH_SIZE (1 << HASH_BITS)
-
-typedef struct VP8LHashChain VP8LHashChain;
-struct VP8LHashChain {
- // The 20 most significant bits contain the offset at which the best match
- // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain
- // (through WINDOW_SIZE = 1<<20).
- // The lower 12 bits contain the length of the match. The 12 bit limit is
- // defined in MaxFindCopyLength with MAX_LENGTH=4096.
- uint32_t* offset_length_;
- // This is the maximum size of the hash_chain that can be constructed.
- // Typically this is the pixel count (width x height) for a given image.
- int size_;
-};
-
-// Must be called first, to set size.
-int VP8LHashChainInit(VP8LHashChain* const p, int size);
-// Pre-compute the best matches for argb.
-int VP8LHashChainFill(VP8LHashChain* const p, int quality,
- const uint32_t* const argb, int xsize, int ysize);
-void VP8LHashChainClear(VP8LHashChain* const p); // release memory
-
-// -----------------------------------------------------------------------------
-// VP8LBackwardRefs (block-based backward-references storage)
-
-// maximum number of reference blocks the image will be segmented into
-#define MAX_REFS_BLOCK_PER_IMAGE 16
-
-typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration
-typedef struct VP8LBackwardRefs VP8LBackwardRefs;
-
-// Container for blocks chain
-struct VP8LBackwardRefs {
- int block_size_; // common block-size
- int error_; // set to true if some memory error occurred
- PixOrCopyBlock* refs_; // list of currently used blocks
- PixOrCopyBlock** tail_; // for list recycling
- PixOrCopyBlock* free_blocks_; // free-list
- PixOrCopyBlock* last_block_; // used for adding new refs (internal)
-};
-
-// Initialize the object. 'block_size' is the common block size to store
-// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE).
-void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size);
-// Release memory for backward references.
-void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs);
-// Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error.
-int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src,
- VP8LBackwardRefs* const dst);
-
-// Cursor for iterating on references content
-typedef struct {
- // public:
- PixOrCopy* cur_pos; // current position
- // private:
- PixOrCopyBlock* cur_block_; // current block in the refs list
- const PixOrCopy* last_pos_; // sentinel for switching to next block
-} VP8LRefsCursor;
-
-// Returns a cursor positioned at the beginning of the references list.
-VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs);
-// Returns true if cursor is pointing at a valid position.
-static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) {
- return (c->cur_pos != NULL);
-}
-// Move to next block of references. Internal, not to be called directly.
-void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c);
-// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk().
-static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) {
- assert(c != NULL);
- assert(VP8LRefsCursorOk(c));
- if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c);
-}
-
-// -----------------------------------------------------------------------------
-// Main entry points
-
-// Evaluates best possible backward references for specified quality.
-// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache
-// bits to use (passing 0 implies disabling the local color cache).
-// The optimal cache bits is evaluated and set for the *cache_bits parameter.
-// The return value is the pointer to the best of the two backward refs viz,
-// refs[0] or refs[1].
-VP8LBackwardRefs* VP8LGetBackwardReferences(
- int width, int height, const uint32_t* const argb, int quality,
- int low_effort, int* const cache_bits,
- const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs[2]);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // WEBP_ENC_BACKWARD_REFERENCES_H_
diff --git a/drivers/webp/enc/config.c b/drivers/webp/enc/config.c
deleted file mode 100644
index 8fd2276cb5..0000000000
--- a/drivers/webp/enc/config.c
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Coding tools configuration
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "webp/encode.h"
-
-//------------------------------------------------------------------------------
-// WebPConfig
-//------------------------------------------------------------------------------
-
-int WebPConfigInitInternal(WebPConfig* config,
- WebPPreset preset, float quality, int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
- return 0; // caller/system version mismatch!
- }
- if (config == NULL) return 0;
-
- config->quality = quality;
- config->target_size = 0;
- config->target_PSNR = 0.;
- config->method = 4;
- config->sns_strength = 50;
- config->filter_strength = 60; // mid-filtering
- config->filter_sharpness = 0;
- config->filter_type = 1; // default: strong (so U/V is filtered too)
- config->partitions = 0;
- config->segments = 4;
- config->pass = 1;
- config->show_compressed = 0;
- config->preprocessing = 0;
- config->autofilter = 0;
- config->partition_limit = 0;
- config->alpha_compression = 1;
- config->alpha_filtering = 1;
- config->alpha_quality = 100;
- config->lossless = 0;
- config->exact = 0;
- config->image_hint = WEBP_HINT_DEFAULT;
- config->emulate_jpeg_size = 0;
- config->thread_level = 0;
- config->low_memory = 0;
- config->near_lossless = 100;
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- config->delta_palettization = 0;
-#endif // WEBP_EXPERIMENTAL_FEATURES
-
- // TODO(skal): tune.
- switch (preset) {
- case WEBP_PRESET_PICTURE:
- config->sns_strength = 80;
- config->filter_sharpness = 4;
- config->filter_strength = 35;
- config->preprocessing &= ~2; // no dithering
- break;
- case WEBP_PRESET_PHOTO:
- config->sns_strength = 80;
- config->filter_sharpness = 3;
- config->filter_strength = 30;
- config->preprocessing |= 2;
- break;
- case WEBP_PRESET_DRAWING:
- config->sns_strength = 25;
- config->filter_sharpness = 6;
- config->filter_strength = 10;
- break;
- case WEBP_PRESET_ICON:
- config->sns_strength = 0;
- config->filter_strength = 0; // disable filtering to retain sharpness
- config->preprocessing &= ~2; // no dithering
- break;
- case WEBP_PRESET_TEXT:
- config->sns_strength = 0;
- config->filter_strength = 0; // disable filtering to retain sharpness
- config->preprocessing &= ~2; // no dithering
- config->segments = 2;
- break;
- case WEBP_PRESET_DEFAULT:
- default:
- break;
- }
- return WebPValidateConfig(config);
-}
-
-int WebPValidateConfig(const WebPConfig* config) {
- if (config == NULL) return 0;
- if (config->quality < 0 || config->quality > 100)
- return 0;
- if (config->target_size < 0)
- return 0;
- if (config->target_PSNR < 0)
- return 0;
- if (config->method < 0 || config->method > 6)
- return 0;
- if (config->segments < 1 || config->segments > 4)
- return 0;
- if (config->sns_strength < 0 || config->sns_strength > 100)
- return 0;
- if (config->filter_strength < 0 || config->filter_strength > 100)
- return 0;
- if (config->filter_sharpness < 0 || config->filter_sharpness > 7)
- return 0;
- if (config->filter_type < 0 || config->filter_type > 1)
- return 0;
- if (config->autofilter < 0 || config->autofilter > 1)
- return 0;
- if (config->pass < 1 || config->pass > 10)
- return 0;
- if (config->show_compressed < 0 || config->show_compressed > 1)
- return 0;
- if (config->preprocessing < 0 || config->preprocessing > 7)
- return 0;
- if (config->partitions < 0 || config->partitions > 3)
- return 0;
- if (config->partition_limit < 0 || config->partition_limit > 100)
- return 0;
- if (config->alpha_compression < 0)
- return 0;
- if (config->alpha_filtering < 0)
- return 0;
- if (config->alpha_quality < 0 || config->alpha_quality > 100)
- return 0;
- if (config->lossless < 0 || config->lossless > 1)
- return 0;
- if (config->near_lossless < 0 || config->near_lossless > 100)
- return 0;
- if (config->image_hint >= WEBP_HINT_LAST)
- return 0;
- if (config->emulate_jpeg_size < 0 || config->emulate_jpeg_size > 1)
- return 0;
- if (config->thread_level < 0 || config->thread_level > 1)
- return 0;
- if (config->low_memory < 0 || config->low_memory > 1)
- return 0;
- if (config->exact < 0 || config->exact > 1)
- return 0;
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (config->delta_palettization < 0 || config->delta_palettization > 1)
- return 0;
-#endif // WEBP_EXPERIMENTAL_FEATURES
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-#define MAX_LEVEL 9
-
-// Mapping between -z level and -m / -q parameter settings.
-static const struct {
- uint8_t method_;
- uint8_t quality_;
-} kLosslessPresets[MAX_LEVEL + 1] = {
- { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 },
- { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 }
-};
-
-int WebPConfigLosslessPreset(WebPConfig* config, int level) {
- if (config == NULL || level < 0 || level > MAX_LEVEL) return 0;
- config->lossless = 1;
- config->method = kLosslessPresets[level].method_;
- config->quality = kLosslessPresets[level].quality_;
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/cost.c b/drivers/webp/enc/cost.c
deleted file mode 100644
index ae7fe01388..0000000000
--- a/drivers/webp/enc/cost.c
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Cost tables for level and modes
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./cost.h"
-
-//------------------------------------------------------------------------------
-// Level cost tables
-
-// For each given level, the following table gives the pattern of contexts to
-// use for coding it (in [][0]) as well as the bit value to use for each
-// context (in [][1]).
-const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = {
- {0x001, 0x000}, {0x007, 0x001}, {0x00f, 0x005},
- {0x00f, 0x00d}, {0x033, 0x003}, {0x033, 0x003}, {0x033, 0x023},
- {0x033, 0x023}, {0x033, 0x023}, {0x033, 0x023}, {0x0d3, 0x013},
- {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013},
- {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x013}, {0x0d3, 0x093},
- {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093},
- {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093},
- {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093},
- {0x0d3, 0x093}, {0x0d3, 0x093}, {0x0d3, 0x093}, {0x153, 0x053},
- {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
- {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
- {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
- {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
- {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
- {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
- {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053},
- {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x053}, {0x153, 0x153}
-};
-
-static int VariableLevelCost(int level, const uint8_t probas[NUM_PROBAS]) {
- int pattern = VP8LevelCodes[level - 1][0];
- int bits = VP8LevelCodes[level - 1][1];
- int cost = 0;
- int i;
- for (i = 2; pattern; ++i) {
- if (pattern & 1) {
- cost += VP8BitCost(bits & 1, probas[i]);
- }
- bits >>= 1;
- pattern >>= 1;
- }
- return cost;
-}
-
-//------------------------------------------------------------------------------
-// Pre-calc level costs once for all
-
-void VP8CalculateLevelCosts(VP8EncProba* const proba) {
- int ctype, band, ctx;
-
- if (!proba->dirty_) return; // nothing to do.
-
- for (ctype = 0; ctype < NUM_TYPES; ++ctype) {
- int n;
- for (band = 0; band < NUM_BANDS; ++band) {
- for (ctx = 0; ctx < NUM_CTX; ++ctx) {
- const uint8_t* const p = proba->coeffs_[ctype][band][ctx];
- uint16_t* const table = proba->level_cost_[ctype][band][ctx];
- const int cost0 = (ctx > 0) ? VP8BitCost(1, p[0]) : 0;
- const int cost_base = VP8BitCost(1, p[1]) + cost0;
- int v;
- table[0] = VP8BitCost(0, p[1]) + cost0;
- for (v = 1; v <= MAX_VARIABLE_LEVEL; ++v) {
- table[v] = cost_base + VariableLevelCost(v, p);
- }
- // Starting at level 67 and up, the variable part of the cost is
- // actually constant.
- }
- }
- for (n = 0; n < 16; ++n) { // replicate bands. We don't need to sentinel.
- for (ctx = 0; ctx < NUM_CTX; ++ctx) {
- proba->remapped_costs_[ctype][n][ctx] =
- proba->level_cost_[ctype][VP8EncBands[n]][ctx];
- }
- }
- }
- proba->dirty_ = 0;
-}
-
-//------------------------------------------------------------------------------
-// Mode cost tables.
-
-// These are the fixed probabilities (in the coding trees) turned into bit-cost
-// by calling VP8BitCost().
-const uint16_t VP8FixedCostsUV[4] = { 302, 984, 439, 642 };
-// note: these values include the fixed VP8BitCost(1, 145) mode selection cost.
-const uint16_t VP8FixedCostsI16[4] = { 663, 919, 872, 919 };
-const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES] = {
- { { 40, 1151, 1723, 1874, 2103, 2019, 1628, 1777, 2226, 2137 },
- { 192, 469, 1296, 1308, 1849, 1794, 1781, 1703, 1713, 1522 },
- { 142, 910, 762, 1684, 1849, 1576, 1460, 1305, 1801, 1657 },
- { 559, 641, 1370, 421, 1182, 1569, 1612, 1725, 863, 1007 },
- { 299, 1059, 1256, 1108, 636, 1068, 1581, 1883, 869, 1142 },
- { 277, 1111, 707, 1362, 1089, 672, 1603, 1541, 1545, 1291 },
- { 214, 781, 1609, 1303, 1632, 2229, 726, 1560, 1713, 918 },
- { 152, 1037, 1046, 1759, 1983, 2174, 1358, 742, 1740, 1390 },
- { 512, 1046, 1420, 753, 752, 1297, 1486, 1613, 460, 1207 },
- { 424, 827, 1362, 719, 1462, 1202, 1199, 1476, 1199, 538 } },
- { { 240, 402, 1134, 1491, 1659, 1505, 1517, 1555, 1979, 2099 },
- { 467, 242, 960, 1232, 1714, 1620, 1834, 1570, 1676, 1391 },
- { 500, 455, 463, 1507, 1699, 1282, 1564, 982, 2114, 2114 },
- { 672, 643, 1372, 331, 1589, 1667, 1453, 1938, 996, 876 },
- { 458, 783, 1037, 911, 738, 968, 1165, 1518, 859, 1033 },
- { 504, 815, 504, 1139, 1219, 719, 1506, 1085, 1268, 1268 },
- { 333, 630, 1445, 1239, 1883, 3672, 799, 1548, 1865, 598 },
- { 399, 644, 746, 1342, 1856, 1350, 1493, 613, 1855, 1015 },
- { 622, 749, 1205, 608, 1066, 1408, 1290, 1406, 546, 971 },
- { 500, 753, 1041, 668, 1230, 1617, 1297, 1425, 1383, 523 } },
- { { 394, 553, 523, 1502, 1536, 981, 1608, 1142, 1666, 2181 },
- { 655, 430, 375, 1411, 1861, 1220, 1677, 1135, 1978, 1553 },
- { 690, 640, 245, 1954, 2070, 1194, 1528, 982, 1972, 2232 },
- { 559, 834, 741, 867, 1131, 980, 1225, 852, 1092, 784 },
- { 690, 875, 516, 959, 673, 894, 1056, 1190, 1528, 1126 },
- { 740, 951, 384, 1277, 1177, 492, 1579, 1155, 1846, 1513 },
- { 323, 775, 1062, 1776, 3062, 1274, 813, 1188, 1372, 655 },
- { 488, 971, 484, 1767, 1515, 1775, 1115, 503, 1539, 1461 },
- { 740, 1006, 998, 709, 851, 1230, 1337, 788, 741, 721 },
- { 522, 1073, 573, 1045, 1346, 887, 1046, 1146, 1203, 697 } },
- { { 105, 864, 1442, 1009, 1934, 1840, 1519, 1920, 1673, 1579 },
- { 534, 305, 1193, 683, 1388, 2164, 1802, 1894, 1264, 1170 },
- { 305, 518, 877, 1108, 1426, 3215, 1425, 1064, 1320, 1242 },
- { 683, 732, 1927, 257, 1493, 2048, 1858, 1552, 1055, 947 },
- { 394, 814, 1024, 660, 959, 1556, 1282, 1289, 893, 1047 },
- { 528, 615, 996, 940, 1201, 635, 1094, 2515, 803, 1358 },
- { 347, 614, 1609, 1187, 3133, 1345, 1007, 1339, 1017, 667 },
- { 218, 740, 878, 1605, 3650, 3650, 1345, 758, 1357, 1617 },
- { 672, 750, 1541, 558, 1257, 1599, 1870, 2135, 402, 1087 },
- { 592, 684, 1161, 430, 1092, 1497, 1475, 1489, 1095, 822 } },
- { { 228, 1056, 1059, 1368, 752, 982, 1512, 1518, 987, 1782 },
- { 494, 514, 818, 942, 965, 892, 1610, 1356, 1048, 1363 },
- { 512, 648, 591, 1042, 761, 991, 1196, 1454, 1309, 1463 },
- { 683, 749, 1043, 676, 841, 1396, 1133, 1138, 654, 939 },
- { 622, 1101, 1126, 994, 361, 1077, 1203, 1318, 877, 1219 },
- { 631, 1068, 857, 1650, 651, 477, 1650, 1419, 828, 1170 },
- { 555, 727, 1068, 1335, 3127, 1339, 820, 1331, 1077, 429 },
- { 504, 879, 624, 1398, 889, 889, 1392, 808, 891, 1406 },
- { 683, 1602, 1289, 977, 578, 983, 1280, 1708, 406, 1122 },
- { 399, 865, 1433, 1070, 1072, 764, 968, 1477, 1223, 678 } },
- { { 333, 760, 935, 1638, 1010, 529, 1646, 1410, 1472, 2219 },
- { 512, 494, 750, 1160, 1215, 610, 1870, 1868, 1628, 1169 },
- { 572, 646, 492, 1934, 1208, 603, 1580, 1099, 1398, 1995 },
- { 786, 789, 942, 581, 1018, 951, 1599, 1207, 731, 768 },
- { 690, 1015, 672, 1078, 582, 504, 1693, 1438, 1108, 2897 },
- { 768, 1267, 571, 2005, 1243, 244, 2881, 1380, 1786, 1453 },
- { 452, 899, 1293, 903, 1311, 3100, 465, 1311, 1319, 813 },
- { 394, 927, 942, 1103, 1358, 1104, 946, 593, 1363, 1109 },
- { 559, 1005, 1007, 1016, 658, 1173, 1021, 1164, 623, 1028 },
- { 564, 796, 632, 1005, 1014, 863, 2316, 1268, 938, 764 } },
- { { 266, 606, 1098, 1228, 1497, 1243, 948, 1030, 1734, 1461 },
- { 366, 585, 901, 1060, 1407, 1247, 876, 1134, 1620, 1054 },
- { 452, 565, 542, 1729, 1479, 1479, 1016, 886, 2938, 1150 },
- { 555, 1088, 1533, 950, 1354, 895, 834, 1019, 1021, 496 },
- { 704, 815, 1193, 971, 973, 640, 1217, 2214, 832, 578 },
- { 672, 1245, 579, 871, 875, 774, 872, 1273, 1027, 949 },
- { 296, 1134, 2050, 1784, 1636, 3425, 442, 1550, 2076, 722 },
- { 342, 982, 1259, 1846, 1848, 1848, 622, 568, 1847, 1052 },
- { 555, 1064, 1304, 828, 746, 1343, 1075, 1329, 1078, 494 },
- { 288, 1167, 1285, 1174, 1639, 1639, 833, 2254, 1304, 509 } },
- { { 342, 719, 767, 1866, 1757, 1270, 1246, 550, 1746, 2151 },
- { 483, 653, 694, 1509, 1459, 1410, 1218, 507, 1914, 1266 },
- { 488, 757, 447, 2979, 1813, 1268, 1654, 539, 1849, 2109 },
- { 522, 1097, 1085, 851, 1365, 1111, 851, 901, 961, 605 },
- { 709, 716, 841, 728, 736, 945, 941, 862, 2845, 1057 },
- { 512, 1323, 500, 1336, 1083, 681, 1342, 717, 1604, 1350 },
- { 452, 1155, 1372, 1900, 1501, 3290, 311, 944, 1919, 922 },
- { 403, 1520, 977, 2132, 1733, 3522, 1076, 276, 3335, 1547 },
- { 559, 1374, 1101, 615, 673, 2462, 974, 795, 984, 984 },
- { 547, 1122, 1062, 812, 1410, 951, 1140, 622, 1268, 651 } },
- { { 165, 982, 1235, 938, 1334, 1366, 1659, 1578, 964, 1612 },
- { 592, 422, 925, 847, 1139, 1112, 1387, 2036, 861, 1041 },
- { 403, 837, 732, 770, 941, 1658, 1250, 809, 1407, 1407 },
- { 896, 874, 1071, 381, 1568, 1722, 1437, 2192, 480, 1035 },
- { 640, 1098, 1012, 1032, 684, 1382, 1581, 2106, 416, 865 },
- { 559, 1005, 819, 914, 710, 770, 1418, 920, 838, 1435 },
- { 415, 1258, 1245, 870, 1278, 3067, 770, 1021, 1287, 522 },
- { 406, 990, 601, 1009, 1265, 1265, 1267, 759, 1017, 1277 },
- { 968, 1182, 1329, 788, 1032, 1292, 1705, 1714, 203, 1403 },
- { 732, 877, 1279, 471, 901, 1161, 1545, 1294, 755, 755 } },
- { { 111, 931, 1378, 1185, 1933, 1648, 1148, 1714, 1873, 1307 },
- { 406, 414, 1030, 1023, 1910, 1404, 1313, 1647, 1509, 793 },
- { 342, 640, 575, 1088, 1241, 1349, 1161, 1350, 1756, 1502 },
- { 559, 766, 1185, 357, 1682, 1428, 1329, 1897, 1219, 802 },
- { 473, 909, 1164, 771, 719, 2508, 1427, 1432, 722, 782 },
- { 342, 892, 785, 1145, 1150, 794, 1296, 1550, 973, 1057 },
- { 208, 1036, 1326, 1343, 1606, 3395, 815, 1455, 1618, 712 },
- { 228, 928, 890, 1046, 3499, 1711, 994, 829, 1720, 1318 },
- { 768, 724, 1058, 636, 991, 1075, 1319, 1324, 616, 825 },
- { 305, 1167, 1358, 899, 1587, 1587, 987, 1988, 1332, 501 } }
-};
-
-//------------------------------------------------------------------------------
-// helper functions for residuals struct VP8Residual.
-
-void VP8InitResidual(int first, int coeff_type,
- VP8Encoder* const enc, VP8Residual* const res) {
- res->coeff_type = coeff_type;
- res->prob = enc->proba_.coeffs_[coeff_type];
- res->stats = enc->proba_.stats_[coeff_type];
- res->costs = enc->proba_.remapped_costs_[coeff_type];
- res->first = first;
-}
-
-//------------------------------------------------------------------------------
-// Mode costs
-
-int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) {
- const int x = (it->i4_ & 3), y = (it->i4_ >> 2);
- VP8Residual res;
- VP8Encoder* const enc = it->enc_;
- int R = 0;
- int ctx;
-
- VP8InitResidual(0, 3, enc, &res);
- ctx = it->top_nz_[x] + it->left_nz_[y];
- VP8SetResidualCoeffs(levels, &res);
- R += VP8GetResidualCost(ctx, &res);
- return R;
-}
-
-int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) {
- VP8Residual res;
- VP8Encoder* const enc = it->enc_;
- int x, y;
- int R = 0;
-
- VP8IteratorNzToBytes(it); // re-import the non-zero context
-
- // DC
- VP8InitResidual(0, 1, enc, &res);
- VP8SetResidualCoeffs(rd->y_dc_levels, &res);
- R += VP8GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res);
-
- // AC
- VP8InitResidual(1, 0, enc, &res);
- for (y = 0; y < 4; ++y) {
- for (x = 0; x < 4; ++x) {
- const int ctx = it->top_nz_[x] + it->left_nz_[y];
- VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
- R += VP8GetResidualCost(ctx, &res);
- it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0);
- }
- }
- return R;
-}
-
-int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) {
- VP8Residual res;
- VP8Encoder* const enc = it->enc_;
- int ch, x, y;
- int R = 0;
-
- VP8IteratorNzToBytes(it); // re-import the non-zero context
-
- VP8InitResidual(0, 2, enc, &res);
- for (ch = 0; ch <= 2; ch += 2) {
- for (y = 0; y < 2; ++y) {
- for (x = 0; x < 2; ++x) {
- const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
- R += VP8GetResidualCost(ctx, &res);
- it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0);
- }
- }
- }
- return R;
-}
-
-
-//------------------------------------------------------------------------------
-// Recording of token probabilities.
-
-// Record proba context used
-static int Record(int bit, proba_t* const stats) {
- proba_t p = *stats;
- if (p >= 0xffff0000u) { // an overflow is inbound.
- p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2.
- }
- // record bit count (lower 16 bits) and increment total count (upper 16 bits).
- p += 0x00010000u + bit;
- *stats = p;
- return bit;
-}
-
-// We keep the table-free variant around for reference, in case.
-#define USE_LEVEL_CODE_TABLE
-
-// Simulate block coding, but only record statistics.
-// Note: no need to record the fixed probas.
-int VP8RecordCoeffs(int ctx, const VP8Residual* const res) {
- int n = res->first;
- // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1
- proba_t* s = res->stats[n][ctx];
- if (res->last < 0) {
- Record(0, s + 0);
- return 0;
- }
- while (n <= res->last) {
- int v;
- Record(1, s + 0); // order of record doesn't matter
- while ((v = res->coeffs[n++]) == 0) {
- Record(0, s + 1);
- s = res->stats[VP8EncBands[n]][0];
- }
- Record(1, s + 1);
- if (!Record(2u < (unsigned int)(v + 1), s + 2)) { // v = -1 or 1
- s = res->stats[VP8EncBands[n]][1];
- } else {
- v = abs(v);
-#if !defined(USE_LEVEL_CODE_TABLE)
- if (!Record(v > 4, s + 3)) {
- if (Record(v != 2, s + 4))
- Record(v == 4, s + 5);
- } else if (!Record(v > 10, s + 6)) {
- Record(v > 6, s + 7);
- } else if (!Record((v >= 3 + (8 << 2)), s + 8)) {
- Record((v >= 3 + (8 << 1)), s + 9);
- } else {
- Record((v >= 3 + (8 << 3)), s + 10);
- }
-#else
- if (v > MAX_VARIABLE_LEVEL) {
- v = MAX_VARIABLE_LEVEL;
- }
-
- {
- const int bits = VP8LevelCodes[v - 1][1];
- int pattern = VP8LevelCodes[v - 1][0];
- int i;
- for (i = 0; (pattern >>= 1) != 0; ++i) {
- const int mask = 2 << i;
- if (pattern & 1) Record(!!(bits & mask), s + 3 + i);
- }
- }
-#endif
- s = res->stats[VP8EncBands[n]][2];
- }
- }
- if (n < 16) Record(0, s + 0);
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/cost.h b/drivers/webp/enc/cost.h
deleted file mode 100644
index 20960d6d74..0000000000
--- a/drivers/webp/enc/cost.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Cost tables for level and modes.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_ENC_COST_H_
-#define WEBP_ENC_COST_H_
-
-#include <assert.h>
-#include <stdlib.h>
-#include "./vp8enci.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// On-the-fly info about the current set of residuals. Handy to avoid
-// passing zillions of params.
-typedef struct VP8Residual VP8Residual;
-struct VP8Residual {
- int first;
- int last;
- const int16_t* coeffs;
-
- int coeff_type;
- ProbaArray* prob;
- StatsArray* stats;
- CostArrayPtr costs;
-};
-
-void VP8InitResidual(int first, int coeff_type,
- VP8Encoder* const enc, VP8Residual* const res);
-
-int VP8RecordCoeffs(int ctx, const VP8Residual* const res);
-
-// Cost of coding one event with probability 'proba'.
-static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) {
- return !bit ? VP8EntropyCost[proba] : VP8EntropyCost[255 - proba];
-}
-
-// Level cost calculations
-extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2];
-void VP8CalculateLevelCosts(VP8EncProba* const proba);
-static WEBP_INLINE int VP8LevelCost(const uint16_t* const table, int level) {
- return VP8LevelFixedCosts[level]
- + table[(level > MAX_VARIABLE_LEVEL) ? MAX_VARIABLE_LEVEL : level];
-}
-
-// Mode costs
-extern const uint16_t VP8FixedCostsUV[4];
-extern const uint16_t VP8FixedCostsI16[4];
-extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES];
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_ENC_COST_H_ */
diff --git a/drivers/webp/enc/delta_palettization.c b/drivers/webp/enc/delta_palettization.c
deleted file mode 100644
index 8bd3a3d233..0000000000
--- a/drivers/webp/enc/delta_palettization.c
+++ /dev/null
@@ -1,455 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Mislav Bradac (mislavm@google.com)
-//
-
-#include "./delta_palettization.h"
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
-#include "webp/types.h"
-#include "../dsp/lossless.h"
-
-#define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b))
-
-// Format allows palette up to 256 entries, but more palette entries produce
-// bigger entropy. In the future it will probably be useful to add more entries
-// that are far from the origin of the palette or choose remaining entries
-// dynamically.
-#define DELTA_PALETTE_SIZE 226
-
-// Palette used for delta_palettization. Entries are roughly sorted by distance
-// of their signed equivalents from the origin.
-static const uint32_t kDeltaPalette[DELTA_PALETTE_SIZE] = {
- MK_COL(0u, 0u, 0u),
- MK_COL(255u, 255u, 255u),
- MK_COL(1u, 1u, 1u),
- MK_COL(254u, 254u, 254u),
- MK_COL(2u, 2u, 2u),
- MK_COL(4u, 4u, 4u),
- MK_COL(252u, 252u, 252u),
- MK_COL(250u, 0u, 0u),
- MK_COL(0u, 250u, 0u),
- MK_COL(0u, 0u, 250u),
- MK_COL(6u, 0u, 0u),
- MK_COL(0u, 6u, 0u),
- MK_COL(0u, 0u, 6u),
- MK_COL(0u, 0u, 248u),
- MK_COL(0u, 0u, 8u),
- MK_COL(0u, 248u, 0u),
- MK_COL(0u, 248u, 248u),
- MK_COL(0u, 248u, 8u),
- MK_COL(0u, 8u, 0u),
- MK_COL(0u, 8u, 248u),
- MK_COL(0u, 8u, 8u),
- MK_COL(8u, 8u, 8u),
- MK_COL(248u, 0u, 0u),
- MK_COL(248u, 0u, 248u),
- MK_COL(248u, 0u, 8u),
- MK_COL(248u, 248u, 0u),
- MK_COL(248u, 8u, 0u),
- MK_COL(8u, 0u, 0u),
- MK_COL(8u, 0u, 248u),
- MK_COL(8u, 0u, 8u),
- MK_COL(8u, 248u, 0u),
- MK_COL(8u, 8u, 0u),
- MK_COL(23u, 23u, 23u),
- MK_COL(13u, 13u, 13u),
- MK_COL(232u, 232u, 232u),
- MK_COL(244u, 244u, 244u),
- MK_COL(245u, 245u, 250u),
- MK_COL(50u, 50u, 50u),
- MK_COL(204u, 204u, 204u),
- MK_COL(236u, 236u, 236u),
- MK_COL(16u, 16u, 16u),
- MK_COL(240u, 16u, 16u),
- MK_COL(16u, 240u, 16u),
- MK_COL(240u, 240u, 16u),
- MK_COL(16u, 16u, 240u),
- MK_COL(240u, 16u, 240u),
- MK_COL(16u, 240u, 240u),
- MK_COL(240u, 240u, 240u),
- MK_COL(0u, 0u, 232u),
- MK_COL(0u, 232u, 0u),
- MK_COL(232u, 0u, 0u),
- MK_COL(0u, 0u, 24u),
- MK_COL(0u, 24u, 0u),
- MK_COL(24u, 0u, 0u),
- MK_COL(32u, 32u, 32u),
- MK_COL(224u, 32u, 32u),
- MK_COL(32u, 224u, 32u),
- MK_COL(224u, 224u, 32u),
- MK_COL(32u, 32u, 224u),
- MK_COL(224u, 32u, 224u),
- MK_COL(32u, 224u, 224u),
- MK_COL(224u, 224u, 224u),
- MK_COL(0u, 0u, 176u),
- MK_COL(0u, 0u, 80u),
- MK_COL(0u, 176u, 0u),
- MK_COL(0u, 176u, 176u),
- MK_COL(0u, 176u, 80u),
- MK_COL(0u, 80u, 0u),
- MK_COL(0u, 80u, 176u),
- MK_COL(0u, 80u, 80u),
- MK_COL(176u, 0u, 0u),
- MK_COL(176u, 0u, 176u),
- MK_COL(176u, 0u, 80u),
- MK_COL(176u, 176u, 0u),
- MK_COL(176u, 80u, 0u),
- MK_COL(80u, 0u, 0u),
- MK_COL(80u, 0u, 176u),
- MK_COL(80u, 0u, 80u),
- MK_COL(80u, 176u, 0u),
- MK_COL(80u, 80u, 0u),
- MK_COL(0u, 0u, 152u),
- MK_COL(0u, 0u, 104u),
- MK_COL(0u, 152u, 0u),
- MK_COL(0u, 152u, 152u),
- MK_COL(0u, 152u, 104u),
- MK_COL(0u, 104u, 0u),
- MK_COL(0u, 104u, 152u),
- MK_COL(0u, 104u, 104u),
- MK_COL(152u, 0u, 0u),
- MK_COL(152u, 0u, 152u),
- MK_COL(152u, 0u, 104u),
- MK_COL(152u, 152u, 0u),
- MK_COL(152u, 104u, 0u),
- MK_COL(104u, 0u, 0u),
- MK_COL(104u, 0u, 152u),
- MK_COL(104u, 0u, 104u),
- MK_COL(104u, 152u, 0u),
- MK_COL(104u, 104u, 0u),
- MK_COL(216u, 216u, 216u),
- MK_COL(216u, 216u, 40u),
- MK_COL(216u, 216u, 176u),
- MK_COL(216u, 216u, 80u),
- MK_COL(216u, 40u, 216u),
- MK_COL(216u, 40u, 40u),
- MK_COL(216u, 40u, 176u),
- MK_COL(216u, 40u, 80u),
- MK_COL(216u, 176u, 216u),
- MK_COL(216u, 176u, 40u),
- MK_COL(216u, 176u, 176u),
- MK_COL(216u, 176u, 80u),
- MK_COL(216u, 80u, 216u),
- MK_COL(216u, 80u, 40u),
- MK_COL(216u, 80u, 176u),
- MK_COL(216u, 80u, 80u),
- MK_COL(40u, 216u, 216u),
- MK_COL(40u, 216u, 40u),
- MK_COL(40u, 216u, 176u),
- MK_COL(40u, 216u, 80u),
- MK_COL(40u, 40u, 216u),
- MK_COL(40u, 40u, 40u),
- MK_COL(40u, 40u, 176u),
- MK_COL(40u, 40u, 80u),
- MK_COL(40u, 176u, 216u),
- MK_COL(40u, 176u, 40u),
- MK_COL(40u, 176u, 176u),
- MK_COL(40u, 176u, 80u),
- MK_COL(40u, 80u, 216u),
- MK_COL(40u, 80u, 40u),
- MK_COL(40u, 80u, 176u),
- MK_COL(40u, 80u, 80u),
- MK_COL(80u, 216u, 216u),
- MK_COL(80u, 216u, 40u),
- MK_COL(80u, 216u, 176u),
- MK_COL(80u, 216u, 80u),
- MK_COL(80u, 40u, 216u),
- MK_COL(80u, 40u, 40u),
- MK_COL(80u, 40u, 176u),
- MK_COL(80u, 40u, 80u),
- MK_COL(80u, 176u, 216u),
- MK_COL(80u, 176u, 40u),
- MK_COL(80u, 176u, 176u),
- MK_COL(80u, 176u, 80u),
- MK_COL(80u, 80u, 216u),
- MK_COL(80u, 80u, 40u),
- MK_COL(80u, 80u, 176u),
- MK_COL(80u, 80u, 80u),
- MK_COL(0u, 0u, 192u),
- MK_COL(0u, 0u, 64u),
- MK_COL(0u, 0u, 128u),
- MK_COL(0u, 192u, 0u),
- MK_COL(0u, 192u, 192u),
- MK_COL(0u, 192u, 64u),
- MK_COL(0u, 192u, 128u),
- MK_COL(0u, 64u, 0u),
- MK_COL(0u, 64u, 192u),
- MK_COL(0u, 64u, 64u),
- MK_COL(0u, 64u, 128u),
- MK_COL(0u, 128u, 0u),
- MK_COL(0u, 128u, 192u),
- MK_COL(0u, 128u, 64u),
- MK_COL(0u, 128u, 128u),
- MK_COL(176u, 216u, 216u),
- MK_COL(176u, 216u, 40u),
- MK_COL(176u, 216u, 176u),
- MK_COL(176u, 216u, 80u),
- MK_COL(176u, 40u, 216u),
- MK_COL(176u, 40u, 40u),
- MK_COL(176u, 40u, 176u),
- MK_COL(176u, 40u, 80u),
- MK_COL(176u, 176u, 216u),
- MK_COL(176u, 176u, 40u),
- MK_COL(176u, 176u, 176u),
- MK_COL(176u, 176u, 80u),
- MK_COL(176u, 80u, 216u),
- MK_COL(176u, 80u, 40u),
- MK_COL(176u, 80u, 176u),
- MK_COL(176u, 80u, 80u),
- MK_COL(192u, 0u, 0u),
- MK_COL(192u, 0u, 192u),
- MK_COL(192u, 0u, 64u),
- MK_COL(192u, 0u, 128u),
- MK_COL(192u, 192u, 0u),
- MK_COL(192u, 192u, 192u),
- MK_COL(192u, 192u, 64u),
- MK_COL(192u, 192u, 128u),
- MK_COL(192u, 64u, 0u),
- MK_COL(192u, 64u, 192u),
- MK_COL(192u, 64u, 64u),
- MK_COL(192u, 64u, 128u),
- MK_COL(192u, 128u, 0u),
- MK_COL(192u, 128u, 192u),
- MK_COL(192u, 128u, 64u),
- MK_COL(192u, 128u, 128u),
- MK_COL(64u, 0u, 0u),
- MK_COL(64u, 0u, 192u),
- MK_COL(64u, 0u, 64u),
- MK_COL(64u, 0u, 128u),
- MK_COL(64u, 192u, 0u),
- MK_COL(64u, 192u, 192u),
- MK_COL(64u, 192u, 64u),
- MK_COL(64u, 192u, 128u),
- MK_COL(64u, 64u, 0u),
- MK_COL(64u, 64u, 192u),
- MK_COL(64u, 64u, 64u),
- MK_COL(64u, 64u, 128u),
- MK_COL(64u, 128u, 0u),
- MK_COL(64u, 128u, 192u),
- MK_COL(64u, 128u, 64u),
- MK_COL(64u, 128u, 128u),
- MK_COL(128u, 0u, 0u),
- MK_COL(128u, 0u, 192u),
- MK_COL(128u, 0u, 64u),
- MK_COL(128u, 0u, 128u),
- MK_COL(128u, 192u, 0u),
- MK_COL(128u, 192u, 192u),
- MK_COL(128u, 192u, 64u),
- MK_COL(128u, 192u, 128u),
- MK_COL(128u, 64u, 0u),
- MK_COL(128u, 64u, 192u),
- MK_COL(128u, 64u, 64u),
- MK_COL(128u, 64u, 128u),
- MK_COL(128u, 128u, 0u),
- MK_COL(128u, 128u, 192u),
- MK_COL(128u, 128u, 64u),
- MK_COL(128u, 128u, 128u),
-};
-
-#undef MK_COL
-
-//------------------------------------------------------------------------------
-// TODO(skal): move the functions to dsp/lossless.c when the correct
-// granularity is found. For now, we'll just copy-paste some useful bits
-// here instead.
-
-// In-place sum of each component with mod 256.
-static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
- const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u);
- const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu);
- *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
-}
-
-static WEBP_INLINE uint32_t Clip255(uint32_t a) {
- if (a < 256) {
- return a;
- }
- // return 0, when a is a negative integer.
- // return 255, when a is positive.
- return ~a >> 24;
-}
-
-// Delta palettization functions.
-static WEBP_INLINE int Square(int x) {
- return x * x;
-}
-
-static WEBP_INLINE uint32_t Intensity(uint32_t a) {
- return
- 30 * ((a >> 16) & 0xff) +
- 59 * ((a >> 8) & 0xff) +
- 11 * ((a >> 0) & 0xff);
-}
-
-static uint32_t CalcDist(uint32_t predicted_value, uint32_t actual_value,
- uint32_t palette_entry) {
- int i;
- uint32_t distance = 0;
- AddPixelsEq(&predicted_value, palette_entry);
- for (i = 0; i < 32; i += 8) {
- const int32_t av = (actual_value >> i) & 0xff;
- const int32_t pv = (predicted_value >> i) & 0xff;
- distance += Square(pv - av);
- }
- // We sum square of intensity difference with factor 10, but because Intensity
- // returns 100 times real intensity we need to multiply differences of colors
- // by 1000.
- distance *= 1000u;
- distance += Square(Intensity(predicted_value)
- - Intensity(actual_value));
- return distance;
-}
-
-static uint32_t Predict(int x, int y, uint32_t* image) {
- const uint32_t t = (y == 0) ? ARGB_BLACK : image[x];
- const uint32_t l = (x == 0) ? ARGB_BLACK : image[x - 1];
- const uint32_t p =
- (((((t >> 24) & 0xff) + ((l >> 24) & 0xff)) / 2) << 24) +
- (((((t >> 16) & 0xff) + ((l >> 16) & 0xff)) / 2) << 16) +
- (((((t >> 8) & 0xff) + ((l >> 8) & 0xff)) / 2) << 8) +
- (((((t >> 0) & 0xff) + ((l >> 0) & 0xff)) / 2) << 0);
- if (x == 0 && y == 0) return ARGB_BLACK;
- if (x == 0) return t;
- if (y == 0) return l;
- return p;
-}
-
-static WEBP_INLINE int AddSubtractComponentFullWithCoefficient(
- int a, int b, int c) {
- return Clip255(a + ((b - c) >> 2));
-}
-
-static WEBP_INLINE uint32_t ClampedAddSubtractFullWithCoefficient(
- uint32_t c0, uint32_t c1, uint32_t c2) {
- const int a = AddSubtractComponentFullWithCoefficient(
- c0 >> 24, c1 >> 24, c2 >> 24);
- const int r = AddSubtractComponentFullWithCoefficient((c0 >> 16) & 0xff,
- (c1 >> 16) & 0xff,
- (c2 >> 16) & 0xff);
- const int g = AddSubtractComponentFullWithCoefficient((c0 >> 8) & 0xff,
- (c1 >> 8) & 0xff,
- (c2 >> 8) & 0xff);
- const int b = AddSubtractComponentFullWithCoefficient(
- c0 & 0xff, c1 & 0xff, c2 & 0xff);
- return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
-}
-
-//------------------------------------------------------------------------------
-
-// Find palette entry with minimum error from difference of actual pixel value
-// and predicted pixel value. Propagate error of pixel to its top and left pixel
-// in src array. Write predicted_value + palette_entry to new_image. Return
-// index of best palette entry.
-static int FindBestPaletteEntry(uint32_t src, uint32_t predicted_value,
- const uint32_t palette[], int palette_size) {
- int i;
- int idx = 0;
- uint32_t best_distance = CalcDist(predicted_value, src, palette[0]);
- for (i = 1; i < palette_size; ++i) {
- const uint32_t distance = CalcDist(predicted_value, src, palette[i]);
- if (distance < best_distance) {
- best_distance = distance;
- idx = i;
- }
- }
- return idx;
-}
-
-static void ApplyBestPaletteEntry(int x, int y,
- uint32_t new_value, uint32_t palette_value,
- uint32_t* src, int src_stride,
- uint32_t* new_image) {
- AddPixelsEq(&new_value, palette_value);
- if (x > 0) {
- src[x - 1] = ClampedAddSubtractFullWithCoefficient(src[x - 1],
- new_value, src[x]);
- }
- if (y > 0) {
- src[x - src_stride] =
- ClampedAddSubtractFullWithCoefficient(src[x - src_stride],
- new_value, src[x]);
- }
- new_image[x] = new_value;
-}
-
-//------------------------------------------------------------------------------
-// Main entry point
-
-static WebPEncodingError ApplyDeltaPalette(uint32_t* src, uint32_t* dst,
- uint32_t src_stride,
- uint32_t dst_stride,
- const uint32_t* palette,
- int palette_size,
- int width, int height,
- int num_passes) {
- int x, y;
- WebPEncodingError err = VP8_ENC_OK;
- uint32_t* new_image = (uint32_t*)WebPSafeMalloc(width, sizeof(*new_image));
- uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row));
- if (new_image == NULL || tmp_row == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- while (num_passes--) {
- uint32_t* cur_src = src;
- uint32_t* cur_dst = dst;
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const uint32_t predicted_value = Predict(x, y, new_image);
- tmp_row[x] = FindBestPaletteEntry(cur_src[x], predicted_value,
- palette, palette_size);
- ApplyBestPaletteEntry(x, y, predicted_value, palette[tmp_row[x]],
- cur_src, src_stride, new_image);
- }
- for (x = 0; x < width; ++x) {
- cur_dst[x] = palette[tmp_row[x]];
- }
- cur_src += src_stride;
- cur_dst += dst_stride;
- }
- }
- Error:
- WebPSafeFree(new_image);
- WebPSafeFree(tmp_row);
- return err;
-}
-
-// replaces enc->argb_ by a palettizable approximation of it,
-// and generates optimal enc->palette_[]
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) {
- const WebPPicture* const pic = enc->pic_;
- uint32_t* src = pic->argb;
- uint32_t* dst = enc->argb_;
- const int width = pic->width;
- const int height = pic->height;
-
- WebPEncodingError err = VP8_ENC_OK;
- memcpy(enc->palette_, kDeltaPalette, sizeof(kDeltaPalette));
- enc->palette_[DELTA_PALETTE_SIZE - 1] = src[0] - 0xff000000u;
- enc->palette_size_ = DELTA_PALETTE_SIZE;
- err = ApplyDeltaPalette(src, dst, pic->argb_stride, enc->current_width_,
- enc->palette_, enc->palette_size_,
- width, height, 2);
- if (err != VP8_ENC_OK) goto Error;
-
- Error:
- return err;
-}
-
-#else // !WEBP_EXPERIMENTAL_FEATURES
-
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) {
- (void)enc;
- return VP8_ENC_ERROR_INVALID_CONFIGURATION;
-}
-
-#endif // WEBP_EXPERIMENTAL_FEATURES
diff --git a/drivers/webp/enc/delta_palettization.h b/drivers/webp/enc/delta_palettization.h
deleted file mode 100644
index 54195d452c..0000000000
--- a/drivers/webp/enc/delta_palettization.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Mislav Bradac (mislavm@google.com)
-//
-
-#ifndef WEBP_ENC_DELTA_PALETTIZATION_H_
-#define WEBP_ENC_DELTA_PALETTIZATION_H_
-
-#include "webp/encode.h"
-#include "../enc/vp8li.h"
-
-// Replaces enc->argb_[] input by a palettizable approximation of it,
-// and generates optimal enc->palette_[].
-// This function can revert enc->use_palette_ / enc->use_predict_ flag
-// if delta-palettization is not producing expected saving.
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc);
-
-#endif // WEBP_ENC_DELTA_PALETTIZATION_H_
diff --git a/drivers/webp/enc/filter.c b/drivers/webp/enc/filter.c
deleted file mode 100644
index e8ea8b4ff2..0000000000
--- a/drivers/webp/enc/filter.c
+++ /dev/null
@@ -1,306 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Selecting filter level
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#include <assert.h>
-#include "./vp8enci.h"
-#include "../dsp/dsp.h"
-
-// This table gives, for a given sharpness, the filtering strength to be
-// used (at least) in order to filter a given edge step delta.
-// This is constructed by brute force inspection: for all delta, we iterate
-// over all possible filtering strength / thresh until needs_filter() returns
-// true.
-#define MAX_DELTA_SIZE 64
-static const uint8_t kLevelsFromDelta[8][MAX_DELTA_SIZE] = {
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 },
- { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 18,
- 20, 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42,
- 44, 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
- { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 19,
- 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43,
- 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
- { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19,
- 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43,
- 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
- { 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20,
- 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44,
- 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
- { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20,
- 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44,
- 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
- { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 21,
- 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45,
- 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
- { 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21,
- 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45,
- 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }
-};
-
-int VP8FilterStrengthFromDelta(int sharpness, int delta) {
- const int pos = (delta < MAX_DELTA_SIZE) ? delta : MAX_DELTA_SIZE - 1;
- assert(sharpness >= 0 && sharpness <= 7);
- return kLevelsFromDelta[sharpness][pos];
-}
-
-//------------------------------------------------------------------------------
-// Paragraph 15.4: compute the inner-edge filtering strength
-
-static int GetILevel(int sharpness, int level) {
- if (sharpness > 0) {
- if (sharpness > 4) {
- level >>= 2;
- } else {
- level >>= 1;
- }
- if (level > 9 - sharpness) {
- level = 9 - sharpness;
- }
- }
- if (level < 1) level = 1;
- return level;
-}
-
-static void DoFilter(const VP8EncIterator* const it, int level) {
- const VP8Encoder* const enc = it->enc_;
- const int ilevel = GetILevel(enc->config_->filter_sharpness, level);
- const int limit = 2 * level + ilevel;
-
- uint8_t* const y_dst = it->yuv_out2_ + Y_OFF_ENC;
- uint8_t* const u_dst = it->yuv_out2_ + U_OFF_ENC;
- uint8_t* const v_dst = it->yuv_out2_ + V_OFF_ENC;
-
- // copy current block to yuv_out2_
- memcpy(y_dst, it->yuv_out_, YUV_SIZE_ENC * sizeof(uint8_t));
-
- if (enc->filter_hdr_.simple_ == 1) { // simple
- VP8SimpleHFilter16i(y_dst, BPS, limit);
- VP8SimpleVFilter16i(y_dst, BPS, limit);
- } else { // complex
- const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
- VP8HFilter16i(y_dst, BPS, limit, ilevel, hev_thresh);
- VP8HFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh);
- VP8VFilter16i(y_dst, BPS, limit, ilevel, hev_thresh);
- VP8VFilter8i(u_dst, v_dst, BPS, limit, ilevel, hev_thresh);
- }
-}
-
-//------------------------------------------------------------------------------
-// SSIM metric
-
-static const double kMinValue = 1.e-10; // minimal threshold
-
-void VP8SSIMAddStats(const VP8DistoStats* const src, VP8DistoStats* const dst) {
- dst->w += src->w;
- dst->xm += src->xm;
- dst->ym += src->ym;
- dst->xxm += src->xxm;
- dst->xym += src->xym;
- dst->yym += src->yym;
-}
-
-double VP8SSIMGet(const VP8DistoStats* const stats) {
- const double xmxm = stats->xm * stats->xm;
- const double ymym = stats->ym * stats->ym;
- const double xmym = stats->xm * stats->ym;
- const double w2 = stats->w * stats->w;
- double sxx = stats->xxm * stats->w - xmxm;
- double syy = stats->yym * stats->w - ymym;
- double sxy = stats->xym * stats->w - xmym;
- double C1, C2;
- double fnum;
- double fden;
- // small errors are possible, due to rounding. Clamp to zero.
- if (sxx < 0.) sxx = 0.;
- if (syy < 0.) syy = 0.;
- C1 = 6.5025 * w2;
- C2 = 58.5225 * w2;
- fnum = (2 * xmym + C1) * (2 * sxy + C2);
- fden = (xmxm + ymym + C1) * (sxx + syy + C2);
- return (fden != 0.) ? fnum / fden : kMinValue;
-}
-
-double VP8SSIMGetSquaredError(const VP8DistoStats* const s) {
- if (s->w > 0.) {
- const double iw2 = 1. / (s->w * s->w);
- const double sxx = s->xxm * s->w - s->xm * s->xm;
- const double syy = s->yym * s->w - s->ym * s->ym;
- const double sxy = s->xym * s->w - s->xm * s->ym;
- const double SSE = iw2 * (sxx + syy - 2. * sxy);
- if (SSE > kMinValue) return SSE;
- }
- return kMinValue;
-}
-
-#define LIMIT(A, M) ((A) > (M) ? (M) : (A))
-static void VP8SSIMAccumulateRow(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int y, int W, int H,
- VP8DistoStats* const stats) {
- int x = 0;
- const int w0 = LIMIT(VP8_SSIM_KERNEL, W);
- for (x = 0; x < w0; ++x) {
- VP8SSIMAccumulateClipped(src1, stride1, src2, stride2, x, y, W, H, stats);
- }
- for (; x <= W - 8 + VP8_SSIM_KERNEL; ++x) {
- VP8SSIMAccumulate(
- src1 + (y - VP8_SSIM_KERNEL) * stride1 + (x - VP8_SSIM_KERNEL), stride1,
- src2 + (y - VP8_SSIM_KERNEL) * stride2 + (x - VP8_SSIM_KERNEL), stride2,
- stats);
- }
- for (; x < W; ++x) {
- VP8SSIMAccumulateClipped(src1, stride1, src2, stride2, x, y, W, H, stats);
- }
-}
-
-void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int W, int H, VP8DistoStats* const stats) {
- int x, y;
- const int h0 = LIMIT(VP8_SSIM_KERNEL, H);
- const int h1 = LIMIT(VP8_SSIM_KERNEL, H - VP8_SSIM_KERNEL);
- for (y = 0; y < h0; ++y) {
- for (x = 0; x < W; ++x) {
- VP8SSIMAccumulateClipped(src1, stride1, src2, stride2, x, y, W, H, stats);
- }
- }
- for (; y < h1; ++y) {
- VP8SSIMAccumulateRow(src1, stride1, src2, stride2, y, W, H, stats);
- }
- for (; y < H; ++y) {
- for (x = 0; x < W; ++x) {
- VP8SSIMAccumulateClipped(src1, stride1, src2, stride2, x, y, W, H, stats);
- }
- }
-}
-#undef LIMIT
-
-static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) {
- int x, y;
- VP8DistoStats s = { .0, .0, .0, .0, .0, .0 };
-
- // compute SSIM in a 10 x 10 window
- for (y = VP8_SSIM_KERNEL; y < 16 - VP8_SSIM_KERNEL; y++) {
- for (x = VP8_SSIM_KERNEL; x < 16 - VP8_SSIM_KERNEL; x++) {
- VP8SSIMAccumulateClipped(yuv1 + Y_OFF_ENC, BPS, yuv2 + Y_OFF_ENC, BPS,
- x, y, 16, 16, &s);
- }
- }
- for (x = 1; x < 7; x++) {
- for (y = 1; y < 7; y++) {
- VP8SSIMAccumulateClipped(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS,
- x, y, 8, 8, &s);
- VP8SSIMAccumulateClipped(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS,
- x, y, 8, 8, &s);
- }
- }
- return VP8SSIMGet(&s);
-}
-
-//------------------------------------------------------------------------------
-// Exposed APIs: Encoder should call the following 3 functions to adjust
-// loop filter strength
-
-void VP8InitFilter(VP8EncIterator* const it) {
- if (it->lf_stats_ != NULL) {
- int s, i;
- for (s = 0; s < NUM_MB_SEGMENTS; s++) {
- for (i = 0; i < MAX_LF_LEVELS; i++) {
- (*it->lf_stats_)[s][i] = 0;
- }
- }
- VP8SSIMDspInit();
- }
-}
-
-void VP8StoreFilterStats(VP8EncIterator* const it) {
- int d;
- VP8Encoder* const enc = it->enc_;
- const int s = it->mb_->segment_;
- const int level0 = enc->dqm_[s].fstrength_;
-
- // explore +/-quant range of values around level0
- const int delta_min = -enc->dqm_[s].quant_;
- const int delta_max = enc->dqm_[s].quant_;
- const int step_size = (delta_max - delta_min >= 4) ? 4 : 1;
-
- if (it->lf_stats_ == NULL) return;
-
- // NOTE: Currently we are applying filter only across the sublock edges
- // There are two reasons for that.
- // 1. Applying filter on macro block edges will change the pixels in
- // the left and top macro blocks. That will be hard to restore
- // 2. Macro Blocks on the bottom and right are not yet compressed. So we
- // cannot apply filter on the right and bottom macro block edges.
- if (it->mb_->type_ == 1 && it->mb_->skip_) return;
-
- // Always try filter level zero
- (*it->lf_stats_)[s][0] += GetMBSSIM(it->yuv_in_, it->yuv_out_);
-
- for (d = delta_min; d <= delta_max; d += step_size) {
- const int level = level0 + d;
- if (level <= 0 || level >= MAX_LF_LEVELS) {
- continue;
- }
- DoFilter(it, level);
- (*it->lf_stats_)[s][level] += GetMBSSIM(it->yuv_in_, it->yuv_out2_);
- }
-}
-
-void VP8AdjustFilterStrength(VP8EncIterator* const it) {
- VP8Encoder* const enc = it->enc_;
- if (it->lf_stats_ != NULL) {
- int s;
- for (s = 0; s < NUM_MB_SEGMENTS; s++) {
- int i, best_level = 0;
- // Improvement over filter level 0 should be at least 1e-5 (relatively)
- double best_v = 1.00001 * (*it->lf_stats_)[s][0];
- for (i = 1; i < MAX_LF_LEVELS; i++) {
- const double v = (*it->lf_stats_)[s][i];
- if (v > best_v) {
- best_v = v;
- best_level = i;
- }
- }
- enc->dqm_[s].fstrength_ = best_level;
- }
- } else if (enc->config_->filter_strength > 0) {
- int max_level = 0;
- int s;
- for (s = 0; s < NUM_MB_SEGMENTS; s++) {
- VP8SegmentInfo* const dqm = &enc->dqm_[s];
- // this '>> 3' accounts for some inverse WHT scaling
- const int delta = (dqm->max_edge_ * dqm->y2_.q_[1]) >> 3;
- const int level =
- VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, delta);
- if (level > dqm->fstrength_) {
- dqm->fstrength_ = level;
- }
- if (max_level < dqm->fstrength_) {
- max_level = dqm->fstrength_;
- }
- }
- enc->filter_hdr_.level_ = max_level;
- }
-}
-
-// -----------------------------------------------------------------------------
diff --git a/drivers/webp/enc/frame.c b/drivers/webp/enc/frame.c
deleted file mode 100644
index 65a98ada4d..0000000000
--- a/drivers/webp/enc/frame.c
+++ /dev/null
@@ -1,850 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// frame coding and analysis
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <string.h>
-#include <math.h>
-
-#include "./cost.h"
-#include "./vp8enci.h"
-#include "../dsp/dsp.h"
-#include "webp/format_constants.h" // RIFF constants
-
-#define SEGMENT_VISU 0
-#define DEBUG_SEARCH 0 // useful to track search convergence
-
-//------------------------------------------------------------------------------
-// multi-pass convergence
-
-#define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \
- VP8_FRAME_HEADER_SIZE)
-#define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT
-// we allow 2k of extra head-room in PARTITION0 limit.
-#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11)
-
-typedef struct { // struct for organizing convergence in either size or PSNR
- int is_first;
- float dq;
- float q, last_q;
- double value, last_value; // PSNR or size
- double target;
- int do_size_search;
-} PassStats;
-
-static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) {
- const uint64_t target_size = (uint64_t)enc->config_->target_size;
- const int do_size_search = (target_size != 0);
- const float target_PSNR = enc->config_->target_PSNR;
-
- s->is_first = 1;
- s->dq = 10.f;
- s->q = s->last_q = enc->config_->quality;
- s->target = do_size_search ? (double)target_size
- : (target_PSNR > 0.) ? target_PSNR
- : 40.; // default, just in case
- s->value = s->last_value = 0.;
- s->do_size_search = do_size_search;
- return do_size_search;
-}
-
-static float Clamp(float v, float min, float max) {
- return (v < min) ? min : (v > max) ? max : v;
-}
-
-static float ComputeNextQ(PassStats* const s) {
- float dq;
- if (s->is_first) {
- dq = (s->value > s->target) ? -s->dq : s->dq;
- s->is_first = 0;
- } else if (s->value != s->last_value) {
- const double slope = (s->target - s->value) / (s->last_value - s->value);
- dq = (float)(slope * (s->last_q - s->q));
- } else {
- dq = 0.; // we're done?!
- }
- // Limit variable to avoid large swings.
- s->dq = Clamp(dq, -30.f, 30.f);
- s->last_q = s->q;
- s->last_value = s->value;
- s->q = Clamp(s->q + s->dq, 0.f, 100.f);
- return s->q;
-}
-
-//------------------------------------------------------------------------------
-// Tables for level coding
-
-const uint8_t VP8Cat3[] = { 173, 148, 140 };
-const uint8_t VP8Cat4[] = { 176, 155, 140, 135 };
-const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 };
-const uint8_t VP8Cat6[] =
- { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 };
-
-//------------------------------------------------------------------------------
-// Reset the statistics about: number of skips, token proba, level cost,...
-
-static void ResetStats(VP8Encoder* const enc) {
- VP8EncProba* const proba = &enc->proba_;
- VP8CalculateLevelCosts(proba);
- proba->nb_skip_ = 0;
-}
-
-//------------------------------------------------------------------------------
-// Skip decision probability
-
-#define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK.
-
-static int CalcSkipProba(uint64_t nb, uint64_t total) {
- return (int)(total ? (total - nb) * 255 / total : 255);
-}
-
-// Returns the bit-cost for coding the skip probability.
-static int FinalizeSkipProba(VP8Encoder* const enc) {
- VP8EncProba* const proba = &enc->proba_;
- const int nb_mbs = enc->mb_w_ * enc->mb_h_;
- const int nb_events = proba->nb_skip_;
- int size;
- proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs);
- proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD);
- size = 256; // 'use_skip_proba' bit
- if (proba->use_skip_proba_) {
- size += nb_events * VP8BitCost(1, proba->skip_proba_)
- + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_);
- size += 8 * 256; // cost of signaling the skip_proba_ itself.
- }
- return size;
-}
-
-// Collect statistics and deduce probabilities for next coding pass.
-// Return the total bit-cost for coding the probability updates.
-static int CalcTokenProba(int nb, int total) {
- assert(nb <= total);
- return nb ? (255 - nb * 255 / total) : 255;
-}
-
-// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability.
-static int BranchCost(int nb, int total, int proba) {
- return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba);
-}
-
-static void ResetTokenStats(VP8Encoder* const enc) {
- VP8EncProba* const proba = &enc->proba_;
- memset(proba->stats_, 0, sizeof(proba->stats_));
-}
-
-static int FinalizeTokenProbas(VP8EncProba* const proba) {
- int has_changed = 0;
- int size = 0;
- int t, b, c, p;
- for (t = 0; t < NUM_TYPES; ++t) {
- for (b = 0; b < NUM_BANDS; ++b) {
- for (c = 0; c < NUM_CTX; ++c) {
- for (p = 0; p < NUM_PROBAS; ++p) {
- const proba_t stats = proba->stats_[t][b][c][p];
- const int nb = (stats >> 0) & 0xffff;
- const int total = (stats >> 16) & 0xffff;
- const int update_proba = VP8CoeffsUpdateProba[t][b][c][p];
- const int old_p = VP8CoeffsProba0[t][b][c][p];
- const int new_p = CalcTokenProba(nb, total);
- const int old_cost = BranchCost(nb, total, old_p)
- + VP8BitCost(0, update_proba);
- const int new_cost = BranchCost(nb, total, new_p)
- + VP8BitCost(1, update_proba)
- + 8 * 256;
- const int use_new_p = (old_cost > new_cost);
- size += VP8BitCost(use_new_p, update_proba);
- if (use_new_p) { // only use proba that seem meaningful enough.
- proba->coeffs_[t][b][c][p] = new_p;
- has_changed |= (new_p != old_p);
- size += 8 * 256;
- } else {
- proba->coeffs_[t][b][c][p] = old_p;
- }
- }
- }
- }
- }
- proba->dirty_ = has_changed;
- return size;
-}
-
-//------------------------------------------------------------------------------
-// Finalize Segment probability based on the coding tree
-
-static int GetProba(int a, int b) {
- const int total = a + b;
- return (total == 0) ? 255 // that's the default probability.
- : (255 * a + total / 2) / total; // rounded proba
-}
-
-static void SetSegmentProbas(VP8Encoder* const enc) {
- int p[NUM_MB_SEGMENTS] = { 0 };
- int n;
-
- for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
- const VP8MBInfo* const mb = &enc->mb_info_[n];
- p[mb->segment_]++;
- }
- if (enc->pic_->stats != NULL) {
- for (n = 0; n < NUM_MB_SEGMENTS; ++n) {
- enc->pic_->stats->segment_size[n] = p[n];
- }
- }
- if (enc->segment_hdr_.num_segments_ > 1) {
- uint8_t* const probas = enc->proba_.segments_;
- probas[0] = GetProba(p[0] + p[1], p[2] + p[3]);
- probas[1] = GetProba(p[0], p[1]);
- probas[2] = GetProba(p[2], p[3]);
-
- enc->segment_hdr_.update_map_ =
- (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255);
- enc->segment_hdr_.size_ =
- p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) +
- p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) +
- p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) +
- p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2]));
- } else {
- enc->segment_hdr_.update_map_ = 0;
- enc->segment_hdr_.size_ = 0;
- }
-}
-
-//------------------------------------------------------------------------------
-// Coefficient coding
-
-static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
- int n = res->first;
- // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
- const uint8_t* p = res->prob[n][ctx];
- if (!VP8PutBit(bw, res->last >= 0, p[0])) {
- return 0;
- }
-
- while (n < 16) {
- const int c = res->coeffs[n++];
- const int sign = c < 0;
- int v = sign ? -c : c;
- if (!VP8PutBit(bw, v != 0, p[1])) {
- p = res->prob[VP8EncBands[n]][0];
- continue;
- }
- if (!VP8PutBit(bw, v > 1, p[2])) {
- p = res->prob[VP8EncBands[n]][1];
- } else {
- if (!VP8PutBit(bw, v > 4, p[3])) {
- if (VP8PutBit(bw, v != 2, p[4]))
- VP8PutBit(bw, v == 4, p[5]);
- } else if (!VP8PutBit(bw, v > 10, p[6])) {
- if (!VP8PutBit(bw, v > 6, p[7])) {
- VP8PutBit(bw, v == 6, 159);
- } else {
- VP8PutBit(bw, v >= 9, 165);
- VP8PutBit(bw, !(v & 1), 145);
- }
- } else {
- int mask;
- const uint8_t* tab;
- if (v < 3 + (8 << 1)) { // VP8Cat3 (3b)
- VP8PutBit(bw, 0, p[8]);
- VP8PutBit(bw, 0, p[9]);
- v -= 3 + (8 << 0);
- mask = 1 << 2;
- tab = VP8Cat3;
- } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b)
- VP8PutBit(bw, 0, p[8]);
- VP8PutBit(bw, 1, p[9]);
- v -= 3 + (8 << 1);
- mask = 1 << 3;
- tab = VP8Cat4;
- } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b)
- VP8PutBit(bw, 1, p[8]);
- VP8PutBit(bw, 0, p[10]);
- v -= 3 + (8 << 2);
- mask = 1 << 4;
- tab = VP8Cat5;
- } else { // VP8Cat6 (11b)
- VP8PutBit(bw, 1, p[8]);
- VP8PutBit(bw, 1, p[10]);
- v -= 3 + (8 << 3);
- mask = 1 << 10;
- tab = VP8Cat6;
- }
- while (mask) {
- VP8PutBit(bw, !!(v & mask), *tab++);
- mask >>= 1;
- }
- }
- p = res->prob[VP8EncBands[n]][2];
- }
- VP8PutBitUniform(bw, sign);
- if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) {
- return 1; // EOB
- }
- }
- return 1;
-}
-
-static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it,
- const VP8ModeScore* const rd) {
- int x, y, ch;
- VP8Residual res;
- uint64_t pos1, pos2, pos3;
- const int i16 = (it->mb_->type_ == 1);
- const int segment = it->mb_->segment_;
- VP8Encoder* const enc = it->enc_;
-
- VP8IteratorNzToBytes(it);
-
- pos1 = VP8BitWriterPos(bw);
- if (i16) {
- VP8InitResidual(0, 1, enc, &res);
- VP8SetResidualCoeffs(rd->y_dc_levels, &res);
- it->top_nz_[8] = it->left_nz_[8] =
- PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res);
- VP8InitResidual(1, 0, enc, &res);
- } else {
- VP8InitResidual(0, 3, enc, &res);
- }
-
- // luma-AC
- for (y = 0; y < 4; ++y) {
- for (x = 0; x < 4; ++x) {
- const int ctx = it->top_nz_[x] + it->left_nz_[y];
- VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
- it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res);
- }
- }
- pos2 = VP8BitWriterPos(bw);
-
- // U/V
- VP8InitResidual(0, 2, enc, &res);
- for (ch = 0; ch <= 2; ch += 2) {
- for (y = 0; y < 2; ++y) {
- for (x = 0; x < 2; ++x) {
- const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
- it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
- PutCoeffs(bw, ctx, &res);
- }
- }
- }
- pos3 = VP8BitWriterPos(bw);
- it->luma_bits_ = pos2 - pos1;
- it->uv_bits_ = pos3 - pos2;
- it->bit_count_[segment][i16] += it->luma_bits_;
- it->bit_count_[segment][2] += it->uv_bits_;
- VP8IteratorBytesToNz(it);
-}
-
-// Same as CodeResiduals, but doesn't actually write anything.
-// Instead, it just records the event distribution.
-static void RecordResiduals(VP8EncIterator* const it,
- const VP8ModeScore* const rd) {
- int x, y, ch;
- VP8Residual res;
- VP8Encoder* const enc = it->enc_;
-
- VP8IteratorNzToBytes(it);
-
- if (it->mb_->type_ == 1) { // i16x16
- VP8InitResidual(0, 1, enc, &res);
- VP8SetResidualCoeffs(rd->y_dc_levels, &res);
- it->top_nz_[8] = it->left_nz_[8] =
- VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
- VP8InitResidual(1, 0, enc, &res);
- } else {
- VP8InitResidual(0, 3, enc, &res);
- }
-
- // luma-AC
- for (y = 0; y < 4; ++y) {
- for (x = 0; x < 4; ++x) {
- const int ctx = it->top_nz_[x] + it->left_nz_[y];
- VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
- it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res);
- }
- }
-
- // U/V
- VP8InitResidual(0, 2, enc, &res);
- for (ch = 0; ch <= 2; ch += 2) {
- for (y = 0; y < 2; ++y) {
- for (x = 0; x < 2; ++x) {
- const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
- it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
- VP8RecordCoeffs(ctx, &res);
- }
- }
- }
-
- VP8IteratorBytesToNz(it);
-}
-
-//------------------------------------------------------------------------------
-// Token buffer
-
-#if !defined(DISABLE_TOKEN_BUFFER)
-
-static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd,
- VP8TBuffer* const tokens) {
- int x, y, ch;
- VP8Residual res;
- VP8Encoder* const enc = it->enc_;
-
- VP8IteratorNzToBytes(it);
- if (it->mb_->type_ == 1) { // i16x16
- const int ctx = it->top_nz_[8] + it->left_nz_[8];
- VP8InitResidual(0, 1, enc, &res);
- VP8SetResidualCoeffs(rd->y_dc_levels, &res);
- it->top_nz_[8] = it->left_nz_[8] =
- VP8RecordCoeffTokens(ctx, 1,
- res.first, res.last, res.coeffs, tokens);
- VP8RecordCoeffs(ctx, &res);
- VP8InitResidual(1, 0, enc, &res);
- } else {
- VP8InitResidual(0, 3, enc, &res);
- }
-
- // luma-AC
- for (y = 0; y < 4; ++y) {
- for (x = 0; x < 4; ++x) {
- const int ctx = it->top_nz_[x] + it->left_nz_[y];
- VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
- it->top_nz_[x] = it->left_nz_[y] =
- VP8RecordCoeffTokens(ctx, res.coeff_type,
- res.first, res.last, res.coeffs, tokens);
- VP8RecordCoeffs(ctx, &res);
- }
- }
-
- // U/V
- VP8InitResidual(0, 2, enc, &res);
- for (ch = 0; ch <= 2; ch += 2) {
- for (y = 0; y < 2; ++y) {
- for (x = 0; x < 2; ++x) {
- const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
- it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
- VP8RecordCoeffTokens(ctx, 2,
- res.first, res.last, res.coeffs, tokens);
- VP8RecordCoeffs(ctx, &res);
- }
- }
- }
- VP8IteratorBytesToNz(it);
- return !tokens->error_;
-}
-
-#endif // !DISABLE_TOKEN_BUFFER
-
-//------------------------------------------------------------------------------
-// ExtraInfo map / Debug function
-
-#if SEGMENT_VISU
-static void SetBlock(uint8_t* p, int value, int size) {
- int y;
- for (y = 0; y < size; ++y) {
- memset(p, value, size);
- p += BPS;
- }
-}
-#endif
-
-static void ResetSSE(VP8Encoder* const enc) {
- enc->sse_[0] = 0;
- enc->sse_[1] = 0;
- enc->sse_[2] = 0;
- // Note: enc->sse_[3] is managed by alpha.c
- enc->sse_count_ = 0;
-}
-
-static void StoreSSE(const VP8EncIterator* const it) {
- VP8Encoder* const enc = it->enc_;
- const uint8_t* const in = it->yuv_in_;
- const uint8_t* const out = it->yuv_out_;
- // Note: not totally accurate at boundary. And doesn't include in-loop filter.
- enc->sse_[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC);
- enc->sse_[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC);
- enc->sse_[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC);
- enc->sse_count_ += 16 * 16;
-}
-
-static void StoreSideInfo(const VP8EncIterator* const it) {
- VP8Encoder* const enc = it->enc_;
- const VP8MBInfo* const mb = it->mb_;
- WebPPicture* const pic = enc->pic_;
-
- if (pic->stats != NULL) {
- StoreSSE(it);
- enc->block_count_[0] += (mb->type_ == 0);
- enc->block_count_[1] += (mb->type_ == 1);
- enc->block_count_[2] += (mb->skip_ != 0);
- }
-
- if (pic->extra_info != NULL) {
- uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_];
- switch (pic->extra_info_type) {
- case 1: *info = mb->type_; break;
- case 2: *info = mb->segment_; break;
- case 3: *info = enc->dqm_[mb->segment_].quant_; break;
- case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break;
- case 5: *info = mb->uv_mode_; break;
- case 6: {
- const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3);
- *info = (b > 255) ? 255 : b; break;
- }
- case 7: *info = mb->alpha_; break;
- default: *info = 0; break;
- }
- }
-#if SEGMENT_VISU // visualize segments and prediction modes
- SetBlock(it->yuv_out_ + Y_OFF_ENC, mb->segment_ * 64, 16);
- SetBlock(it->yuv_out_ + U_OFF_ENC, it->preds_[0] * 64, 8);
- SetBlock(it->yuv_out_ + V_OFF_ENC, mb->uv_mode_ * 64, 8);
-#endif
-}
-
-static double GetPSNR(uint64_t mse, uint64_t size) {
- return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99;
-}
-
-//------------------------------------------------------------------------------
-// StatLoop(): only collect statistics (number of skips, token usage, ...).
-// This is used for deciding optimal probabilities. It also modifies the
-// quantizer value if some target (size, PSNR) was specified.
-
-static void SetLoopParams(VP8Encoder* const enc, float q) {
- // Make sure the quality parameter is inside valid bounds
- q = Clamp(q, 0.f, 100.f);
-
- VP8SetSegmentParams(enc, q); // setup segment quantizations and filters
- SetSegmentProbas(enc); // compute segment probabilities
-
- ResetStats(enc);
- ResetSSE(enc);
-}
-
-static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt,
- int nb_mbs, int percent_delta,
- PassStats* const s) {
- VP8EncIterator it;
- uint64_t size = 0;
- uint64_t size_p0 = 0;
- uint64_t distortion = 0;
- const uint64_t pixel_count = nb_mbs * 384;
-
- VP8IteratorInit(enc, &it);
- SetLoopParams(enc, s->q);
- do {
- VP8ModeScore info;
- VP8IteratorImport(&it, NULL);
- if (VP8Decimate(&it, &info, rd_opt)) {
- // Just record the number of skips and act like skip_proba is not used.
- enc->proba_.nb_skip_++;
- }
- RecordResiduals(&it, &info);
- size += info.R + info.H;
- size_p0 += info.H;
- distortion += info.D;
- if (percent_delta && !VP8IteratorProgress(&it, percent_delta))
- return 0;
- VP8IteratorSaveBoundary(&it);
- } while (VP8IteratorNext(&it) && --nb_mbs > 0);
-
- size_p0 += enc->segment_hdr_.size_;
- if (s->do_size_search) {
- size += FinalizeSkipProba(enc);
- size += FinalizeTokenProbas(&enc->proba_);
- size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE;
- s->value = (double)size;
- } else {
- s->value = GetPSNR(distortion, pixel_count);
- }
- return size_p0;
-}
-
-static int StatLoop(VP8Encoder* const enc) {
- const int method = enc->method_;
- const int do_search = enc->do_search_;
- const int fast_probe = ((method == 0 || method == 3) && !do_search);
- int num_pass_left = enc->config_->pass;
- const int task_percent = 20;
- const int percent_per_pass =
- (task_percent + num_pass_left / 2) / num_pass_left;
- const int final_percent = enc->percent_ + task_percent;
- const VP8RDLevel rd_opt =
- (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE;
- int nb_mbs = enc->mb_w_ * enc->mb_h_;
- PassStats stats;
-
- InitPassStats(enc, &stats);
- ResetTokenStats(enc);
-
- // Fast mode: quick analysis pass over few mbs. Better than nothing.
- if (fast_probe) {
- if (method == 3) { // we need more stats for method 3 to be reliable.
- nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100;
- } else {
- nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50;
- }
- }
-
- while (num_pass_left-- > 0) {
- const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) ||
- (num_pass_left == 0) ||
- (enc->max_i4_header_bits_ == 0);
- const uint64_t size_p0 =
- OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats);
- if (size_p0 == 0) return 0;
-#if (DEBUG_SEARCH > 0)
- printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n",
- num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q);
-#endif
- if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) {
- ++num_pass_left;
- enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation...
- continue; // ...and start over
- }
- if (is_last_pass) {
- break;
- }
- // If no target size: just do several pass without changing 'q'
- if (do_search) {
- ComputeNextQ(&stats);
- if (fabs(stats.dq) <= DQ_LIMIT) break;
- }
- }
- if (!do_search || !stats.do_size_search) {
- // Need to finalize probas now, since it wasn't done during the search.
- FinalizeSkipProba(enc);
- FinalizeTokenProbas(&enc->proba_);
- }
- VP8CalculateLevelCosts(&enc->proba_); // finalize costs
- return WebPReportProgress(enc->pic_, final_percent, &enc->percent_);
-}
-
-//------------------------------------------------------------------------------
-// Main loops
-//
-
-static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 };
-
-static int PreLoopInitialize(VP8Encoder* const enc) {
- int p;
- int ok = 1;
- const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant_ >> 4];
- const int bytes_per_parts =
- enc->mb_w_ * enc->mb_h_ * average_bytes_per_MB / enc->num_parts_;
- // Initialize the bit-writers
- for (p = 0; ok && p < enc->num_parts_; ++p) {
- ok = VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
- }
- if (!ok) {
- VP8EncFreeBitWriters(enc); // malloc error occurred
- WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
- return ok;
-}
-
-static int PostLoopFinalize(VP8EncIterator* const it, int ok) {
- VP8Encoder* const enc = it->enc_;
- if (ok) { // Finalize the partitions, check for extra errors.
- int p;
- for (p = 0; p < enc->num_parts_; ++p) {
- VP8BitWriterFinish(enc->parts_ + p);
- ok &= !enc->parts_[p].error_;
- }
- }
-
- if (ok) { // All good. Finish up.
- if (enc->pic_->stats != NULL) { // finalize byte counters...
- int i, s;
- for (i = 0; i <= 2; ++i) {
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- enc->residual_bytes_[i][s] = (int)((it->bit_count_[s][i] + 7) >> 3);
- }
- }
- }
- VP8AdjustFilterStrength(it); // ...and store filter stats.
- } else {
- // Something bad happened -> need to do some memory cleanup.
- VP8EncFreeBitWriters(enc);
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// VP8EncLoop(): does the final bitstream coding.
-
-static void ResetAfterSkip(VP8EncIterator* const it) {
- if (it->mb_->type_ == 1) {
- *it->nz_ = 0; // reset all predictors
- it->left_nz_[8] = 0;
- } else {
- *it->nz_ &= (1 << 24); // preserve the dc_nz bit
- }
-}
-
-int VP8EncLoop(VP8Encoder* const enc) {
- VP8EncIterator it;
- int ok = PreLoopInitialize(enc);
- if (!ok) return 0;
-
- StatLoop(enc); // stats-collection loop
-
- VP8IteratorInit(enc, &it);
- VP8InitFilter(&it);
- do {
- VP8ModeScore info;
- const int dont_use_skip = !enc->proba_.use_skip_proba_;
- const VP8RDLevel rd_opt = enc->rd_opt_level_;
-
- VP8IteratorImport(&it, NULL);
- // Warning! order is important: first call VP8Decimate() and
- // *then* decide how to code the skip decision if there's one.
- if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
- CodeResiduals(it.bw_, &it, &info);
- } else { // reset predictors after a skip
- ResetAfterSkip(&it);
- }
- StoreSideInfo(&it);
- VP8StoreFilterStats(&it);
- VP8IteratorExport(&it);
- ok = VP8IteratorProgress(&it, 20);
- VP8IteratorSaveBoundary(&it);
- } while (ok && VP8IteratorNext(&it));
-
- return PostLoopFinalize(&it, ok);
-}
-
-//------------------------------------------------------------------------------
-// Single pass using Token Buffer.
-
-#if !defined(DISABLE_TOKEN_BUFFER)
-
-#define MIN_COUNT 96 // minimum number of macroblocks before updating stats
-
-int VP8EncTokenLoop(VP8Encoder* const enc) {
- // Roughly refresh the proba eight times per pass
- int max_count = (enc->mb_w_ * enc->mb_h_) >> 3;
- int num_pass_left = enc->config_->pass;
- const int do_search = enc->do_search_;
- VP8EncIterator it;
- VP8EncProba* const proba = &enc->proba_;
- const VP8RDLevel rd_opt = enc->rd_opt_level_;
- const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384;
- PassStats stats;
- int ok;
-
- InitPassStats(enc, &stats);
- ok = PreLoopInitialize(enc);
- if (!ok) return 0;
-
- if (max_count < MIN_COUNT) max_count = MIN_COUNT;
-
- assert(enc->num_parts_ == 1);
- assert(enc->use_tokens_);
- assert(proba->use_skip_proba_ == 0);
- assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful
- assert(num_pass_left > 0);
-
- while (ok && num_pass_left-- > 0) {
- const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) ||
- (num_pass_left == 0) ||
- (enc->max_i4_header_bits_ == 0);
- uint64_t size_p0 = 0;
- uint64_t distortion = 0;
- int cnt = max_count;
- VP8IteratorInit(enc, &it);
- SetLoopParams(enc, stats.q);
- if (is_last_pass) {
- ResetTokenStats(enc);
- VP8InitFilter(&it); // don't collect stats until last pass (too costly)
- }
- VP8TBufferClear(&enc->tokens_);
- do {
- VP8ModeScore info;
- VP8IteratorImport(&it, NULL);
- if (--cnt < 0) {
- FinalizeTokenProbas(proba);
- VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt
- cnt = max_count;
- }
- VP8Decimate(&it, &info, rd_opt);
- ok = RecordTokens(&it, &info, &enc->tokens_);
- if (!ok) {
- WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
- break;
- }
- size_p0 += info.H;
- distortion += info.D;
- if (is_last_pass) {
- StoreSideInfo(&it);
- VP8StoreFilterStats(&it);
- VP8IteratorExport(&it);
- ok = VP8IteratorProgress(&it, 20);
- }
- VP8IteratorSaveBoundary(&it);
- } while (ok && VP8IteratorNext(&it));
- if (!ok) break;
-
- size_p0 += enc->segment_hdr_.size_;
- if (stats.do_size_search) {
- uint64_t size = FinalizeTokenProbas(&enc->proba_);
- size += VP8EstimateTokenSize(&enc->tokens_,
- (const uint8_t*)proba->coeffs_);
- size = (size + size_p0 + 1024) >> 11; // -> size in bytes
- size += HEADER_SIZE_ESTIMATE;
- stats.value = (double)size;
- } else { // compute and store PSNR
- stats.value = GetPSNR(distortion, pixel_count);
- }
-
-#if (DEBUG_SEARCH > 0)
- printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n",
- num_pass_left, stats.last_value, stats.value,
- stats.last_q, stats.q, stats.dq);
-#endif
- if (size_p0 > PARTITION0_SIZE_LIMIT) {
- ++num_pass_left;
- enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation...
- continue; // ...and start over
- }
- if (is_last_pass) {
- break; // done
- }
- if (do_search) {
- ComputeNextQ(&stats); // Adjust q
- }
- }
- if (ok) {
- if (!stats.do_size_search) {
- FinalizeTokenProbas(&enc->proba_);
- }
- ok = VP8EmitTokens(&enc->tokens_, enc->parts_ + 0,
- (const uint8_t*)proba->coeffs_, 1);
- }
- ok = ok && WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
- return PostLoopFinalize(&it, ok);
-}
-
-#else
-
-int VP8EncTokenLoop(VP8Encoder* const enc) {
- (void)enc;
- return 0; // we shouldn't be here.
-}
-
-#endif // DISABLE_TOKEN_BUFFER
-
-//------------------------------------------------------------------------------
-
diff --git a/drivers/webp/enc/histogram.c b/drivers/webp/enc/histogram.c
deleted file mode 100644
index 61544f4ccd..0000000000
--- a/drivers/webp/enc/histogram.c
+++ /dev/null
@@ -1,937 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-//
-#ifdef HAVE_CONFIG_H
-#include "webp/config.h"
-#endif
-
-#include <math.h>
-
-#include "./backward_references.h"
-#include "./histogram.h"
-#include "../dsp/lossless.h"
-#include "../utils/utils.h"
-
-#define MAX_COST 1.e38
-
-// Number of partitions for the three dominant (literal, red and blue) symbol
-// costs.
-#define NUM_PARTITIONS 4
-// The size of the bin-hash corresponding to the three dominant costs.
-#define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS)
-// Maximum number of histograms allowed in greedy combining algorithm.
-#define MAX_HISTO_GREEDY 100
-
-static void HistogramClear(VP8LHistogram* const p) {
- uint32_t* const literal = p->literal_;
- const int cache_bits = p->palette_code_bits_;
- const int histo_size = VP8LGetHistogramSize(cache_bits);
- memset(p, 0, histo_size);
- p->palette_code_bits_ = cache_bits;
- p->literal_ = literal;
-}
-
-// Swap two histogram pointers.
-static void HistogramSwap(VP8LHistogram** const A, VP8LHistogram** const B) {
- VP8LHistogram* const tmp = *A;
- *A = *B;
- *B = tmp;
-}
-
-static void HistogramCopy(const VP8LHistogram* const src,
- VP8LHistogram* const dst) {
- uint32_t* const dst_literal = dst->literal_;
- const int dst_cache_bits = dst->palette_code_bits_;
- const int histo_size = VP8LGetHistogramSize(dst_cache_bits);
- assert(src->palette_code_bits_ == dst_cache_bits);
- memcpy(dst, src, histo_size);
- dst->literal_ = dst_literal;
-}
-
-int VP8LGetHistogramSize(int cache_bits) {
- const int literal_size = VP8LHistogramNumCodes(cache_bits);
- const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size;
- assert(total_size <= (size_t)0x7fffffff);
- return (int)total_size;
-}
-
-void VP8LFreeHistogram(VP8LHistogram* const histo) {
- WebPSafeFree(histo);
-}
-
-void VP8LFreeHistogramSet(VP8LHistogramSet* const histo) {
- WebPSafeFree(histo);
-}
-
-void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
- VP8LHistogram* const histo) {
- VP8LRefsCursor c = VP8LRefsCursorInit(refs);
- while (VP8LRefsCursorOk(&c)) {
- VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos);
- VP8LRefsCursorNext(&c);
- }
-}
-
-void VP8LHistogramCreate(VP8LHistogram* const p,
- const VP8LBackwardRefs* const refs,
- int palette_code_bits) {
- if (palette_code_bits >= 0) {
- p->palette_code_bits_ = palette_code_bits;
- }
- HistogramClear(p);
- VP8LHistogramStoreRefs(refs, p);
-}
-
-void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) {
- p->palette_code_bits_ = palette_code_bits;
- HistogramClear(p);
-}
-
-VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
- VP8LHistogram* histo = NULL;
- const int total_size = VP8LGetHistogramSize(cache_bits);
- uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
- if (memory == NULL) return NULL;
- histo = (VP8LHistogram*)memory;
- // literal_ won't necessary be aligned.
- histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
- VP8LHistogramInit(histo, cache_bits);
- return histo;
-}
-
-VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
- int i;
- VP8LHistogramSet* set;
- const int histo_size = VP8LGetHistogramSize(cache_bits);
- const size_t total_size =
- sizeof(*set) + size * (sizeof(*set->histograms) +
- histo_size + WEBP_ALIGN_CST);
- uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
- if (memory == NULL) return NULL;
-
- set = (VP8LHistogramSet*)memory;
- memory += sizeof(*set);
- set->histograms = (VP8LHistogram**)memory;
- memory += size * sizeof(*set->histograms);
- set->max_size = size;
- set->size = size;
- for (i = 0; i < size; ++i) {
- memory = (uint8_t*)WEBP_ALIGN(memory);
- set->histograms[i] = (VP8LHistogram*)memory;
- // literal_ won't necessary be aligned.
- set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
- VP8LHistogramInit(set->histograms[i], cache_bits);
- memory += histo_size;
- }
- return set;
-}
-
-// -----------------------------------------------------------------------------
-
-void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
- const PixOrCopy* const v) {
- if (PixOrCopyIsLiteral(v)) {
- ++histo->alpha_[PixOrCopyLiteral(v, 3)];
- ++histo->red_[PixOrCopyLiteral(v, 2)];
- ++histo->literal_[PixOrCopyLiteral(v, 1)];
- ++histo->blue_[PixOrCopyLiteral(v, 0)];
- } else if (PixOrCopyIsCacheIdx(v)) {
- const int literal_ix =
- NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v);
- ++histo->literal_[literal_ix];
- } else {
- int code, extra_bits;
- VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits);
- ++histo->literal_[NUM_LITERAL_CODES + code];
- VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits);
- ++histo->distance_[code];
- }
-}
-
-// -----------------------------------------------------------------------------
-// Entropy-related functions.
-
-static WEBP_INLINE double BitsEntropyRefine(const VP8LBitEntropy* entropy) {
- double mix;
- if (entropy->nonzeros < 5) {
- if (entropy->nonzeros <= 1) {
- return 0;
- }
- // Two symbols, they will be 0 and 1 in a Huffman code.
- // Let's mix in a bit of entropy to favor good clustering when
- // distributions of these are combined.
- if (entropy->nonzeros == 2) {
- return 0.99 * entropy->sum + 0.01 * entropy->entropy;
- }
- // No matter what the entropy says, we cannot be better than min_limit
- // with Huffman coding. I am mixing a bit of entropy into the
- // min_limit since it produces much better (~0.5 %) compression results
- // perhaps because of better entropy clustering.
- if (entropy->nonzeros == 3) {
- mix = 0.95;
- } else {
- mix = 0.7; // nonzeros == 4.
- }
- } else {
- mix = 0.627;
- }
-
- {
- double min_limit = 2 * entropy->sum - entropy->max_val;
- min_limit = mix * min_limit + (1.0 - mix) * entropy->entropy;
- return (entropy->entropy < min_limit) ? min_limit : entropy->entropy;
- }
-}
-
-double VP8LBitsEntropy(const uint32_t* const array, int n,
- uint32_t* const trivial_symbol) {
- VP8LBitEntropy entropy;
- VP8LBitsEntropyUnrefined(array, n, &entropy);
- if (trivial_symbol != NULL) {
- *trivial_symbol =
- (entropy.nonzeros == 1) ? entropy.nonzero_code : VP8L_NON_TRIVIAL_SYM;
- }
-
- return BitsEntropyRefine(&entropy);
-}
-
-static double InitialHuffmanCost(void) {
- // Small bias because Huffman code length is typically not stored in
- // full length.
- static const int kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3;
- static const double kSmallBias = 9.1;
- return kHuffmanCodeOfHuffmanCodeSize - kSmallBias;
-}
-
-// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3)
-static double FinalHuffmanCost(const VP8LStreaks* const stats) {
- double retval = InitialHuffmanCost();
- retval += stats->counts[0] * 1.5625 + 0.234375 * stats->streaks[0][1];
- retval += stats->counts[1] * 2.578125 + 0.703125 * stats->streaks[1][1];
- retval += 1.796875 * stats->streaks[0][0];
- retval += 3.28125 * stats->streaks[1][0];
- return retval;
-}
-
-// Get the symbol entropy for the distribution 'population'.
-// Set 'trivial_sym', if there's only one symbol present in the distribution.
-static double PopulationCost(const uint32_t* const population, int length,
- uint32_t* const trivial_sym) {
- VP8LBitEntropy bit_entropy;
- VP8LStreaks stats;
- VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats);
- if (trivial_sym != NULL) {
- *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code
- : VP8L_NON_TRIVIAL_SYM;
- }
-
- return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
-}
-
-static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X,
- const uint32_t* const Y,
- int length) {
- VP8LBitEntropy bit_entropy;
- VP8LStreaks stats;
- VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats);
-
- return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
-}
-
-// Estimates the Entropy + Huffman + other block overhead size cost.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
- return
- PopulationCost(
- p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL)
- + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL)
- + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES)
- + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES);
-}
-
-// -----------------------------------------------------------------------------
-// Various histogram combine/cost-eval functions
-
-static int GetCombinedHistogramEntropy(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- double cost_threshold,
- double* cost) {
- const int palette_code_bits = a->palette_code_bits_;
- assert(a->palette_code_bits_ == b->palette_code_bits_);
- *cost += GetCombinedEntropy(a->literal_, b->literal_,
- VP8LHistogramNumCodes(palette_code_bits));
- *cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES,
- b->literal_ + NUM_LITERAL_CODES,
- NUM_LENGTH_CODES);
- if (*cost > cost_threshold) return 0;
-
- *cost += GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES);
- if (*cost > cost_threshold) return 0;
-
- *cost += GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES);
- if (*cost > cost_threshold) return 0;
-
- *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES);
- if (*cost > cost_threshold) return 0;
-
- *cost += GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES);
- *cost +=
- VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES);
- if (*cost > cost_threshold) return 0;
-
- return 1;
-}
-
-// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing
-// to the threshold value 'cost_threshold'. The score returned is
-// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed.
-// Since the previous score passed is 'cost_threshold', we only need to compare
-// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out
-// early.
-static double HistogramAddEval(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out,
- double cost_threshold) {
- double cost = 0;
- const double sum_cost = a->bit_cost_ + b->bit_cost_;
- cost_threshold += sum_cost;
-
- if (GetCombinedHistogramEntropy(a, b, cost_threshold, &cost)) {
- VP8LHistogramAdd(a, b, out);
- out->bit_cost_ = cost;
- out->palette_code_bits_ = a->palette_code_bits_;
- out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_) ?
- a->trivial_symbol_ : VP8L_NON_TRIVIAL_SYM;
- }
-
- return cost - sum_cost;
-}
-
-// Same as HistogramAddEval(), except that the resulting histogram
-// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit
-// the term C(b) which is constant over all the evaluations.
-static double HistogramAddThresh(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- double cost_threshold) {
- double cost = -a->bit_cost_;
- GetCombinedHistogramEntropy(a, b, cost_threshold, &cost);
- return cost;
-}
-
-// -----------------------------------------------------------------------------
-
-// The structure to keep track of cost range for the three dominant entropy
-// symbols.
-// TODO(skal): Evaluate if float can be used here instead of double for
-// representing the entropy costs.
-typedef struct {
- double literal_max_;
- double literal_min_;
- double red_max_;
- double red_min_;
- double blue_max_;
- double blue_min_;
-} DominantCostRange;
-
-static void DominantCostRangeInit(DominantCostRange* const c) {
- c->literal_max_ = 0.;
- c->literal_min_ = MAX_COST;
- c->red_max_ = 0.;
- c->red_min_ = MAX_COST;
- c->blue_max_ = 0.;
- c->blue_min_ = MAX_COST;
-}
-
-static void UpdateDominantCostRange(
- const VP8LHistogram* const h, DominantCostRange* const c) {
- if (c->literal_max_ < h->literal_cost_) c->literal_max_ = h->literal_cost_;
- if (c->literal_min_ > h->literal_cost_) c->literal_min_ = h->literal_cost_;
- if (c->red_max_ < h->red_cost_) c->red_max_ = h->red_cost_;
- if (c->red_min_ > h->red_cost_) c->red_min_ = h->red_cost_;
- if (c->blue_max_ < h->blue_cost_) c->blue_max_ = h->blue_cost_;
- if (c->blue_min_ > h->blue_cost_) c->blue_min_ = h->blue_cost_;
-}
-
-static void UpdateHistogramCost(VP8LHistogram* const h) {
- uint32_t alpha_sym, red_sym, blue_sym;
- const double alpha_cost =
- PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym);
- const double distance_cost =
- PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) +
- VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES);
- const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_);
- h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) +
- VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES,
- NUM_LENGTH_CODES);
- h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym);
- h->blue_cost_ = PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym);
- h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ +
- alpha_cost + distance_cost;
- if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) {
- h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM;
- } else {
- h->trivial_symbol_ =
- ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0);
- }
-}
-
-static int GetBinIdForEntropy(double min, double max, double val) {
- const double range = max - min;
- if (range > 0.) {
- const double delta = val - min;
- return (int)((NUM_PARTITIONS - 1e-6) * delta / range);
- } else {
- return 0;
- }
-}
-
-static int GetHistoBinIndex(const VP8LHistogram* const h,
- const DominantCostRange* const c, int low_effort) {
- int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_,
- h->literal_cost_);
- assert(bin_id < NUM_PARTITIONS);
- if (!low_effort) {
- bin_id = bin_id * NUM_PARTITIONS
- + GetBinIdForEntropy(c->red_min_, c->red_max_, h->red_cost_);
- bin_id = bin_id * NUM_PARTITIONS
- + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_);
- assert(bin_id < BIN_SIZE);
- }
- return bin_id;
-}
-
-// Construct the histograms from backward references.
-static void HistogramBuild(
- int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs,
- VP8LHistogramSet* const image_histo) {
- int x = 0, y = 0;
- const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits);
- VP8LHistogram** const histograms = image_histo->histograms;
- VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
- assert(histo_bits > 0);
- while (VP8LRefsCursorOk(&c)) {
- const PixOrCopy* const v = c.cur_pos;
- const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits);
- VP8LHistogramAddSinglePixOrCopy(histograms[ix], v);
- x += PixOrCopyLength(v);
- while (x >= xsize) {
- x -= xsize;
- ++y;
- }
- VP8LRefsCursorNext(&c);
- }
-}
-
-// Copies the histograms and computes its bit_cost.
-static void HistogramCopyAndAnalyze(
- VP8LHistogramSet* const orig_histo, VP8LHistogramSet* const image_histo) {
- int i;
- const int histo_size = orig_histo->size;
- VP8LHistogram** const orig_histograms = orig_histo->histograms;
- VP8LHistogram** const histograms = image_histo->histograms;
- for (i = 0; i < histo_size; ++i) {
- VP8LHistogram* const histo = orig_histograms[i];
- UpdateHistogramCost(histo);
- // Copy histograms from orig_histo[] to image_histo[].
- HistogramCopy(histo, histograms[i]);
- }
-}
-
-// Partition histograms to different entropy bins for three dominant (literal,
-// red and blue) symbol costs and compute the histogram aggregate bit_cost.
-static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
- int16_t* const bin_map, int low_effort) {
- int i;
- VP8LHistogram** const histograms = image_histo->histograms;
- const int histo_size = image_histo->size;
- const int bin_depth = histo_size + 1;
- DominantCostRange cost_range;
- DominantCostRangeInit(&cost_range);
-
- // Analyze the dominant (literal, red and blue) entropy costs.
- for (i = 0; i < histo_size; ++i) {
- VP8LHistogram* const histo = histograms[i];
- UpdateDominantCostRange(histo, &cost_range);
- }
-
- // bin-hash histograms on three of the dominant (literal, red and blue)
- // symbol costs.
- for (i = 0; i < histo_size; ++i) {
- const VP8LHistogram* const histo = histograms[i];
- const int bin_id = GetHistoBinIndex(histo, &cost_range, low_effort);
- const int bin_offset = bin_id * bin_depth;
- // bin_map[n][0] for every bin 'n' maintains the counter for the number of
- // histograms in that bin.
- // Get and increment the num_histos in that bin.
- const int num_histos = ++bin_map[bin_offset];
- assert(bin_offset + num_histos < bin_depth * BIN_SIZE);
- // Add histogram i'th index at num_histos (last) position in the bin_map.
- bin_map[bin_offset + num_histos] = i;
- }
-}
-
-// Compact the histogram set by removing unused entries.
-static void HistogramCompactBins(VP8LHistogramSet* const image_histo) {
- VP8LHistogram** const histograms = image_histo->histograms;
- int i, j;
-
- for (i = 0, j = 0; i < image_histo->size; ++i) {
- if (histograms[i] != NULL && histograms[i]->bit_cost_ != 0.) {
- if (j < i) {
- histograms[j] = histograms[i];
- histograms[i] = NULL;
- }
- ++j;
- }
- }
- image_histo->size = j;
-}
-
-static VP8LHistogram* HistogramCombineEntropyBin(
- VP8LHistogramSet* const image_histo,
- VP8LHistogram* cur_combo,
- int16_t* const bin_map, int bin_depth, int num_bins,
- double combine_cost_factor, int low_effort) {
- int bin_id;
- VP8LHistogram** const histograms = image_histo->histograms;
-
- for (bin_id = 0; bin_id < num_bins; ++bin_id) {
- const int bin_offset = bin_id * bin_depth;
- const int num_histos = bin_map[bin_offset];
- const int idx1 = bin_map[bin_offset + 1];
- int num_combine_failures = 0;
- int n;
- for (n = 2; n <= num_histos; ++n) {
- const int idx2 = bin_map[bin_offset + n];
- if (low_effort) {
- // Merge all histograms with the same bin index, irrespective of cost of
- // the merged histograms.
- VP8LHistogramAdd(histograms[idx1], histograms[idx2], histograms[idx1]);
- histograms[idx2]->bit_cost_ = 0.;
- } else {
- const double bit_cost_idx2 = histograms[idx2]->bit_cost_;
- if (bit_cost_idx2 > 0.) {
- const double bit_cost_thresh = -bit_cost_idx2 * combine_cost_factor;
- const double curr_cost_diff =
- HistogramAddEval(histograms[idx1], histograms[idx2],
- cur_combo, bit_cost_thresh);
- if (curr_cost_diff < bit_cost_thresh) {
- // Try to merge two histograms only if the combo is a trivial one or
- // the two candidate histograms are already non-trivial.
- // For some images, 'try_combine' turns out to be false for a lot of
- // histogram pairs. In that case, we fallback to combining
- // histograms as usual to avoid increasing the header size.
- const int try_combine =
- (cur_combo->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM) ||
- ((histograms[idx1]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) &&
- (histograms[idx2]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM));
- const int max_combine_failures = 32;
- if (try_combine || (num_combine_failures >= max_combine_failures)) {
- HistogramSwap(&cur_combo, &histograms[idx1]);
- histograms[idx2]->bit_cost_ = 0.;
- } else {
- ++num_combine_failures;
- }
- }
- }
- }
- }
- if (low_effort) {
- // Update the bit_cost for the merged histograms (per bin index).
- UpdateHistogramCost(histograms[idx1]);
- }
- }
- HistogramCompactBins(image_histo);
- return cur_combo;
-}
-
-static uint32_t MyRand(uint32_t *seed) {
- *seed *= 16807U;
- if (*seed == 0) {
- *seed = 1;
- }
- return *seed;
-}
-
-// -----------------------------------------------------------------------------
-// Histogram pairs priority queue
-
-// Pair of histograms. Negative idx1 value means that pair is out-of-date.
-typedef struct {
- int idx1;
- int idx2;
- double cost_diff;
- double cost_combo;
-} HistogramPair;
-
-typedef struct {
- HistogramPair* queue;
- int size;
- int max_size;
-} HistoQueue;
-
-static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) {
- histo_queue->size = 0;
- // max_index^2 for the queue size is safe. If you look at
- // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes
- // data to the queue, you insert at most:
- // - max_index*(max_index-1)/2 (the first two for loops)
- // - max_index - 1 in the last for loop at the first iteration of the while
- // loop, max_index - 2 at the second iteration ... therefore
- // max_index*(max_index-1)/2 overall too
- histo_queue->max_size = max_index * max_index;
- // We allocate max_size + 1 because the last element at index "size" is
- // used as temporary data (and it could be up to max_size).
- histo_queue->queue = WebPSafeMalloc(histo_queue->max_size + 1,
- sizeof(*histo_queue->queue));
- return histo_queue->queue != NULL;
-}
-
-static void HistoQueueClear(HistoQueue* const histo_queue) {
- assert(histo_queue != NULL);
- WebPSafeFree(histo_queue->queue);
-}
-
-static void SwapHistogramPairs(HistogramPair *p1,
- HistogramPair *p2) {
- const HistogramPair tmp = *p1;
- *p1 = *p2;
- *p2 = tmp;
-}
-
-// Given a valid priority queue in range [0, queue_size) this function checks
-// whether histo_queue[queue_size] should be accepted and swaps it with the
-// front if it is smaller. Otherwise, it leaves it as is.
-static void UpdateQueueFront(HistoQueue* const histo_queue) {
- if (histo_queue->queue[histo_queue->size].cost_diff >= 0) return;
-
- if (histo_queue->queue[histo_queue->size].cost_diff <
- histo_queue->queue[0].cost_diff) {
- SwapHistogramPairs(histo_queue->queue,
- histo_queue->queue + histo_queue->size);
- }
- ++histo_queue->size;
-
- // We cannot add more elements than the capacity.
- // The allocation adds an extra element to the official capacity so that
- // histo_queue->queue[histo_queue->max_size] is read/written within bound.
- assert(histo_queue->size <= histo_queue->max_size);
-}
-
-// -----------------------------------------------------------------------------
-
-static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2,
- HistogramPair* const pair) {
- VP8LHistogram* h1;
- VP8LHistogram* h2;
- double sum_cost;
-
- if (idx1 > idx2) {
- const int tmp = idx2;
- idx2 = idx1;
- idx1 = tmp;
- }
- pair->idx1 = idx1;
- pair->idx2 = idx2;
- h1 = histograms[idx1];
- h2 = histograms[idx2];
- sum_cost = h1->bit_cost_ + h2->bit_cost_;
- pair->cost_combo = 0.;
- GetCombinedHistogramEntropy(h1, h2, sum_cost, &pair->cost_combo);
- pair->cost_diff = pair->cost_combo - sum_cost;
-}
-
-// Combines histograms by continuously choosing the one with the highest cost
-// reduction.
-static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) {
- int ok = 0;
- int image_histo_size = image_histo->size;
- int i, j;
- VP8LHistogram** const histograms = image_histo->histograms;
- // Indexes of remaining histograms.
- int* const clusters = WebPSafeMalloc(image_histo_size, sizeof(*clusters));
- // Priority queue of histogram pairs.
- HistoQueue histo_queue;
-
- if (!HistoQueueInit(&histo_queue, image_histo_size) || clusters == NULL) {
- goto End;
- }
-
- for (i = 0; i < image_histo_size; ++i) {
- // Initialize clusters indexes.
- clusters[i] = i;
- for (j = i + 1; j < image_histo_size; ++j) {
- // Initialize positions array.
- PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size]);
- UpdateQueueFront(&histo_queue);
- }
- }
-
- while (image_histo_size > 1 && histo_queue.size > 0) {
- HistogramPair* copy_to;
- const int idx1 = histo_queue.queue[0].idx1;
- const int idx2 = histo_queue.queue[0].idx2;
- VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]);
- histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo;
- // Remove merged histogram.
- for (i = 0; i + 1 < image_histo_size; ++i) {
- if (clusters[i] >= idx2) {
- clusters[i] = clusters[i + 1];
- }
- }
- --image_histo_size;
-
- // Remove pairs intersecting the just combined best pair. This will
- // therefore pop the head of the queue.
- copy_to = histo_queue.queue;
- for (i = 0; i < histo_queue.size; ++i) {
- HistogramPair* const p = histo_queue.queue + i;
- if (p->idx1 == idx1 || p->idx2 == idx1 ||
- p->idx1 == idx2 || p->idx2 == idx2) {
- // Do not copy the invalid pair.
- continue;
- }
- if (p->cost_diff < histo_queue.queue[0].cost_diff) {
- // Replace the top of the queue if we found better.
- SwapHistogramPairs(histo_queue.queue, p);
- }
- SwapHistogramPairs(copy_to, p);
- ++copy_to;
- }
- histo_queue.size = (int)(copy_to - histo_queue.queue);
-
- // Push new pairs formed with combined histogram to the queue.
- for (i = 0; i < image_histo_size; ++i) {
- if (clusters[i] != idx1) {
- PreparePair(histograms, idx1, clusters[i],
- &histo_queue.queue[histo_queue.size]);
- UpdateQueueFront(&histo_queue);
- }
- }
- }
- // Move remaining histograms to the beginning of the array.
- for (i = 0; i < image_histo_size; ++i) {
- if (i != clusters[i]) { // swap the two histograms
- HistogramSwap(&histograms[i], &histograms[clusters[i]]);
- }
- }
-
- image_histo->size = image_histo_size;
- ok = 1;
-
- End:
- WebPSafeFree(clusters);
- HistoQueueClear(&histo_queue);
- return ok;
-}
-
-static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
- VP8LHistogram* tmp_histo,
- VP8LHistogram* best_combo,
- int quality, int min_cluster_size) {
- int iter;
- uint32_t seed = 0;
- int tries_with_no_success = 0;
- int image_histo_size = image_histo->size;
- const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8;
- const int outer_iters = image_histo_size * iter_mult;
- const int num_pairs = image_histo_size / 2;
- const int num_tries_no_success = outer_iters / 2;
- VP8LHistogram** const histograms = image_histo->histograms;
-
- // Collapse similar histograms in 'image_histo'.
- ++min_cluster_size;
- for (iter = 0;
- iter < outer_iters && image_histo_size >= min_cluster_size;
- ++iter) {
- double best_cost_diff = 0.;
- int best_idx1 = -1, best_idx2 = 1;
- int j;
- const int num_tries =
- (num_pairs < image_histo_size) ? num_pairs : image_histo_size;
- seed += iter;
- for (j = 0; j < num_tries; ++j) {
- double curr_cost_diff;
- // Choose two histograms at random and try to combine them.
- const uint32_t idx1 = MyRand(&seed) % image_histo_size;
- const uint32_t tmp = (j & 7) + 1;
- const uint32_t diff =
- (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1);
- const uint32_t idx2 = (idx1 + diff + 1) % image_histo_size;
- if (idx1 == idx2) {
- continue;
- }
-
- // Calculate cost reduction on combining.
- curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2],
- tmp_histo, best_cost_diff);
- if (curr_cost_diff < best_cost_diff) { // found a better pair?
- HistogramSwap(&best_combo, &tmp_histo);
- best_cost_diff = curr_cost_diff;
- best_idx1 = idx1;
- best_idx2 = idx2;
- }
- }
-
- if (best_idx1 >= 0) {
- HistogramSwap(&best_combo, &histograms[best_idx1]);
- // swap best_idx2 slot with last one (which is now unused)
- --image_histo_size;
- if (best_idx2 != image_histo_size) {
- HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]);
- histograms[image_histo_size] = NULL;
- }
- tries_with_no_success = 0;
- }
- if (++tries_with_no_success >= num_tries_no_success) {
- break;
- }
- }
- image_histo->size = image_histo_size;
-}
-
-// -----------------------------------------------------------------------------
-// Histogram refinement
-
-// Find the best 'out' histogram for each of the 'in' histograms.
-// Note: we assume that out[]->bit_cost_ is already up-to-date.
-static void HistogramRemap(const VP8LHistogramSet* const in,
- const VP8LHistogramSet* const out,
- uint16_t* const symbols) {
- int i;
- VP8LHistogram** const in_histo = in->histograms;
- VP8LHistogram** const out_histo = out->histograms;
- const int in_size = in->size;
- const int out_size = out->size;
- if (out_size > 1) {
- for (i = 0; i < in_size; ++i) {
- int best_out = 0;
- double best_bits = MAX_COST;
- int k;
- for (k = 0; k < out_size; ++k) {
- const double cur_bits =
- HistogramAddThresh(out_histo[k], in_histo[i], best_bits);
- if (k == 0 || cur_bits < best_bits) {
- best_bits = cur_bits;
- best_out = k;
- }
- }
- symbols[i] = best_out;
- }
- } else {
- assert(out_size == 1);
- for (i = 0; i < in_size; ++i) {
- symbols[i] = 0;
- }
- }
-
- // Recompute each out based on raw and symbols.
- for (i = 0; i < out_size; ++i) {
- HistogramClear(out_histo[i]);
- }
-
- for (i = 0; i < in_size; ++i) {
- const int idx = symbols[i];
- VP8LHistogramAdd(in_histo[i], out_histo[idx], out_histo[idx]);
- }
-}
-
-static double GetCombineCostFactor(int histo_size, int quality) {
- double combine_cost_factor = 0.16;
- if (quality < 90) {
- if (histo_size > 256) combine_cost_factor /= 2.;
- if (histo_size > 512) combine_cost_factor /= 2.;
- if (histo_size > 1024) combine_cost_factor /= 2.;
- if (quality <= 50) combine_cost_factor /= 2.;
- }
- return combine_cost_factor;
-}
-
-int VP8LGetHistoImageSymbols(int xsize, int ysize,
- const VP8LBackwardRefs* const refs,
- int quality, int low_effort,
- int histo_bits, int cache_bits,
- VP8LHistogramSet* const image_histo,
- VP8LHistogramSet* const tmp_histos,
- uint16_t* const histogram_symbols) {
- int ok = 0;
- const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1;
- const int histo_ysize = histo_bits ? VP8LSubSampleSize(ysize, histo_bits) : 1;
- const int image_histo_raw_size = histo_xsize * histo_ysize;
- const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE;
-
- // The bin_map for every bin follows following semantics:
- // bin_map[n][0] = num_histo; // The number of histograms in that bin.
- // bin_map[n][1] = index of first histogram in that bin;
- // bin_map[n][num_histo] = index of last histogram in that bin;
- // bin_map[n][num_histo + 1] ... bin_map[n][bin_depth - 1] = unused indices.
- const int bin_depth = image_histo_raw_size + 1;
- int16_t* bin_map = NULL;
- VP8LHistogramSet* const orig_histo =
- VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits);
- VP8LHistogram* cur_combo;
- const int entropy_combine =
- (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
-
- if (orig_histo == NULL) goto Error;
-
- // Don't attempt linear bin-partition heuristic for:
- // histograms of small sizes, as bin_map will be very sparse and;
- // Maximum quality (q==100), to preserve the compression gains at that level.
- if (entropy_combine) {
- const int bin_map_size = bin_depth * entropy_combine_num_bins;
- bin_map = (int16_t*)WebPSafeCalloc(bin_map_size, sizeof(*bin_map));
- if (bin_map == NULL) goto Error;
- }
-
- // Construct the histograms from backward references.
- HistogramBuild(xsize, histo_bits, refs, orig_histo);
- // Copies the histograms and computes its bit_cost.
- HistogramCopyAndAnalyze(orig_histo, image_histo);
-
- cur_combo = tmp_histos->histograms[1]; // pick up working slot
- if (entropy_combine) {
- const double combine_cost_factor =
- GetCombineCostFactor(image_histo_raw_size, quality);
- HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort);
- // Collapse histograms with similar entropy.
- cur_combo = HistogramCombineEntropyBin(image_histo, cur_combo, bin_map,
- bin_depth, entropy_combine_num_bins,
- combine_cost_factor, low_effort);
- }
-
- // Don't combine the histograms using stochastic and greedy heuristics for
- // low-effort compression mode.
- if (!low_effort || !entropy_combine) {
- const float x = quality / 100.f;
- // cubic ramp between 1 and MAX_HISTO_GREEDY:
- const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1));
- HistogramCombineStochastic(image_histo, tmp_histos->histograms[0],
- cur_combo, quality, threshold_size);
- if ((image_histo->size <= threshold_size) &&
- !HistogramCombineGreedy(image_histo)) {
- goto Error;
- }
- }
-
- // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also.
- // Find the optimal map from original histograms to the final ones.
- HistogramRemap(orig_histo, image_histo, histogram_symbols);
-
- ok = 1;
-
- Error:
- WebPSafeFree(bin_map);
- VP8LFreeHistogramSet(orig_histo);
- return ok;
-}
diff --git a/drivers/webp/enc/histogram.h b/drivers/webp/enc/histogram.h
deleted file mode 100644
index 59de42b33e..0000000000
--- a/drivers/webp/enc/histogram.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-//
-// Models the histograms of literal and distance codes.
-
-#ifndef WEBP_ENC_HISTOGRAM_H_
-#define WEBP_ENC_HISTOGRAM_H_
-
-#include <string.h>
-
-#include "./backward_references.h"
-#include "webp/format_constants.h"
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Not a trivial literal symbol.
-#define VP8L_NON_TRIVIAL_SYM (0xffffffff)
-
-// A simple container for histograms of data.
-typedef struct {
- // literal_ contains green literal, palette-code and
- // copy-length-prefix histogram
- uint32_t* literal_; // Pointer to the allocated buffer for literal.
- uint32_t red_[NUM_LITERAL_CODES];
- uint32_t blue_[NUM_LITERAL_CODES];
- uint32_t alpha_[NUM_LITERAL_CODES];
- // Backward reference prefix-code histogram.
- uint32_t distance_[NUM_DISTANCE_CODES];
- int palette_code_bits_;
- uint32_t trivial_symbol_; // True, if histograms for Red, Blue & Alpha
- // literal symbols are single valued.
- double bit_cost_; // cached value of bit cost.
- double literal_cost_; // Cached values of dominant entropy costs:
- double red_cost_; // literal, red & blue.
- double blue_cost_;
-} VP8LHistogram;
-
-// Collection of histograms with fixed capacity, allocated as one
-// big memory chunk. Can be destroyed by calling WebPSafeFree().
-typedef struct {
- int size; // number of slots currently in use
- int max_size; // maximum capacity
- VP8LHistogram** histograms;
-} VP8LHistogramSet;
-
-// Create the histogram.
-//
-// The input data is the PixOrCopy data, which models the literals, stop
-// codes and backward references (both distances and lengths). Also: if
-// palette_code_bits is >= 0, initialize the histogram with this value.
-void VP8LHistogramCreate(VP8LHistogram* const p,
- const VP8LBackwardRefs* const refs,
- int palette_code_bits);
-
-// Return the size of the histogram for a given palette_code_bits.
-int VP8LGetHistogramSize(int palette_code_bits);
-
-// Set the palette_code_bits and reset the stats.
-void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
-
-// Collect all the references into a histogram (without reset)
-void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
- VP8LHistogram* const histo);
-
-// Free the memory allocated for the histogram.
-void VP8LFreeHistogram(VP8LHistogram* const histo);
-
-// Free the memory allocated for the histogram set.
-void VP8LFreeHistogramSet(VP8LHistogramSet* const histo);
-
-// Allocate an array of pointer to histograms, allocated and initialized
-// using 'cache_bits'. Return NULL in case of memory error.
-VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);
-
-// Allocate and initialize histogram object with specified 'cache_bits'.
-// Returns NULL in case of memory error.
-// Special case of VP8LAllocateHistogramSet, with size equals 1.
-VP8LHistogram* VP8LAllocateHistogram(int cache_bits);
-
-// Accumulate a token 'v' into a histogram.
-void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
- const PixOrCopy* const v);
-
-static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) {
- return NUM_LITERAL_CODES + NUM_LENGTH_CODES +
- ((palette_code_bits > 0) ? (1 << palette_code_bits) : 0);
-}
-
-// Builds the histogram image.
-int VP8LGetHistoImageSymbols(int xsize, int ysize,
- const VP8LBackwardRefs* const refs,
- int quality, int low_effort,
- int histogram_bits, int cache_bits,
- VP8LHistogramSet* const image_in,
- VP8LHistogramSet* const tmp_histos,
- uint16_t* const histogram_symbols);
-
-// Returns the entropy for the symbols in the input array.
-// Also sets trivial_symbol to the code value, if the array has only one code
-// value. Otherwise, set it to VP8L_NON_TRIVIAL_SYM.
-double VP8LBitsEntropy(const uint32_t* const array, int n,
- uint32_t* const trivial_symbol);
-
-// Estimate how many bits the combined entropy of literals and distance
-// approximately maps to.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // WEBP_ENC_HISTOGRAM_H_
diff --git a/drivers/webp/enc/iterator.c b/drivers/webp/enc/iterator.c
deleted file mode 100644
index 99d960a547..0000000000
--- a/drivers/webp/enc/iterator.c
+++ /dev/null
@@ -1,456 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// VP8Iterator: block iterator
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <string.h>
-
-#include "./vp8enci.h"
-
-//------------------------------------------------------------------------------
-// VP8Iterator
-//------------------------------------------------------------------------------
-
-static void InitLeft(VP8EncIterator* const it) {
- it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] =
- (it->y_ > 0) ? 129 : 127;
- memset(it->y_left_, 129, 16);
- memset(it->u_left_, 129, 8);
- memset(it->v_left_, 129, 8);
- it->left_nz_[8] = 0;
-}
-
-static void InitTop(VP8EncIterator* const it) {
- const VP8Encoder* const enc = it->enc_;
- const size_t top_size = enc->mb_w_ * 16;
- memset(enc->y_top_, 127, 2 * top_size);
- memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_));
-}
-
-void VP8IteratorSetRow(VP8EncIterator* const it, int y) {
- VP8Encoder* const enc = it->enc_;
- it->x_ = 0;
- it->y_ = y;
- it->bw_ = &enc->parts_[y & (enc->num_parts_ - 1)];
- it->preds_ = enc->preds_ + y * 4 * enc->preds_w_;
- it->nz_ = enc->nz_;
- it->mb_ = enc->mb_info_ + y * enc->mb_w_;
- it->y_top_ = enc->y_top_;
- it->uv_top_ = enc->uv_top_;
- InitLeft(it);
-}
-
-void VP8IteratorReset(VP8EncIterator* const it) {
- VP8Encoder* const enc = it->enc_;
- VP8IteratorSetRow(it, 0);
- VP8IteratorSetCountDown(it, enc->mb_w_ * enc->mb_h_); // default
- InitTop(it);
- InitLeft(it);
- memset(it->bit_count_, 0, sizeof(it->bit_count_));
- it->do_trellis_ = 0;
-}
-
-void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down) {
- it->count_down_ = it->count_down0_ = count_down;
-}
-
-int VP8IteratorIsDone(const VP8EncIterator* const it) {
- return (it->count_down_ <= 0);
-}
-
-void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
- it->enc_ = enc;
- it->y_stride_ = enc->pic_->y_stride;
- it->uv_stride_ = enc->pic_->uv_stride;
- it->yuv_in_ = (uint8_t*)WEBP_ALIGN(it->yuv_mem_);
- it->yuv_out_ = it->yuv_in_ + YUV_SIZE_ENC;
- it->yuv_out2_ = it->yuv_out_ + YUV_SIZE_ENC;
- it->yuv_p_ = it->yuv_out2_ + YUV_SIZE_ENC;
- it->lf_stats_ = enc->lf_stats_;
- it->percent0_ = enc->percent_;
- it->y_left_ = (uint8_t*)WEBP_ALIGN(it->yuv_left_mem_ + 1);
- it->u_left_ = it->y_left_ + 16 + 16;
- it->v_left_ = it->u_left_ + 16;
- VP8IteratorReset(it);
-}
-
-int VP8IteratorProgress(const VP8EncIterator* const it, int delta) {
- VP8Encoder* const enc = it->enc_;
- if (delta && enc->pic_->progress_hook != NULL) {
- const int done = it->count_down0_ - it->count_down_;
- const int percent = (it->count_down0_ <= 0)
- ? it->percent0_
- : it->percent0_ + delta * done / it->count_down0_;
- return WebPReportProgress(enc->pic_, percent, &enc->percent_);
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Import the source samples into the cache. Takes care of replicating
-// boundary pixels if necessary.
-
-static WEBP_INLINE int MinSize(int a, int b) { return (a < b) ? a : b; }
-
-static void ImportBlock(const uint8_t* src, int src_stride,
- uint8_t* dst, int w, int h, int size) {
- int i;
- for (i = 0; i < h; ++i) {
- memcpy(dst, src, w);
- if (w < size) {
- memset(dst + w, dst[w - 1], size - w);
- }
- dst += BPS;
- src += src_stride;
- }
- for (i = h; i < size; ++i) {
- memcpy(dst, dst - BPS, size);
- dst += BPS;
- }
-}
-
-static void ImportLine(const uint8_t* src, int src_stride,
- uint8_t* dst, int len, int total_len) {
- int i;
- for (i = 0; i < len; ++i, src += src_stride) dst[i] = *src;
- for (; i < total_len; ++i) dst[i] = dst[len - 1];
-}
-
-void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) {
- const VP8Encoder* const enc = it->enc_;
- const int x = it->x_, y = it->y_;
- const WebPPicture* const pic = enc->pic_;
- const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16;
- const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8;
- const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8;
- const int w = MinSize(pic->width - x * 16, 16);
- const int h = MinSize(pic->height - y * 16, 16);
- const int uv_w = (w + 1) >> 1;
- const int uv_h = (h + 1) >> 1;
-
- ImportBlock(ysrc, pic->y_stride, it->yuv_in_ + Y_OFF_ENC, w, h, 16);
- ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF_ENC, uv_w, uv_h, 8);
- ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF_ENC, uv_w, uv_h, 8);
-
- if (tmp_32 == NULL) return;
-
- // Import source (uncompressed) samples into boundary.
- if (x == 0) {
- InitLeft(it);
- } else {
- if (y == 0) {
- it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] = 127;
- } else {
- it->y_left_[-1] = ysrc[- 1 - pic->y_stride];
- it->u_left_[-1] = usrc[- 1 - pic->uv_stride];
- it->v_left_[-1] = vsrc[- 1 - pic->uv_stride];
- }
- ImportLine(ysrc - 1, pic->y_stride, it->y_left_, h, 16);
- ImportLine(usrc - 1, pic->uv_stride, it->u_left_, uv_h, 8);
- ImportLine(vsrc - 1, pic->uv_stride, it->v_left_, uv_h, 8);
- }
-
- it->y_top_ = tmp_32 + 0;
- it->uv_top_ = tmp_32 + 16;
- if (y == 0) {
- memset(tmp_32, 127, 32 * sizeof(*tmp_32));
- } else {
- ImportLine(ysrc - pic->y_stride, 1, tmp_32, w, 16);
- ImportLine(usrc - pic->uv_stride, 1, tmp_32 + 16, uv_w, 8);
- ImportLine(vsrc - pic->uv_stride, 1, tmp_32 + 16 + 8, uv_w, 8);
- }
-}
-
-//------------------------------------------------------------------------------
-// Copy back the compressed samples into user space if requested.
-
-static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride,
- int w, int h) {
- while (h-- > 0) {
- memcpy(dst, src, w);
- dst += dst_stride;
- src += BPS;
- }
-}
-
-void VP8IteratorExport(const VP8EncIterator* const it) {
- const VP8Encoder* const enc = it->enc_;
- if (enc->config_->show_compressed) {
- const int x = it->x_, y = it->y_;
- const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC;
- const uint8_t* const usrc = it->yuv_out_ + U_OFF_ENC;
- const uint8_t* const vsrc = it->yuv_out_ + V_OFF_ENC;
- const WebPPicture* const pic = enc->pic_;
- uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16;
- uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8;
- uint8_t* const vdst = pic->v + (y * pic->uv_stride + x) * 8;
- int w = (pic->width - x * 16);
- int h = (pic->height - y * 16);
-
- if (w > 16) w = 16;
- if (h > 16) h = 16;
-
- // Luma plane
- ExportBlock(ysrc, ydst, pic->y_stride, w, h);
-
- { // U/V planes
- const int uv_w = (w + 1) >> 1;
- const int uv_h = (h + 1) >> 1;
- ExportBlock(usrc, udst, pic->uv_stride, uv_w, uv_h);
- ExportBlock(vsrc, vdst, pic->uv_stride, uv_w, uv_h);
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// Non-zero contexts setup/teardown
-
-// Nz bits:
-// 0 1 2 3 Y
-// 4 5 6 7
-// 8 9 10 11
-// 12 13 14 15
-// 16 17 U
-// 18 19
-// 20 21 V
-// 22 23
-// 24 DC-intra16
-
-// Convert packed context to byte array
-#define BIT(nz, n) (!!((nz) & (1 << (n))))
-
-void VP8IteratorNzToBytes(VP8EncIterator* const it) {
- const int tnz = it->nz_[0], lnz = it->nz_[-1];
- int* const top_nz = it->top_nz_;
- int* const left_nz = it->left_nz_;
-
- // Top-Y
- top_nz[0] = BIT(tnz, 12);
- top_nz[1] = BIT(tnz, 13);
- top_nz[2] = BIT(tnz, 14);
- top_nz[3] = BIT(tnz, 15);
- // Top-U
- top_nz[4] = BIT(tnz, 18);
- top_nz[5] = BIT(tnz, 19);
- // Top-V
- top_nz[6] = BIT(tnz, 22);
- top_nz[7] = BIT(tnz, 23);
- // DC
- top_nz[8] = BIT(tnz, 24);
-
- // left-Y
- left_nz[0] = BIT(lnz, 3);
- left_nz[1] = BIT(lnz, 7);
- left_nz[2] = BIT(lnz, 11);
- left_nz[3] = BIT(lnz, 15);
- // left-U
- left_nz[4] = BIT(lnz, 17);
- left_nz[5] = BIT(lnz, 19);
- // left-V
- left_nz[6] = BIT(lnz, 21);
- left_nz[7] = BIT(lnz, 23);
- // left-DC is special, iterated separately
-}
-
-void VP8IteratorBytesToNz(VP8EncIterator* const it) {
- uint32_t nz = 0;
- const int* const top_nz = it->top_nz_;
- const int* const left_nz = it->left_nz_;
- // top
- nz |= (top_nz[0] << 12) | (top_nz[1] << 13);
- nz |= (top_nz[2] << 14) | (top_nz[3] << 15);
- nz |= (top_nz[4] << 18) | (top_nz[5] << 19);
- nz |= (top_nz[6] << 22) | (top_nz[7] << 23);
- nz |= (top_nz[8] << 24); // we propagate the _top_ bit, esp. for intra4
- // left
- nz |= (left_nz[0] << 3) | (left_nz[1] << 7);
- nz |= (left_nz[2] << 11);
- nz |= (left_nz[4] << 17) | (left_nz[6] << 21);
-
- *it->nz_ = nz;
-}
-
-#undef BIT
-
-//------------------------------------------------------------------------------
-// Advance to the next position, doing the bookkeeping.
-
-void VP8IteratorSaveBoundary(VP8EncIterator* const it) {
- VP8Encoder* const enc = it->enc_;
- const int x = it->x_, y = it->y_;
- const uint8_t* const ysrc = it->yuv_out_ + Y_OFF_ENC;
- const uint8_t* const uvsrc = it->yuv_out_ + U_OFF_ENC;
- if (x < enc->mb_w_ - 1) { // left
- int i;
- for (i = 0; i < 16; ++i) {
- it->y_left_[i] = ysrc[15 + i * BPS];
- }
- for (i = 0; i < 8; ++i) {
- it->u_left_[i] = uvsrc[7 + i * BPS];
- it->v_left_[i] = uvsrc[15 + i * BPS];
- }
- // top-left (before 'top'!)
- it->y_left_[-1] = it->y_top_[15];
- it->u_left_[-1] = it->uv_top_[0 + 7];
- it->v_left_[-1] = it->uv_top_[8 + 7];
- }
- if (y < enc->mb_h_ - 1) { // top
- memcpy(it->y_top_, ysrc + 15 * BPS, 16);
- memcpy(it->uv_top_, uvsrc + 7 * BPS, 8 + 8);
- }
-}
-
-int VP8IteratorNext(VP8EncIterator* const it) {
- it->preds_ += 4;
- it->mb_ += 1;
- it->nz_ += 1;
- it->y_top_ += 16;
- it->uv_top_ += 16;
- it->x_ += 1;
- if (it->x_ == it->enc_->mb_w_) {
- VP8IteratorSetRow(it, ++it->y_);
- }
- return (0 < --it->count_down_);
-}
-
-//------------------------------------------------------------------------------
-// Helper function to set mode properties
-
-void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) {
- uint8_t* preds = it->preds_;
- int y;
- for (y = 0; y < 4; ++y) {
- memset(preds, mode, 4);
- preds += it->enc_->preds_w_;
- }
- it->mb_->type_ = 1;
-}
-
-void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes) {
- uint8_t* preds = it->preds_;
- int y;
- for (y = 4; y > 0; --y) {
- memcpy(preds, modes, 4 * sizeof(*modes));
- preds += it->enc_->preds_w_;
- modes += 4;
- }
- it->mb_->type_ = 0;
-}
-
-void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode) {
- it->mb_->uv_mode_ = mode;
-}
-
-void VP8SetSkip(const VP8EncIterator* const it, int skip) {
- it->mb_->skip_ = skip;
-}
-
-void VP8SetSegment(const VP8EncIterator* const it, int segment) {
- it->mb_->segment_ = segment;
-}
-
-//------------------------------------------------------------------------------
-// Intra4x4 sub-blocks iteration
-//
-// We store and update the boundary samples into an array of 37 pixels. They
-// are updated as we iterate and reconstructs each intra4x4 blocks in turn.
-// The position of the samples has the following snake pattern:
-//
-// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36 <- Top-right
-// --+-----------+-----------+-----------+-----------+
-// 15| 19| 23| 27| 31|
-// 14| 18| 22| 26| 30|
-// 13| 17| 21| 25| 29|
-// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28|
-// --+-----------+-----------+-----------+-----------+
-// 11| 15| 19| 23| 27|
-// 10| 14| 18| 22| 26|
-// 9| 13| 17| 21| 25|
-// 8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24|
-// --+-----------+-----------+-----------+-----------+
-// 7| 11| 15| 19| 23|
-// 6| 10| 14| 18| 22|
-// 5| 9| 13| 17| 21|
-// 4| 5 6 7 8| 9 10 11 12|13 14 15 16|17 18 19 20|
-// --+-----------+-----------+-----------+-----------+
-// 3| 7| 11| 15| 19|
-// 2| 6| 10| 14| 18|
-// 1| 5| 9| 13| 17|
-// 0| 1 2 3 4| 5 6 7 8| 9 10 11 12|13 14 15 16|
-// --+-----------+-----------+-----------+-----------+
-
-// Array to record the position of the top sample to pass to the prediction
-// functions in dsp.c.
-static const uint8_t VP8TopLeftI4[16] = {
- 17, 21, 25, 29,
- 13, 17, 21, 25,
- 9, 13, 17, 21,
- 5, 9, 13, 17
-};
-
-void VP8IteratorStartI4(VP8EncIterator* const it) {
- const VP8Encoder* const enc = it->enc_;
- int i;
-
- it->i4_ = 0; // first 4x4 sub-block
- it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0];
-
- // Import the boundary samples
- for (i = 0; i < 17; ++i) { // left
- it->i4_boundary_[i] = it->y_left_[15 - i];
- }
- for (i = 0; i < 16; ++i) { // top
- it->i4_boundary_[17 + i] = it->y_top_[i];
- }
- // top-right samples have a special case on the far right of the picture
- if (it->x_ < enc->mb_w_ - 1) {
- for (i = 16; i < 16 + 4; ++i) {
- it->i4_boundary_[17 + i] = it->y_top_[i];
- }
- } else { // else, replicate the last valid pixel four times
- for (i = 16; i < 16 + 4; ++i) {
- it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15];
- }
- }
- VP8IteratorNzToBytes(it); // import the non-zero context
-}
-
-int VP8IteratorRotateI4(VP8EncIterator* const it,
- const uint8_t* const yuv_out) {
- const uint8_t* const blk = yuv_out + VP8Scan[it->i4_];
- uint8_t* const top = it->i4_top_;
- int i;
-
- // Update the cache with 7 fresh samples
- for (i = 0; i <= 3; ++i) {
- top[-4 + i] = blk[i + 3 * BPS]; // store future top samples
- }
- if ((it->i4_ & 3) != 3) { // if not on the right sub-blocks #3, #7, #11, #15
- for (i = 0; i <= 2; ++i) { // store future left samples
- top[i] = blk[3 + (2 - i) * BPS];
- }
- } else { // else replicate top-right samples, as says the specs.
- for (i = 0; i <= 3; ++i) {
- top[i] = top[i + 4];
- }
- }
- // move pointers to next sub-block
- ++it->i4_;
- if (it->i4_ == 16) { // we're done
- return 0;
- }
-
- it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_];
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
diff --git a/drivers/webp/enc/near_lossless.c b/drivers/webp/enc/near_lossless.c
deleted file mode 100644
index f4ab91f571..0000000000
--- a/drivers/webp/enc/near_lossless.c
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Near-lossless image preprocessing adjusts pixel values to help
-// compressibility with a guarantee of maximum deviation between original and
-// resulting pixel values.
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-// Converted to C by Aleksander Kramarz (akramarz@google.com)
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "../dsp/lossless.h"
-#include "../utils/utils.h"
-#include "./vp8enci.h"
-
-#define MIN_DIM_FOR_NEAR_LOSSLESS 64
-#define MAX_LIMIT_BITS 5
-
-// Quantizes the value up or down to a multiple of 1<<bits (or to 255),
-// choosing the closer one, resolving ties using bankers' rounding.
-static int FindClosestDiscretized(int a, int bits) {
- const int mask = (1 << bits) - 1;
- const int biased = a + (mask >> 1) + ((a >> bits) & 1);
- assert(bits > 0);
- if (biased > 0xff) return 0xff;
- return biased & ~mask;
-}
-
-// Applies FindClosestDiscretized to all channels of pixel.
-static uint32_t ClosestDiscretizedArgb(uint32_t a, int bits) {
- return
- (FindClosestDiscretized(a >> 24, bits) << 24) |
- (FindClosestDiscretized((a >> 16) & 0xff, bits) << 16) |
- (FindClosestDiscretized((a >> 8) & 0xff, bits) << 8) |
- (FindClosestDiscretized(a & 0xff, bits));
-}
-
-// Checks if distance between corresponding channel values of pixels a and b
-// is within the given limit.
-static int IsNear(uint32_t a, uint32_t b, int limit) {
- int k;
- for (k = 0; k < 4; ++k) {
- const int delta =
- (int)((a >> (k * 8)) & 0xff) - (int)((b >> (k * 8)) & 0xff);
- if (delta >= limit || delta <= -limit) {
- return 0;
- }
- }
- return 1;
-}
-
-static int IsSmooth(const uint32_t* const prev_row,
- const uint32_t* const curr_row,
- const uint32_t* const next_row,
- int ix, int limit) {
- // Check that all pixels in 4-connected neighborhood are smooth.
- return (IsNear(curr_row[ix], curr_row[ix - 1], limit) &&
- IsNear(curr_row[ix], curr_row[ix + 1], limit) &&
- IsNear(curr_row[ix], prev_row[ix], limit) &&
- IsNear(curr_row[ix], next_row[ix], limit));
-}
-
-// Adjusts pixel values of image with given maximum error.
-static void NearLossless(int xsize, int ysize, uint32_t* argb,
- int limit_bits, uint32_t* copy_buffer) {
- int x, y;
- const int limit = 1 << limit_bits;
- uint32_t* prev_row = copy_buffer;
- uint32_t* curr_row = prev_row + xsize;
- uint32_t* next_row = curr_row + xsize;
- memcpy(copy_buffer, argb, xsize * 2 * sizeof(argb[0]));
-
- for (y = 1; y < ysize - 1; ++y) {
- uint32_t* const curr_argb_row = argb + y * xsize;
- uint32_t* const next_argb_row = curr_argb_row + xsize;
- memcpy(next_row, next_argb_row, xsize * sizeof(argb[0]));
- for (x = 1; x < xsize - 1; ++x) {
- if (!IsSmooth(prev_row, curr_row, next_row, x, limit)) {
- curr_argb_row[x] = ClosestDiscretizedArgb(curr_row[x], limit_bits);
- }
- }
- {
- // Three-way swap.
- uint32_t* const temp = prev_row;
- prev_row = curr_row;
- curr_row = next_row;
- next_row = temp;
- }
- }
-}
-
-int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality) {
- int i;
- uint32_t* const copy_buffer =
- (uint32_t*)WebPSafeMalloc(xsize * 3, sizeof(*copy_buffer));
- const int limit_bits = VP8LNearLosslessBits(quality);
- assert(argb != NULL);
- assert(limit_bits >= 0);
- assert(limit_bits <= MAX_LIMIT_BITS);
- if (copy_buffer == NULL) {
- return 0;
- }
- // For small icon images, don't attempt to apply near-lossless compression.
- if (xsize < MIN_DIM_FOR_NEAR_LOSSLESS && ysize < MIN_DIM_FOR_NEAR_LOSSLESS) {
- WebPSafeFree(copy_buffer);
- return 1;
- }
-
- for (i = limit_bits; i != 0; --i) {
- NearLossless(xsize, ysize, argb, i, copy_buffer);
- }
- WebPSafeFree(copy_buffer);
- return 1;
-}
diff --git a/drivers/webp/enc/picture.c b/drivers/webp/enc/picture.c
deleted file mode 100644
index d9befbc47d..0000000000
--- a/drivers/webp/enc/picture.c
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebPPicture class basis
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "./vp8enci.h"
-#include "../dsp/dsp.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// WebPPicture
-//------------------------------------------------------------------------------
-
-static int DummyWriter(const uint8_t* data, size_t data_size,
- const WebPPicture* const picture) {
- // The following are to prevent 'unused variable' error message.
- (void)data;
- (void)data_size;
- (void)picture;
- return 1;
-}
-
-int WebPPictureInitInternal(WebPPicture* picture, int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
- return 0; // caller/system version mismatch!
- }
- if (picture != NULL) {
- memset(picture, 0, sizeof(*picture));
- picture->writer = DummyWriter;
- WebPEncodingSetError(picture, VP8_ENC_OK);
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-static void WebPPictureResetBufferARGB(WebPPicture* const picture) {
- picture->memory_argb_ = NULL;
- picture->argb = NULL;
- picture->argb_stride = 0;
-}
-
-static void WebPPictureResetBufferYUVA(WebPPicture* const picture) {
- picture->memory_ = NULL;
- picture->y = picture->u = picture->v = picture->a = NULL;
- picture->y_stride = picture->uv_stride = 0;
- picture->a_stride = 0;
-}
-
-void WebPPictureResetBuffers(WebPPicture* const picture) {
- WebPPictureResetBufferARGB(picture);
- WebPPictureResetBufferYUVA(picture);
-}
-
-int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height) {
- void* memory;
- const uint64_t argb_size = (uint64_t)width * height;
-
- assert(picture != NULL);
-
- WebPSafeFree(picture->memory_argb_);
- WebPPictureResetBufferARGB(picture);
-
- if (width <= 0 || height <= 0) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
- }
- // allocate a new buffer.
- memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb));
- if (memory == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
- // TODO(skal): align plane to cache line?
- picture->memory_argb_ = memory;
- picture->argb = (uint32_t*)memory;
- picture->argb_stride = width;
- return 1;
-}
-
-int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) {
- const WebPEncCSP uv_csp = picture->colorspace & WEBP_CSP_UV_MASK;
- const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT;
- const int y_stride = width;
- const int uv_width = (width + 1) >> 1;
- const int uv_height = (height + 1) >> 1;
- const int uv_stride = uv_width;
- int a_width, a_stride;
- uint64_t y_size, uv_size, a_size, total_size;
- uint8_t* mem;
-
- assert(picture != NULL);
-
- WebPSafeFree(picture->memory_);
- WebPPictureResetBufferYUVA(picture);
-
- if (uv_csp != WEBP_YUV420) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
- }
-
- // alpha
- a_width = has_alpha ? width : 0;
- a_stride = a_width;
- y_size = (uint64_t)y_stride * height;
- uv_size = (uint64_t)uv_stride * uv_height;
- a_size = (uint64_t)a_stride * height;
-
- total_size = y_size + a_size + 2 * uv_size;
-
- // Security and validation checks
- if (width <= 0 || height <= 0 || // luma/alpha param error
- uv_width < 0 || uv_height < 0) { // u/v param error
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
- }
- // allocate a new buffer.
- mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem));
- if (mem == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
-
- // From now on, we're in the clear, we can no longer fail...
- picture->memory_ = (void*)mem;
- picture->y_stride = y_stride;
- picture->uv_stride = uv_stride;
- picture->a_stride = a_stride;
-
- // TODO(skal): we could align the y/u/v planes and adjust stride.
- picture->y = mem;
- mem += y_size;
-
- picture->u = mem;
- mem += uv_size;
- picture->v = mem;
- mem += uv_size;
-
- if (a_size > 0) {
- picture->a = mem;
- mem += a_size;
- }
- (void)mem; // makes the static analyzer happy
- return 1;
-}
-
-int WebPPictureAlloc(WebPPicture* picture) {
- if (picture != NULL) {
- const int width = picture->width;
- const int height = picture->height;
-
- WebPPictureFree(picture); // erase previous buffer
-
- if (!picture->use_argb) {
- return WebPPictureAllocYUVA(picture, width, height);
- } else {
- return WebPPictureAllocARGB(picture, width, height);
- }
- }
- return 1;
-}
-
-void WebPPictureFree(WebPPicture* picture) {
- if (picture != NULL) {
- WebPSafeFree(picture->memory_);
- WebPSafeFree(picture->memory_argb_);
- WebPPictureResetBuffers(picture);
- }
-}
-
-//------------------------------------------------------------------------------
-// WebPMemoryWriter: Write-to-memory
-
-void WebPMemoryWriterInit(WebPMemoryWriter* writer) {
- writer->mem = NULL;
- writer->size = 0;
- writer->max_size = 0;
-}
-
-int WebPMemoryWrite(const uint8_t* data, size_t data_size,
- const WebPPicture* picture) {
- WebPMemoryWriter* const w = (WebPMemoryWriter*)picture->custom_ptr;
- uint64_t next_size;
- if (w == NULL) {
- return 1;
- }
- next_size = (uint64_t)w->size + data_size;
- if (next_size > w->max_size) {
- uint8_t* new_mem;
- uint64_t next_max_size = 2ULL * w->max_size;
- if (next_max_size < next_size) next_max_size = next_size;
- if (next_max_size < 8192ULL) next_max_size = 8192ULL;
- new_mem = (uint8_t*)WebPSafeMalloc(next_max_size, 1);
- if (new_mem == NULL) {
- return 0;
- }
- if (w->size > 0) {
- memcpy(new_mem, w->mem, w->size);
- }
- WebPSafeFree(w->mem);
- w->mem = new_mem;
- // down-cast is ok, thanks to WebPSafeMalloc
- w->max_size = (size_t)next_max_size;
- }
- if (data_size > 0) {
- memcpy(w->mem + w->size, data, data_size);
- w->size += data_size;
- }
- return 1;
-}
-
-void WebPMemoryWriterClear(WebPMemoryWriter* writer) {
- if (writer != NULL) {
- WebPSafeFree(writer->mem);
- writer->mem = NULL;
- writer->size = 0;
- writer->max_size = 0;
- }
-}
-
-//------------------------------------------------------------------------------
-// Simplest high-level calls:
-
-typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int);
-
-static size_t Encode(const uint8_t* rgba, int width, int height, int stride,
- Importer import, float quality_factor, int lossless,
- uint8_t** output) {
- WebPPicture pic;
- WebPConfig config;
- WebPMemoryWriter wrt;
- int ok;
-
- if (output == NULL) return 0;
-
- if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality_factor) ||
- !WebPPictureInit(&pic)) {
- return 0; // shouldn't happen, except if system installation is broken
- }
-
- config.lossless = !!lossless;
- pic.use_argb = !!lossless;
- pic.width = width;
- pic.height = height;
- pic.writer = WebPMemoryWrite;
- pic.custom_ptr = &wrt;
- WebPMemoryWriterInit(&wrt);
-
- ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic);
- WebPPictureFree(&pic);
- if (!ok) {
- WebPMemoryWriterClear(&wrt);
- *output = NULL;
- return 0;
- }
- *output = wrt.mem;
- return wrt.size;
-}
-
-#define ENCODE_FUNC(NAME, IMPORTER) \
-size_t NAME(const uint8_t* in, int w, int h, int bps, float q, \
- uint8_t** out) { \
- return Encode(in, w, h, bps, IMPORTER, q, 0, out); \
-}
-
-ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB)
-ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR)
-ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA)
-ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA)
-
-#undef ENCODE_FUNC
-
-#define LOSSLESS_DEFAULT_QUALITY 70.
-#define LOSSLESS_ENCODE_FUNC(NAME, IMPORTER) \
-size_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) { \
- return Encode(in, w, h, bps, IMPORTER, LOSSLESS_DEFAULT_QUALITY, 1, out); \
-}
-
-LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB)
-LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR)
-LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA)
-LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA)
-
-#undef LOSSLESS_ENCODE_FUNC
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/picture_csp.c b/drivers/webp/enc/picture_csp.c
deleted file mode 100644
index 607a6240b0..0000000000
--- a/drivers/webp/enc/picture_csp.c
+++ /dev/null
@@ -1,1168 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebPPicture utils for colorspace conversion
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include "./vp8enci.h"
-#include "../utils/random.h"
-#include "../utils/utils.h"
-#include "../dsp/yuv.h"
-
-// Uncomment to disable gamma-compression during RGB->U/V averaging
-#define USE_GAMMA_COMPRESSION
-
-// If defined, use table to compute x / alpha.
-#define USE_INVERSE_ALPHA_TABLE
-
-static const union {
- uint32_t argb;
- uint8_t bytes[4];
-} test_endian = { 0xff000000u };
-#define ALPHA_IS_LAST (test_endian.bytes[3] == 0xff)
-
-//------------------------------------------------------------------------------
-// Detection of non-trivial transparency
-
-// Returns true if alpha[] has non-0xff values.
-static int CheckNonOpaque(const uint8_t* alpha, int width, int height,
- int x_step, int y_step) {
- if (alpha == NULL) return 0;
- while (height-- > 0) {
- int x;
- for (x = 0; x < width * x_step; x += x_step) {
- if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time.
- }
- alpha += y_step;
- }
- return 0;
-}
-
-// Checking for the presence of non-opaque alpha.
-int WebPPictureHasTransparency(const WebPPicture* picture) {
- if (picture == NULL) return 0;
- if (!picture->use_argb) {
- return CheckNonOpaque(picture->a, picture->width, picture->height,
- 1, picture->a_stride);
- } else {
- int x, y;
- const uint32_t* argb = picture->argb;
- if (argb == NULL) return 0;
- for (y = 0; y < picture->height; ++y) {
- for (x = 0; x < picture->width; ++x) {
- if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff
- }
- argb += picture->argb_stride;
- }
- }
- return 0;
-}
-
-//------------------------------------------------------------------------------
-// Code for gamma correction
-
-#if defined(USE_GAMMA_COMPRESSION)
-
-// gamma-compensates loss of resolution during chroma subsampling
-#define kGamma 0.80 // for now we use a different gamma value than kGammaF
-#define kGammaFix 12 // fixed-point precision for linear values
-#define kGammaScale ((1 << kGammaFix) - 1)
-#define kGammaTabFix 7 // fixed-point fractional bits precision
-#define kGammaTabScale (1 << kGammaTabFix)
-#define kGammaTabRounder (kGammaTabScale >> 1)
-#define kGammaTabSize (1 << (kGammaFix - kGammaTabFix))
-
-static int kLinearToGammaTab[kGammaTabSize + 1];
-static uint16_t kGammaToLinearTab[256];
-static volatile int kGammaTablesOk = 0;
-
-static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) {
- if (!kGammaTablesOk) {
- int v;
- const double scale = (double)(1 << kGammaTabFix) / kGammaScale;
- const double norm = 1. / 255.;
- for (v = 0; v <= 255; ++v) {
- kGammaToLinearTab[v] =
- (uint16_t)(pow(norm * v, kGamma) * kGammaScale + .5);
- }
- for (v = 0; v <= kGammaTabSize; ++v) {
- kLinearToGammaTab[v] = (int)(255. * pow(scale * v, 1. / kGamma) + .5);
- }
- kGammaTablesOk = 1;
- }
-}
-
-static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) {
- return kGammaToLinearTab[v];
-}
-
-static WEBP_INLINE int Interpolate(int v) {
- const int tab_pos = v >> (kGammaTabFix + 2); // integer part
- const int x = v & ((kGammaTabScale << 2) - 1); // fractional part
- const int v0 = kLinearToGammaTab[tab_pos];
- const int v1 = kLinearToGammaTab[tab_pos + 1];
- const int y = v1 * x + v0 * ((kGammaTabScale << 2) - x); // interpolate
- assert(tab_pos + 1 < kGammaTabSize + 1);
- return y;
-}
-
-// Convert a linear value 'v' to YUV_FIX+2 fixed-point precision
-// U/V value, suitable for RGBToU/V calls.
-static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) {
- const int y = Interpolate(base_value << shift); // final uplifted value
- return (y + kGammaTabRounder) >> kGammaTabFix; // descale
-}
-
-#else
-
-static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) {}
-static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; }
-static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) {
- return (int)(base_value << shift);
-}
-
-#endif // USE_GAMMA_COMPRESSION
-
-//------------------------------------------------------------------------------
-// RGB -> YUV conversion
-
-static int RGBToY(int r, int g, int b, VP8Random* const rg) {
- return (rg == NULL) ? VP8RGBToY(r, g, b, YUV_HALF)
- : VP8RGBToY(r, g, b, VP8RandomBits(rg, YUV_FIX));
-}
-
-static int RGBToU(int r, int g, int b, VP8Random* const rg) {
- return (rg == NULL) ? VP8RGBToU(r, g, b, YUV_HALF << 2)
- : VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2));
-}
-
-static int RGBToV(int r, int g, int b, VP8Random* const rg) {
- return (rg == NULL) ? VP8RGBToV(r, g, b, YUV_HALF << 2)
- : VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2));
-}
-
-//------------------------------------------------------------------------------
-// Smart RGB->YUV conversion
-
-static const int kNumIterations = 6;
-static const int kMinDimensionIterativeConversion = 4;
-
-// We could use SFIX=0 and only uint8_t for fixed_y_t, but it produces some
-// banding sometimes. Better use extra precision.
-#define SFIX 2 // fixed-point precision of RGB and Y/W
-typedef int16_t fixed_t; // signed type with extra SFIX precision for UV
-typedef uint16_t fixed_y_t; // unsigned type with extra SFIX precision for W
-
-#define SHALF (1 << SFIX >> 1)
-#define MAX_Y_T ((256 << SFIX) - 1)
-#define SROUNDER (1 << (YUV_FIX + SFIX - 1))
-
-#if defined(USE_GAMMA_COMPRESSION)
-
-// float variant of gamma-correction
-// We use tables of different size and precision, along with a 'real-world'
-// Gamma value close to ~2.
-#define kGammaF 2.2
-static float kGammaToLinearTabF[MAX_Y_T + 1]; // size scales with Y_FIX
-static float kLinearToGammaTabF[kGammaTabSize + 2];
-static volatile int kGammaTablesFOk = 0;
-
-static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {
- if (!kGammaTablesFOk) {
- int v;
- const double norm = 1. / MAX_Y_T;
- const double scale = 1. / kGammaTabSize;
- for (v = 0; v <= MAX_Y_T; ++v) {
- kGammaToLinearTabF[v] = (float)pow(norm * v, kGammaF);
- }
- for (v = 0; v <= kGammaTabSize; ++v) {
- kLinearToGammaTabF[v] = (float)(MAX_Y_T * pow(scale * v, 1. / kGammaF));
- }
- // to prevent small rounding errors to cause read-overflow:
- kLinearToGammaTabF[kGammaTabSize + 1] = kLinearToGammaTabF[kGammaTabSize];
- kGammaTablesFOk = 1;
- }
-}
-
-static WEBP_INLINE float GammaToLinearF(int v) {
- return kGammaToLinearTabF[v];
-}
-
-static WEBP_INLINE int LinearToGammaF(float value) {
- const float v = value * kGammaTabSize;
- const int tab_pos = (int)v;
- const float x = v - (float)tab_pos; // fractional part
- const float v0 = kLinearToGammaTabF[tab_pos + 0];
- const float v1 = kLinearToGammaTabF[tab_pos + 1];
- const float y = v1 * x + v0 * (1.f - x); // interpolate
- return (int)(y + .5);
-}
-
-#else
-
-static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {}
-static WEBP_INLINE float GammaToLinearF(int v) {
- const float norm = 1.f / MAX_Y_T;
- return norm * v;
-}
-static WEBP_INLINE int LinearToGammaF(float value) {
- return (int)(MAX_Y_T * value + .5);
-}
-
-#endif // USE_GAMMA_COMPRESSION
-
-//------------------------------------------------------------------------------
-
-static uint8_t clip_8b(fixed_t v) {
- return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u;
-}
-
-static fixed_y_t clip_y(int y) {
- return (!(y & ~MAX_Y_T)) ? (fixed_y_t)y : (y < 0) ? 0 : MAX_Y_T;
-}
-
-//------------------------------------------------------------------------------
-
-static int RGBToGray(int r, int g, int b) {
- const int luma = 19595 * r + 38470 * g + 7471 * b + YUV_HALF;
- return (luma >> YUV_FIX);
-}
-
-static float RGBToGrayF(float r, float g, float b) {
- return 0.299f * r + 0.587f * g + 0.114f * b;
-}
-
-static int ScaleDown(int a, int b, int c, int d) {
- const float A = GammaToLinearF(a);
- const float B = GammaToLinearF(b);
- const float C = GammaToLinearF(c);
- const float D = GammaToLinearF(d);
- return LinearToGammaF(0.25f * (A + B + C + D));
-}
-
-static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int len) {
- while (len-- > 0) {
- const float R = GammaToLinearF(src[0]);
- const float G = GammaToLinearF(src[1]);
- const float B = GammaToLinearF(src[2]);
- const float Y = RGBToGrayF(R, G, B);
- *dst++ = (fixed_y_t)LinearToGammaF(Y);
- src += 3;
- }
-}
-
-static int UpdateChroma(const fixed_y_t* src1,
- const fixed_y_t* src2,
- fixed_t* dst, fixed_y_t* tmp, int len) {
- int diff = 0;
- while (len--> 0) {
- const int r = ScaleDown(src1[0], src1[3], src2[0], src2[3]);
- const int g = ScaleDown(src1[1], src1[4], src2[1], src2[4]);
- const int b = ScaleDown(src1[2], src1[5], src2[2], src2[5]);
- const int W = RGBToGray(r, g, b);
- const int r_avg = (src1[0] + src1[3] + src2[0] + src2[3] + 2) >> 2;
- const int g_avg = (src1[1] + src1[4] + src2[1] + src2[4] + 2) >> 2;
- const int b_avg = (src1[2] + src1[5] + src2[2] + src2[5] + 2) >> 2;
- dst[0] = (fixed_t)(r - W);
- dst[1] = (fixed_t)(g - W);
- dst[2] = (fixed_t)(b - W);
- dst += 3;
- src1 += 6;
- src2 += 6;
- if (tmp != NULL) {
- tmp[0] = tmp[1] = clip_y(W);
- tmp += 2;
- }
- diff += abs(RGBToGray(r_avg, g_avg, b_avg) - W);
- }
- return diff;
-}
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE int Filter(const fixed_t* const A, const fixed_t* const B,
- int rightwise) {
- int v;
- if (!rightwise) {
- v = (A[0] * 9 + A[-3] * 3 + B[0] * 3 + B[-3]);
- } else {
- v = (A[0] * 9 + A[+3] * 3 + B[0] * 3 + B[+3]);
- }
- return (v + 8) >> 4;
-}
-
-static WEBP_INLINE int Filter2(int A, int B) { return (A * 3 + B + 2) >> 2; }
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE fixed_y_t UpLift(uint8_t a) { // 8bit -> SFIX
- return ((fixed_y_t)a << SFIX) | SHALF;
-}
-
-static void ImportOneRow(const uint8_t* const r_ptr,
- const uint8_t* const g_ptr,
- const uint8_t* const b_ptr,
- int step,
- int pic_width,
- fixed_y_t* const dst) {
- int i;
- for (i = 0; i < pic_width; ++i) {
- const int off = i * step;
- dst[3 * i + 0] = UpLift(r_ptr[off]);
- dst[3 * i + 1] = UpLift(g_ptr[off]);
- dst[3 * i + 2] = UpLift(b_ptr[off]);
- }
- if (pic_width & 1) { // replicate rightmost pixel
- memcpy(dst + 3 * pic_width, dst + 3 * (pic_width - 1), 3 * sizeof(*dst));
- }
-}
-
-static void InterpolateTwoRows(const fixed_y_t* const best_y,
- const fixed_t* const prev_uv,
- const fixed_t* const cur_uv,
- const fixed_t* const next_uv,
- int w,
- fixed_y_t* const out1,
- fixed_y_t* const out2) {
- int i, k;
- { // special boundary case for i==0
- const int W0 = best_y[0];
- const int W1 = best_y[w];
- for (k = 0; k <= 2; ++k) {
- out1[k] = clip_y(Filter2(cur_uv[k], prev_uv[k]) + W0);
- out2[k] = clip_y(Filter2(cur_uv[k], next_uv[k]) + W1);
- }
- }
- for (i = 1; i < w - 1; ++i) {
- const int W0 = best_y[i + 0];
- const int W1 = best_y[i + w];
- const int off = 3 * (i >> 1);
- for (k = 0; k <= 2; ++k) {
- const int tmp0 = Filter(cur_uv + off + k, prev_uv + off + k, i & 1);
- const int tmp1 = Filter(cur_uv + off + k, next_uv + off + k, i & 1);
- out1[3 * i + k] = clip_y(tmp0 + W0);
- out2[3 * i + k] = clip_y(tmp1 + W1);
- }
- }
- { // special boundary case for i == w - 1
- const int W0 = best_y[i + 0];
- const int W1 = best_y[i + w];
- const int off = 3 * (i >> 1);
- for (k = 0; k <= 2; ++k) {
- out1[3 * i + k] = clip_y(Filter2(cur_uv[off + k], prev_uv[off + k]) + W0);
- out2[3 * i + k] = clip_y(Filter2(cur_uv[off + k], next_uv[off + k]) + W1);
- }
- }
-}
-
-static WEBP_INLINE uint8_t ConvertRGBToY(int r, int g, int b) {
- const int luma = 16839 * r + 33059 * g + 6420 * b + SROUNDER;
- return clip_8b(16 + (luma >> (YUV_FIX + SFIX)));
-}
-
-static WEBP_INLINE uint8_t ConvertRGBToU(int r, int g, int b) {
- const int u = -9719 * r - 19081 * g + 28800 * b + SROUNDER;
- return clip_8b(128 + (u >> (YUV_FIX + SFIX)));
-}
-
-static WEBP_INLINE uint8_t ConvertRGBToV(int r, int g, int b) {
- const int v = +28800 * r - 24116 * g - 4684 * b + SROUNDER;
- return clip_8b(128 + (v >> (YUV_FIX + SFIX)));
-}
-
-static int ConvertWRGBToYUV(const fixed_y_t* const best_y,
- const fixed_t* const best_uv,
- WebPPicture* const picture) {
- int i, j;
- const int w = (picture->width + 1) & ~1;
- const int h = (picture->height + 1) & ~1;
- const int uv_w = w >> 1;
- const int uv_h = h >> 1;
- for (j = 0; j < picture->height; ++j) {
- for (i = 0; i < picture->width; ++i) {
- const int off = 3 * ((i >> 1) + (j >> 1) * uv_w);
- const int off2 = i + j * picture->y_stride;
- const int W = best_y[i + j * w];
- const int r = best_uv[off + 0] + W;
- const int g = best_uv[off + 1] + W;
- const int b = best_uv[off + 2] + W;
- picture->y[off2] = ConvertRGBToY(r, g, b);
- }
- }
- for (j = 0; j < uv_h; ++j) {
- uint8_t* const dst_u = picture->u + j * picture->uv_stride;
- uint8_t* const dst_v = picture->v + j * picture->uv_stride;
- for (i = 0; i < uv_w; ++i) {
- const int off = 3 * (i + j * uv_w);
- const int r = best_uv[off + 0];
- const int g = best_uv[off + 1];
- const int b = best_uv[off + 2];
- dst_u[i] = ConvertRGBToU(r, g, b);
- dst_v[i] = ConvertRGBToV(r, g, b);
- }
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Main function
-
-#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T)))
-
-static int PreprocessARGB(const uint8_t* const r_ptr,
- const uint8_t* const g_ptr,
- const uint8_t* const b_ptr,
- int step, int rgb_stride,
- WebPPicture* const picture) {
- // we expand the right/bottom border if needed
- const int w = (picture->width + 1) & ~1;
- const int h = (picture->height + 1) & ~1;
- const int uv_w = w >> 1;
- const int uv_h = h >> 1;
- int i, j, iter;
-
- // TODO(skal): allocate one big memory chunk. But for now, it's easier
- // for valgrind debugging to have several chunks.
- fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch
- fixed_y_t* const best_y = SAFE_ALLOC(w, h, fixed_y_t);
- fixed_y_t* const target_y = SAFE_ALLOC(w, h, fixed_y_t);
- fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t);
- fixed_t* const best_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
- fixed_t* const target_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
- fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t);
- int ok;
- int diff_sum = 0;
- const int first_diff_threshold = (int)(2.5 * w * h);
- const int min_improvement = 5; // stop if improvement is below this %
- const int min_first_improvement = 80;
-
- if (best_y == NULL || best_uv == NULL ||
- target_y == NULL || target_uv == NULL ||
- best_rgb_y == NULL || best_rgb_uv == NULL ||
- tmp_buffer == NULL) {
- ok = WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- goto End;
- }
- assert(picture->width >= kMinDimensionIterativeConversion);
- assert(picture->height >= kMinDimensionIterativeConversion);
-
- // Import RGB samples to W/RGB representation.
- for (j = 0; j < picture->height; j += 2) {
- const int is_last_row = (j == picture->height - 1);
- fixed_y_t* const src1 = tmp_buffer;
- fixed_y_t* const src2 = tmp_buffer + 3 * w;
- const int off1 = j * rgb_stride;
- const int off2 = off1 + rgb_stride;
- const int uv_off = (j >> 1) * 3 * uv_w;
- fixed_y_t* const dst_y = best_y + j * w;
-
- // prepare two rows of input
- ImportOneRow(r_ptr + off1, g_ptr + off1, b_ptr + off1,
- step, picture->width, src1);
- if (!is_last_row) {
- ImportOneRow(r_ptr + off2, g_ptr + off2, b_ptr + off2,
- step, picture->width, src2);
- } else {
- memcpy(src2, src1, 3 * w * sizeof(*src2));
- }
- UpdateW(src1, target_y + (j + 0) * w, w);
- UpdateW(src2, target_y + (j + 1) * w, w);
- diff_sum += UpdateChroma(src1, src2, target_uv + uv_off, dst_y, uv_w);
- memcpy(best_uv + uv_off, target_uv + uv_off, 3 * uv_w * sizeof(*best_uv));
- memcpy(dst_y + w, dst_y, w * sizeof(*dst_y));
- }
-
- // Iterate and resolve clipping conflicts.
- for (iter = 0; iter < kNumIterations; ++iter) {
- int k;
- const fixed_t* cur_uv = best_uv;
- const fixed_t* prev_uv = best_uv;
- const int old_diff_sum = diff_sum;
- diff_sum = 0;
- for (j = 0; j < h; j += 2) {
- fixed_y_t* const src1 = tmp_buffer;
- fixed_y_t* const src2 = tmp_buffer + 3 * w;
- {
- const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0);
- InterpolateTwoRows(best_y + j * w, prev_uv, cur_uv, next_uv,
- w, src1, src2);
- prev_uv = cur_uv;
- cur_uv = next_uv;
- }
-
- UpdateW(src1, best_rgb_y + 0 * w, w);
- UpdateW(src2, best_rgb_y + 1 * w, w);
- diff_sum += UpdateChroma(src1, src2, best_rgb_uv, NULL, uv_w);
-
- // update two rows of Y and one row of RGB
- for (i = 0; i < 2 * w; ++i) {
- const int off = i + j * w;
- const int diff_y = target_y[off] - best_rgb_y[i];
- const int new_y = (int)best_y[off] + diff_y;
- best_y[off] = clip_y(new_y);
- }
- for (i = 0; i < uv_w; ++i) {
- const int off = 3 * (i + (j >> 1) * uv_w);
- int W;
- for (k = 0; k <= 2; ++k) {
- const int diff_uv = (int)target_uv[off + k] - best_rgb_uv[3 * i + k];
- best_uv[off + k] += diff_uv;
- }
- W = RGBToGray(best_uv[off + 0], best_uv[off + 1], best_uv[off + 2]);
- for (k = 0; k <= 2; ++k) {
- best_uv[off + k] -= W;
- }
- }
- }
- // test exit condition
- if (diff_sum > 0) {
- const int improvement = 100 * abs(diff_sum - old_diff_sum) / diff_sum;
- // Check if first iteration gave good result already, without a large
- // jump of improvement (otherwise it means we need to try few extra
- // iterations, just to be sure).
- if (iter == 0 && diff_sum < first_diff_threshold &&
- improvement < min_first_improvement) {
- break;
- }
- // then, check if improvement is stalling.
- if (improvement < min_improvement) {
- break;
- }
- } else {
- break;
- }
- }
-
- // final reconstruction
- ok = ConvertWRGBToYUV(best_y, best_uv, picture);
-
- End:
- WebPSafeFree(best_y);
- WebPSafeFree(best_uv);
- WebPSafeFree(target_y);
- WebPSafeFree(target_uv);
- WebPSafeFree(best_rgb_y);
- WebPSafeFree(best_rgb_uv);
- WebPSafeFree(tmp_buffer);
- return ok;
-}
-#undef SAFE_ALLOC
-
-//------------------------------------------------------------------------------
-// "Fast" regular RGB->YUV
-
-#define SUM4(ptr, step) LinearToGamma( \
- GammaToLinear((ptr)[0]) + \
- GammaToLinear((ptr)[(step)]) + \
- GammaToLinear((ptr)[rgb_stride]) + \
- GammaToLinear((ptr)[rgb_stride + (step)]), 0) \
-
-#define SUM2(ptr) \
- LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1)
-
-#define SUM2ALPHA(ptr) ((ptr)[0] + (ptr)[rgb_stride])
-#define SUM4ALPHA(ptr) (SUM2ALPHA(ptr) + SUM2ALPHA((ptr) + 4))
-
-#if defined(USE_INVERSE_ALPHA_TABLE)
-
-static const int kAlphaFix = 19;
-// Following table is (1 << kAlphaFix) / a. The (v * kInvAlpha[a]) >> kAlphaFix
-// formula is then equal to v / a in most (99.6%) cases. Note that this table
-// and constant are adjusted very tightly to fit 32b arithmetic.
-// In particular, they use the fact that the operands for 'v / a' are actually
-// derived as v = (a0.p0 + a1.p1 + a2.p2 + a3.p3) and a = a0 + a1 + a2 + a3
-// with ai in [0..255] and pi in [0..1<<kGammaFix). The constraint to avoid
-// overflow is: kGammaFix + kAlphaFix <= 31.
-static const uint32_t kInvAlpha[4 * 0xff + 1] = {
- 0, /* alpha = 0 */
- 524288, 262144, 174762, 131072, 104857, 87381, 74898, 65536,
- 58254, 52428, 47662, 43690, 40329, 37449, 34952, 32768,
- 30840, 29127, 27594, 26214, 24966, 23831, 22795, 21845,
- 20971, 20164, 19418, 18724, 18078, 17476, 16912, 16384,
- 15887, 15420, 14979, 14563, 14169, 13797, 13443, 13107,
- 12787, 12483, 12192, 11915, 11650, 11397, 11155, 10922,
- 10699, 10485, 10280, 10082, 9892, 9709, 9532, 9362,
- 9198, 9039, 8886, 8738, 8594, 8456, 8322, 8192,
- 8065, 7943, 7825, 7710, 7598, 7489, 7384, 7281,
- 7182, 7084, 6990, 6898, 6808, 6721, 6636, 6553,
- 6472, 6393, 6316, 6241, 6168, 6096, 6026, 5957,
- 5890, 5825, 5761, 5698, 5637, 5577, 5518, 5461,
- 5405, 5349, 5295, 5242, 5190, 5140, 5090, 5041,
- 4993, 4946, 4899, 4854, 4809, 4766, 4723, 4681,
- 4639, 4599, 4559, 4519, 4481, 4443, 4405, 4369,
- 4332, 4297, 4262, 4228, 4194, 4161, 4128, 4096,
- 4064, 4032, 4002, 3971, 3942, 3912, 3883, 3855,
- 3826, 3799, 3771, 3744, 3718, 3692, 3666, 3640,
- 3615, 3591, 3566, 3542, 3518, 3495, 3472, 3449,
- 3426, 3404, 3382, 3360, 3339, 3318, 3297, 3276,
- 3256, 3236, 3216, 3196, 3177, 3158, 3139, 3120,
- 3102, 3084, 3066, 3048, 3030, 3013, 2995, 2978,
- 2962, 2945, 2928, 2912, 2896, 2880, 2864, 2849,
- 2833, 2818, 2803, 2788, 2774, 2759, 2744, 2730,
- 2716, 2702, 2688, 2674, 2661, 2647, 2634, 2621,
- 2608, 2595, 2582, 2570, 2557, 2545, 2532, 2520,
- 2508, 2496, 2484, 2473, 2461, 2449, 2438, 2427,
- 2416, 2404, 2394, 2383, 2372, 2361, 2351, 2340,
- 2330, 2319, 2309, 2299, 2289, 2279, 2269, 2259,
- 2250, 2240, 2231, 2221, 2212, 2202, 2193, 2184,
- 2175, 2166, 2157, 2148, 2139, 2131, 2122, 2114,
- 2105, 2097, 2088, 2080, 2072, 2064, 2056, 2048,
- 2040, 2032, 2024, 2016, 2008, 2001, 1993, 1985,
- 1978, 1971, 1963, 1956, 1949, 1941, 1934, 1927,
- 1920, 1913, 1906, 1899, 1892, 1885, 1879, 1872,
- 1865, 1859, 1852, 1846, 1839, 1833, 1826, 1820,
- 1814, 1807, 1801, 1795, 1789, 1783, 1777, 1771,
- 1765, 1759, 1753, 1747, 1741, 1736, 1730, 1724,
- 1718, 1713, 1707, 1702, 1696, 1691, 1685, 1680,
- 1675, 1669, 1664, 1659, 1653, 1648, 1643, 1638,
- 1633, 1628, 1623, 1618, 1613, 1608, 1603, 1598,
- 1593, 1588, 1583, 1579, 1574, 1569, 1565, 1560,
- 1555, 1551, 1546, 1542, 1537, 1533, 1528, 1524,
- 1519, 1515, 1510, 1506, 1502, 1497, 1493, 1489,
- 1485, 1481, 1476, 1472, 1468, 1464, 1460, 1456,
- 1452, 1448, 1444, 1440, 1436, 1432, 1428, 1424,
- 1420, 1416, 1413, 1409, 1405, 1401, 1398, 1394,
- 1390, 1387, 1383, 1379, 1376, 1372, 1368, 1365,
- 1361, 1358, 1354, 1351, 1347, 1344, 1340, 1337,
- 1334, 1330, 1327, 1323, 1320, 1317, 1314, 1310,
- 1307, 1304, 1300, 1297, 1294, 1291, 1288, 1285,
- 1281, 1278, 1275, 1272, 1269, 1266, 1263, 1260,
- 1257, 1254, 1251, 1248, 1245, 1242, 1239, 1236,
- 1233, 1230, 1227, 1224, 1222, 1219, 1216, 1213,
- 1210, 1208, 1205, 1202, 1199, 1197, 1194, 1191,
- 1188, 1186, 1183, 1180, 1178, 1175, 1172, 1170,
- 1167, 1165, 1162, 1159, 1157, 1154, 1152, 1149,
- 1147, 1144, 1142, 1139, 1137, 1134, 1132, 1129,
- 1127, 1125, 1122, 1120, 1117, 1115, 1113, 1110,
- 1108, 1106, 1103, 1101, 1099, 1096, 1094, 1092,
- 1089, 1087, 1085, 1083, 1081, 1078, 1076, 1074,
- 1072, 1069, 1067, 1065, 1063, 1061, 1059, 1057,
- 1054, 1052, 1050, 1048, 1046, 1044, 1042, 1040,
- 1038, 1036, 1034, 1032, 1030, 1028, 1026, 1024,
- 1022, 1020, 1018, 1016, 1014, 1012, 1010, 1008,
- 1006, 1004, 1002, 1000, 998, 996, 994, 992,
- 991, 989, 987, 985, 983, 981, 979, 978,
- 976, 974, 972, 970, 969, 967, 965, 963,
- 961, 960, 958, 956, 954, 953, 951, 949,
- 948, 946, 944, 942, 941, 939, 937, 936,
- 934, 932, 931, 929, 927, 926, 924, 923,
- 921, 919, 918, 916, 914, 913, 911, 910,
- 908, 907, 905, 903, 902, 900, 899, 897,
- 896, 894, 893, 891, 890, 888, 887, 885,
- 884, 882, 881, 879, 878, 876, 875, 873,
- 872, 870, 869, 868, 866, 865, 863, 862,
- 860, 859, 858, 856, 855, 853, 852, 851,
- 849, 848, 846, 845, 844, 842, 841, 840,
- 838, 837, 836, 834, 833, 832, 830, 829,
- 828, 826, 825, 824, 823, 821, 820, 819,
- 817, 816, 815, 814, 812, 811, 810, 809,
- 807, 806, 805, 804, 802, 801, 800, 799,
- 798, 796, 795, 794, 793, 791, 790, 789,
- 788, 787, 786, 784, 783, 782, 781, 780,
- 779, 777, 776, 775, 774, 773, 772, 771,
- 769, 768, 767, 766, 765, 764, 763, 762,
- 760, 759, 758, 757, 756, 755, 754, 753,
- 752, 751, 750, 748, 747, 746, 745, 744,
- 743, 742, 741, 740, 739, 738, 737, 736,
- 735, 734, 733, 732, 731, 730, 729, 728,
- 727, 726, 725, 724, 723, 722, 721, 720,
- 719, 718, 717, 716, 715, 714, 713, 712,
- 711, 710, 709, 708, 707, 706, 705, 704,
- 703, 702, 701, 700, 699, 699, 698, 697,
- 696, 695, 694, 693, 692, 691, 690, 689,
- 688, 688, 687, 686, 685, 684, 683, 682,
- 681, 680, 680, 679, 678, 677, 676, 675,
- 674, 673, 673, 672, 671, 670, 669, 668,
- 667, 667, 666, 665, 664, 663, 662, 661,
- 661, 660, 659, 658, 657, 657, 656, 655,
- 654, 653, 652, 652, 651, 650, 649, 648,
- 648, 647, 646, 645, 644, 644, 643, 642,
- 641, 640, 640, 639, 638, 637, 637, 636,
- 635, 634, 633, 633, 632, 631, 630, 630,
- 629, 628, 627, 627, 626, 625, 624, 624,
- 623, 622, 621, 621, 620, 619, 618, 618,
- 617, 616, 616, 615, 614, 613, 613, 612,
- 611, 611, 610, 609, 608, 608, 607, 606,
- 606, 605, 604, 604, 603, 602, 601, 601,
- 600, 599, 599, 598, 597, 597, 596, 595,
- 595, 594, 593, 593, 592, 591, 591, 590,
- 589, 589, 588, 587, 587, 586, 585, 585,
- 584, 583, 583, 582, 581, 581, 580, 579,
- 579, 578, 578, 577, 576, 576, 575, 574,
- 574, 573, 572, 572, 571, 571, 570, 569,
- 569, 568, 568, 567, 566, 566, 565, 564,
- 564, 563, 563, 562, 561, 561, 560, 560,
- 559, 558, 558, 557, 557, 556, 555, 555,
- 554, 554, 553, 553, 552, 551, 551, 550,
- 550, 549, 548, 548, 547, 547, 546, 546,
- 545, 544, 544, 543, 543, 542, 542, 541,
- 541, 540, 539, 539, 538, 538, 537, 537,
- 536, 536, 535, 534, 534, 533, 533, 532,
- 532, 531, 531, 530, 530, 529, 529, 528,
- 527, 527, 526, 526, 525, 525, 524, 524,
- 523, 523, 522, 522, 521, 521, 520, 520,
- 519, 519, 518, 518, 517, 517, 516, 516,
- 515, 515, 514, 514
-};
-
-// Note that LinearToGamma() expects the values to be premultiplied by 4,
-// so we incorporate this factor 4 inside the DIVIDE_BY_ALPHA macro directly.
-#define DIVIDE_BY_ALPHA(sum, a) (((sum) * kInvAlpha[(a)]) >> (kAlphaFix - 2))
-
-#else
-
-#define DIVIDE_BY_ALPHA(sum, a) (4 * (sum) / (a))
-
-#endif // USE_INVERSE_ALPHA_TABLE
-
-static WEBP_INLINE int LinearToGammaWeighted(const uint8_t* src,
- const uint8_t* a_ptr,
- uint32_t total_a, int step,
- int rgb_stride) {
- const uint32_t sum =
- a_ptr[0] * GammaToLinear(src[0]) +
- a_ptr[step] * GammaToLinear(src[step]) +
- a_ptr[rgb_stride] * GammaToLinear(src[rgb_stride]) +
- a_ptr[rgb_stride + step] * GammaToLinear(src[rgb_stride + step]);
- assert(total_a > 0 && total_a <= 4 * 0xff);
-#if defined(USE_INVERSE_ALPHA_TABLE)
- assert((uint64_t)sum * kInvAlpha[total_a] < ((uint64_t)1 << 32));
-#endif
- return LinearToGamma(DIVIDE_BY_ALPHA(sum, total_a), 0);
-}
-
-static WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr,
- const uint8_t* const g_ptr,
- const uint8_t* const b_ptr,
- int step,
- uint8_t* const dst_y,
- int width,
- VP8Random* const rg) {
- int i, j;
- for (i = 0, j = 0; i < width; i += 1, j += step) {
- dst_y[i] = RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], rg);
- }
-}
-
-static WEBP_INLINE void AccumulateRGBA(const uint8_t* const r_ptr,
- const uint8_t* const g_ptr,
- const uint8_t* const b_ptr,
- const uint8_t* const a_ptr,
- int rgb_stride,
- uint16_t* dst, int width) {
- int i, j;
- // we loop over 2x2 blocks and produce one R/G/B/A value for each.
- for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * 4, dst += 4) {
- const uint32_t a = SUM4ALPHA(a_ptr + j);
- int r, g, b;
- if (a == 4 * 0xff || a == 0) {
- r = SUM4(r_ptr + j, 4);
- g = SUM4(g_ptr + j, 4);
- b = SUM4(b_ptr + j, 4);
- } else {
- r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 4, rgb_stride);
- g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 4, rgb_stride);
- b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 4, rgb_stride);
- }
- dst[0] = r;
- dst[1] = g;
- dst[2] = b;
- dst[3] = a;
- }
- if (width & 1) {
- const uint32_t a = 2u * SUM2ALPHA(a_ptr + j);
- int r, g, b;
- if (a == 4 * 0xff || a == 0) {
- r = SUM2(r_ptr + j);
- g = SUM2(g_ptr + j);
- b = SUM2(b_ptr + j);
- } else {
- r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 0, rgb_stride);
- g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 0, rgb_stride);
- b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 0, rgb_stride);
- }
- dst[0] = r;
- dst[1] = g;
- dst[2] = b;
- dst[3] = a;
- }
-}
-
-static WEBP_INLINE void AccumulateRGB(const uint8_t* const r_ptr,
- const uint8_t* const g_ptr,
- const uint8_t* const b_ptr,
- int step, int rgb_stride,
- uint16_t* dst, int width) {
- int i, j;
- for (i = 0, j = 0; i < (width >> 1); i += 1, j += 2 * step, dst += 4) {
- dst[0] = SUM4(r_ptr + j, step);
- dst[1] = SUM4(g_ptr + j, step);
- dst[2] = SUM4(b_ptr + j, step);
- }
- if (width & 1) {
- dst[0] = SUM2(r_ptr + j);
- dst[1] = SUM2(g_ptr + j);
- dst[2] = SUM2(b_ptr + j);
- }
-}
-
-static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb,
- uint8_t* const dst_u,
- uint8_t* const dst_v,
- int width,
- VP8Random* const rg) {
- int i;
- for (i = 0; i < width; i += 1, rgb += 4) {
- const int r = rgb[0], g = rgb[1], b = rgb[2];
- dst_u[i] = RGBToU(r, g, b, rg);
- dst_v[i] = RGBToV(r, g, b, rg);
- }
-}
-
-static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
- const uint8_t* const g_ptr,
- const uint8_t* const b_ptr,
- const uint8_t* const a_ptr,
- int step, // bytes per pixel
- int rgb_stride, // bytes per scanline
- float dithering,
- int use_iterative_conversion,
- WebPPicture* const picture) {
- int y;
- const int width = picture->width;
- const int height = picture->height;
- const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride);
- const int is_rgb = (r_ptr < b_ptr); // otherwise it's bgr
-
- picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420;
- picture->use_argb = 0;
-
- // disable smart conversion if source is too small (overkill).
- if (width < kMinDimensionIterativeConversion ||
- height < kMinDimensionIterativeConversion) {
- use_iterative_conversion = 0;
- }
-
- if (!WebPPictureAllocYUVA(picture, width, height)) {
- return 0;
- }
- if (has_alpha) {
- WebPInitAlphaProcessing();
- assert(step == 4);
-#if defined(USE_GAMMA_COMPRESSION) && defined(USE_INVERSE_ALPHA_TABLE)
- assert(kAlphaFix + kGammaFix <= 31);
-#endif
- }
-
- if (use_iterative_conversion) {
- InitGammaTablesF();
- if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) {
- return 0;
- }
- if (has_alpha) {
- WebPExtractAlpha(a_ptr, rgb_stride, width, height,
- picture->a, picture->a_stride);
- }
- } else {
- const int uv_width = (width + 1) >> 1;
- int use_dsp = (step == 3); // use special function in this case
- // temporary storage for accumulated R/G/B values during conversion to U/V
- uint16_t* const tmp_rgb =
- (uint16_t*)WebPSafeMalloc(4 * uv_width, sizeof(*tmp_rgb));
- uint8_t* dst_y = picture->y;
- uint8_t* dst_u = picture->u;
- uint8_t* dst_v = picture->v;
- uint8_t* dst_a = picture->a;
-
- VP8Random base_rg;
- VP8Random* rg = NULL;
- if (dithering > 0.) {
- VP8InitRandom(&base_rg, dithering);
- rg = &base_rg;
- use_dsp = 0; // can't use dsp in this case
- }
- WebPInitConvertARGBToYUV();
- InitGammaTables();
-
- if (tmp_rgb == NULL) return 0; // malloc error
-
- // Downsample Y/U/V planes, two rows at a time
- for (y = 0; y < (height >> 1); ++y) {
- int rows_have_alpha = has_alpha;
- const int off1 = (2 * y + 0) * rgb_stride;
- const int off2 = (2 * y + 1) * rgb_stride;
- if (use_dsp) {
- if (is_rgb) {
- WebPConvertRGB24ToY(r_ptr + off1, dst_y, width);
- WebPConvertRGB24ToY(r_ptr + off2, dst_y + picture->y_stride, width);
- } else {
- WebPConvertBGR24ToY(b_ptr + off1, dst_y, width);
- WebPConvertBGR24ToY(b_ptr + off2, dst_y + picture->y_stride, width);
- }
- } else {
- ConvertRowToY(r_ptr + off1, g_ptr + off1, b_ptr + off1, step,
- dst_y, width, rg);
- ConvertRowToY(r_ptr + off2, g_ptr + off2, b_ptr + off2, step,
- dst_y + picture->y_stride, width, rg);
- }
- dst_y += 2 * picture->y_stride;
- if (has_alpha) {
- rows_have_alpha &= !WebPExtractAlpha(a_ptr + off1, rgb_stride,
- width, 2,
- dst_a, picture->a_stride);
- dst_a += 2 * picture->a_stride;
- }
- // Collect averaged R/G/B(/A)
- if (!rows_have_alpha) {
- AccumulateRGB(r_ptr + off1, g_ptr + off1, b_ptr + off1,
- step, rgb_stride, tmp_rgb, width);
- } else {
- AccumulateRGBA(r_ptr + off1, g_ptr + off1, b_ptr + off1, a_ptr + off1,
- rgb_stride, tmp_rgb, width);
- }
- // Convert to U/V
- if (rg == NULL) {
- WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width);
- } else {
- ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg);
- }
- dst_u += picture->uv_stride;
- dst_v += picture->uv_stride;
- }
- if (height & 1) { // extra last row
- const int off = 2 * y * rgb_stride;
- int row_has_alpha = has_alpha;
- if (use_dsp) {
- if (r_ptr < b_ptr) {
- WebPConvertRGB24ToY(r_ptr + off, dst_y, width);
- } else {
- WebPConvertBGR24ToY(b_ptr + off, dst_y, width);
- }
- } else {
- ConvertRowToY(r_ptr + off, g_ptr + off, b_ptr + off, step,
- dst_y, width, rg);
- }
- if (row_has_alpha) {
- row_has_alpha &= !WebPExtractAlpha(a_ptr + off, 0, width, 1, dst_a, 0);
- }
- // Collect averaged R/G/B(/A)
- if (!row_has_alpha) {
- // Collect averaged R/G/B
- AccumulateRGB(r_ptr + off, g_ptr + off, b_ptr + off,
- step, /* rgb_stride = */ 0, tmp_rgb, width);
- } else {
- AccumulateRGBA(r_ptr + off, g_ptr + off, b_ptr + off, a_ptr + off,
- /* rgb_stride = */ 0, tmp_rgb, width);
- }
- if (rg == NULL) {
- WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width);
- } else {
- ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg);
- }
- }
- WebPSafeFree(tmp_rgb);
- }
- return 1;
-}
-
-#undef SUM4
-#undef SUM2
-#undef SUM4ALPHA
-#undef SUM2ALPHA
-
-//------------------------------------------------------------------------------
-// call for ARGB->YUVA conversion
-
-static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace,
- float dithering, int use_iterative_conversion) {
- if (picture == NULL) return 0;
- if (picture->argb == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
- } else if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
- } else {
- const uint8_t* const argb = (const uint8_t*)picture->argb;
- const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1;
- const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2;
- const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3;
- const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0;
-
- picture->colorspace = WEBP_YUV420;
- return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
- dithering, use_iterative_conversion, picture);
- }
-}
-
-int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace,
- float dithering) {
- return PictureARGBToYUVA(picture, colorspace, dithering, 0);
-}
-
-int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) {
- return PictureARGBToYUVA(picture, colorspace, 0.f, 0);
-}
-
-int WebPPictureSmartARGBToYUVA(WebPPicture* picture) {
- return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1);
-}
-
-//------------------------------------------------------------------------------
-// call for YUVA -> ARGB conversion
-
-int WebPPictureYUVAToARGB(WebPPicture* picture) {
- if (picture == NULL) return 0;
- if (picture->y == NULL || picture->u == NULL || picture->v == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
- }
- if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
- }
- if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
- }
- // Allocate a new argb buffer (discarding the previous one).
- if (!WebPPictureAllocARGB(picture, picture->width, picture->height)) return 0;
- picture->use_argb = 1;
-
- // Convert
- {
- int y;
- const int width = picture->width;
- const int height = picture->height;
- const int argb_stride = 4 * picture->argb_stride;
- uint8_t* dst = (uint8_t*)picture->argb;
- const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
- WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST);
-
- // First row, with replicated top samples.
- upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
- cur_y += picture->y_stride;
- dst += argb_stride;
- // Center rows.
- for (y = 1; y + 1 < height; y += 2) {
- const uint8_t* const top_u = cur_u;
- const uint8_t* const top_v = cur_v;
- cur_u += picture->uv_stride;
- cur_v += picture->uv_stride;
- upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v,
- dst, dst + argb_stride, width);
- cur_y += 2 * picture->y_stride;
- dst += 2 * argb_stride;
- }
- // Last row (if needed), with replicated bottom samples.
- if (height > 1 && !(height & 1)) {
- upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
- }
- // Insert alpha values if needed, in replacement for the default 0xff ones.
- if (picture->colorspace & WEBP_CSP_ALPHA_BIT) {
- for (y = 0; y < height; ++y) {
- uint32_t* const argb_dst = picture->argb + y * picture->argb_stride;
- const uint8_t* const src = picture->a + y * picture->a_stride;
- int x;
- for (x = 0; x < width; ++x) {
- argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24);
- }
- }
- }
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// automatic import / conversion
-
-static int Import(WebPPicture* const picture,
- const uint8_t* const rgb, int rgb_stride,
- int step, int swap_rb, int import_alpha) {
- int y;
- const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0);
- const uint8_t* const g_ptr = rgb + 1;
- const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2);
- const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL;
- const int width = picture->width;
- const int height = picture->height;
-
- if (!picture->use_argb) {
- return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride,
- 0.f /* no dithering */, 0, picture);
- }
- if (!WebPPictureAlloc(picture)) return 0;
-
- VP8EncDspARGBInit();
-
- if (import_alpha) {
- assert(step == 4);
- for (y = 0; y < height; ++y) {
- uint32_t* const dst = &picture->argb[y * picture->argb_stride];
- const int offset = y * rgb_stride;
- VP8PackARGB(a_ptr + offset, r_ptr + offset, g_ptr + offset,
- b_ptr + offset, width, dst);
- }
- } else {
- assert(step >= 3);
- for (y = 0; y < height; ++y) {
- uint32_t* const dst = &picture->argb[y * picture->argb_stride];
- const int offset = y * rgb_stride;
- VP8PackRGB(r_ptr + offset, g_ptr + offset, b_ptr + offset,
- width, step, dst);
- }
- }
- return 1;
-}
-
-// Public API
-
-int WebPPictureImportRGB(WebPPicture* picture,
- const uint8_t* rgb, int rgb_stride) {
- return (picture != NULL && rgb != NULL)
- ? Import(picture, rgb, rgb_stride, 3, 0, 0)
- : 0;
-}
-
-int WebPPictureImportBGR(WebPPicture* picture,
- const uint8_t* rgb, int rgb_stride) {
- return (picture != NULL && rgb != NULL)
- ? Import(picture, rgb, rgb_stride, 3, 1, 0)
- : 0;
-}
-
-int WebPPictureImportRGBA(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return (picture != NULL && rgba != NULL)
- ? Import(picture, rgba, rgba_stride, 4, 0, 1)
- : 0;
-}
-
-int WebPPictureImportBGRA(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return (picture != NULL && rgba != NULL)
- ? Import(picture, rgba, rgba_stride, 4, 1, 1)
- : 0;
-}
-
-int WebPPictureImportRGBX(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return (picture != NULL && rgba != NULL)
- ? Import(picture, rgba, rgba_stride, 4, 0, 0)
- : 0;
-}
-
-int WebPPictureImportBGRX(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return (picture != NULL && rgba != NULL)
- ? Import(picture, rgba, rgba_stride, 4, 1, 0)
- : 0;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/picture_psnr.c b/drivers/webp/enc/picture_psnr.c
deleted file mode 100644
index 81ab1b5ca1..0000000000
--- a/drivers/webp/enc/picture_psnr.c
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebPPicture tools for measuring distortion
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <math.h>
-#include <stdlib.h>
-
-#include "./vp8enci.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// local-min distortion
-//
-// For every pixel in the *reference* picture, we search for the local best
-// match in the compressed image. This is not a symmetrical measure.
-
-#define RADIUS 2 // search radius. Shouldn't be too large.
-
-static void AccumulateLSIM(const uint8_t* src, int src_stride,
- const uint8_t* ref, int ref_stride,
- int w, int h, VP8DistoStats* stats) {
- int x, y;
- double total_sse = 0.;
- for (y = 0; y < h; ++y) {
- const int y_0 = (y - RADIUS < 0) ? 0 : y - RADIUS;
- const int y_1 = (y + RADIUS + 1 >= h) ? h : y + RADIUS + 1;
- for (x = 0; x < w; ++x) {
- const int x_0 = (x - RADIUS < 0) ? 0 : x - RADIUS;
- const int x_1 = (x + RADIUS + 1 >= w) ? w : x + RADIUS + 1;
- double best_sse = 255. * 255.;
- const double value = (double)ref[y * ref_stride + x];
- int i, j;
- for (j = y_0; j < y_1; ++j) {
- const uint8_t* const s = src + j * src_stride;
- for (i = x_0; i < x_1; ++i) {
- const double diff = s[i] - value;
- const double sse = diff * diff;
- if (sse < best_sse) best_sse = sse;
- }
- }
- total_sse += best_sse;
- }
- }
- stats->w = w * h;
- stats->xm = 0;
- stats->ym = 0;
- stats->xxm = total_sse;
- stats->yym = 0;
- stats->xxm = 0;
-}
-#undef RADIUS
-
-//------------------------------------------------------------------------------
-// Distortion
-
-// Max value returned in case of exact similarity.
-static const double kMinDistortion_dB = 99.;
-static float GetPSNR(const double v) {
- return (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.))
- : kMinDistortion_dB);
-}
-
-int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref,
- int type, float result[5]) {
- VP8DistoStats stats[5];
- int w, h;
-
- memset(stats, 0, sizeof(stats));
-
- VP8SSIMDspInit();
-
- if (src == NULL || ref == NULL ||
- src->width != ref->width || src->height != ref->height ||
- src->use_argb != ref->use_argb || result == NULL) {
- return 0;
- }
- w = src->width;
- h = src->height;
-
- if (src->use_argb == 1) {
- if (src->argb == NULL || ref->argb == NULL) {
- return 0;
- } else {
- int i, j, c;
- uint8_t* tmp1, *tmp2;
- uint8_t* const tmp_plane =
- (uint8_t*)WebPSafeMalloc(2ULL * w * h, sizeof(*tmp_plane));
- if (tmp_plane == NULL) return 0;
- tmp1 = tmp_plane;
- tmp2 = tmp_plane + w * h;
- for (c = 0; c < 4; ++c) {
- for (j = 0; j < h; ++j) {
- for (i = 0; i < w; ++i) {
- tmp1[j * w + i] = src->argb[i + j * src->argb_stride] >> (c * 8);
- tmp2[j * w + i] = ref->argb[i + j * ref->argb_stride] >> (c * 8);
- }
- }
- if (type >= 2) {
- AccumulateLSIM(tmp1, w, tmp2, w, w, h, &stats[c]);
- } else {
- VP8SSIMAccumulatePlane(tmp1, w, tmp2, w, w, h, &stats[c]);
- }
- }
- free(tmp_plane);
- }
- } else {
- int has_alpha, uv_w, uv_h;
- if (src->y == NULL || ref->y == NULL ||
- src->u == NULL || ref->u == NULL ||
- src->v == NULL || ref->v == NULL) {
- return 0;
- }
- has_alpha = !!(src->colorspace & WEBP_CSP_ALPHA_BIT);
- if (has_alpha != !!(ref->colorspace & WEBP_CSP_ALPHA_BIT) ||
- (has_alpha && (src->a == NULL || ref->a == NULL))) {
- return 0;
- }
-
- uv_w = (src->width + 1) >> 1;
- uv_h = (src->height + 1) >> 1;
- if (type >= 2) {
- AccumulateLSIM(src->y, src->y_stride, ref->y, ref->y_stride,
- w, h, &stats[0]);
- AccumulateLSIM(src->u, src->uv_stride, ref->u, ref->uv_stride,
- uv_w, uv_h, &stats[1]);
- AccumulateLSIM(src->v, src->uv_stride, ref->v, ref->uv_stride,
- uv_w, uv_h, &stats[2]);
- if (has_alpha) {
- AccumulateLSIM(src->a, src->a_stride, ref->a, ref->a_stride,
- w, h, &stats[3]);
- }
- } else {
- VP8SSIMAccumulatePlane(src->y, src->y_stride,
- ref->y, ref->y_stride,
- w, h, &stats[0]);
- VP8SSIMAccumulatePlane(src->u, src->uv_stride,
- ref->u, ref->uv_stride,
- uv_w, uv_h, &stats[1]);
- VP8SSIMAccumulatePlane(src->v, src->uv_stride,
- ref->v, ref->uv_stride,
- uv_w, uv_h, &stats[2]);
- if (has_alpha) {
- VP8SSIMAccumulatePlane(src->a, src->a_stride,
- ref->a, ref->a_stride,
- w, h, &stats[3]);
- }
- }
- }
- // Final stat calculations.
- {
- int c;
- for (c = 0; c <= 4; ++c) {
- if (type == 1) {
- const double v = VP8SSIMGet(&stats[c]);
- result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v)
- : kMinDistortion_dB);
- } else {
- const double v = VP8SSIMGetSquaredError(&stats[c]);
- result[c] = GetPSNR(v);
- }
- // Accumulate forward
- if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]);
- }
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/picture_rescale.c b/drivers/webp/enc/picture_rescale.c
deleted file mode 100644
index 9f19e8e80f..0000000000
--- a/drivers/webp/enc/picture_rescale.c
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebPPicture tools: copy, crop, rescaling and view.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "./vp8enci.h"
-#include "../utils/rescaler.h"
-#include "../utils/utils.h"
-
-#define HALVE(x) (((x) + 1) >> 1)
-
-// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them
-// into 'dst'. Mark 'dst' as not owning any memory.
-static void PictureGrabSpecs(const WebPPicture* const src,
- WebPPicture* const dst) {
- assert(src != NULL && dst != NULL);
- *dst = *src;
- WebPPictureResetBuffers(dst);
-}
-
-//------------------------------------------------------------------------------
-
-// Adjust top-left corner to chroma sample position.
-static void SnapTopLeftPosition(const WebPPicture* const pic,
- int* const left, int* const top) {
- if (!pic->use_argb) {
- *left &= ~1;
- *top &= ~1;
- }
-}
-
-// Adjust top-left corner and verify that the sub-rectangle is valid.
-static int AdjustAndCheckRectangle(const WebPPicture* const pic,
- int* const left, int* const top,
- int width, int height) {
- SnapTopLeftPosition(pic, left, top);
- if ((*left) < 0 || (*top) < 0) return 0;
- if (width <= 0 || height <= 0) return 0;
- if ((*left) + width > pic->width) return 0;
- if ((*top) + height > pic->height) return 0;
- return 1;
-}
-
-int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) {
- if (src == NULL || dst == NULL) return 0;
- if (src == dst) return 1;
-
- PictureGrabSpecs(src, dst);
- if (!WebPPictureAlloc(dst)) return 0;
-
- if (!src->use_argb) {
- WebPCopyPlane(src->y, src->y_stride,
- dst->y, dst->y_stride, dst->width, dst->height);
- WebPCopyPlane(src->u, src->uv_stride, dst->u, dst->uv_stride,
- HALVE(dst->width), HALVE(dst->height));
- WebPCopyPlane(src->v, src->uv_stride, dst->v, dst->uv_stride,
- HALVE(dst->width), HALVE(dst->height));
- if (dst->a != NULL) {
- WebPCopyPlane(src->a, src->a_stride,
- dst->a, dst->a_stride, dst->width, dst->height);
- }
- } else {
- WebPCopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride,
- (uint8_t*)dst->argb, 4 * dst->argb_stride,
- 4 * dst->width, dst->height);
- }
- return 1;
-}
-
-int WebPPictureIsView(const WebPPicture* picture) {
- if (picture == NULL) return 0;
- if (picture->use_argb) {
- return (picture->memory_argb_ == NULL);
- }
- return (picture->memory_ == NULL);
-}
-
-int WebPPictureView(const WebPPicture* src,
- int left, int top, int width, int height,
- WebPPicture* dst) {
- if (src == NULL || dst == NULL) return 0;
-
- // verify rectangle position.
- if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0;
-
- if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'.
- PictureGrabSpecs(src, dst);
- }
- dst->width = width;
- dst->height = height;
- if (!src->use_argb) {
- dst->y = src->y + top * src->y_stride + left;
- dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1);
- dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1);
- dst->y_stride = src->y_stride;
- dst->uv_stride = src->uv_stride;
- if (src->a != NULL) {
- dst->a = src->a + top * src->a_stride + left;
- dst->a_stride = src->a_stride;
- }
- } else {
- dst->argb = src->argb + top * src->argb_stride + left;
- dst->argb_stride = src->argb_stride;
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Picture cropping
-
-int WebPPictureCrop(WebPPicture* pic,
- int left, int top, int width, int height) {
- WebPPicture tmp;
-
- if (pic == NULL) return 0;
- if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0;
-
- PictureGrabSpecs(pic, &tmp);
- tmp.width = width;
- tmp.height = height;
- if (!WebPPictureAlloc(&tmp)) return 0;
-
- if (!pic->use_argb) {
- const int y_offset = top * pic->y_stride + left;
- const int uv_offset = (top / 2) * pic->uv_stride + left / 2;
- WebPCopyPlane(pic->y + y_offset, pic->y_stride,
- tmp.y, tmp.y_stride, width, height);
- WebPCopyPlane(pic->u + uv_offset, pic->uv_stride,
- tmp.u, tmp.uv_stride, HALVE(width), HALVE(height));
- WebPCopyPlane(pic->v + uv_offset, pic->uv_stride,
- tmp.v, tmp.uv_stride, HALVE(width), HALVE(height));
-
- if (tmp.a != NULL) {
- const int a_offset = top * pic->a_stride + left;
- WebPCopyPlane(pic->a + a_offset, pic->a_stride,
- tmp.a, tmp.a_stride, width, height);
- }
- } else {
- const uint8_t* const src =
- (const uint8_t*)(pic->argb + top * pic->argb_stride + left);
- WebPCopyPlane(src, pic->argb_stride * 4, (uint8_t*)tmp.argb,
- tmp.argb_stride * 4, width * 4, height);
- }
- WebPPictureFree(pic);
- *pic = tmp;
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Simple picture rescaler
-
-static void RescalePlane(const uint8_t* src,
- int src_width, int src_height, int src_stride,
- uint8_t* dst,
- int dst_width, int dst_height, int dst_stride,
- rescaler_t* const work,
- int num_channels) {
- WebPRescaler rescaler;
- int y = 0;
- WebPRescalerInit(&rescaler, src_width, src_height,
- dst, dst_width, dst_height, dst_stride,
- num_channels, work);
- while (y < src_height) {
- y += WebPRescalerImport(&rescaler, src_height - y,
- src + y * src_stride, src_stride);
- WebPRescalerExport(&rescaler);
- }
-}
-
-static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) {
- assert(pic->argb != NULL);
- WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb),
- pic->width, pic->height, inverse);
-}
-
-static void AlphaMultiplyY(WebPPicture* const pic, int inverse) {
- if (pic->a != NULL) {
- WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride,
- pic->width, pic->height, inverse);
- }
-}
-
-int WebPPictureRescale(WebPPicture* pic, int width, int height) {
- WebPPicture tmp;
- int prev_width, prev_height;
- rescaler_t* work;
-
- if (pic == NULL) return 0;
- prev_width = pic->width;
- prev_height = pic->height;
- if (!WebPRescalerGetScaledDimensions(
- prev_width, prev_height, &width, &height)) {
- return 0;
- }
-
- PictureGrabSpecs(pic, &tmp);
- tmp.width = width;
- tmp.height = height;
- if (!WebPPictureAlloc(&tmp)) return 0;
-
- if (!pic->use_argb) {
- work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work));
- if (work == NULL) {
- WebPPictureFree(&tmp);
- return 0;
- }
- // If present, we need to rescale alpha first (for AlphaMultiplyY).
- if (pic->a != NULL) {
- WebPInitAlphaProcessing();
- RescalePlane(pic->a, prev_width, prev_height, pic->a_stride,
- tmp.a, width, height, tmp.a_stride, work, 1);
- }
-
- // We take transparency into account on the luma plane only. That's not
- // totally exact blending, but still is a good approximation.
- AlphaMultiplyY(pic, 0);
- RescalePlane(pic->y, prev_width, prev_height, pic->y_stride,
- tmp.y, width, height, tmp.y_stride, work, 1);
- AlphaMultiplyY(&tmp, 1);
-
- RescalePlane(pic->u,
- HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
- tmp.u,
- HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
- RescalePlane(pic->v,
- HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
- tmp.v,
- HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
- } else {
- work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work));
- if (work == NULL) {
- WebPPictureFree(&tmp);
- return 0;
- }
- // In order to correctly interpolate colors, we need to apply the alpha
- // weighting first (black-matting), scale the RGB values, and remove
- // the premultiplication afterward (while preserving the alpha channel).
- WebPInitAlphaProcessing();
- AlphaMultiplyARGB(pic, 0);
- RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height,
- pic->argb_stride * 4,
- (uint8_t*)tmp.argb, width, height,
- tmp.argb_stride * 4,
- work, 4);
- AlphaMultiplyARGB(&tmp, 1);
- }
- WebPPictureFree(pic);
- WebPSafeFree(work);
- *pic = tmp;
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/picture_tools.c b/drivers/webp/enc/picture_tools.c
deleted file mode 100644
index bf97af8408..0000000000
--- a/drivers/webp/enc/picture_tools.c
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebPPicture tools: alpha handling, etc.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-
-#include "./vp8enci.h"
-#include "../dsp/yuv.h"
-
-static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) {
- return (0xff000000u | (r << 16) | (g << 8) | b);
-}
-
-//------------------------------------------------------------------------------
-// Helper: clean up fully transparent area to help compressibility.
-
-#define SIZE 8
-#define SIZE2 (SIZE / 2)
-static int is_transparent_area(const uint8_t* ptr, int stride, int size) {
- int y, x;
- for (y = 0; y < size; ++y) {
- for (x = 0; x < size; ++x) {
- if (ptr[x]) {
- return 0;
- }
- }
- ptr += stride;
- }
- return 1;
-}
-
-static int is_transparent_argb_area(const uint32_t* ptr, int stride, int size) {
- int y, x;
- for (y = 0; y < size; ++y) {
- for (x = 0; x < size; ++x) {
- if (ptr[x] & 0xff000000u) {
- return 0;
- }
- }
- ptr += stride;
- }
- return 1;
-}
-
-static void flatten(uint8_t* ptr, int v, int stride, int size) {
- int y;
- for (y = 0; y < size; ++y) {
- memset(ptr, v, size);
- ptr += stride;
- }
-}
-
-static void flatten_argb(uint32_t* ptr, uint32_t v, int stride, int size) {
- int x, y;
- for (y = 0; y < size; ++y) {
- for (x = 0; x < size; ++x) ptr[x] = v;
- ptr += stride;
- }
-}
-
-void WebPCleanupTransparentArea(WebPPicture* pic) {
- int x, y, w, h;
- if (pic == NULL) return;
- w = pic->width / SIZE;
- h = pic->height / SIZE;
-
- // note: we ignore the left-overs on right/bottom
- if (pic->use_argb) {
- uint32_t argb_value = 0;
- for (y = 0; y < h; ++y) {
- int need_reset = 1;
- for (x = 0; x < w; ++x) {
- const int off = (y * pic->argb_stride + x) * SIZE;
- if (is_transparent_argb_area(pic->argb + off, pic->argb_stride, SIZE)) {
- if (need_reset) {
- argb_value = pic->argb[off];
- need_reset = 0;
- }
- flatten_argb(pic->argb + off, argb_value, pic->argb_stride, SIZE);
- } else {
- need_reset = 1;
- }
- }
- }
- } else {
- const uint8_t* const a_ptr = pic->a;
- int values[3] = { 0 };
- if (a_ptr == NULL) return; // nothing to do
- for (y = 0; y < h; ++y) {
- int need_reset = 1;
- for (x = 0; x < w; ++x) {
- const int off_a = (y * pic->a_stride + x) * SIZE;
- const int off_y = (y * pic->y_stride + x) * SIZE;
- const int off_uv = (y * pic->uv_stride + x) * SIZE2;
- if (is_transparent_area(a_ptr + off_a, pic->a_stride, SIZE)) {
- if (need_reset) {
- values[0] = pic->y[off_y];
- values[1] = pic->u[off_uv];
- values[2] = pic->v[off_uv];
- need_reset = 0;
- }
- flatten(pic->y + off_y, values[0], pic->y_stride, SIZE);
- flatten(pic->u + off_uv, values[1], pic->uv_stride, SIZE2);
- flatten(pic->v + off_uv, values[2], pic->uv_stride, SIZE2);
- } else {
- need_reset = 1;
- }
- }
- }
- }
-}
-
-#undef SIZE
-#undef SIZE2
-
-void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) {
- int x, y, w, h;
- uint32_t* argb;
- assert(pic != NULL && pic->use_argb);
- w = pic->width;
- h = pic->height;
- argb = pic->argb;
-
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- if ((argb[x] & 0xff000000) == 0) {
- argb[x] = 0x00000000;
- }
- }
- argb += pic->argb_stride;
- }
-}
-
-//------------------------------------------------------------------------------
-// Blend color and remove transparency info
-
-#define BLEND(V0, V1, ALPHA) \
- ((((V0) * (255 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 16)
-#define BLEND_10BIT(V0, V1, ALPHA) \
- ((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 18)
-
-void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) {
- const int red = (background_rgb >> 16) & 0xff;
- const int green = (background_rgb >> 8) & 0xff;
- const int blue = (background_rgb >> 0) & 0xff;
- int x, y;
- if (pic == NULL) return;
- if (!pic->use_argb) {
- const int uv_width = (pic->width >> 1); // omit last pixel during u/v loop
- const int Y0 = VP8RGBToY(red, green, blue, YUV_HALF);
- // VP8RGBToU/V expects the u/v values summed over four pixels
- const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
- const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
- const int has_alpha = pic->colorspace & WEBP_CSP_ALPHA_BIT;
- if (!has_alpha || pic->a == NULL) return; // nothing to do
- for (y = 0; y < pic->height; ++y) {
- // Luma blending
- uint8_t* const y_ptr = pic->y + y * pic->y_stride;
- uint8_t* const a_ptr = pic->a + y * pic->a_stride;
- for (x = 0; x < pic->width; ++x) {
- const int alpha = a_ptr[x];
- if (alpha < 0xff) {
- y_ptr[x] = BLEND(Y0, y_ptr[x], a_ptr[x]);
- }
- }
- // Chroma blending every even line
- if ((y & 1) == 0) {
- uint8_t* const u = pic->u + (y >> 1) * pic->uv_stride;
- uint8_t* const v = pic->v + (y >> 1) * pic->uv_stride;
- uint8_t* const a_ptr2 =
- (y + 1 == pic->height) ? a_ptr : a_ptr + pic->a_stride;
- for (x = 0; x < uv_width; ++x) {
- // Average four alpha values into a single blending weight.
- // TODO(skal): might lead to visible contouring. Can we do better?
- const int alpha =
- a_ptr[2 * x + 0] + a_ptr[2 * x + 1] +
- a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1];
- u[x] = BLEND_10BIT(U0, u[x], alpha);
- v[x] = BLEND_10BIT(V0, v[x], alpha);
- }
- if (pic->width & 1) { // rightmost pixel
- const int alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]);
- u[x] = BLEND_10BIT(U0, u[x], alpha);
- v[x] = BLEND_10BIT(V0, v[x], alpha);
- }
- }
- memset(a_ptr, 0xff, pic->width);
- }
- } else {
- uint32_t* argb = pic->argb;
- const uint32_t background = MakeARGB32(red, green, blue);
- for (y = 0; y < pic->height; ++y) {
- for (x = 0; x < pic->width; ++x) {
- const int alpha = (argb[x] >> 24) & 0xff;
- if (alpha != 0xff) {
- if (alpha > 0) {
- int r = (argb[x] >> 16) & 0xff;
- int g = (argb[x] >> 8) & 0xff;
- int b = (argb[x] >> 0) & 0xff;
- r = BLEND(red, r, alpha);
- g = BLEND(green, g, alpha);
- b = BLEND(blue, b, alpha);
- argb[x] = MakeARGB32(r, g, b);
- } else {
- argb[x] = background;
- }
- }
- }
- argb += pic->argb_stride;
- }
- }
-}
-
-#undef BLEND
-#undef BLEND_10BIT
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/quant.c b/drivers/webp/enc/quant.c
deleted file mode 100644
index 549ad26f93..0000000000
--- a/drivers/webp/enc/quant.c
+++ /dev/null
@@ -1,1283 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Quantization
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <math.h>
-#include <stdlib.h> // for abs()
-
-#include "./vp8enci.h"
-#include "./cost.h"
-
-#define DO_TRELLIS_I4 1
-#define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate.
-#define DO_TRELLIS_UV 0 // disable trellis for UV. Risky. Not worth.
-#define USE_TDISTO 1
-
-#define MID_ALPHA 64 // neutral value for susceptibility
-#define MIN_ALPHA 30 // lowest usable value for susceptibility
-#define MAX_ALPHA 100 // higher meaningful value for susceptibility
-
-#define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP
- // power-law modulation. Must be strictly less than 1.
-
-// number of non-zero coeffs below which we consider the block very flat
-// (and apply a penalty to complex predictions)
-#define FLATNESS_LIMIT_I16 10 // I16 mode
-#define FLATNESS_LIMIT_I4 3 // I4 mode
-#define FLATNESS_LIMIT_UV 2 // UV mode
-#define FLATNESS_PENALTY 140 // roughly ~1bit per block
-
-#define MULT_8B(a, b) (((a) * (b) + 128) >> 8)
-
-#define RD_DISTO_MULT 256 // distortion multiplier (equivalent of lambda)
-
-// #define DEBUG_BLOCK
-
-//------------------------------------------------------------------------------
-
-#if defined(DEBUG_BLOCK)
-
-#include <stdio.h>
-#include <stdlib.h>
-
-static void PrintBlockInfo(const VP8EncIterator* const it,
- const VP8ModeScore* const rd) {
- int i, j;
- const int is_i16 = (it->mb_->type_ == 1);
- const uint8_t* const y_in = it->yuv_in_ + Y_OFF_ENC;
- const uint8_t* const y_out = it->yuv_out_ + Y_OFF_ENC;
- const uint8_t* const uv_in = it->yuv_in_ + U_OFF_ENC;
- const uint8_t* const uv_out = it->yuv_out_ + U_OFF_ENC;
- printf("SOURCE / OUTPUT / ABS DELTA\n");
- for (j = 0; j < 16; ++j) {
- for (i = 0; i < 16; ++i) printf("%3d ", y_in[i + j * BPS]);
- printf(" ");
- for (i = 0; i < 16; ++i) printf("%3d ", y_out[i + j * BPS]);
- printf(" ");
- for (i = 0; i < 16; ++i) {
- printf("%1d ", abs(y_in[i + j * BPS] - y_out[i + j * BPS]));
- }
- printf("\n");
- }
- printf("\n"); // newline before the U/V block
- for (j = 0; j < 8; ++j) {
- for (i = 0; i < 8; ++i) printf("%3d ", uv_in[i + j * BPS]);
- printf(" ");
- for (i = 8; i < 16; ++i) printf("%3d ", uv_in[i + j * BPS]);
- printf(" ");
- for (i = 0; i < 8; ++i) printf("%3d ", uv_out[i + j * BPS]);
- printf(" ");
- for (i = 8; i < 16; ++i) printf("%3d ", uv_out[i + j * BPS]);
- printf(" ");
- for (i = 0; i < 8; ++i) {
- printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS]));
- }
- printf(" ");
- for (i = 8; i < 16; ++i) {
- printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS]));
- }
- printf("\n");
- }
- printf("\nD:%d SD:%d R:%d H:%d nz:0x%x score:%d\n",
- (int)rd->D, (int)rd->SD, (int)rd->R, (int)rd->H, (int)rd->nz,
- (int)rd->score);
- if (is_i16) {
- printf("Mode: %d\n", rd->mode_i16);
- printf("y_dc_levels:");
- for (i = 0; i < 16; ++i) printf("%3d ", rd->y_dc_levels[i]);
- printf("\n");
- } else {
- printf("Modes[16]: ");
- for (i = 0; i < 16; ++i) printf("%d ", rd->modes_i4[i]);
- printf("\n");
- }
- printf("y_ac_levels:\n");
- for (j = 0; j < 16; ++j) {
- for (i = is_i16 ? 1 : 0; i < 16; ++i) {
- printf("%4d ", rd->y_ac_levels[j][i]);
- }
- printf("\n");
- }
- printf("\n");
- printf("uv_levels (mode=%d):\n", rd->mode_uv);
- for (j = 0; j < 8; ++j) {
- for (i = 0; i < 16; ++i) {
- printf("%4d ", rd->uv_levels[j][i]);
- }
- printf("\n");
- }
-}
-
-#endif // DEBUG_BLOCK
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE int clip(int v, int m, int M) {
- return v < m ? m : v > M ? M : v;
-}
-
-static const uint8_t kZigzag[16] = {
- 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
-};
-
-static const uint8_t kDcTable[128] = {
- 4, 5, 6, 7, 8, 9, 10, 10,
- 11, 12, 13, 14, 15, 16, 17, 17,
- 18, 19, 20, 20, 21, 21, 22, 22,
- 23, 23, 24, 25, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36,
- 37, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 63, 64, 65, 66,
- 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 76, 77, 78, 79, 80, 81,
- 82, 83, 84, 85, 86, 87, 88, 89,
- 91, 93, 95, 96, 98, 100, 101, 102,
- 104, 106, 108, 110, 112, 114, 116, 118,
- 122, 124, 126, 128, 130, 132, 134, 136,
- 138, 140, 143, 145, 148, 151, 154, 157
-};
-
-static const uint16_t kAcTable[128] = {
- 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 60,
- 62, 64, 66, 68, 70, 72, 74, 76,
- 78, 80, 82, 84, 86, 88, 90, 92,
- 94, 96, 98, 100, 102, 104, 106, 108,
- 110, 112, 114, 116, 119, 122, 125, 128,
- 131, 134, 137, 140, 143, 146, 149, 152,
- 155, 158, 161, 164, 167, 170, 173, 177,
- 181, 185, 189, 193, 197, 201, 205, 209,
- 213, 217, 221, 225, 229, 234, 239, 245,
- 249, 254, 259, 264, 269, 274, 279, 284
-};
-
-static const uint16_t kAcTable2[128] = {
- 8, 8, 9, 10, 12, 13, 15, 17,
- 18, 20, 21, 23, 24, 26, 27, 29,
- 31, 32, 34, 35, 37, 38, 40, 41,
- 43, 44, 46, 48, 49, 51, 52, 54,
- 55, 57, 58, 60, 62, 63, 65, 66,
- 68, 69, 71, 72, 74, 75, 77, 79,
- 80, 82, 83, 85, 86, 88, 89, 93,
- 96, 99, 102, 105, 108, 111, 114, 117,
- 120, 124, 127, 130, 133, 136, 139, 142,
- 145, 148, 151, 155, 158, 161, 164, 167,
- 170, 173, 176, 179, 184, 189, 193, 198,
- 203, 207, 212, 217, 221, 226, 230, 235,
- 240, 244, 249, 254, 258, 263, 268, 274,
- 280, 286, 292, 299, 305, 311, 317, 323,
- 330, 336, 342, 348, 354, 362, 370, 379,
- 385, 393, 401, 409, 416, 424, 432, 440
-};
-
-static const uint8_t kBiasMatrices[3][2] = { // [luma-ac,luma-dc,chroma][dc,ac]
- { 96, 110 }, { 96, 108 }, { 110, 115 }
-};
-
-// Sharpening by (slightly) raising the hi-frequency coeffs.
-// Hack-ish but helpful for mid-bitrate range. Use with care.
-#define SHARPEN_BITS 11 // number of descaling bits for sharpening bias
-static const uint8_t kFreqSharpening[16] = {
- 0, 30, 60, 90,
- 30, 60, 90, 90,
- 60, 90, 90, 90,
- 90, 90, 90, 90
-};
-
-//------------------------------------------------------------------------------
-// Initialize quantization parameters in VP8Matrix
-
-// Returns the average quantizer
-static int ExpandMatrix(VP8Matrix* const m, int type) {
- int i, sum;
- for (i = 0; i < 2; ++i) {
- const int is_ac_coeff = (i > 0);
- const int bias = kBiasMatrices[type][is_ac_coeff];
- m->iq_[i] = (1 << QFIX) / m->q_[i];
- m->bias_[i] = BIAS(bias);
- // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is:
- // * zero if coeff <= zthresh
- // * non-zero if coeff > zthresh
- m->zthresh_[i] = ((1 << QFIX) - 1 - m->bias_[i]) / m->iq_[i];
- }
- for (i = 2; i < 16; ++i) {
- m->q_[i] = m->q_[1];
- m->iq_[i] = m->iq_[1];
- m->bias_[i] = m->bias_[1];
- m->zthresh_[i] = m->zthresh_[1];
- }
- for (sum = 0, i = 0; i < 16; ++i) {
- if (type == 0) { // we only use sharpening for AC luma coeffs
- m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> SHARPEN_BITS;
- } else {
- m->sharpen_[i] = 0;
- }
- sum += m->q_[i];
- }
- return (sum + 8) >> 4;
-}
-
-static void CheckLambdaValue(int* const v) { if (*v < 1) *v = 1; }
-
-static void SetupMatrices(VP8Encoder* enc) {
- int i;
- const int tlambda_scale =
- (enc->method_ >= 4) ? enc->config_->sns_strength
- : 0;
- const int num_segments = enc->segment_hdr_.num_segments_;
- for (i = 0; i < num_segments; ++i) {
- VP8SegmentInfo* const m = &enc->dqm_[i];
- const int q = m->quant_;
- int q_i4, q_i16, q_uv;
- m->y1_.q_[0] = kDcTable[clip(q + enc->dq_y1_dc_, 0, 127)];
- m->y1_.q_[1] = kAcTable[clip(q, 0, 127)];
-
- m->y2_.q_[0] = kDcTable[ clip(q + enc->dq_y2_dc_, 0, 127)] * 2;
- m->y2_.q_[1] = kAcTable2[clip(q + enc->dq_y2_ac_, 0, 127)];
-
- m->uv_.q_[0] = kDcTable[clip(q + enc->dq_uv_dc_, 0, 117)];
- m->uv_.q_[1] = kAcTable[clip(q + enc->dq_uv_ac_, 0, 127)];
-
- q_i4 = ExpandMatrix(&m->y1_, 0);
- q_i16 = ExpandMatrix(&m->y2_, 1);
- q_uv = ExpandMatrix(&m->uv_, 2);
-
- m->lambda_i4_ = (3 * q_i4 * q_i4) >> 7;
- m->lambda_i16_ = (3 * q_i16 * q_i16);
- m->lambda_uv_ = (3 * q_uv * q_uv) >> 6;
- m->lambda_mode_ = (1 * q_i4 * q_i4) >> 7;
- m->lambda_trellis_i4_ = (7 * q_i4 * q_i4) >> 3;
- m->lambda_trellis_i16_ = (q_i16 * q_i16) >> 2;
- m->lambda_trellis_uv_ = (q_uv * q_uv) << 1;
- m->tlambda_ = (tlambda_scale * q_i4) >> 5;
-
- // none of these constants should be < 1
- CheckLambdaValue(&m->lambda_i4_);
- CheckLambdaValue(&m->lambda_i16_);
- CheckLambdaValue(&m->lambda_uv_);
- CheckLambdaValue(&m->lambda_mode_);
- CheckLambdaValue(&m->lambda_trellis_i4_);
- CheckLambdaValue(&m->lambda_trellis_i16_);
- CheckLambdaValue(&m->lambda_trellis_uv_);
- CheckLambdaValue(&m->tlambda_);
-
- m->min_disto_ = 10 * m->y1_.q_[0]; // quantization-aware min disto
- m->max_edge_ = 0;
-
- m->i4_penalty_ = 1000 * q_i4 * q_i4;
- }
-}
-
-//------------------------------------------------------------------------------
-// Initialize filtering parameters
-
-// Very small filter-strength values have close to no visual effect. So we can
-// save a little decoding-CPU by turning filtering off for these.
-#define FSTRENGTH_CUTOFF 2
-
-static void SetupFilterStrength(VP8Encoder* const enc) {
- int i;
- // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering.
- const int level0 = 5 * enc->config_->filter_strength;
- for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
- VP8SegmentInfo* const m = &enc->dqm_[i];
- // We focus on the quantization of AC coeffs.
- const int qstep = kAcTable[clip(m->quant_, 0, 127)] >> 2;
- const int base_strength =
- VP8FilterStrengthFromDelta(enc->filter_hdr_.sharpness_, qstep);
- // Segments with lower complexity ('beta') will be less filtered.
- const int f = base_strength * level0 / (256 + m->beta_);
- m->fstrength_ = (f < FSTRENGTH_CUTOFF) ? 0 : (f > 63) ? 63 : f;
- }
- // We record the initial strength (mainly for the case of 1-segment only).
- enc->filter_hdr_.level_ = enc->dqm_[0].fstrength_;
- enc->filter_hdr_.simple_ = (enc->config_->filter_type == 0);
- enc->filter_hdr_.sharpness_ = enc->config_->filter_sharpness;
-}
-
-//------------------------------------------------------------------------------
-
-// Note: if you change the values below, remember that the max range
-// allowed by the syntax for DQ_UV is [-16,16].
-#define MAX_DQ_UV (6)
-#define MIN_DQ_UV (-4)
-
-// We want to emulate jpeg-like behaviour where the expected "good" quality
-// is around q=75. Internally, our "good" middle is around c=50. So we
-// map accordingly using linear piece-wise function
-static double QualityToCompression(double c) {
- const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.;
- // The file size roughly scales as pow(quantizer, 3.). Actually, the
- // exponent is somewhere between 2.8 and 3.2, but we're mostly interested
- // in the mid-quant range. So we scale the compressibility inversely to
- // this power-law: quant ~= compression ^ 1/3. This law holds well for
- // low quant. Finer modeling for high-quant would make use of kAcTable[]
- // more explicitly.
- const double v = pow(linear_c, 1 / 3.);
- return v;
-}
-
-static double QualityToJPEGCompression(double c, double alpha) {
- // We map the complexity 'alpha' and quality setting 'c' to a compression
- // exponent empirically matched to the compression curve of libjpeg6b.
- // On average, the WebP output size will be roughly similar to that of a
- // JPEG file compressed with same quality factor.
- const double amin = 0.30;
- const double amax = 0.85;
- const double exp_min = 0.4;
- const double exp_max = 0.9;
- const double slope = (exp_min - exp_max) / (amax - amin);
- // Linearly interpolate 'expn' from exp_min to exp_max
- // in the [amin, amax] range.
- const double expn = (alpha > amax) ? exp_min
- : (alpha < amin) ? exp_max
- : exp_max + slope * (alpha - amin);
- const double v = pow(c, expn);
- return v;
-}
-
-static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1,
- const VP8SegmentInfo* const S2) {
- return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_);
-}
-
-static void SimplifySegments(VP8Encoder* const enc) {
- int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 };
- // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an
- // explicit check is needed to avoid a spurious warning about 'i' exceeding
- // array bounds of 'dqm_' with some compilers (noticed with gcc-4.9).
- const int num_segments = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS)
- ? enc->segment_hdr_.num_segments_
- : NUM_MB_SEGMENTS;
- int num_final_segments = 1;
- int s1, s2;
- for (s1 = 1; s1 < num_segments; ++s1) { // find similar segments
- const VP8SegmentInfo* const S1 = &enc->dqm_[s1];
- int found = 0;
- // check if we already have similar segment
- for (s2 = 0; s2 < num_final_segments; ++s2) {
- const VP8SegmentInfo* const S2 = &enc->dqm_[s2];
- if (SegmentsAreEquivalent(S1, S2)) {
- found = 1;
- break;
- }
- }
- map[s1] = s2;
- if (!found) {
- if (num_final_segments != s1) {
- enc->dqm_[num_final_segments] = enc->dqm_[s1];
- }
- ++num_final_segments;
- }
- }
- if (num_final_segments < num_segments) { // Remap
- int i = enc->mb_w_ * enc->mb_h_;
- while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_];
- enc->segment_hdr_.num_segments_ = num_final_segments;
- // Replicate the trailing segment infos (it's mostly cosmetics)
- for (i = num_final_segments; i < num_segments; ++i) {
- enc->dqm_[i] = enc->dqm_[num_final_segments - 1];
- }
- }
-}
-
-void VP8SetSegmentParams(VP8Encoder* const enc, float quality) {
- int i;
- int dq_uv_ac, dq_uv_dc;
- const int num_segments = enc->segment_hdr_.num_segments_;
- const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.;
- const double Q = quality / 100.;
- const double c_base = enc->config_->emulate_jpeg_size ?
- QualityToJPEGCompression(Q, enc->alpha_ / 255.) :
- QualityToCompression(Q);
- for (i = 0; i < num_segments; ++i) {
- // We modulate the base coefficient to accommodate for the quantization
- // susceptibility and allow denser segments to be quantized more.
- const double expn = 1. - amp * enc->dqm_[i].alpha_;
- const double c = pow(c_base, expn);
- const int q = (int)(127. * (1. - c));
- assert(expn > 0.);
- enc->dqm_[i].quant_ = clip(q, 0, 127);
- }
-
- // purely indicative in the bitstream (except for the 1-segment case)
- enc->base_quant_ = enc->dqm_[0].quant_;
-
- // fill-in values for the unused segments (required by the syntax)
- for (i = num_segments; i < NUM_MB_SEGMENTS; ++i) {
- enc->dqm_[i].quant_ = enc->base_quant_;
- }
-
- // uv_alpha_ is normally spread around ~60. The useful range is
- // typically ~30 (quite bad) to ~100 (ok to decimate UV more).
- // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv.
- dq_uv_ac = (enc->uv_alpha_ - MID_ALPHA) * (MAX_DQ_UV - MIN_DQ_UV)
- / (MAX_ALPHA - MIN_ALPHA);
- // we rescale by the user-defined strength of adaptation
- dq_uv_ac = dq_uv_ac * enc->config_->sns_strength / 100;
- // and make it safe.
- dq_uv_ac = clip(dq_uv_ac, MIN_DQ_UV, MAX_DQ_UV);
- // We also boost the dc-uv-quant a little, based on sns-strength, since
- // U/V channels are quite more reactive to high quants (flat DC-blocks
- // tend to appear, and are unpleasant).
- dq_uv_dc = -4 * enc->config_->sns_strength / 100;
- dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed
-
- enc->dq_y1_dc_ = 0; // TODO(skal): dq-lum
- enc->dq_y2_dc_ = 0;
- enc->dq_y2_ac_ = 0;
- enc->dq_uv_dc_ = dq_uv_dc;
- enc->dq_uv_ac_ = dq_uv_ac;
-
- SetupFilterStrength(enc); // initialize segments' filtering, eventually
-
- if (num_segments > 1) SimplifySegments(enc);
-
- SetupMatrices(enc); // finalize quantization matrices
-}
-
-//------------------------------------------------------------------------------
-// Form the predictions in cache
-
-// Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index
-const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 };
-const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 };
-
-// Must be indexed using {B_DC_PRED -> B_HU_PRED} as index
-const int VP8I4ModeOffsets[NUM_BMODES] = {
- I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4
-};
-
-void VP8MakeLuma16Preds(const VP8EncIterator* const it) {
- const uint8_t* const left = it->x_ ? it->y_left_ : NULL;
- const uint8_t* const top = it->y_ ? it->y_top_ : NULL;
- VP8EncPredLuma16(it->yuv_p_, left, top);
-}
-
-void VP8MakeChroma8Preds(const VP8EncIterator* const it) {
- const uint8_t* const left = it->x_ ? it->u_left_ : NULL;
- const uint8_t* const top = it->y_ ? it->uv_top_ : NULL;
- VP8EncPredChroma8(it->yuv_p_, left, top);
-}
-
-void VP8MakeIntra4Preds(const VP8EncIterator* const it) {
- VP8EncPredLuma4(it->yuv_p_, it->i4_top_);
-}
-
-//------------------------------------------------------------------------------
-// Quantize
-
-// Layout:
-// +----+----+
-// |YYYY|UUVV| 0
-// |YYYY|UUVV| 4
-// |YYYY|....| 8
-// |YYYY|....| 12
-// +----+----+
-
-const int VP8Scan[16] = { // Luma
- 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
- 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
- 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
- 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS,
-};
-
-static const int VP8ScanUV[4 + 4] = {
- 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U
- 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V
-};
-
-//------------------------------------------------------------------------------
-// Distortion measurement
-
-static const uint16_t kWeightY[16] = {
- 38, 32, 20, 9, 32, 28, 17, 7, 20, 17, 10, 4, 9, 7, 4, 2
-};
-
-static const uint16_t kWeightTrellis[16] = {
-#if USE_TDISTO == 0
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
-#else
- 30, 27, 19, 11,
- 27, 24, 17, 10,
- 19, 17, 12, 8,
- 11, 10, 8, 6
-#endif
-};
-
-// Init/Copy the common fields in score.
-static void InitScore(VP8ModeScore* const rd) {
- rd->D = 0;
- rd->SD = 0;
- rd->R = 0;
- rd->H = 0;
- rd->nz = 0;
- rd->score = MAX_COST;
-}
-
-static void CopyScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
- dst->D = src->D;
- dst->SD = src->SD;
- dst->R = src->R;
- dst->H = src->H;
- dst->nz = src->nz; // note that nz is not accumulated, but just copied.
- dst->score = src->score;
-}
-
-static void AddScore(VP8ModeScore* const dst, const VP8ModeScore* const src) {
- dst->D += src->D;
- dst->SD += src->SD;
- dst->R += src->R;
- dst->H += src->H;
- dst->nz |= src->nz; // here, new nz bits are accumulated.
- dst->score += src->score;
-}
-
-//------------------------------------------------------------------------------
-// Performs trellis-optimized quantization.
-
-// Trellis node
-typedef struct {
- int8_t prev; // best previous node
- int8_t sign; // sign of coeff_i
- int16_t level; // level
-} Node;
-
-// Score state
-typedef struct {
- score_t score; // partial RD score
- const uint16_t* costs; // shortcut to cost tables
-} ScoreState;
-
-// If a coefficient was quantized to a value Q (using a neutral bias),
-// we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA]
-// We don't test negative values though.
-#define MIN_DELTA 0 // how much lower level to try
-#define MAX_DELTA 1 // how much higher
-#define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA)
-#define NODE(n, l) (nodes[(n)][(l) + MIN_DELTA])
-#define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA])
-
-static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) {
- rd->score = (rd->R + rd->H) * lambda + RD_DISTO_MULT * (rd->D + rd->SD);
-}
-
-static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate,
- score_t distortion) {
- return rate * lambda + RD_DISTO_MULT * distortion;
-}
-
-static int TrellisQuantizeBlock(const VP8Encoder* const enc,
- int16_t in[16], int16_t out[16],
- int ctx0, int coeff_type,
- const VP8Matrix* const mtx,
- int lambda) {
- const ProbaArray* const probas = enc->proba_.coeffs_[coeff_type];
- CostArrayPtr const costs =
- (CostArrayPtr)enc->proba_.remapped_costs_[coeff_type];
- const int first = (coeff_type == 0) ? 1 : 0;
- Node nodes[16][NUM_NODES];
- ScoreState score_states[2][NUM_NODES];
- ScoreState* ss_cur = &SCORE_STATE(0, MIN_DELTA);
- ScoreState* ss_prev = &SCORE_STATE(1, MIN_DELTA);
- int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous
- score_t best_score;
- int n, m, p, last;
-
- {
- score_t cost;
- const int thresh = mtx->q_[1] * mtx->q_[1] / 4;
- const int last_proba = probas[VP8EncBands[first]][ctx0][0];
-
- // compute the position of the last interesting coefficient
- last = first - 1;
- for (n = 15; n >= first; --n) {
- const int j = kZigzag[n];
- const int err = in[j] * in[j];
- if (err > thresh) {
- last = n;
- break;
- }
- }
- // we don't need to go inspect up to n = 16 coeffs. We can just go up
- // to last + 1 (inclusive) without losing much.
- if (last < 15) ++last;
-
- // compute 'skip' score. This is the max score one can do.
- cost = VP8BitCost(0, last_proba);
- best_score = RDScoreTrellis(lambda, cost, 0);
-
- // initialize source node.
- for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
- const score_t rate = (ctx0 == 0) ? VP8BitCost(1, last_proba) : 0;
- ss_cur[m].score = RDScoreTrellis(lambda, rate, 0);
- ss_cur[m].costs = costs[first][ctx0];
- }
- }
-
- // traverse trellis.
- for (n = first; n <= last; ++n) {
- const int j = kZigzag[n];
- const uint32_t Q = mtx->q_[j];
- const uint32_t iQ = mtx->iq_[j];
- const uint32_t B = BIAS(0x00); // neutral bias
- // note: it's important to take sign of the _original_ coeff,
- // so we don't have to consider level < 0 afterward.
- const int sign = (in[j] < 0);
- const uint32_t coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
- int level0 = QUANTDIV(coeff0, iQ, B);
- if (level0 > MAX_LEVEL) level0 = MAX_LEVEL;
-
- { // Swap current and previous score states
- ScoreState* const tmp = ss_cur;
- ss_cur = ss_prev;
- ss_prev = tmp;
- }
-
- // test all alternate level values around level0.
- for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
- Node* const cur = &NODE(n, m);
- int level = level0 + m;
- const int ctx = (level > 2) ? 2 : level;
- const int band = VP8EncBands[n + 1];
- score_t base_score, last_pos_score;
- score_t best_cur_score = MAX_COST;
- int best_prev = 0; // default, in case
-
- ss_cur[m].score = MAX_COST;
- ss_cur[m].costs = costs[n + 1][ctx];
- if (level > MAX_LEVEL || level < 0) { // node is dead?
- continue;
- }
-
- // Compute extra rate cost if last coeff's position is < 15
- {
- const score_t last_pos_cost =
- (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0;
- last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 0);
- }
-
- {
- // Compute delta_error = how much coding this level will
- // subtract to max_error as distortion.
- // Here, distortion = sum of (|coeff_i| - level_i * Q_i)^2
- const int new_error = coeff0 - level * Q;
- const int delta_error =
- kWeightTrellis[j] * (new_error * new_error - coeff0 * coeff0);
- base_score = RDScoreTrellis(lambda, 0, delta_error);
- }
-
- // Inspect all possible non-dead predecessors. Retain only the best one.
- for (p = -MIN_DELTA; p <= MAX_DELTA; ++p) {
- // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically
- // eliminated since their score can't be better than the current best.
- const score_t cost = VP8LevelCost(ss_prev[p].costs, level);
- // Examine node assuming it's a non-terminal one.
- const score_t score =
- base_score + ss_prev[p].score + RDScoreTrellis(lambda, cost, 0);
- if (score < best_cur_score) {
- best_cur_score = score;
- best_prev = p;
- }
- }
- // Store best finding in current node.
- cur->sign = sign;
- cur->level = level;
- cur->prev = best_prev;
- ss_cur[m].score = best_cur_score;
-
- // Now, record best terminal node (and thus best entry in the graph).
- if (level != 0) {
- const score_t score = best_cur_score + last_pos_score;
- if (score < best_score) {
- best_score = score;
- best_path[0] = n; // best eob position
- best_path[1] = m; // best node index
- best_path[2] = best_prev; // best predecessor
- }
- }
- }
- }
-
- // Fresh start
- memset(in + first, 0, (16 - first) * sizeof(*in));
- memset(out + first, 0, (16 - first) * sizeof(*out));
- if (best_path[0] == -1) {
- return 0; // skip!
- }
-
- {
- // Unwind the best path.
- // Note: best-prev on terminal node is not necessarily equal to the
- // best_prev for non-terminal. So we patch best_path[2] in.
- int nz = 0;
- int best_node = best_path[1];
- n = best_path[0];
- NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal
-
- for (; n >= first; --n) {
- const Node* const node = &NODE(n, best_node);
- const int j = kZigzag[n];
- out[n] = node->sign ? -node->level : node->level;
- nz |= node->level;
- in[j] = out[n] * mtx->q_[j];
- best_node = node->prev;
- }
- return (nz != 0);
- }
-}
-
-#undef NODE
-
-//------------------------------------------------------------------------------
-// Performs: difference, transform, quantize, back-transform, add
-// all at once. Output is the reconstructed block in *yuv_out, and the
-// quantized levels in *levels.
-
-static int ReconstructIntra16(VP8EncIterator* const it,
- VP8ModeScore* const rd,
- uint8_t* const yuv_out,
- int mode) {
- const VP8Encoder* const enc = it->enc_;
- const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
- const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
- const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
- int nz = 0;
- int n;
- int16_t tmp[16][16], dc_tmp[16];
-
- for (n = 0; n < 16; n += 2) {
- VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]);
- }
- VP8FTransformWHT(tmp[0], dc_tmp);
- nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &dqm->y2_) << 24;
-
- if (DO_TRELLIS_I16 && it->do_trellis_) {
- int x, y;
- VP8IteratorNzToBytes(it);
- for (y = 0, n = 0; y < 4; ++y) {
- for (x = 0; x < 4; ++x, ++n) {
- const int ctx = it->top_nz_[x] + it->left_nz_[y];
- const int non_zero =
- TrellisQuantizeBlock(enc, tmp[n], rd->y_ac_levels[n], ctx, 0,
- &dqm->y1_, dqm->lambda_trellis_i16_);
- it->top_nz_[x] = it->left_nz_[y] = non_zero;
- rd->y_ac_levels[n][0] = 0;
- nz |= non_zero << n;
- }
- }
- } else {
- for (n = 0; n < 16; n += 2) {
- // Zero-out the first coeff, so that: a) nz is correct below, and
- // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified.
- tmp[n][0] = tmp[n + 1][0] = 0;
- nz |= VP8EncQuantize2Blocks(tmp[n], rd->y_ac_levels[n], &dqm->y1_) << n;
- assert(rd->y_ac_levels[n + 0][0] == 0);
- assert(rd->y_ac_levels[n + 1][0] == 0);
- }
- }
-
- // Transform back
- VP8TransformWHT(dc_tmp, tmp[0]);
- for (n = 0; n < 16; n += 2) {
- VP8ITransform(ref + VP8Scan[n], tmp[n], yuv_out + VP8Scan[n], 1);
- }
-
- return nz;
-}
-
-static int ReconstructIntra4(VP8EncIterator* const it,
- int16_t levels[16],
- const uint8_t* const src,
- uint8_t* const yuv_out,
- int mode) {
- const VP8Encoder* const enc = it->enc_;
- const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode];
- const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
- int nz = 0;
- int16_t tmp[16];
-
- VP8FTransform(src, ref, tmp);
- if (DO_TRELLIS_I4 && it->do_trellis_) {
- const int x = it->i4_ & 3, y = it->i4_ >> 2;
- const int ctx = it->top_nz_[x] + it->left_nz_[y];
- nz = TrellisQuantizeBlock(enc, tmp, levels, ctx, 3, &dqm->y1_,
- dqm->lambda_trellis_i4_);
- } else {
- nz = VP8EncQuantizeBlock(tmp, levels, &dqm->y1_);
- }
- VP8ITransform(ref, tmp, yuv_out, 0);
- return nz;
-}
-
-static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
- uint8_t* const yuv_out, int mode) {
- const VP8Encoder* const enc = it->enc_;
- const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
- const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
- const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
- int nz = 0;
- int n;
- int16_t tmp[8][16];
-
- for (n = 0; n < 8; n += 2) {
- VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[n], tmp[n]);
- }
- if (DO_TRELLIS_UV && it->do_trellis_) {
- int ch, x, y;
- for (ch = 0, n = 0; ch <= 2; ch += 2) {
- for (y = 0; y < 2; ++y) {
- for (x = 0; x < 2; ++x, ++n) {
- const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
- const int non_zero =
- TrellisQuantizeBlock(enc, tmp[n], rd->uv_levels[n], ctx, 2,
- &dqm->uv_, dqm->lambda_trellis_uv_);
- it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = non_zero;
- nz |= non_zero << n;
- }
- }
- }
- } else {
- for (n = 0; n < 8; n += 2) {
- nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n;
- }
- }
-
- for (n = 0; n < 8; n += 2) {
- VP8ITransform(ref + VP8ScanUV[n], tmp[n], yuv_out + VP8ScanUV[n], 1);
- }
- return (nz << 16);
-}
-
-//------------------------------------------------------------------------------
-// RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost.
-// Pick the mode is lower RD-cost = Rate + lambda * Distortion.
-
-static void StoreMaxDelta(VP8SegmentInfo* const dqm, const int16_t DCs[16]) {
- // We look at the first three AC coefficients to determine what is the average
- // delta between each sub-4x4 block.
- const int v0 = abs(DCs[1]);
- const int v1 = abs(DCs[4]);
- const int v2 = abs(DCs[5]);
- int max_v = (v0 > v1) ? v1 : v0;
- max_v = (v2 > max_v) ? v2 : max_v;
- if (max_v > dqm->max_edge_) dqm->max_edge_ = max_v;
-}
-
-static void SwapModeScore(VP8ModeScore** a, VP8ModeScore** b) {
- VP8ModeScore* const tmp = *a;
- *a = *b;
- *b = tmp;
-}
-
-static void SwapPtr(uint8_t** a, uint8_t** b) {
- uint8_t* const tmp = *a;
- *a = *b;
- *b = tmp;
-}
-
-static void SwapOut(VP8EncIterator* const it) {
- SwapPtr(&it->yuv_out_, &it->yuv_out2_);
-}
-
-static score_t IsFlat(const int16_t* levels, int num_blocks, score_t thresh) {
- score_t score = 0;
- while (num_blocks-- > 0) { // TODO(skal): refine positional scoring?
- int i;
- for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC
- score += (levels[i] != 0);
- if (score > thresh) return 0;
- }
- levels += 16;
- }
- return 1;
-}
-
-static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
- const int kNumBlocks = 16;
- VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
- const int lambda = dqm->lambda_i16_;
- const int tlambda = dqm->tlambda_;
- const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
- VP8ModeScore rd_tmp;
- VP8ModeScore* rd_cur = &rd_tmp;
- VP8ModeScore* rd_best = rd;
- int mode;
-
- rd->mode_i16 = -1;
- for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
- uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC; // scratch buffer
- rd_cur->mode_i16 = mode;
-
- // Reconstruct
- rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode);
-
- // Measure RD-score
- rd_cur->D = VP8SSE16x16(src, tmp_dst);
- rd_cur->SD =
- tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) : 0;
- rd_cur->H = VP8FixedCostsI16[mode];
- rd_cur->R = VP8GetCostLuma16(it, rd_cur);
- if (mode > 0 &&
- IsFlat(rd_cur->y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16)) {
- // penalty to avoid flat area to be mispredicted by complex mode
- rd_cur->R += FLATNESS_PENALTY * kNumBlocks;
- }
-
- // Since we always examine Intra16 first, we can overwrite *rd directly.
- SetRDScore(lambda, rd_cur);
- if (mode == 0 || rd_cur->score < rd_best->score) {
- SwapModeScore(&rd_cur, &rd_best);
- SwapOut(it);
- }
- }
- if (rd_best != rd) {
- memcpy(rd, rd_best, sizeof(*rd));
- }
- SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision.
- VP8SetIntra16Mode(it, rd->mode_i16);
-
- // we have a blocky macroblock (only DCs are non-zero) with fairly high
- // distortion, record max delta so we can later adjust the minimal filtering
- // strength needed to smooth these blocks out.
- if ((rd->nz & 0xffff) == 0 && rd->D > dqm->min_disto_) {
- StoreMaxDelta(dqm, rd->y_dc_levels);
- }
-}
-
-//------------------------------------------------------------------------------
-
-// return the cost array corresponding to the surrounding prediction modes.
-static const uint16_t* GetCostModeI4(VP8EncIterator* const it,
- const uint8_t modes[16]) {
- const int preds_w = it->enc_->preds_w_;
- const int x = (it->i4_ & 3), y = it->i4_ >> 2;
- const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1];
- const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4];
- return VP8FixedCostsI4[top][left];
-}
-
-static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
- const VP8Encoder* const enc = it->enc_;
- const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_];
- const int lambda = dqm->lambda_i4_;
- const int tlambda = dqm->tlambda_;
- const uint8_t* const src0 = it->yuv_in_ + Y_OFF_ENC;
- uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC;
- int total_header_bits = 0;
- VP8ModeScore rd_best;
-
- if (enc->max_i4_header_bits_ == 0) {
- return 0;
- }
-
- InitScore(&rd_best);
- rd_best.H = 211; // '211' is the value of VP8BitCost(0, 145)
- SetRDScore(dqm->lambda_mode_, &rd_best);
- VP8IteratorStartI4(it);
- do {
- const int kNumBlocks = 1;
- VP8ModeScore rd_i4;
- int mode;
- int best_mode = -1;
- const uint8_t* const src = src0 + VP8Scan[it->i4_];
- const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4);
- uint8_t* best_block = best_blocks + VP8Scan[it->i4_];
- uint8_t* tmp_dst = it->yuv_p_ + I4TMP; // scratch buffer.
-
- InitScore(&rd_i4);
- VP8MakeIntra4Preds(it);
- for (mode = 0; mode < NUM_BMODES; ++mode) {
- VP8ModeScore rd_tmp;
- int16_t tmp_levels[16];
-
- // Reconstruct
- rd_tmp.nz =
- ReconstructIntra4(it, tmp_levels, src, tmp_dst, mode) << it->i4_;
-
- // Compute RD-score
- rd_tmp.D = VP8SSE4x4(src, tmp_dst);
- rd_tmp.SD =
- tlambda ? MULT_8B(tlambda, VP8TDisto4x4(src, tmp_dst, kWeightY))
- : 0;
- rd_tmp.H = mode_costs[mode];
-
- // Add flatness penalty
- if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) {
- rd_tmp.R = FLATNESS_PENALTY * kNumBlocks;
- } else {
- rd_tmp.R = 0;
- }
-
- // early-out check
- SetRDScore(lambda, &rd_tmp);
- if (best_mode >= 0 && rd_tmp.score >= rd_i4.score) continue;
-
- // finish computing score
- rd_tmp.R += VP8GetCostLuma4(it, tmp_levels);
- SetRDScore(lambda, &rd_tmp);
-
- if (best_mode < 0 || rd_tmp.score < rd_i4.score) {
- CopyScore(&rd_i4, &rd_tmp);
- best_mode = mode;
- SwapPtr(&tmp_dst, &best_block);
- memcpy(rd_best.y_ac_levels[it->i4_], tmp_levels,
- sizeof(rd_best.y_ac_levels[it->i4_]));
- }
- }
- SetRDScore(dqm->lambda_mode_, &rd_i4);
- AddScore(&rd_best, &rd_i4);
- if (rd_best.score >= rd->score) {
- return 0;
- }
- total_header_bits += (int)rd_i4.H; // <- equal to mode_costs[best_mode];
- if (total_header_bits > enc->max_i4_header_bits_) {
- return 0;
- }
- // Copy selected samples if not in the right place already.
- if (best_block != best_blocks + VP8Scan[it->i4_]) {
- VP8Copy4x4(best_block, best_blocks + VP8Scan[it->i4_]);
- }
- rd->modes_i4[it->i4_] = best_mode;
- it->top_nz_[it->i4_ & 3] = it->left_nz_[it->i4_ >> 2] = (rd_i4.nz ? 1 : 0);
- } while (VP8IteratorRotateI4(it, best_blocks));
-
- // finalize state
- CopyScore(rd, &rd_best);
- VP8SetIntra4Mode(it, rd->modes_i4);
- SwapOut(it);
- memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels));
- return 1; // select intra4x4 over intra16x16
-}
-
-//------------------------------------------------------------------------------
-
-static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
- const int kNumBlocks = 8;
- const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
- const int lambda = dqm->lambda_uv_;
- const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
- uint8_t* tmp_dst = it->yuv_out2_ + U_OFF_ENC; // scratch buffer
- uint8_t* dst0 = it->yuv_out_ + U_OFF_ENC;
- uint8_t* dst = dst0;
- VP8ModeScore rd_best;
- int mode;
-
- rd->mode_uv = -1;
- InitScore(&rd_best);
- for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
- VP8ModeScore rd_uv;
-
- // Reconstruct
- rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode);
-
- // Compute RD-score
- rd_uv.D = VP8SSE16x8(src, tmp_dst);
- rd_uv.SD = 0; // not calling TDisto here: it tends to flatten areas.
- rd_uv.H = VP8FixedCostsUV[mode];
- rd_uv.R = VP8GetCostUV(it, &rd_uv);
- if (mode > 0 && IsFlat(rd_uv.uv_levels[0], kNumBlocks, FLATNESS_LIMIT_UV)) {
- rd_uv.R += FLATNESS_PENALTY * kNumBlocks;
- }
-
- SetRDScore(lambda, &rd_uv);
- if (mode == 0 || rd_uv.score < rd_best.score) {
- CopyScore(&rd_best, &rd_uv);
- rd->mode_uv = mode;
- memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels));
- SwapPtr(&dst, &tmp_dst);
- }
- }
- VP8SetIntraUVMode(it, rd->mode_uv);
- AddScore(rd, &rd_best);
- if (dst != dst0) { // copy 16x8 block if needed
- VP8Copy16x8(dst, dst0);
- }
-}
-
-//------------------------------------------------------------------------------
-// Final reconstruction and quantization.
-
-static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) {
- const VP8Encoder* const enc = it->enc_;
- const int is_i16 = (it->mb_->type_ == 1);
- int nz = 0;
-
- if (is_i16) {
- nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]);
- } else {
- VP8IteratorStartI4(it);
- do {
- const int mode =
- it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_];
- const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
- uint8_t* const dst = it->yuv_out_ + Y_OFF_ENC + VP8Scan[it->i4_];
- VP8MakeIntra4Preds(it);
- nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
- src, dst, mode) << it->i4_;
- } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF_ENC));
- }
-
- nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_);
- rd->nz = nz;
-}
-
-// Refine intra16/intra4 sub-modes based on distortion only (not rate).
-static void RefineUsingDistortion(VP8EncIterator* const it,
- int try_both_modes, int refine_uv_mode,
- VP8ModeScore* const rd) {
- score_t best_score = MAX_COST;
- int nz = 0;
- int mode;
- int is_i16 = try_both_modes || (it->mb_->type_ == 1);
-
- const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
- // Some empiric constants, of approximate order of magnitude.
- const int lambda_d_i16 = 106;
- const int lambda_d_i4 = 11;
- const int lambda_d_uv = 120;
- score_t score_i4 = dqm->i4_penalty_;
- score_t i4_bit_sum = 0;
- const score_t bit_limit = it->enc_->mb_header_limit_;
-
- if (is_i16) { // First, evaluate Intra16 distortion
- int best_mode = -1;
- const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
- for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
- const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
- const score_t score = VP8SSE16x16(src, ref) * RD_DISTO_MULT
- + VP8FixedCostsI16[mode] * lambda_d_i16;
- if (mode > 0 && VP8FixedCostsI16[mode] > bit_limit) {
- continue;
- }
- if (score < best_score) {
- best_mode = mode;
- best_score = score;
- }
- }
- VP8SetIntra16Mode(it, best_mode);
- // we'll reconstruct later, if i16 mode actually gets selected
- }
-
- // Next, evaluate Intra4
- if (try_both_modes || !is_i16) {
- // We don't evaluate the rate here, but just account for it through a
- // constant penalty (i4 mode usually needs more bits compared to i16).
- is_i16 = 0;
- VP8IteratorStartI4(it);
- do {
- int best_i4_mode = -1;
- score_t best_i4_score = MAX_COST;
- const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
- const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4);
-
- VP8MakeIntra4Preds(it);
- for (mode = 0; mode < NUM_BMODES; ++mode) {
- const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode];
- const score_t score = VP8SSE4x4(src, ref) * RD_DISTO_MULT
- + mode_costs[mode] * lambda_d_i4;
- if (score < best_i4_score) {
- best_i4_mode = mode;
- best_i4_score = score;
- }
- }
- i4_bit_sum += mode_costs[best_i4_mode];
- rd->modes_i4[it->i4_] = best_i4_mode;
- score_i4 += best_i4_score;
- if (score_i4 >= best_score || i4_bit_sum > bit_limit) {
- // Intra4 won't be better than Intra16. Bail out and pick Intra16.
- is_i16 = 1;
- break;
- } else { // reconstruct partial block inside yuv_out2_ buffer
- uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC + VP8Scan[it->i4_];
- nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
- src, tmp_dst, best_i4_mode) << it->i4_;
- }
- } while (VP8IteratorRotateI4(it, it->yuv_out2_ + Y_OFF_ENC));
- }
-
- // Final reconstruction, depending on which mode is selected.
- if (!is_i16) {
- VP8SetIntra4Mode(it, rd->modes_i4);
- SwapOut(it);
- best_score = score_i4;
- } else {
- nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]);
- }
-
- // ... and UV!
- if (refine_uv_mode) {
- int best_mode = -1;
- score_t best_uv_score = MAX_COST;
- const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
- for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
- const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
- const score_t score = VP8SSE16x8(src, ref) * RD_DISTO_MULT
- + VP8FixedCostsUV[mode] * lambda_d_uv;
- if (score < best_uv_score) {
- best_mode = mode;
- best_uv_score = score;
- }
- }
- VP8SetIntraUVMode(it, best_mode);
- }
- nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_);
-
- rd->nz = nz;
- rd->score = best_score;
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd,
- VP8RDLevel rd_opt) {
- int is_skipped;
- const int method = it->enc_->method_;
-
- InitScore(rd);
-
- // We can perform predictions for Luma16x16 and Chroma8x8 already.
- // Luma4x4 predictions needs to be done as-we-go.
- VP8MakeLuma16Preds(it);
- VP8MakeChroma8Preds(it);
-
- if (rd_opt > RD_OPT_NONE) {
- it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL);
- PickBestIntra16(it, rd);
- if (method >= 2) {
- PickBestIntra4(it, rd);
- }
- PickBestUV(it, rd);
- if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now
- it->do_trellis_ = 1;
- SimpleQuantize(it, rd);
- }
- } else {
- // At this point we have heuristically decided intra16 / intra4.
- // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower).
- // For method <= 1, we don't re-examine the decision but just go ahead with
- // quantization/reconstruction.
- RefineUsingDistortion(it, (method >= 2), (method >= 1), rd);
- }
- is_skipped = (rd->nz == 0);
- VP8SetSkip(it, is_skipped);
- return is_skipped;
-}
diff --git a/drivers/webp/enc/syntax.c b/drivers/webp/enc/syntax.c
deleted file mode 100644
index 2b65f15ca1..0000000000
--- a/drivers/webp/enc/syntax.c
+++ /dev/null
@@ -1,383 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Header syntax writing
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-
-#include "../utils/utils.h"
-#include "webp/format_constants.h" // RIFF constants
-#include "webp/mux_types.h" // ALPHA_FLAG
-#include "./vp8enci.h"
-
-//------------------------------------------------------------------------------
-// Helper functions
-
-static int IsVP8XNeeded(const VP8Encoder* const enc) {
- return !!enc->has_alpha_; // Currently the only case when VP8X is needed.
- // This could change in the future.
-}
-
-static int PutPaddingByte(const WebPPicture* const pic) {
- const uint8_t pad_byte[1] = { 0 };
- return !!pic->writer(pad_byte, 1, pic);
-}
-
-//------------------------------------------------------------------------------
-// Writers for header's various pieces (in order of appearance)
-
-static WebPEncodingError PutRIFFHeader(const VP8Encoder* const enc,
- size_t riff_size) {
- const WebPPicture* const pic = enc->pic_;
- uint8_t riff[RIFF_HEADER_SIZE] = {
- 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P'
- };
- assert(riff_size == (uint32_t)riff_size);
- PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
- if (!pic->writer(riff, sizeof(riff), pic)) {
- return VP8_ENC_ERROR_BAD_WRITE;
- }
- return VP8_ENC_OK;
-}
-
-static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) {
- const WebPPicture* const pic = enc->pic_;
- uint8_t vp8x[CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE] = {
- 'V', 'P', '8', 'X'
- };
- uint32_t flags = 0;
-
- assert(IsVP8XNeeded(enc));
- assert(pic->width >= 1 && pic->height >= 1);
- assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE);
-
- if (enc->has_alpha_) {
- flags |= ALPHA_FLAG;
- }
-
- PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE);
- PutLE32(vp8x + CHUNK_HEADER_SIZE, flags);
- PutLE24(vp8x + CHUNK_HEADER_SIZE + 4, pic->width - 1);
- PutLE24(vp8x + CHUNK_HEADER_SIZE + 7, pic->height - 1);
- if (!pic->writer(vp8x, sizeof(vp8x), pic)) {
- return VP8_ENC_ERROR_BAD_WRITE;
- }
- return VP8_ENC_OK;
-}
-
-static WebPEncodingError PutAlphaChunk(const VP8Encoder* const enc) {
- const WebPPicture* const pic = enc->pic_;
- uint8_t alpha_chunk_hdr[CHUNK_HEADER_SIZE] = {
- 'A', 'L', 'P', 'H'
- };
-
- assert(enc->has_alpha_);
-
- // Alpha chunk header.
- PutLE32(alpha_chunk_hdr + TAG_SIZE, enc->alpha_data_size_);
- if (!pic->writer(alpha_chunk_hdr, sizeof(alpha_chunk_hdr), pic)) {
- return VP8_ENC_ERROR_BAD_WRITE;
- }
-
- // Alpha chunk data.
- if (!pic->writer(enc->alpha_data_, enc->alpha_data_size_, pic)) {
- return VP8_ENC_ERROR_BAD_WRITE;
- }
-
- // Padding.
- if ((enc->alpha_data_size_ & 1) && !PutPaddingByte(pic)) {
- return VP8_ENC_ERROR_BAD_WRITE;
- }
- return VP8_ENC_OK;
-}
-
-static WebPEncodingError PutVP8Header(const WebPPicture* const pic,
- size_t vp8_size) {
- uint8_t vp8_chunk_hdr[CHUNK_HEADER_SIZE] = {
- 'V', 'P', '8', ' '
- };
- assert(vp8_size == (uint32_t)vp8_size);
- PutLE32(vp8_chunk_hdr + TAG_SIZE, (uint32_t)vp8_size);
- if (!pic->writer(vp8_chunk_hdr, sizeof(vp8_chunk_hdr), pic)) {
- return VP8_ENC_ERROR_BAD_WRITE;
- }
- return VP8_ENC_OK;
-}
-
-static WebPEncodingError PutVP8FrameHeader(const WebPPicture* const pic,
- int profile, size_t size0) {
- uint8_t vp8_frm_hdr[VP8_FRAME_HEADER_SIZE];
- uint32_t bits;
-
- if (size0 >= VP8_MAX_PARTITION0_SIZE) { // partition #0 is too big to fit
- return VP8_ENC_ERROR_PARTITION0_OVERFLOW;
- }
-
- // Paragraph 9.1.
- bits = 0 // keyframe (1b)
- | (profile << 1) // profile (3b)
- | (1 << 4) // visible (1b)
- | ((uint32_t)size0 << 5); // partition length (19b)
- vp8_frm_hdr[0] = (bits >> 0) & 0xff;
- vp8_frm_hdr[1] = (bits >> 8) & 0xff;
- vp8_frm_hdr[2] = (bits >> 16) & 0xff;
- // signature
- vp8_frm_hdr[3] = (VP8_SIGNATURE >> 16) & 0xff;
- vp8_frm_hdr[4] = (VP8_SIGNATURE >> 8) & 0xff;
- vp8_frm_hdr[5] = (VP8_SIGNATURE >> 0) & 0xff;
- // dimensions
- vp8_frm_hdr[6] = pic->width & 0xff;
- vp8_frm_hdr[7] = pic->width >> 8;
- vp8_frm_hdr[8] = pic->height & 0xff;
- vp8_frm_hdr[9] = pic->height >> 8;
-
- if (!pic->writer(vp8_frm_hdr, sizeof(vp8_frm_hdr), pic)) {
- return VP8_ENC_ERROR_BAD_WRITE;
- }
- return VP8_ENC_OK;
-}
-
-// WebP Headers.
-static int PutWebPHeaders(const VP8Encoder* const enc, size_t size0,
- size_t vp8_size, size_t riff_size) {
- WebPPicture* const pic = enc->pic_;
- WebPEncodingError err = VP8_ENC_OK;
-
- // RIFF header.
- err = PutRIFFHeader(enc, riff_size);
- if (err != VP8_ENC_OK) goto Error;
-
- // VP8X.
- if (IsVP8XNeeded(enc)) {
- err = PutVP8XHeader(enc);
- if (err != VP8_ENC_OK) goto Error;
- }
-
- // Alpha.
- if (enc->has_alpha_) {
- err = PutAlphaChunk(enc);
- if (err != VP8_ENC_OK) goto Error;
- }
-
- // VP8 header.
- err = PutVP8Header(pic, vp8_size);
- if (err != VP8_ENC_OK) goto Error;
-
- // VP8 frame header.
- err = PutVP8FrameHeader(pic, enc->profile_, size0);
- if (err != VP8_ENC_OK) goto Error;
-
- // All OK.
- return 1;
-
- // Error.
- Error:
- return WebPEncodingSetError(pic, err);
-}
-
-// Segmentation header
-static void PutSegmentHeader(VP8BitWriter* const bw,
- const VP8Encoder* const enc) {
- const VP8EncSegmentHeader* const hdr = &enc->segment_hdr_;
- const VP8EncProba* const proba = &enc->proba_;
- if (VP8PutBitUniform(bw, (hdr->num_segments_ > 1))) {
- // We always 'update' the quant and filter strength values
- const int update_data = 1;
- int s;
- VP8PutBitUniform(bw, hdr->update_map_);
- if (VP8PutBitUniform(bw, update_data)) {
- // we always use absolute values, not relative ones
- VP8PutBitUniform(bw, 1); // (segment_feature_mode = 1. Paragraph 9.3.)
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7);
- }
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6);
- }
- }
- if (hdr->update_map_) {
- for (s = 0; s < 3; ++s) {
- if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) {
- VP8PutBits(bw, proba->segments_[s], 8);
- }
- }
- }
- }
-}
-
-// Filtering parameters header
-static void PutFilterHeader(VP8BitWriter* const bw,
- const VP8EncFilterHeader* const hdr) {
- const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0);
- VP8PutBitUniform(bw, hdr->simple_);
- VP8PutBits(bw, hdr->level_, 6);
- VP8PutBits(bw, hdr->sharpness_, 3);
- if (VP8PutBitUniform(bw, use_lf_delta)) {
- // '0' is the default value for i4x4_lf_delta_ at frame #0.
- const int need_update = (hdr->i4x4_lf_delta_ != 0);
- if (VP8PutBitUniform(bw, need_update)) {
- // we don't use ref_lf_delta => emit four 0 bits
- VP8PutBits(bw, 0, 4);
- // we use mode_lf_delta for i4x4
- VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6);
- VP8PutBits(bw, 0, 3); // all others unused
- }
- }
-}
-
-// Nominal quantization parameters
-static void PutQuant(VP8BitWriter* const bw,
- const VP8Encoder* const enc) {
- VP8PutBits(bw, enc->base_quant_, 7);
- VP8PutSignedBits(bw, enc->dq_y1_dc_, 4);
- VP8PutSignedBits(bw, enc->dq_y2_dc_, 4);
- VP8PutSignedBits(bw, enc->dq_y2_ac_, 4);
- VP8PutSignedBits(bw, enc->dq_uv_dc_, 4);
- VP8PutSignedBits(bw, enc->dq_uv_ac_, 4);
-}
-
-// Partition sizes
-static int EmitPartitionsSize(const VP8Encoder* const enc,
- WebPPicture* const pic) {
- uint8_t buf[3 * (MAX_NUM_PARTITIONS - 1)];
- int p;
- for (p = 0; p < enc->num_parts_ - 1; ++p) {
- const size_t part_size = VP8BitWriterSize(enc->parts_ + p);
- if (part_size >= VP8_MAX_PARTITION_SIZE) {
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_PARTITION_OVERFLOW);
- }
- buf[3 * p + 0] = (part_size >> 0) & 0xff;
- buf[3 * p + 1] = (part_size >> 8) & 0xff;
- buf[3 * p + 2] = (part_size >> 16) & 0xff;
- }
- return p ? pic->writer(buf, 3 * p, pic) : 1;
-}
-
-//------------------------------------------------------------------------------
-
-static int GeneratePartition0(VP8Encoder* const enc) {
- VP8BitWriter* const bw = &enc->bw_;
- const int mb_size = enc->mb_w_ * enc->mb_h_;
- uint64_t pos1, pos2, pos3;
-
- pos1 = VP8BitWriterPos(bw);
- if (!VP8BitWriterInit(bw, mb_size * 7 / 8)) { // ~7 bits per macroblock
- return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
- VP8PutBitUniform(bw, 0); // colorspace
- VP8PutBitUniform(bw, 0); // clamp type
-
- PutSegmentHeader(bw, enc);
- PutFilterHeader(bw, &enc->filter_hdr_);
- VP8PutBits(bw, enc->num_parts_ == 8 ? 3 :
- enc->num_parts_ == 4 ? 2 :
- enc->num_parts_ == 2 ? 1 : 0, 2);
- PutQuant(bw, enc);
- VP8PutBitUniform(bw, 0); // no proba update
- VP8WriteProbas(bw, &enc->proba_);
- pos2 = VP8BitWriterPos(bw);
- VP8CodeIntraModes(enc);
- VP8BitWriterFinish(bw);
-
- pos3 = VP8BitWriterPos(bw);
-
- if (enc->pic_->stats) {
- enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3);
- enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3);
- enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_;
- }
- if (bw->error_) {
- return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
- return 1;
-}
-
-void VP8EncFreeBitWriters(VP8Encoder* const enc) {
- int p;
- VP8BitWriterWipeOut(&enc->bw_);
- for (p = 0; p < enc->num_parts_; ++p) {
- VP8BitWriterWipeOut(enc->parts_ + p);
- }
-}
-
-int VP8EncWrite(VP8Encoder* const enc) {
- WebPPicture* const pic = enc->pic_;
- VP8BitWriter* const bw = &enc->bw_;
- const int task_percent = 19;
- const int percent_per_part = task_percent / enc->num_parts_;
- const int final_percent = enc->percent_ + task_percent;
- int ok = 0;
- size_t vp8_size, pad, riff_size;
- int p;
-
- // Partition #0 with header and partition sizes
- ok = GeneratePartition0(enc);
- if (!ok) return 0;
-
- // Compute VP8 size
- vp8_size = VP8_FRAME_HEADER_SIZE +
- VP8BitWriterSize(bw) +
- 3 * (enc->num_parts_ - 1);
- for (p = 0; p < enc->num_parts_; ++p) {
- vp8_size += VP8BitWriterSize(enc->parts_ + p);
- }
- pad = vp8_size & 1;
- vp8_size += pad;
-
- // Compute RIFF size
- // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size.
- riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8_size;
- if (IsVP8XNeeded(enc)) { // Add size for: VP8X header + data.
- riff_size += CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
- }
- if (enc->has_alpha_) { // Add size for: ALPH header + data.
- const uint32_t padded_alpha_size = enc->alpha_data_size_ +
- (enc->alpha_data_size_ & 1);
- riff_size += CHUNK_HEADER_SIZE + padded_alpha_size;
- }
- // Sanity check.
- if (riff_size > 0xfffffffeU) {
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_FILE_TOO_BIG);
- }
-
- // Emit headers and partition #0
- {
- const uint8_t* const part0 = VP8BitWriterBuf(bw);
- const size_t size0 = VP8BitWriterSize(bw);
- ok = ok && PutWebPHeaders(enc, size0, vp8_size, riff_size)
- && pic->writer(part0, size0, pic)
- && EmitPartitionsSize(enc, pic);
- VP8BitWriterWipeOut(bw); // will free the internal buffer.
- }
-
- // Token partitions
- for (p = 0; p < enc->num_parts_; ++p) {
- const uint8_t* const buf = VP8BitWriterBuf(enc->parts_ + p);
- const size_t size = VP8BitWriterSize(enc->parts_ + p);
- if (size)
- ok = ok && pic->writer(buf, size, pic);
- VP8BitWriterWipeOut(enc->parts_ + p); // will free the internal buffer.
- ok = ok && WebPReportProgress(pic, enc->percent_ + percent_per_part,
- &enc->percent_);
- }
-
- // Padding byte
- if (ok && pad) {
- ok = PutPaddingByte(pic);
- }
-
- enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size);
- ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_);
- return ok;
-}
-
-//------------------------------------------------------------------------------
-
diff --git a/drivers/webp/enc/token.c b/drivers/webp/enc/token.c
deleted file mode 100644
index e73256b37e..0000000000
--- a/drivers/webp/enc/token.c
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Paginated token buffer
-//
-// A 'token' is a bit value associated with a probability, either fixed
-// or a later-to-be-determined after statistics have been collected.
-// For dynamic probability, we just record the slot id (idx) for the probability
-// value in the final probability array (uint8_t* probas in VP8EmitTokens).
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "./cost.h"
-#include "./vp8enci.h"
-#include "../utils/utils.h"
-
-#if !defined(DISABLE_TOKEN_BUFFER)
-
-// we use pages to reduce the number of memcpy()
-#define MIN_PAGE_SIZE 8192 // minimum number of token per page
-#define FIXED_PROBA_BIT (1u << 14)
-
-typedef uint16_t token_t; // bit #15: bit value
- // bit #14: flags for constant proba or idx
- // bits #0..13: slot or constant proba
-struct VP8Tokens {
- VP8Tokens* next_; // pointer to next page
-};
-// Token data is located in memory just after the next_ field.
-// This macro is used to return their address and hide the trick.
-#define TOKEN_DATA(p) ((const token_t*)&(p)[1])
-
-//------------------------------------------------------------------------------
-
-void VP8TBufferInit(VP8TBuffer* const b, int page_size) {
- b->tokens_ = NULL;
- b->pages_ = NULL;
- b->last_page_ = &b->pages_;
- b->left_ = 0;
- b->page_size_ = (page_size < MIN_PAGE_SIZE) ? MIN_PAGE_SIZE : page_size;
- b->error_ = 0;
-}
-
-void VP8TBufferClear(VP8TBuffer* const b) {
- if (b != NULL) {
- VP8Tokens* p = b->pages_;
- while (p != NULL) {
- VP8Tokens* const next = p->next_;
- WebPSafeFree(p);
- p = next;
- }
- VP8TBufferInit(b, b->page_size_);
- }
-}
-
-static int TBufferNewPage(VP8TBuffer* const b) {
- VP8Tokens* page = NULL;
- if (!b->error_) {
- const size_t size = sizeof(*page) + b->page_size_ * sizeof(token_t);
- page = (VP8Tokens*)WebPSafeMalloc(1ULL, size);
- }
- if (page == NULL) {
- b->error_ = 1;
- return 0;
- }
- page->next_ = NULL;
-
- *b->last_page_ = page;
- b->last_page_ = &page->next_;
- b->left_ = b->page_size_;
- b->tokens_ = (token_t*)TOKEN_DATA(page);
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-#define TOKEN_ID(t, b, ctx) \
- (NUM_PROBAS * ((ctx) + NUM_CTX * ((b) + NUM_BANDS * (t))))
-
-static WEBP_INLINE uint32_t AddToken(VP8TBuffer* const b,
- uint32_t bit, uint32_t proba_idx) {
- assert(proba_idx < FIXED_PROBA_BIT);
- assert(bit <= 1);
- if (b->left_ > 0 || TBufferNewPage(b)) {
- const int slot = --b->left_;
- b->tokens_[slot] = (bit << 15) | proba_idx;
- }
- return bit;
-}
-
-static WEBP_INLINE void AddConstantToken(VP8TBuffer* const b,
- uint32_t bit, uint32_t proba) {
- assert(proba < 256);
- assert(bit <= 1);
- if (b->left_ > 0 || TBufferNewPage(b)) {
- const int slot = --b->left_;
- b->tokens_[slot] = (bit << 15) | FIXED_PROBA_BIT | proba;
- }
-}
-
-int VP8RecordCoeffTokens(const int ctx, const int coeff_type,
- int first, int last,
- const int16_t* const coeffs,
- VP8TBuffer* const tokens) {
- int n = first;
- uint32_t base_id = TOKEN_ID(coeff_type, n, ctx);
- if (!AddToken(tokens, last >= 0, base_id + 0)) {
- return 0;
- }
-
- while (n < 16) {
- const int c = coeffs[n++];
- const int sign = c < 0;
- const uint32_t v = sign ? -c : c;
- if (!AddToken(tokens, v != 0, base_id + 1)) {
- base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 0); // ctx=0
- continue;
- }
- if (!AddToken(tokens, v > 1, base_id + 2)) {
- base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 1); // ctx=1
- } else {
- if (!AddToken(tokens, v > 4, base_id + 3)) {
- if (AddToken(tokens, v != 2, base_id + 4))
- AddToken(tokens, v == 4, base_id + 5);
- } else if (!AddToken(tokens, v > 10, base_id + 6)) {
- if (!AddToken(tokens, v > 6, base_id + 7)) {
- AddConstantToken(tokens, v == 6, 159);
- } else {
- AddConstantToken(tokens, v >= 9, 165);
- AddConstantToken(tokens, !(v & 1), 145);
- }
- } else {
- int mask;
- const uint8_t* tab;
- uint32_t residue = v - 3;
- if (residue < (8 << 1)) { // VP8Cat3 (3b)
- AddToken(tokens, 0, base_id + 8);
- AddToken(tokens, 0, base_id + 9);
- residue -= (8 << 0);
- mask = 1 << 2;
- tab = VP8Cat3;
- } else if (residue < (8 << 2)) { // VP8Cat4 (4b)
- AddToken(tokens, 0, base_id + 8);
- AddToken(tokens, 1, base_id + 9);
- residue -= (8 << 1);
- mask = 1 << 3;
- tab = VP8Cat4;
- } else if (residue < (8 << 3)) { // VP8Cat5 (5b)
- AddToken(tokens, 1, base_id + 8);
- AddToken(tokens, 0, base_id + 10);
- residue -= (8 << 2);
- mask = 1 << 4;
- tab = VP8Cat5;
- } else { // VP8Cat6 (11b)
- AddToken(tokens, 1, base_id + 8);
- AddToken(tokens, 1, base_id + 10);
- residue -= (8 << 3);
- mask = 1 << 10;
- tab = VP8Cat6;
- }
- while (mask) {
- AddConstantToken(tokens, !!(residue & mask), *tab++);
- mask >>= 1;
- }
- }
- base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 2); // ctx=2
- }
- AddConstantToken(tokens, sign, 128);
- if (n == 16 || !AddToken(tokens, n <= last, base_id + 0)) {
- return 1; // EOB
- }
- }
- return 1;
-}
-
-#undef TOKEN_ID
-
-//------------------------------------------------------------------------------
-// This function works, but isn't currently used. Saved for later.
-
-#if 0
-
-static void Record(int bit, proba_t* const stats) {
- proba_t p = *stats;
- if (p >= 0xffff0000u) { // an overflow is inbound.
- p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2.
- }
- // record bit count (lower 16 bits) and increment total count (upper 16 bits).
- p += 0x00010000u + bit;
- *stats = p;
-}
-
-void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats) {
- const VP8Tokens* p = b->pages_;
- while (p != NULL) {
- const int N = (p->next_ == NULL) ? b->left_ : 0;
- int n = MAX_NUM_TOKEN;
- const token_t* const tokens = TOKEN_DATA(p);
- while (n-- > N) {
- const token_t token = tokens[n];
- if (!(token & FIXED_PROBA_BIT)) {
- Record((token >> 15) & 1, stats + (token & 0x3fffu));
- }
- }
- p = p->next_;
- }
-}
-
-#endif // 0
-
-//------------------------------------------------------------------------------
-// Final coding pass, with known probabilities
-
-int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw,
- const uint8_t* const probas, int final_pass) {
- const VP8Tokens* p = b->pages_;
- assert(!b->error_);
- while (p != NULL) {
- const VP8Tokens* const next = p->next_;
- const int N = (next == NULL) ? b->left_ : 0;
- int n = b->page_size_;
- const token_t* const tokens = TOKEN_DATA(p);
- while (n-- > N) {
- const token_t token = tokens[n];
- const int bit = (token >> 15) & 1;
- if (token & FIXED_PROBA_BIT) {
- VP8PutBit(bw, bit, token & 0xffu); // constant proba
- } else {
- VP8PutBit(bw, bit, probas[token & 0x3fffu]);
- }
- }
- if (final_pass) WebPSafeFree((void*)p);
- p = next;
- }
- if (final_pass) b->pages_ = NULL;
- return 1;
-}
-
-// Size estimation
-size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas) {
- size_t size = 0;
- const VP8Tokens* p = b->pages_;
- assert(!b->error_);
- while (p != NULL) {
- const VP8Tokens* const next = p->next_;
- const int N = (next == NULL) ? b->left_ : 0;
- int n = b->page_size_;
- const token_t* const tokens = TOKEN_DATA(p);
- while (n-- > N) {
- const token_t token = tokens[n];
- const int bit = token & (1 << 15);
- if (token & FIXED_PROBA_BIT) {
- size += VP8BitCost(bit, token & 0xffu);
- } else {
- size += VP8BitCost(bit, probas[token & 0x3fffu]);
- }
- }
- p = next;
- }
- return size;
-}
-
-//------------------------------------------------------------------------------
-
-#else // DISABLE_TOKEN_BUFFER
-
-void VP8TBufferInit(VP8TBuffer* const b) {
- (void)b;
-}
-void VP8TBufferClear(VP8TBuffer* const b) {
- (void)b;
-}
-
-#endif // !DISABLE_TOKEN_BUFFER
-
diff --git a/drivers/webp/enc/tree.c b/drivers/webp/enc/tree.c
deleted file mode 100644
index f141006d19..0000000000
--- a/drivers/webp/enc/tree.c
+++ /dev/null
@@ -1,504 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Coding of token probabilities, intra modes and segments.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./vp8enci.h"
-
-//------------------------------------------------------------------------------
-// Default probabilities
-
-// Paragraph 13.5
-const uint8_t
- VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 },
- { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 },
- { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 }
- },
- { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 },
- { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 },
- { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 },
- },
- { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 },
- { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 },
- { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 },
- },
- { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 },
- { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 },
- { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 }
- },
- { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 },
- { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 },
- { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 }
- },
- { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 },
- { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 },
- { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 }
- },
- { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- },
- { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 },
- { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 },
- { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 }
- },
- { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 },
- { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 },
- { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 }
- },
- { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 },
- { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 },
- { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 }
- },
- { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 },
- { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 },
- { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 }
- },
- { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 },
- { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 },
- { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 }
- },
- { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 },
- { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 },
- { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 }
- },
- { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 },
- { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 },
- { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 }
- },
- { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 },
- { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 }
- }
- },
- { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 },
- { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 },
- { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 }
- },
- { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 },
- { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 },
- { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 }
- },
- { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 },
- { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 },
- { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 }
- },
- { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 },
- { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 },
- { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- },
- { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 },
- { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 },
- { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 }
- },
- { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 },
- { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 },
- { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 }
- },
- { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 },
- { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 },
- { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 }
- },
- { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 },
- { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 },
- { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 }
- },
- { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 },
- { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 },
- { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 }
- },
- { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 },
- { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 },
- { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 }
- },
- { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 },
- { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 },
- { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 }
- },
- { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- }
-};
-
-void VP8DefaultProbas(VP8Encoder* const enc) {
- VP8EncProba* const probas = &enc->proba_;
- probas->use_skip_proba_ = 0;
- memset(probas->segments_, 255u, sizeof(probas->segments_));
- memcpy(probas->coeffs_, VP8CoeffsProba0, sizeof(VP8CoeffsProba0));
- // Note: we could hard-code the level_costs_ corresponding to VP8CoeffsProba0,
- // but that's ~11k of static data. Better call VP8CalculateLevelCosts() later.
- probas->dirty_ = 1;
-}
-
-// Paragraph 11.5. 900bytes.
-static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
- { { 231, 120, 48, 89, 115, 113, 120, 152, 112 },
- { 152, 179, 64, 126, 170, 118, 46, 70, 95 },
- { 175, 69, 143, 80, 85, 82, 72, 155, 103 },
- { 56, 58, 10, 171, 218, 189, 17, 13, 152 },
- { 114, 26, 17, 163, 44, 195, 21, 10, 173 },
- { 121, 24, 80, 195, 26, 62, 44, 64, 85 },
- { 144, 71, 10, 38, 171, 213, 144, 34, 26 },
- { 170, 46, 55, 19, 136, 160, 33, 206, 71 },
- { 63, 20, 8, 114, 114, 208, 12, 9, 226 },
- { 81, 40, 11, 96, 182, 84, 29, 16, 36 } },
- { { 134, 183, 89, 137, 98, 101, 106, 165, 148 },
- { 72, 187, 100, 130, 157, 111, 32, 75, 80 },
- { 66, 102, 167, 99, 74, 62, 40, 234, 128 },
- { 41, 53, 9, 178, 241, 141, 26, 8, 107 },
- { 74, 43, 26, 146, 73, 166, 49, 23, 157 },
- { 65, 38, 105, 160, 51, 52, 31, 115, 128 },
- { 104, 79, 12, 27, 217, 255, 87, 17, 7 },
- { 87, 68, 71, 44, 114, 51, 15, 186, 23 },
- { 47, 41, 14, 110, 182, 183, 21, 17, 194 },
- { 66, 45, 25, 102, 197, 189, 23, 18, 22 } },
- { { 88, 88, 147, 150, 42, 46, 45, 196, 205 },
- { 43, 97, 183, 117, 85, 38, 35, 179, 61 },
- { 39, 53, 200, 87, 26, 21, 43, 232, 171 },
- { 56, 34, 51, 104, 114, 102, 29, 93, 77 },
- { 39, 28, 85, 171, 58, 165, 90, 98, 64 },
- { 34, 22, 116, 206, 23, 34, 43, 166, 73 },
- { 107, 54, 32, 26, 51, 1, 81, 43, 31 },
- { 68, 25, 106, 22, 64, 171, 36, 225, 114 },
- { 34, 19, 21, 102, 132, 188, 16, 76, 124 },
- { 62, 18, 78, 95, 85, 57, 50, 48, 51 } },
- { { 193, 101, 35, 159, 215, 111, 89, 46, 111 },
- { 60, 148, 31, 172, 219, 228, 21, 18, 111 },
- { 112, 113, 77, 85, 179, 255, 38, 120, 114 },
- { 40, 42, 1, 196, 245, 209, 10, 25, 109 },
- { 88, 43, 29, 140, 166, 213, 37, 43, 154 },
- { 61, 63, 30, 155, 67, 45, 68, 1, 209 },
- { 100, 80, 8, 43, 154, 1, 51, 26, 71 },
- { 142, 78, 78, 16, 255, 128, 34, 197, 171 },
- { 41, 40, 5, 102, 211, 183, 4, 1, 221 },
- { 51, 50, 17, 168, 209, 192, 23, 25, 82 } },
- { { 138, 31, 36, 171, 27, 166, 38, 44, 229 },
- { 67, 87, 58, 169, 82, 115, 26, 59, 179 },
- { 63, 59, 90, 180, 59, 166, 93, 73, 154 },
- { 40, 40, 21, 116, 143, 209, 34, 39, 175 },
- { 47, 15, 16, 183, 34, 223, 49, 45, 183 },
- { 46, 17, 33, 183, 6, 98, 15, 32, 183 },
- { 57, 46, 22, 24, 128, 1, 54, 17, 37 },
- { 65, 32, 73, 115, 28, 128, 23, 128, 205 },
- { 40, 3, 9, 115, 51, 192, 18, 6, 223 },
- { 87, 37, 9, 115, 59, 77, 64, 21, 47 } },
- { { 104, 55, 44, 218, 9, 54, 53, 130, 226 },
- { 64, 90, 70, 205, 40, 41, 23, 26, 57 },
- { 54, 57, 112, 184, 5, 41, 38, 166, 213 },
- { 30, 34, 26, 133, 152, 116, 10, 32, 134 },
- { 39, 19, 53, 221, 26, 114, 32, 73, 255 },
- { 31, 9, 65, 234, 2, 15, 1, 118, 73 },
- { 75, 32, 12, 51, 192, 255, 160, 43, 51 },
- { 88, 31, 35, 67, 102, 85, 55, 186, 85 },
- { 56, 21, 23, 111, 59, 205, 45, 37, 192 },
- { 55, 38, 70, 124, 73, 102, 1, 34, 98 } },
- { { 125, 98, 42, 88, 104, 85, 117, 175, 82 },
- { 95, 84, 53, 89, 128, 100, 113, 101, 45 },
- { 75, 79, 123, 47, 51, 128, 81, 171, 1 },
- { 57, 17, 5, 71, 102, 57, 53, 41, 49 },
- { 38, 33, 13, 121, 57, 73, 26, 1, 85 },
- { 41, 10, 67, 138, 77, 110, 90, 47, 114 },
- { 115, 21, 2, 10, 102, 255, 166, 23, 6 },
- { 101, 29, 16, 10, 85, 128, 101, 196, 26 },
- { 57, 18, 10, 102, 102, 213, 34, 20, 43 },
- { 117, 20, 15, 36, 163, 128, 68, 1, 26 } },
- { { 102, 61, 71, 37, 34, 53, 31, 243, 192 },
- { 69, 60, 71, 38, 73, 119, 28, 222, 37 },
- { 68, 45, 128, 34, 1, 47, 11, 245, 171 },
- { 62, 17, 19, 70, 146, 85, 55, 62, 70 },
- { 37, 43, 37, 154, 100, 163, 85, 160, 1 },
- { 63, 9, 92, 136, 28, 64, 32, 201, 85 },
- { 75, 15, 9, 9, 64, 255, 184, 119, 16 },
- { 86, 6, 28, 5, 64, 255, 25, 248, 1 },
- { 56, 8, 17, 132, 137, 255, 55, 116, 128 },
- { 58, 15, 20, 82, 135, 57, 26, 121, 40 } },
- { { 164, 50, 31, 137, 154, 133, 25, 35, 218 },
- { 51, 103, 44, 131, 131, 123, 31, 6, 158 },
- { 86, 40, 64, 135, 148, 224, 45, 183, 128 },
- { 22, 26, 17, 131, 240, 154, 14, 1, 209 },
- { 45, 16, 21, 91, 64, 222, 7, 1, 197 },
- { 56, 21, 39, 155, 60, 138, 23, 102, 213 },
- { 83, 12, 13, 54, 192, 255, 68, 47, 28 },
- { 85, 26, 85, 85, 128, 128, 32, 146, 171 },
- { 18, 11, 7, 63, 144, 171, 4, 4, 246 },
- { 35, 27, 10, 146, 174, 171, 12, 26, 128 } },
- { { 190, 80, 35, 99, 180, 80, 126, 54, 45 },
- { 85, 126, 47, 87, 176, 51, 41, 20, 32 },
- { 101, 75, 128, 139, 118, 146, 116, 128, 85 },
- { 56, 41, 15, 176, 236, 85, 37, 9, 62 },
- { 71, 30, 17, 119, 118, 255, 17, 18, 138 },
- { 101, 38, 60, 138, 55, 70, 43, 26, 142 },
- { 146, 36, 19, 30, 171, 255, 97, 27, 20 },
- { 138, 45, 61, 62, 219, 1, 81, 188, 64 },
- { 32, 41, 20, 117, 151, 142, 20, 21, 163 },
- { 112, 19, 12, 61, 195, 128, 48, 4, 24 } }
-};
-
-static int PutI4Mode(VP8BitWriter* const bw, int mode,
- const uint8_t* const prob) {
- if (VP8PutBit(bw, mode != B_DC_PRED, prob[0])) {
- if (VP8PutBit(bw, mode != B_TM_PRED, prob[1])) {
- if (VP8PutBit(bw, mode != B_VE_PRED, prob[2])) {
- if (!VP8PutBit(bw, mode >= B_LD_PRED, prob[3])) {
- if (VP8PutBit(bw, mode != B_HE_PRED, prob[4])) {
- VP8PutBit(bw, mode != B_RD_PRED, prob[5]);
- }
- } else {
- if (VP8PutBit(bw, mode != B_LD_PRED, prob[6])) {
- if (VP8PutBit(bw, mode != B_VL_PRED, prob[7])) {
- VP8PutBit(bw, mode != B_HD_PRED, prob[8]);
- }
- }
- }
- }
- }
- }
- return mode;
-}
-
-static void PutI16Mode(VP8BitWriter* const bw, int mode) {
- if (VP8PutBit(bw, (mode == TM_PRED || mode == H_PRED), 156)) {
- VP8PutBit(bw, mode == TM_PRED, 128); // TM or HE
- } else {
- VP8PutBit(bw, mode == V_PRED, 163); // VE or DC
- }
-}
-
-static void PutUVMode(VP8BitWriter* const bw, int uv_mode) {
- if (VP8PutBit(bw, uv_mode != DC_PRED, 142)) {
- if (VP8PutBit(bw, uv_mode != V_PRED, 114)) {
- VP8PutBit(bw, uv_mode != H_PRED, 183); // else: TM_PRED
- }
- }
-}
-
-static void PutSegment(VP8BitWriter* const bw, int s, const uint8_t* p) {
- if (VP8PutBit(bw, s >= 2, p[0])) p += 1;
- VP8PutBit(bw, s & 1, p[1]);
-}
-
-void VP8CodeIntraModes(VP8Encoder* const enc) {
- VP8BitWriter* const bw = &enc->bw_;
- VP8EncIterator it;
- VP8IteratorInit(enc, &it);
- do {
- const VP8MBInfo* const mb = it.mb_;
- const uint8_t* preds = it.preds_;
- if (enc->segment_hdr_.update_map_) {
- PutSegment(bw, mb->segment_, enc->proba_.segments_);
- }
- if (enc->proba_.use_skip_proba_) {
- VP8PutBit(bw, mb->skip_, enc->proba_.skip_proba_);
- }
- if (VP8PutBit(bw, (mb->type_ != 0), 145)) { // i16x16
- PutI16Mode(bw, preds[0]);
- } else {
- const int preds_w = enc->preds_w_;
- const uint8_t* top_pred = preds - preds_w;
- int x, y;
- for (y = 0; y < 4; ++y) {
- int left = preds[-1];
- for (x = 0; x < 4; ++x) {
- const uint8_t* const probas = kBModesProba[top_pred[x]][left];
- left = PutI4Mode(bw, preds[x], probas);
- }
- top_pred = preds;
- preds += preds_w;
- }
- }
- PutUVMode(bw, mb->uv_mode_);
- } while (VP8IteratorNext(&it));
-}
-
-//------------------------------------------------------------------------------
-// Paragraph 13
-
-const uint8_t
- VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 },
- { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 }
- },
- { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 },
- { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- }
-};
-
-void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas) {
- int t, b, c, p;
- for (t = 0; t < NUM_TYPES; ++t) {
- for (b = 0; b < NUM_BANDS; ++b) {
- for (c = 0; c < NUM_CTX; ++c) {
- for (p = 0; p < NUM_PROBAS; ++p) {
- const uint8_t p0 = probas->coeffs_[t][b][c][p];
- const int update = (p0 != VP8CoeffsProba0[t][b][c][p]);
- if (VP8PutBit(bw, update, VP8CoeffsUpdateProba[t][b][c][p])) {
- VP8PutBits(bw, p0, 8);
- }
- }
- }
- }
- }
- if (VP8PutBitUniform(bw, probas->use_skip_proba_)) {
- VP8PutBits(bw, probas->skip_proba_, 8);
- }
-}
-
diff --git a/drivers/webp/enc/vp8enci.h b/drivers/webp/enc/vp8enci.h
deleted file mode 100644
index efd2f19a9b..0000000000
--- a/drivers/webp/enc/vp8enci.h
+++ /dev/null
@@ -1,531 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebP encoder: internal header.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_ENC_VP8ENCI_H_
-#define WEBP_ENC_VP8ENCI_H_
-
-#include <string.h> // for memcpy()
-#include "../dec/common.h"
-#include "../dsp/dsp.h"
-#include "../utils/bit_writer.h"
-#include "../utils/thread.h"
-#include "../utils/utils.h"
-#include "webp/encode.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Various defines and enums
-
-// version numbers
-#define ENC_MAJ_VERSION 0
-#define ENC_MIN_VERSION 5
-#define ENC_REV_VERSION 1
-
-enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
- MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
- MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67)
- };
-
-typedef enum { // Rate-distortion optimization levels
- RD_OPT_NONE = 0, // no rd-opt
- RD_OPT_BASIC = 1, // basic scoring (no trellis)
- RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only
- RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower)
-} VP8RDLevel;
-
-// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
-// The original or reconstructed samples can be accessed using VP8Scan[].
-// The predicted blocks can be accessed using offsets to yuv_p_ and
-// the arrays VP8*ModeOffsets[].
-// * YUV Samples area (yuv_in_/yuv_out_/yuv_out2_)
-// (see VP8Scan[] for accessing the blocks, along with
-// Y_OFF_ENC/U_OFF_ENC/V_OFF_ENC):
-// +----+----+
-// Y_OFF_ENC |YYYY|UUVV|
-// U_OFF_ENC |YYYY|UUVV|
-// V_OFF_ENC |YYYY|....| <- 25% wasted U/V area
-// |YYYY|....|
-// +----+----+
-// * Prediction area ('yuv_p_', size = PRED_SIZE_ENC)
-// Intra16 predictions (16x16 block each, two per row):
-// |I16DC16|I16TM16|
-// |I16VE16|I16HE16|
-// Chroma U/V predictions (16x8 block each, two per row):
-// |C8DC8|C8TM8|
-// |C8VE8|C8HE8|
-// Intra 4x4 predictions (4x4 block each)
-// |I4DC4 I4TM4 I4VE4 I4HE4|I4RD4 I4VR4 I4LD4 I4VL4|
-// |I4HD4 I4HU4 I4TMP .....|.......................| <- ~31% wasted
-#define YUV_SIZE_ENC (BPS * 16)
-#define PRED_SIZE_ENC (32 * BPS + 16 * BPS + 8 * BPS) // I16+Chroma+I4 preds
-#define Y_OFF_ENC (0)
-#define U_OFF_ENC (16)
-#define V_OFF_ENC (16 + 8)
-
-extern const int VP8Scan[16]; // in quant.c
-extern const int VP8UVModeOffsets[4]; // in analyze.c
-extern const int VP8I16ModeOffsets[4];
-extern const int VP8I4ModeOffsets[NUM_BMODES];
-
-// Layout of prediction blocks
-// intra 16x16
-#define I16DC16 (0 * 16 * BPS)
-#define I16TM16 (I16DC16 + 16)
-#define I16VE16 (1 * 16 * BPS)
-#define I16HE16 (I16VE16 + 16)
-// chroma 8x8, two U/V blocks side by side (hence: 16x8 each)
-#define C8DC8 (2 * 16 * BPS)
-#define C8TM8 (C8DC8 + 1 * 16)
-#define C8VE8 (2 * 16 * BPS + 8 * BPS)
-#define C8HE8 (C8VE8 + 1 * 16)
-// intra 4x4
-#define I4DC4 (3 * 16 * BPS + 0)
-#define I4TM4 (I4DC4 + 4)
-#define I4VE4 (I4DC4 + 8)
-#define I4HE4 (I4DC4 + 12)
-#define I4RD4 (I4DC4 + 16)
-#define I4VR4 (I4DC4 + 20)
-#define I4LD4 (I4DC4 + 24)
-#define I4VL4 (I4DC4 + 28)
-#define I4HD4 (3 * 16 * BPS + 4 * BPS)
-#define I4HU4 (I4HD4 + 4)
-#define I4TMP (I4HD4 + 8)
-
-typedef int64_t score_t; // type used for scores, rate, distortion
-// Note that MAX_COST is not the maximum allowed by sizeof(score_t),
-// in order to allow overflowing computations.
-#define MAX_COST ((score_t)0x7fffffffffffffLL)
-
-#define QFIX 17
-#define BIAS(b) ((b) << (QFIX - 8))
-// Fun fact: this is the _only_ line where we're actually being lossy and
-// discarding bits.
-static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) {
- return (int)((n * iQ + B) >> QFIX);
-}
-
-// Uncomment the following to remove token-buffer code:
-// #define DISABLE_TOKEN_BUFFER
-
-//------------------------------------------------------------------------------
-// Headers
-
-typedef uint32_t proba_t; // 16b + 16b
-typedef uint8_t ProbaArray[NUM_CTX][NUM_PROBAS];
-typedef proba_t StatsArray[NUM_CTX][NUM_PROBAS];
-typedef uint16_t CostArray[NUM_CTX][MAX_VARIABLE_LEVEL + 1];
-typedef const uint16_t* (*CostArrayPtr)[NUM_CTX]; // for easy casting
-typedef const uint16_t* CostArrayMap[16][NUM_CTX];
-typedef double LFStats[NUM_MB_SEGMENTS][MAX_LF_LEVELS]; // filter stats
-
-typedef struct VP8Encoder VP8Encoder;
-
-// segment features
-typedef struct {
- int num_segments_; // Actual number of segments. 1 segment only = unused.
- int update_map_; // whether to update the segment map or not.
- // must be 0 if there's only 1 segment.
- int size_; // bit-cost for transmitting the segment map
-} VP8EncSegmentHeader;
-
-// Struct collecting all frame-persistent probabilities.
-typedef struct {
- uint8_t segments_[3]; // probabilities for segment tree
- uint8_t skip_proba_; // final probability of being skipped.
- ProbaArray coeffs_[NUM_TYPES][NUM_BANDS]; // 1056 bytes
- StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes
- CostArray level_cost_[NUM_TYPES][NUM_BANDS]; // 13056 bytes
- CostArrayMap remapped_costs_[NUM_TYPES]; // 1536 bytes
- int dirty_; // if true, need to call VP8CalculateLevelCosts()
- int use_skip_proba_; // Note: we always use skip_proba for now.
- int nb_skip_; // number of skipped blocks
-} VP8EncProba;
-
-// Filter parameters. Not actually used in the code (we don't perform
-// the in-loop filtering), but filled from user's config
-typedef struct {
- int simple_; // filtering type: 0=complex, 1=simple
- int level_; // base filter level [0..63]
- int sharpness_; // [0..7]
- int i4x4_lf_delta_; // delta filter level for i4x4 relative to i16x16
-} VP8EncFilterHeader;
-
-//------------------------------------------------------------------------------
-// Informations about the macroblocks.
-
-typedef struct {
- // block type
- unsigned int type_:2; // 0=i4x4, 1=i16x16
- unsigned int uv_mode_:2;
- unsigned int skip_:1;
- unsigned int segment_:2;
- uint8_t alpha_; // quantization-susceptibility
-} VP8MBInfo;
-
-typedef struct VP8Matrix {
- uint16_t q_[16]; // quantizer steps
- uint16_t iq_[16]; // reciprocals, fixed point.
- uint32_t bias_[16]; // rounding bias
- uint32_t zthresh_[16]; // value below which a coefficient is zeroed
- uint16_t sharpen_[16]; // frequency boosters for slight sharpening
-} VP8Matrix;
-
-typedef struct {
- VP8Matrix y1_, y2_, uv_; // quantization matrices
- int alpha_; // quant-susceptibility, range [-127,127]. Zero is neutral.
- // Lower values indicate a lower risk of blurriness.
- int beta_; // filter-susceptibility, range [0,255].
- int quant_; // final segment quantizer.
- int fstrength_; // final in-loop filtering strength
- int max_edge_; // max edge delta (for filtering strength)
- int min_disto_; // minimum distortion required to trigger filtering record
- // reactivities
- int lambda_i16_, lambda_i4_, lambda_uv_;
- int lambda_mode_, lambda_trellis_, tlambda_;
- int lambda_trellis_i16_, lambda_trellis_i4_, lambda_trellis_uv_;
-
- // lambda values for distortion-based evaluation
- score_t i4_penalty_; // penalty for using Intra4
-} VP8SegmentInfo;
-
-// Handy transient struct to accumulate score and info during RD-optimization
-// and mode evaluation.
-typedef struct {
- score_t D, SD; // Distortion, spectral distortion
- score_t H, R, score; // header bits, rate, score.
- int16_t y_dc_levels[16]; // Quantized levels for luma-DC, luma-AC, chroma.
- int16_t y_ac_levels[16][16];
- int16_t uv_levels[4 + 4][16];
- int mode_i16; // mode number for intra16 prediction
- uint8_t modes_i4[16]; // mode numbers for intra4 predictions
- int mode_uv; // mode number of chroma prediction
- uint32_t nz; // non-zero blocks
-} VP8ModeScore;
-
-// Iterator structure to iterate through macroblocks, pointing to the
-// right neighbouring data (samples, predictions, contexts, ...)
-typedef struct {
- int x_, y_; // current macroblock
- int y_stride_, uv_stride_; // respective strides
- uint8_t* yuv_in_; // input samples
- uint8_t* yuv_out_; // output samples
- uint8_t* yuv_out2_; // secondary buffer swapped with yuv_out_.
- uint8_t* yuv_p_; // scratch buffer for prediction
- VP8Encoder* enc_; // back-pointer
- VP8MBInfo* mb_; // current macroblock
- VP8BitWriter* bw_; // current bit-writer
- uint8_t* preds_; // intra mode predictors (4x4 blocks)
- uint32_t* nz_; // non-zero pattern
- uint8_t i4_boundary_[37]; // 32+5 boundary samples needed by intra4x4
- uint8_t* i4_top_; // pointer to the current top boundary sample
- int i4_; // current intra4x4 mode being tested
- int top_nz_[9]; // top-non-zero context.
- int left_nz_[9]; // left-non-zero. left_nz[8] is independent.
- uint64_t bit_count_[4][3]; // bit counters for coded levels.
- uint64_t luma_bits_; // macroblock bit-cost for luma
- uint64_t uv_bits_; // macroblock bit-cost for chroma
- LFStats* lf_stats_; // filter stats (borrowed from enc_)
- int do_trellis_; // if true, perform extra level optimisation
- int count_down_; // number of mb still to be processed
- int count_down0_; // starting counter value (for progress)
- int percent0_; // saved initial progress percent
-
- uint8_t* y_left_; // left luma samples (addressable from index -1 to 15).
- uint8_t* u_left_; // left u samples (addressable from index -1 to 7)
- uint8_t* v_left_; // left v samples (addressable from index -1 to 7)
-
- uint8_t* y_top_; // top luma samples at position 'x_'
- uint8_t* uv_top_; // top u/v samples at position 'x_', packed as 16 bytes
-
- // memory for storing y/u/v_left_
- uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + WEBP_ALIGN_CST];
- // memory for yuv_*
- uint8_t yuv_mem_[3 * YUV_SIZE_ENC + PRED_SIZE_ENC + WEBP_ALIGN_CST];
-} VP8EncIterator;
-
- // in iterator.c
-// must be called first
-void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it);
-// restart a scan
-void VP8IteratorReset(VP8EncIterator* const it);
-// reset iterator position to row 'y'
-void VP8IteratorSetRow(VP8EncIterator* const it, int y);
-// set count down (=number of iterations to go)
-void VP8IteratorSetCountDown(VP8EncIterator* const it, int count_down);
-// return true if iteration is finished
-int VP8IteratorIsDone(const VP8EncIterator* const it);
-// Import uncompressed samples from source.
-// If tmp_32 is not NULL, import boundary samples too.
-// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory.
-void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32);
-// export decimated samples
-void VP8IteratorExport(const VP8EncIterator* const it);
-// go to next macroblock. Returns false if not finished.
-int VP8IteratorNext(VP8EncIterator* const it);
-// save the yuv_out_ boundary values to top_/left_ arrays for next iterations.
-void VP8IteratorSaveBoundary(VP8EncIterator* const it);
-// Report progression based on macroblock rows. Return 0 for user-abort request.
-int VP8IteratorProgress(const VP8EncIterator* const it,
- int final_delta_percent);
-// Intra4x4 iterations
-void VP8IteratorStartI4(VP8EncIterator* const it);
-// returns true if not done.
-int VP8IteratorRotateI4(VP8EncIterator* const it,
- const uint8_t* const yuv_out);
-
-// Non-zero context setup/teardown
-void VP8IteratorNzToBytes(VP8EncIterator* const it);
-void VP8IteratorBytesToNz(VP8EncIterator* const it);
-
-// Helper functions to set mode properties
-void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode);
-void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes);
-void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode);
-void VP8SetSkip(const VP8EncIterator* const it, int skip);
-void VP8SetSegment(const VP8EncIterator* const it, int segment);
-
-//------------------------------------------------------------------------------
-// Paginated token buffer
-
-typedef struct VP8Tokens VP8Tokens; // struct details in token.c
-
-typedef struct {
-#if !defined(DISABLE_TOKEN_BUFFER)
- VP8Tokens* pages_; // first page
- VP8Tokens** last_page_; // last page
- uint16_t* tokens_; // set to (*last_page_)->tokens_
- int left_; // how many free tokens left before the page is full
- int page_size_; // number of tokens per page
-#endif
- int error_; // true in case of malloc error
-} VP8TBuffer;
-
-// initialize an empty buffer
-void VP8TBufferInit(VP8TBuffer* const b, int page_size);
-void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory
-
-#if !defined(DISABLE_TOKEN_BUFFER)
-
-// Finalizes bitstream when probabilities are known.
-// Deletes the allocated token memory if final_pass is true.
-int VP8EmitTokens(VP8TBuffer* const b, VP8BitWriter* const bw,
- const uint8_t* const probas, int final_pass);
-
-// record the coding of coefficients without knowing the probabilities yet
-int VP8RecordCoeffTokens(const int ctx, const int coeff_type,
- int first, int last,
- const int16_t* const coeffs,
- VP8TBuffer* const tokens);
-
-// Estimate the final coded size given a set of 'probas'.
-size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas);
-
-// unused for now
-void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats);
-
-#endif // !DISABLE_TOKEN_BUFFER
-
-//------------------------------------------------------------------------------
-// VP8Encoder
-
-struct VP8Encoder {
- const WebPConfig* config_; // user configuration and parameters
- WebPPicture* pic_; // input / output picture
-
- // headers
- VP8EncFilterHeader filter_hdr_; // filtering information
- VP8EncSegmentHeader segment_hdr_; // segment information
-
- int profile_; // VP8's profile, deduced from Config.
-
- // dimension, in macroblock units.
- int mb_w_, mb_h_;
- int preds_w_; // stride of the *preds_ prediction plane (=4*mb_w + 1)
-
- // number of partitions (1, 2, 4 or 8 = MAX_NUM_PARTITIONS)
- int num_parts_;
-
- // per-partition boolean decoders.
- VP8BitWriter bw_; // part0
- VP8BitWriter parts_[MAX_NUM_PARTITIONS]; // token partitions
- VP8TBuffer tokens_; // token buffer
-
- int percent_; // for progress
-
- // transparency blob
- int has_alpha_;
- uint8_t* alpha_data_; // non-NULL if transparency is present
- uint32_t alpha_data_size_;
- WebPWorker alpha_worker_;
-
- // quantization info (one set of DC/AC dequant factor per segment)
- VP8SegmentInfo dqm_[NUM_MB_SEGMENTS];
- int base_quant_; // nominal quantizer value. Only used
- // for relative coding of segments' quant.
- int alpha_; // global susceptibility (<=> complexity)
- int uv_alpha_; // U/V quantization susceptibility
- // global offset of quantizers, shared by all segments
- int dq_y1_dc_;
- int dq_y2_dc_, dq_y2_ac_;
- int dq_uv_dc_, dq_uv_ac_;
-
- // probabilities and statistics
- VP8EncProba proba_;
- uint64_t sse_[4]; // sum of Y/U/V/A squared errors for all macroblocks
- uint64_t sse_count_; // pixel count for the sse_[] stats
- int coded_size_;
- int residual_bytes_[3][4];
- int block_count_[3];
-
- // quality/speed settings
- int method_; // 0=fastest, 6=best/slowest.
- VP8RDLevel rd_opt_level_; // Deduced from method_.
- int max_i4_header_bits_; // partition #0 safeness factor
- int mb_header_limit_; // rough limit for header bits per MB
- int thread_level_; // derived from config->thread_level
- int do_search_; // derived from config->target_XXX
- int use_tokens_; // if true, use token buffer
-
- // Memory
- VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1)
- uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1)
- uint32_t* nz_; // non-zero bit context: mb_w+1
- uint8_t* y_top_; // top luma samples.
- uint8_t* uv_top_; // top u/v samples.
- // U and V are packed into 16 bytes (8 U + 8 V)
- LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off)
-};
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
- // in tree.c
-extern const uint8_t VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS];
-extern const uint8_t
- VP8CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS];
-// Reset the token probabilities to their initial (default) values
-void VP8DefaultProbas(VP8Encoder* const enc);
-// Write the token probabilities
-void VP8WriteProbas(VP8BitWriter* const bw, const VP8EncProba* const probas);
-// Writes the partition #0 modes (that is: all intra modes)
-void VP8CodeIntraModes(VP8Encoder* const enc);
-
- // in syntax.c
-// Generates the final bitstream by coding the partition0 and headers,
-// and appending an assembly of all the pre-coded token partitions.
-// Return true if everything is ok.
-int VP8EncWrite(VP8Encoder* const enc);
-// Release memory allocated for bit-writing in VP8EncLoop & seq.
-void VP8EncFreeBitWriters(VP8Encoder* const enc);
-
- // in frame.c
-extern const uint8_t VP8Cat3[];
-extern const uint8_t VP8Cat4[];
-extern const uint8_t VP8Cat5[];
-extern const uint8_t VP8Cat6[];
-
-// Form all the four Intra16x16 predictions in the yuv_p_ cache
-void VP8MakeLuma16Preds(const VP8EncIterator* const it);
-// Form all the four Chroma8x8 predictions in the yuv_p_ cache
-void VP8MakeChroma8Preds(const VP8EncIterator* const it);
-// Form all the ten Intra4x4 predictions in the yuv_p_ cache
-// for the 4x4 block it->i4_
-void VP8MakeIntra4Preds(const VP8EncIterator* const it);
-// Rate calculation
-int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd);
-int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]);
-int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd);
-// Main coding calls
-int VP8EncLoop(VP8Encoder* const enc);
-int VP8EncTokenLoop(VP8Encoder* const enc);
-
- // in webpenc.c
-// Assign an error code to a picture. Return false for convenience.
-int WebPEncodingSetError(const WebPPicture* const pic, WebPEncodingError error);
-int WebPReportProgress(const WebPPicture* const pic,
- int percent, int* const percent_store);
-
- // in analysis.c
-// Main analysis loop. Decides the segmentations and complexity.
-// Assigns a first guess for Intra16 and uvmode_ prediction modes.
-int VP8EncAnalyze(VP8Encoder* const enc);
-
- // in quant.c
-// Sets up segment's quantization values, base_quant_ and filter strengths.
-void VP8SetSegmentParams(VP8Encoder* const enc, float quality);
-// Pick best modes and fills the levels. Returns true if skipped.
-int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd,
- VP8RDLevel rd_opt);
-
- // in alpha.c
-void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression
-int VP8EncStartAlpha(VP8Encoder* const enc); // start alpha coding process
-int VP8EncFinishAlpha(VP8Encoder* const enc); // finalize compressed data
-int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data
-
- // in filter.c
-void VP8SSIMAddStats(const VP8DistoStats* const src, VP8DistoStats* const dst);
-void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int W, int H, VP8DistoStats* const stats);
-double VP8SSIMGet(const VP8DistoStats* const stats);
-double VP8SSIMGetSquaredError(const VP8DistoStats* const stats);
-
-// autofilter
-void VP8InitFilter(VP8EncIterator* const it);
-void VP8StoreFilterStats(VP8EncIterator* const it);
-void VP8AdjustFilterStrength(VP8EncIterator* const it);
-
-// returns the approximate filtering strength needed to smooth a edge
-// step of 'delta', given a sharpness parameter 'sharpness'.
-int VP8FilterStrengthFromDelta(int sharpness, int delta);
-
- // misc utils for picture_*.c:
-
-// Remove reference to the ARGB/YUVA buffer (doesn't free anything).
-void WebPPictureResetBuffers(WebPPicture* const picture);
-
-// Allocates ARGB buffer of given dimension (previous one is always free'd).
-// Preserves the YUV(A) buffer. Returns false in case of error (invalid param,
-// out-of-memory).
-int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height);
-
-// Allocates YUVA buffer of given dimension (previous one is always free'd).
-// Uses picture->csp to determine whether an alpha buffer is needed.
-// Preserves the ARGB buffer.
-// Returns false in case of error (invalid param, out-of-memory).
-int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height);
-
-// Clean-up the RGB samples under fully transparent area, to help lossless
-// compressibility (no guarantee, though). Assumes that pic->use_argb is true.
-void WebPCleanupTransparentAreaLossless(WebPPicture* const pic);
-
- // in near_lossless.c
-// Near lossless preprocessing in RGB color-space.
-int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality);
-// Near lossless adjustment for predictors.
-void VP8ApplyNearLosslessPredict(int xsize, int ysize, int pred_bits,
- const uint32_t* argb_orig,
- uint32_t* argb, uint32_t* argb_scratch,
- const uint32_t* const transform_data,
- int quality, int subtract_green);
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_ENC_VP8ENCI_H_ */
diff --git a/drivers/webp/enc/vp8l.c b/drivers/webp/enc/vp8l.c
deleted file mode 100644
index 1f2d41ea91..0000000000
--- a/drivers/webp/enc/vp8l.c
+++ /dev/null
@@ -1,1603 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// main entry for the lossless encoder.
-//
-// Author: Vikas Arora (vikaas.arora@gmail.com)
-//
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "./backward_references.h"
-#include "./histogram.h"
-#include "./vp8enci.h"
-#include "./vp8li.h"
-#include "../dsp/lossless.h"
-#include "../utils/bit_writer.h"
-#include "../utils/huffman_encode.h"
-#include "../utils/utils.h"
-#include "webp/format_constants.h"
-
-#include "./delta_palettization.h"
-
-#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer.
-// Maximum number of histogram images (sub-blocks).
-#define MAX_HUFF_IMAGE_SIZE 2600
-
-// Palette reordering for smaller sum of deltas (and for smaller storage).
-
-static int PaletteCompareColorsForQsort(const void* p1, const void* p2) {
- const uint32_t a = WebPMemToUint32(p1);
- const uint32_t b = WebPMemToUint32(p2);
- assert(a != b);
- return (a < b) ? -1 : 1;
-}
-
-static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) {
- return (v <= 128) ? v : (256 - v);
-}
-
-// Computes a value that is related to the entropy created by the
-// palette entry diff.
-//
-// Note that the last & 0xff is a no-operation in the next statement, but
-// removed by most compilers and is here only for regularity of the code.
-static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) {
- const uint32_t diff = VP8LSubPixels(col1, col2);
- const int kMoreWeightForRGBThanForAlpha = 9;
- uint32_t score;
- score = PaletteComponentDistance((diff >> 0) & 0xff);
- score += PaletteComponentDistance((diff >> 8) & 0xff);
- score += PaletteComponentDistance((diff >> 16) & 0xff);
- score *= kMoreWeightForRGBThanForAlpha;
- score += PaletteComponentDistance((diff >> 24) & 0xff);
- return score;
-}
-
-static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) {
- const uint32_t tmp = *col1;
- *col1 = *col2;
- *col2 = tmp;
-}
-
-static void GreedyMinimizeDeltas(uint32_t palette[], int num_colors) {
- // Find greedily always the closest color of the predicted color to minimize
- // deltas in the palette. This reduces storage needs since the
- // palette is stored with delta encoding.
- uint32_t predict = 0x00000000;
- int i, k;
- for (i = 0; i < num_colors; ++i) {
- int best_ix = i;
- uint32_t best_score = ~0U;
- for (k = i; k < num_colors; ++k) {
- const uint32_t cur_score = PaletteColorDistance(palette[k], predict);
- if (best_score > cur_score) {
- best_score = cur_score;
- best_ix = k;
- }
- }
- SwapColor(&palette[best_ix], &palette[i]);
- predict = palette[i];
- }
-}
-
-// The palette has been sorted by alpha. This function checks if the other
-// components of the palette have a monotonic development with regards to
-// position in the palette. If all have monotonic development, there is
-// no benefit to re-organize them greedily. A monotonic development
-// would be spotted in green-only situations (like lossy alpha) or gray-scale
-// images.
-static int PaletteHasNonMonotonousDeltas(uint32_t palette[], int num_colors) {
- uint32_t predict = 0x000000;
- int i;
- uint8_t sign_found = 0x00;
- for (i = 0; i < num_colors; ++i) {
- const uint32_t diff = VP8LSubPixels(palette[i], predict);
- const uint8_t rd = (diff >> 16) & 0xff;
- const uint8_t gd = (diff >> 8) & 0xff;
- const uint8_t bd = (diff >> 0) & 0xff;
- if (rd != 0x00) {
- sign_found |= (rd < 0x80) ? 1 : 2;
- }
- if (gd != 0x00) {
- sign_found |= (gd < 0x80) ? 8 : 16;
- }
- if (bd != 0x00) {
- sign_found |= (bd < 0x80) ? 64 : 128;
- }
- predict = palette[i];
- }
- return (sign_found & (sign_found << 1)) != 0; // two consequent signs.
-}
-
-// -----------------------------------------------------------------------------
-// Palette
-
-// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE,
-// creates a palette and returns true, else returns false.
-static int AnalyzeAndCreatePalette(const WebPPicture* const pic,
- int low_effort,
- uint32_t palette[MAX_PALETTE_SIZE],
- int* const palette_size) {
- const int num_colors = WebPGetColorPalette(pic, palette);
- if (num_colors > MAX_PALETTE_SIZE) return 0;
- *palette_size = num_colors;
- qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort);
- if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) {
- GreedyMinimizeDeltas(palette, num_colors);
- }
- return 1;
-}
-
-// These five modes are evaluated and their respective entropy is computed.
-typedef enum {
- kDirect = 0,
- kSpatial = 1,
- kSubGreen = 2,
- kSpatialSubGreen = 3,
- kPalette = 4,
- kNumEntropyIx = 5
-} EntropyIx;
-
-typedef enum {
- kHistoAlpha = 0,
- kHistoAlphaPred,
- kHistoGreen,
- kHistoGreenPred,
- kHistoRed,
- kHistoRedPred,
- kHistoBlue,
- kHistoBluePred,
- kHistoRedSubGreen,
- kHistoRedPredSubGreen,
- kHistoBlueSubGreen,
- kHistoBluePredSubGreen,
- kHistoPalette,
- kHistoTotal // Must be last.
-} HistoIx;
-
-static void AddSingleSubGreen(uint32_t p, uint32_t* r, uint32_t* b) {
- const uint32_t green = p >> 8; // The upper bits are masked away later.
- ++r[((p >> 16) - green) & 0xff];
- ++b[(p - green) & 0xff];
-}
-
-static void AddSingle(uint32_t p,
- uint32_t* a, uint32_t* r, uint32_t* g, uint32_t* b) {
- ++a[p >> 24];
- ++r[(p >> 16) & 0xff];
- ++g[(p >> 8) & 0xff];
- ++b[(p & 0xff)];
-}
-
-static int AnalyzeEntropy(const uint32_t* argb,
- int width, int height, int argb_stride,
- int use_palette,
- EntropyIx* const min_entropy_ix,
- int* const red_and_blue_always_zero) {
- // Allocate histogram set with cache_bits = 0.
- uint32_t* const histo =
- (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256);
- if (histo != NULL) {
- int i, x, y;
- const uint32_t* prev_row = argb;
- const uint32_t* curr_row = argb + argb_stride;
- for (y = 1; y < height; ++y) {
- uint32_t prev_pix = curr_row[0];
- for (x = 1; x < width; ++x) {
- const uint32_t pix = curr_row[x];
- const uint32_t pix_diff = VP8LSubPixels(pix, prev_pix);
- if ((pix_diff == 0) || (pix == prev_row[x])) continue;
- prev_pix = pix;
- AddSingle(pix,
- &histo[kHistoAlpha * 256],
- &histo[kHistoRed * 256],
- &histo[kHistoGreen * 256],
- &histo[kHistoBlue * 256]);
- AddSingle(pix_diff,
- &histo[kHistoAlphaPred * 256],
- &histo[kHistoRedPred * 256],
- &histo[kHistoGreenPred * 256],
- &histo[kHistoBluePred * 256]);
- AddSingleSubGreen(pix,
- &histo[kHistoRedSubGreen * 256],
- &histo[kHistoBlueSubGreen * 256]);
- AddSingleSubGreen(pix_diff,
- &histo[kHistoRedPredSubGreen * 256],
- &histo[kHistoBluePredSubGreen * 256]);
- {
- // Approximate the palette by the entropy of the multiplicative hash.
- const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24;
- ++histo[kHistoPalette * 256 + (hash & 0xff)];
- }
- }
- prev_row = curr_row;
- curr_row += argb_stride;
- }
- {
- double entropy_comp[kHistoTotal];
- double entropy[kNumEntropyIx];
- EntropyIx k;
- EntropyIx last_mode_to_analyze =
- use_palette ? kPalette : kSpatialSubGreen;
- int j;
- // Let's add one zero to the predicted histograms. The zeros are removed
- // too efficiently by the pix_diff == 0 comparison, at least one of the
- // zeros is likely to exist.
- ++histo[kHistoRedPredSubGreen * 256];
- ++histo[kHistoBluePredSubGreen * 256];
- ++histo[kHistoRedPred * 256];
- ++histo[kHistoGreenPred * 256];
- ++histo[kHistoBluePred * 256];
- ++histo[kHistoAlphaPred * 256];
-
- for (j = 0; j < kHistoTotal; ++j) {
- entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256, NULL);
- }
- entropy[kDirect] = entropy_comp[kHistoAlpha] +
- entropy_comp[kHistoRed] +
- entropy_comp[kHistoGreen] +
- entropy_comp[kHistoBlue];
- entropy[kSpatial] = entropy_comp[kHistoAlphaPred] +
- entropy_comp[kHistoRedPred] +
- entropy_comp[kHistoGreenPred] +
- entropy_comp[kHistoBluePred];
- entropy[kSubGreen] = entropy_comp[kHistoAlpha] +
- entropy_comp[kHistoRedSubGreen] +
- entropy_comp[kHistoGreen] +
- entropy_comp[kHistoBlueSubGreen];
- entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] +
- entropy_comp[kHistoRedPredSubGreen] +
- entropy_comp[kHistoGreenPred] +
- entropy_comp[kHistoBluePredSubGreen];
- // Palette mode seems more efficient in a breakeven case. Bias with 1.0.
- entropy[kPalette] = entropy_comp[kHistoPalette] - 1.0;
-
- *min_entropy_ix = kDirect;
- for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) {
- if (entropy[*min_entropy_ix] > entropy[k]) {
- *min_entropy_ix = k;
- }
- }
- *red_and_blue_always_zero = 1;
- // Let's check if the histogram of the chosen entropy mode has
- // non-zero red and blue values. If all are zero, we can later skip
- // the cross color optimization.
- {
- static const uint8_t kHistoPairs[5][2] = {
- { kHistoRed, kHistoBlue },
- { kHistoRedPred, kHistoBluePred },
- { kHistoRedSubGreen, kHistoBlueSubGreen },
- { kHistoRedPredSubGreen, kHistoBluePredSubGreen },
- { kHistoRed, kHistoBlue }
- };
- const uint32_t* const red_histo =
- &histo[256 * kHistoPairs[*min_entropy_ix][0]];
- const uint32_t* const blue_histo =
- &histo[256 * kHistoPairs[*min_entropy_ix][1]];
- for (i = 1; i < 256; ++i) {
- if ((red_histo[i] | blue_histo[i]) != 0) {
- *red_and_blue_always_zero = 0;
- break;
- }
- }
- }
- }
- WebPSafeFree(histo);
- return 1;
- } else {
- return 0;
- }
-}
-
-static int GetHistoBits(int method, int use_palette, int width, int height) {
- // Make tile size a function of encoding method (Range: 0 to 6).
- int histo_bits = (use_palette ? 9 : 7) - method;
- while (1) {
- const int huff_image_size = VP8LSubSampleSize(width, histo_bits) *
- VP8LSubSampleSize(height, histo_bits);
- if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break;
- ++histo_bits;
- }
- return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS :
- (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits;
-}
-
-static int GetTransformBits(int method, int histo_bits) {
- const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5;
- return (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits;
-}
-
-static int AnalyzeAndInit(VP8LEncoder* const enc) {
- const WebPPicture* const pic = enc->pic_;
- const int width = pic->width;
- const int height = pic->height;
- const int pix_cnt = width * height;
- const WebPConfig* const config = enc->config_;
- const int method = config->method;
- const int low_effort = (config->method == 0);
- // we round the block size up, so we're guaranteed to have
- // at max MAX_REFS_BLOCK_PER_IMAGE blocks used:
- int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1;
- assert(pic != NULL && pic->argb != NULL);
-
- enc->use_cross_color_ = 0;
- enc->use_predict_ = 0;
- enc->use_subtract_green_ = 0;
- enc->use_palette_ =
- AnalyzeAndCreatePalette(pic, low_effort,
- enc->palette_, &enc->palette_size_);
-
- // TODO(jyrki): replace the decision to be based on an actual estimate
- // of entropy, or even spatial variance of entropy.
- enc->histo_bits_ = GetHistoBits(method, enc->use_palette_,
- pic->width, pic->height);
- enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_);
-
- if (low_effort) {
- // AnalyzeEntropy is somewhat slow.
- enc->use_predict_ = !enc->use_palette_;
- enc->use_subtract_green_ = !enc->use_palette_;
- enc->use_cross_color_ = 0;
- } else {
- int red_and_blue_always_zero;
- EntropyIx min_entropy_ix;
- if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride,
- enc->use_palette_, &min_entropy_ix,
- &red_and_blue_always_zero)) {
- return 0;
- }
- enc->use_palette_ = (min_entropy_ix == kPalette);
- enc->use_subtract_green_ =
- (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen);
- enc->use_predict_ =
- (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen);
- enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_;
- }
-
- if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0;
-
- // palette-friendly input typically uses less literals
- // -> reduce block size a bit
- if (enc->use_palette_) refs_block_size /= 2;
- VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size);
- VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size);
-
- return 1;
-}
-
-// Returns false in case of memory error.
-static int GetHuffBitLengthsAndCodes(
- const VP8LHistogramSet* const histogram_image,
- HuffmanTreeCode* const huffman_codes) {
- int i, k;
- int ok = 0;
- uint64_t total_length_size = 0;
- uint8_t* mem_buf = NULL;
- const int histogram_image_size = histogram_image->size;
- int max_num_symbols = 0;
- uint8_t* buf_rle = NULL;
- HuffmanTree* huff_tree = NULL;
-
- // Iterate over all histograms and get the aggregate number of codes used.
- for (i = 0; i < histogram_image_size; ++i) {
- const VP8LHistogram* const histo = histogram_image->histograms[i];
- HuffmanTreeCode* const codes = &huffman_codes[5 * i];
- for (k = 0; k < 5; ++k) {
- const int num_symbols =
- (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) :
- (k == 4) ? NUM_DISTANCE_CODES : 256;
- codes[k].num_symbols = num_symbols;
- total_length_size += num_symbols;
- }
- }
-
- // Allocate and Set Huffman codes.
- {
- uint16_t* codes;
- uint8_t* lengths;
- mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size,
- sizeof(*lengths) + sizeof(*codes));
- if (mem_buf == NULL) goto End;
-
- codes = (uint16_t*)mem_buf;
- lengths = (uint8_t*)&codes[total_length_size];
- for (i = 0; i < 5 * histogram_image_size; ++i) {
- const int bit_length = huffman_codes[i].num_symbols;
- huffman_codes[i].codes = codes;
- huffman_codes[i].code_lengths = lengths;
- codes += bit_length;
- lengths += bit_length;
- if (max_num_symbols < bit_length) {
- max_num_symbols = bit_length;
- }
- }
- }
-
- buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols);
- huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols,
- sizeof(*huff_tree));
- if (buf_rle == NULL || huff_tree == NULL) goto End;
-
- // Create Huffman trees.
- for (i = 0; i < histogram_image_size; ++i) {
- HuffmanTreeCode* const codes = &huffman_codes[5 * i];
- VP8LHistogram* const histo = histogram_image->histograms[i];
- VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0);
- VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1);
- VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2);
- VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3);
- VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4);
- }
- ok = 1;
- End:
- WebPSafeFree(huff_tree);
- WebPSafeFree(buf_rle);
- if (!ok) {
- WebPSafeFree(mem_buf);
- memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
- }
- return ok;
-}
-
-static void StoreHuffmanTreeOfHuffmanTreeToBitMask(
- VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) {
- // RFC 1951 will calm you down if you are worried about this funny sequence.
- // This sequence is tuned from that, but more weighted for lower symbol count,
- // and more spiking histograms.
- static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = {
- 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
- };
- int i;
- // Throw away trailing zeros:
- int codes_to_store = CODE_LENGTH_CODES;
- for (; codes_to_store > 4; --codes_to_store) {
- if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {
- break;
- }
- }
- VP8LPutBits(bw, codes_to_store - 4, 4);
- for (i = 0; i < codes_to_store; ++i) {
- VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3);
- }
-}
-
-static void ClearHuffmanTreeIfOnlyOneSymbol(
- HuffmanTreeCode* const huffman_code) {
- int k;
- int count = 0;
- for (k = 0; k < huffman_code->num_symbols; ++k) {
- if (huffman_code->code_lengths[k] != 0) {
- ++count;
- if (count > 1) return;
- }
- }
- for (k = 0; k < huffman_code->num_symbols; ++k) {
- huffman_code->code_lengths[k] = 0;
- huffman_code->codes[k] = 0;
- }
-}
-
-static void StoreHuffmanTreeToBitMask(
- VP8LBitWriter* const bw,
- const HuffmanTreeToken* const tokens, const int num_tokens,
- const HuffmanTreeCode* const huffman_code) {
- int i;
- for (i = 0; i < num_tokens; ++i) {
- const int ix = tokens[i].code;
- const int extra_bits = tokens[i].extra_bits;
- VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]);
- switch (ix) {
- case 16:
- VP8LPutBits(bw, extra_bits, 2);
- break;
- case 17:
- VP8LPutBits(bw, extra_bits, 3);
- break;
- case 18:
- VP8LPutBits(bw, extra_bits, 7);
- break;
- }
- }
-}
-
-// 'huff_tree' and 'tokens' are pre-alloacted buffers.
-static void StoreFullHuffmanCode(VP8LBitWriter* const bw,
- HuffmanTree* const huff_tree,
- HuffmanTreeToken* const tokens,
- const HuffmanTreeCode* const tree) {
- uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 };
- uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 };
- const int max_tokens = tree->num_symbols;
- int num_tokens;
- HuffmanTreeCode huffman_code;
- huffman_code.num_symbols = CODE_LENGTH_CODES;
- huffman_code.code_lengths = code_length_bitdepth;
- huffman_code.codes = code_length_bitdepth_symbols;
-
- VP8LPutBits(bw, 0, 1);
- num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
- {
- uint32_t histogram[CODE_LENGTH_CODES] = { 0 };
- uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 };
- int i;
- for (i = 0; i < num_tokens; ++i) {
- ++histogram[tokens[i].code];
- }
-
- VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code);
- }
-
- StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth);
- ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code);
- {
- int trailing_zero_bits = 0;
- int trimmed_length = num_tokens;
- int write_trimmed_length;
- int length;
- int i = num_tokens;
- while (i-- > 0) {
- const int ix = tokens[i].code;
- if (ix == 0 || ix == 17 || ix == 18) {
- --trimmed_length; // discount trailing zeros
- trailing_zero_bits += code_length_bitdepth[ix];
- if (ix == 17) {
- trailing_zero_bits += 3;
- } else if (ix == 18) {
- trailing_zero_bits += 7;
- }
- } else {
- break;
- }
- }
- write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12);
- length = write_trimmed_length ? trimmed_length : num_tokens;
- VP8LPutBits(bw, write_trimmed_length, 1);
- if (write_trimmed_length) {
- const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1);
- const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2;
- VP8LPutBits(bw, nbitpairs - 1, 3);
- assert(trimmed_length >= 2);
- VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2);
- }
- StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code);
- }
-}
-
-// 'huff_tree' and 'tokens' are pre-alloacted buffers.
-static void StoreHuffmanCode(VP8LBitWriter* const bw,
- HuffmanTree* const huff_tree,
- HuffmanTreeToken* const tokens,
- const HuffmanTreeCode* const huffman_code) {
- int i;
- int count = 0;
- int symbols[2] = { 0, 0 };
- const int kMaxBits = 8;
- const int kMaxSymbol = 1 << kMaxBits;
-
- // Check whether it's a small tree.
- for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) {
- if (huffman_code->code_lengths[i] != 0) {
- if (count < 2) symbols[count] = i;
- ++count;
- }
- }
-
- if (count == 0) { // emit minimal tree for empty cases
- // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0
- VP8LPutBits(bw, 0x01, 4);
- } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) {
- VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols.
- VP8LPutBits(bw, count - 1, 1);
- if (symbols[0] <= 1) {
- VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value.
- VP8LPutBits(bw, symbols[0], 1);
- } else {
- VP8LPutBits(bw, 1, 1);
- VP8LPutBits(bw, symbols[0], 8);
- }
- if (count == 2) {
- VP8LPutBits(bw, symbols[1], 8);
- }
- } else {
- StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code);
- }
-}
-
-static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw,
- const HuffmanTreeCode* const code,
- int code_index) {
- const int depth = code->code_lengths[code_index];
- const int symbol = code->codes[code_index];
- VP8LPutBits(bw, symbol, depth);
-}
-
-static WEBP_INLINE void WriteHuffmanCodeWithExtraBits(
- VP8LBitWriter* const bw,
- const HuffmanTreeCode* const code,
- int code_index,
- int bits,
- int n_bits) {
- const int depth = code->code_lengths[code_index];
- const int symbol = code->codes[code_index];
- VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits);
-}
-
-static WebPEncodingError StoreImageToBitMask(
- VP8LBitWriter* const bw, int width, int histo_bits,
- VP8LBackwardRefs* const refs,
- const uint16_t* histogram_symbols,
- const HuffmanTreeCode* const huffman_codes) {
- const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
- const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits);
- // x and y trace the position in the image.
- int x = 0;
- int y = 0;
- int tile_x = x & tile_mask;
- int tile_y = y & tile_mask;
- int histogram_ix = histogram_symbols[0];
- const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix;
- VP8LRefsCursor c = VP8LRefsCursorInit(refs);
- while (VP8LRefsCursorOk(&c)) {
- const PixOrCopy* const v = c.cur_pos;
- if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) {
- tile_x = x & tile_mask;
- tile_y = y & tile_mask;
- histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize +
- (x >> histo_bits)];
- codes = huffman_codes + 5 * histogram_ix;
- }
- if (PixOrCopyIsLiteral(v)) {
- static const int order[] = { 1, 2, 0, 3 };
- int k;
- for (k = 0; k < 4; ++k) {
- const int code = PixOrCopyLiteral(v, order[k]);
- WriteHuffmanCode(bw, codes + k, code);
- }
- } else if (PixOrCopyIsCacheIdx(v)) {
- const int code = PixOrCopyCacheIdx(v);
- const int literal_ix = 256 + NUM_LENGTH_CODES + code;
- WriteHuffmanCode(bw, codes, literal_ix);
- } else {
- int bits, n_bits;
- int code;
-
- const int distance = PixOrCopyDistance(v);
- VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
- WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits);
-
- // Don't write the distance with the extra bits code since
- // the distance can be up to 18 bits of extra bits, and the prefix
- // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits.
- // TODO(jyrki): optimize this further.
- VP8LPrefixEncode(distance, &code, &n_bits, &bits);
- WriteHuffmanCode(bw, codes + 4, code);
- VP8LPutBits(bw, bits, n_bits);
- }
- x += PixOrCopyLength(v);
- while (x >= width) {
- x -= width;
- ++y;
- }
- VP8LRefsCursorNext(&c);
- }
- return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK;
-}
-
-// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31
-static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw,
- const uint32_t* const argb,
- VP8LHashChain* const hash_chain,
- VP8LBackwardRefs refs_array[2],
- int width, int height,
- int quality) {
- int i;
- int max_tokens = 0;
- WebPEncodingError err = VP8_ENC_OK;
- VP8LBackwardRefs* refs;
- HuffmanTreeToken* tokens = NULL;
- HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } };
- const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol
- int cache_bits = 0;
- VP8LHistogramSet* histogram_image = NULL;
- HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc(
- 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree));
- if (huff_tree == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- // Calculate backward references from ARGB image.
- if (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits,
- hash_chain, refs_array);
- if (refs == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- histogram_image = VP8LAllocateHistogramSet(1, cache_bits);
- if (histogram_image == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- // Build histogram image and symbols from backward references.
- VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
-
- // Create Huffman bit lengths and codes for each histogram image.
- assert(histogram_image->size == 1);
- if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- // No color cache, no Huffman image.
- VP8LPutBits(bw, 0, 1);
-
- // Find maximum number of symbols for the huffman tree-set.
- for (i = 0; i < 5; ++i) {
- HuffmanTreeCode* const codes = &huffman_codes[i];
- if (max_tokens < codes->num_symbols) {
- max_tokens = codes->num_symbols;
- }
- }
-
- tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens));
- if (tokens == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- // Store Huffman codes.
- for (i = 0; i < 5; ++i) {
- HuffmanTreeCode* const codes = &huffman_codes[i];
- StoreHuffmanCode(bw, huff_tree, tokens, codes);
- ClearHuffmanTreeIfOnlyOneSymbol(codes);
- }
-
- // Store actual literals.
- err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols,
- huffman_codes);
-
- Error:
- WebPSafeFree(tokens);
- WebPSafeFree(huff_tree);
- VP8LFreeHistogramSet(histogram_image);
- WebPSafeFree(huffman_codes[0].codes);
- return err;
-}
-
-static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw,
- const uint32_t* const argb,
- VP8LHashChain* const hash_chain,
- VP8LBackwardRefs refs_array[2],
- int width, int height, int quality,
- int low_effort,
- int use_cache, int* cache_bits,
- int histogram_bits,
- size_t init_byte_position,
- int* const hdr_size,
- int* const data_size) {
- WebPEncodingError err = VP8_ENC_OK;
- const uint32_t histogram_image_xysize =
- VP8LSubSampleSize(width, histogram_bits) *
- VP8LSubSampleSize(height, histogram_bits);
- VP8LHistogramSet* histogram_image = NULL;
- VP8LHistogramSet* tmp_histos = NULL;
- int histogram_image_size = 0;
- size_t bit_array_size = 0;
- HuffmanTree* huff_tree = NULL;
- HuffmanTreeToken* tokens = NULL;
- HuffmanTreeCode* huffman_codes = NULL;
- VP8LBackwardRefs refs;
- VP8LBackwardRefs* best_refs;
- uint16_t* const histogram_symbols =
- (uint16_t*)WebPSafeMalloc(histogram_image_xysize,
- sizeof(*histogram_symbols));
- assert(histogram_bits >= MIN_HUFFMAN_BITS);
- assert(histogram_bits <= MAX_HUFFMAN_BITS);
- assert(hdr_size != NULL);
- assert(data_size != NULL);
-
- VP8LBackwardRefsInit(&refs, refs_array[0].block_size_);
- if (histogram_symbols == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- *cache_bits = use_cache ? MAX_COLOR_CACHE_BITS : 0;
- // 'best_refs' is the reference to the best backward refs and points to one
- // of refs_array[0] or refs_array[1].
- // Calculate backward references from ARGB image.
- if (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- best_refs = VP8LGetBackwardReferences(width, height, argb, quality,
- low_effort, cache_bits, hash_chain,
- refs_array);
- if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- histogram_image =
- VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits);
- tmp_histos = VP8LAllocateHistogramSet(2, *cache_bits);
- if (histogram_image == NULL || tmp_histos == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- // Build histogram image and symbols from backward references.
- if (!VP8LGetHistoImageSymbols(width, height, &refs, quality, low_effort,
- histogram_bits, *cache_bits, histogram_image,
- tmp_histos, histogram_symbols)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- // Create Huffman bit lengths and codes for each histogram image.
- histogram_image_size = histogram_image->size;
- bit_array_size = 5 * histogram_image_size;
- huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size,
- sizeof(*huffman_codes));
- // Note: some histogram_image entries may point to tmp_histos[], so the latter
- // need to outlive the following call to GetHuffBitLengthsAndCodes().
- if (huffman_codes == NULL ||
- !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- // Free combined histograms.
- VP8LFreeHistogramSet(histogram_image);
- histogram_image = NULL;
-
- // Free scratch histograms.
- VP8LFreeHistogramSet(tmp_histos);
- tmp_histos = NULL;
-
- // Color Cache parameters.
- if (*cache_bits > 0) {
- VP8LPutBits(bw, 1, 1);
- VP8LPutBits(bw, *cache_bits, 4);
- } else {
- VP8LPutBits(bw, 0, 1);
- }
-
- // Huffman image + meta huffman.
- {
- const int write_histogram_image = (histogram_image_size > 1);
- VP8LPutBits(bw, write_histogram_image, 1);
- if (write_histogram_image) {
- uint32_t* const histogram_argb =
- (uint32_t*)WebPSafeMalloc(histogram_image_xysize,
- sizeof(*histogram_argb));
- int max_index = 0;
- uint32_t i;
- if (histogram_argb == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- for (i = 0; i < histogram_image_xysize; ++i) {
- const int symbol_index = histogram_symbols[i] & 0xffff;
- histogram_argb[i] = (symbol_index << 8);
- if (symbol_index >= max_index) {
- max_index = symbol_index + 1;
- }
- }
- histogram_image_size = max_index;
-
- VP8LPutBits(bw, histogram_bits - 2, 3);
- err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array,
- VP8LSubSampleSize(width, histogram_bits),
- VP8LSubSampleSize(height, histogram_bits),
- quality);
- WebPSafeFree(histogram_argb);
- if (err != VP8_ENC_OK) goto Error;
- }
- }
-
- // Store Huffman codes.
- {
- int i;
- int max_tokens = 0;
- huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES,
- sizeof(*huff_tree));
- if (huff_tree == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- // Find maximum number of symbols for the huffman tree-set.
- for (i = 0; i < 5 * histogram_image_size; ++i) {
- HuffmanTreeCode* const codes = &huffman_codes[i];
- if (max_tokens < codes->num_symbols) {
- max_tokens = codes->num_symbols;
- }
- }
- tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens,
- sizeof(*tokens));
- if (tokens == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- for (i = 0; i < 5 * histogram_image_size; ++i) {
- HuffmanTreeCode* const codes = &huffman_codes[i];
- StoreHuffmanCode(bw, huff_tree, tokens, codes);
- ClearHuffmanTreeIfOnlyOneSymbol(codes);
- }
- }
-
- *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position);
- // Store actual literals.
- err = StoreImageToBitMask(bw, width, histogram_bits, &refs,
- histogram_symbols, huffman_codes);
- *data_size =
- (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size);
-
- Error:
- WebPSafeFree(tokens);
- WebPSafeFree(huff_tree);
- VP8LFreeHistogramSet(histogram_image);
- VP8LFreeHistogramSet(tmp_histos);
- VP8LBackwardRefsClear(&refs);
- if (huffman_codes != NULL) {
- WebPSafeFree(huffman_codes->codes);
- WebPSafeFree(huffman_codes);
- }
- WebPSafeFree(histogram_symbols);
- return err;
-}
-
-// -----------------------------------------------------------------------------
-// Transforms
-
-static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height,
- VP8LBitWriter* const bw) {
- VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
- VP8LPutBits(bw, SUBTRACT_GREEN, 2);
- VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height);
-}
-
-static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc,
- int width, int height,
- int quality, int low_effort,
- int used_subtract_green,
- VP8LBitWriter* const bw) {
- const int pred_bits = enc->transform_bits_;
- const int transform_width = VP8LSubSampleSize(width, pred_bits);
- const int transform_height = VP8LSubSampleSize(height, pred_bits);
- // we disable near-lossless quantization if palette is used.
- const int near_lossless_strength = enc->use_palette_ ? 100
- : enc->config_->near_lossless;
-
- VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_,
- enc->argb_scratch_, enc->transform_data_,
- near_lossless_strength, enc->config_->exact,
- used_subtract_green);
- VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
- VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
- assert(pred_bits >= 2);
- VP8LPutBits(bw, pred_bits - 2, 3);
- return EncodeImageNoHuffman(bw, enc->transform_data_,
- (VP8LHashChain*)&enc->hash_chain_,
- (VP8LBackwardRefs*)enc->refs_, // cast const away
- transform_width, transform_height,
- quality);
-}
-
-static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc,
- int width, int height,
- int quality,
- VP8LBitWriter* const bw) {
- const int ccolor_transform_bits = enc->transform_bits_;
- const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits);
- const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits);
-
- VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality,
- enc->argb_, enc->transform_data_);
- VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
- VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2);
- assert(ccolor_transform_bits >= 2);
- VP8LPutBits(bw, ccolor_transform_bits - 2, 3);
- return EncodeImageNoHuffman(bw, enc->transform_data_,
- (VP8LHashChain*)&enc->hash_chain_,
- (VP8LBackwardRefs*)enc->refs_, // cast const away
- transform_width, transform_height,
- quality);
-}
-
-// -----------------------------------------------------------------------------
-
-static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic,
- size_t riff_size, size_t vp8l_size) {
- uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = {
- 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P',
- 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE,
- };
- PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
- PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size);
- if (!pic->writer(riff, sizeof(riff), pic)) {
- return VP8_ENC_ERROR_BAD_WRITE;
- }
- return VP8_ENC_OK;
-}
-
-static int WriteImageSize(const WebPPicture* const pic,
- VP8LBitWriter* const bw) {
- const int width = pic->width - 1;
- const int height = pic->height - 1;
- assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION);
-
- VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS);
- VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS);
- return !bw->error_;
-}
-
-static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) {
- VP8LPutBits(bw, has_alpha, 1);
- VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS);
- return !bw->error_;
-}
-
-static WebPEncodingError WriteImage(const WebPPicture* const pic,
- VP8LBitWriter* const bw,
- size_t* const coded_size) {
- WebPEncodingError err = VP8_ENC_OK;
- const uint8_t* const webpll_data = VP8LBitWriterFinish(bw);
- const size_t webpll_size = VP8LBitWriterNumBytes(bw);
- const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size;
- const size_t pad = vp8l_size & 1;
- const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad;
-
- err = WriteRiffHeader(pic, riff_size, vp8l_size);
- if (err != VP8_ENC_OK) goto Error;
-
- if (!pic->writer(webpll_data, webpll_size, pic)) {
- err = VP8_ENC_ERROR_BAD_WRITE;
- goto Error;
- }
-
- if (pad) {
- const uint8_t pad_byte[1] = { 0 };
- if (!pic->writer(pad_byte, 1, pic)) {
- err = VP8_ENC_ERROR_BAD_WRITE;
- goto Error;
- }
- }
- *coded_size = CHUNK_HEADER_SIZE + riff_size;
- return VP8_ENC_OK;
-
- Error:
- return err;
-}
-
-// -----------------------------------------------------------------------------
-
-static void ClearTransformBuffer(VP8LEncoder* const enc) {
- WebPSafeFree(enc->transform_mem_);
- enc->transform_mem_ = NULL;
- enc->transform_mem_size_ = 0;
-}
-
-// Allocates the memory for argb (W x H) buffer, 2 rows of context for
-// prediction and transform data.
-// Flags influencing the memory allocated:
-// enc->transform_bits_
-// enc->use_predict_, enc->use_cross_color_
-static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
- int width, int height) {
- WebPEncodingError err = VP8_ENC_OK;
- const uint64_t image_size = width * height;
- // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra
- // pixel in each, plus 2 regular scanlines of bytes.
- // TODO(skal): Clean up by using arithmetic in bytes instead of words.
- const uint64_t argb_scratch_size =
- enc->use_predict_
- ? (width + 1) * 2 +
- (width * 2 + sizeof(uint32_t) - 1) / sizeof(uint32_t)
- : 0;
- const uint64_t transform_data_size =
- (enc->use_predict_ || enc->use_cross_color_)
- ? VP8LSubSampleSize(width, enc->transform_bits_) *
- VP8LSubSampleSize(height, enc->transform_bits_)
- : 0;
- const uint64_t max_alignment_in_words =
- (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t);
- const uint64_t mem_size =
- image_size + max_alignment_in_words +
- argb_scratch_size + max_alignment_in_words +
- transform_data_size;
- uint32_t* mem = enc->transform_mem_;
- if (mem == NULL || mem_size > enc->transform_mem_size_) {
- ClearTransformBuffer(enc);
- mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem));
- if (mem == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- enc->transform_mem_ = mem;
- enc->transform_mem_size_ = (size_t)mem_size;
- }
- enc->argb_ = mem;
- mem = (uint32_t*)WEBP_ALIGN(mem + image_size);
- enc->argb_scratch_ = mem;
- mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size);
- enc->transform_data_ = mem;
-
- enc->current_width_ = width;
- Error:
- return err;
-}
-
-static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) {
- WebPEncodingError err = VP8_ENC_OK;
- const WebPPicture* const picture = enc->pic_;
- const int width = picture->width;
- const int height = picture->height;
- int y;
- err = AllocateTransformBuffer(enc, width, height);
- if (err != VP8_ENC_OK) return err;
- for (y = 0; y < height; ++y) {
- memcpy(enc->argb_ + y * width,
- picture->argb + y * picture->argb_stride,
- width * sizeof(*enc->argb_));
- }
- assert(enc->current_width_ == width);
- return VP8_ENC_OK;
-}
-
-// -----------------------------------------------------------------------------
-
-static int SearchColor(const uint32_t sorted[], uint32_t color, int hi) {
- int low = 0;
- if (sorted[low] == color) return low; // loop invariant: sorted[low] != color
- while (1) {
- const int mid = (low + hi) >> 1;
- if (sorted[mid] == color) {
- return mid;
- } else if (sorted[mid] < color) {
- low = mid;
- } else {
- hi = mid;
- }
- }
-}
-
-// Sort palette in increasing order and prepare an inverse mapping array.
-static void PrepareMapToPalette(const uint32_t palette[], int num_colors,
- uint32_t sorted[], int idx_map[]) {
- int i;
- memcpy(sorted, palette, num_colors * sizeof(*sorted));
- qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort);
- for (i = 0; i < num_colors; ++i) {
- idx_map[SearchColor(sorted, palette[i], num_colors)] = i;
- }
-}
-
-static void MapToPalette(const uint32_t sorted_palette[], int num_colors,
- uint32_t* const last_pix, int* const last_idx,
- const int idx_map[],
- const uint32_t* src, uint8_t* dst, int width) {
- int x;
- int prev_idx = *last_idx;
- uint32_t prev_pix = *last_pix;
- for (x = 0; x < width; ++x) {
- const uint32_t pix = src[x];
- if (pix != prev_pix) {
- prev_idx = idx_map[SearchColor(sorted_palette, pix, num_colors)];
- prev_pix = pix;
- }
- dst[x] = prev_idx;
- }
- *last_idx = prev_idx;
- *last_pix = prev_pix;
-}
-
-// Remap argb values in src[] to packed palettes entries in dst[]
-// using 'row' as a temporary buffer of size 'width'.
-// We assume that all src[] values have a corresponding entry in the palette.
-// Note: src[] can be the same as dst[]
-static WebPEncodingError ApplyPalette(const uint32_t* src, uint32_t src_stride,
- uint32_t* dst, uint32_t dst_stride,
- const uint32_t* palette, int palette_size,
- int width, int height, int xbits) {
- // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be
- // made to work in-place.
- uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row));
- int i, x, y;
- int use_LUT = 1;
-
- if (tmp_row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
- for (i = 0; i < palette_size; ++i) {
- if ((palette[i] & 0xffff00ffu) != 0) {
- use_LUT = 0;
- break;
- }
- }
-
- if (use_LUT) {
- uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 };
- for (i = 0; i < palette_size; ++i) {
- const int color = (palette[i] >> 8) & 0xff;
- inv_palette[color] = i;
- }
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const int color = (src[x] >> 8) & 0xff;
- tmp_row[x] = inv_palette[color];
- }
- VP8LBundleColorMap(tmp_row, width, xbits, dst);
- src += src_stride;
- dst += dst_stride;
- }
- } else {
- // Use 1 pixel cache for ARGB pixels.
- uint32_t last_pix;
- int last_idx;
- uint32_t sorted[MAX_PALETTE_SIZE];
- int idx_map[MAX_PALETTE_SIZE];
- PrepareMapToPalette(palette, palette_size, sorted, idx_map);
- last_pix = palette[0];
- last_idx = 0;
- for (y = 0; y < height; ++y) {
- MapToPalette(sorted, palette_size, &last_pix, &last_idx,
- idx_map, src, tmp_row, width);
- VP8LBundleColorMap(tmp_row, width, xbits, dst);
- src += src_stride;
- dst += dst_stride;
- }
- }
- WebPSafeFree(tmp_row);
- return VP8_ENC_OK;
-}
-
-// Note: Expects "enc->palette_" to be set properly.
-static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc,
- int in_place) {
- WebPEncodingError err = VP8_ENC_OK;
- const WebPPicture* const pic = enc->pic_;
- const int width = pic->width;
- const int height = pic->height;
- const uint32_t* const palette = enc->palette_;
- const uint32_t* src = in_place ? enc->argb_ : pic->argb;
- const int src_stride = in_place ? enc->current_width_ : pic->argb_stride;
- const int palette_size = enc->palette_size_;
- int xbits;
-
- // Replace each input pixel by corresponding palette index.
- // This is done line by line.
- if (palette_size <= 4) {
- xbits = (palette_size <= 2) ? 3 : 2;
- } else {
- xbits = (palette_size <= 16) ? 1 : 0;
- }
-
- err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
- if (err != VP8_ENC_OK) return err;
-
- err = ApplyPalette(src, src_stride,
- enc->argb_, enc->current_width_,
- palette, palette_size, width, height, xbits);
- return err;
-}
-
-// Save palette_[] to bitstream.
-static WebPEncodingError EncodePalette(VP8LBitWriter* const bw,
- VP8LEncoder* const enc) {
- int i;
- uint32_t tmp_palette[MAX_PALETTE_SIZE];
- const int palette_size = enc->palette_size_;
- const uint32_t* const palette = enc->palette_;
- VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
- VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2);
- assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE);
- VP8LPutBits(bw, palette_size - 1, 8);
- for (i = palette_size - 1; i >= 1; --i) {
- tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
- }
- tmp_palette[0] = palette[0];
- return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_,
- palette_size, 1, 20 /* quality */);
-}
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
-
-static WebPEncodingError EncodeDeltaPalettePredictorImage(
- VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality) {
- const WebPPicture* const pic = enc->pic_;
- const int width = pic->width;
- const int height = pic->height;
-
- const int pred_bits = 5;
- const int transform_width = VP8LSubSampleSize(width, pred_bits);
- const int transform_height = VP8LSubSampleSize(height, pred_bits);
- const int pred = 7; // default is Predictor7 (Top/Left Average)
- const int tiles_per_row = VP8LSubSampleSize(width, pred_bits);
- const int tiles_per_col = VP8LSubSampleSize(height, pred_bits);
- uint32_t* predictors;
- int tile_x, tile_y;
- WebPEncodingError err = VP8_ENC_OK;
-
- predictors = (uint32_t*)WebPSafeMalloc(tiles_per_col * tiles_per_row,
- sizeof(*predictors));
- if (predictors == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
-
- for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
- for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
- predictors[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
- }
- }
-
- VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
- VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
- VP8LPutBits(bw, pred_bits - 2, 3);
- err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_,
- (VP8LBackwardRefs*)enc->refs_, // cast const away
- transform_width, transform_height,
- quality);
- WebPSafeFree(predictors);
- return err;
-}
-
-#endif // WEBP_EXPERIMENTAL_FEATURES
-
-// -----------------------------------------------------------------------------
-// VP8LEncoder
-
-static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
- const WebPPicture* const picture) {
- VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc));
- if (enc == NULL) {
- WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- return NULL;
- }
- enc->config_ = config;
- enc->pic_ = picture;
-
- VP8LEncDspInit();
-
- return enc;
-}
-
-static void VP8LEncoderDelete(VP8LEncoder* enc) {
- if (enc != NULL) {
- VP8LHashChainClear(&enc->hash_chain_);
- VP8LBackwardRefsClear(&enc->refs_[0]);
- VP8LBackwardRefsClear(&enc->refs_[1]);
- ClearTransformBuffer(enc);
- WebPSafeFree(enc);
- }
-}
-
-// -----------------------------------------------------------------------------
-// Main call
-
-WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
- const WebPPicture* const picture,
- VP8LBitWriter* const bw, int use_cache) {
- WebPEncodingError err = VP8_ENC_OK;
- const int quality = (int)config->quality;
- const int low_effort = (config->method == 0);
- const int width = picture->width;
- const int height = picture->height;
- VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
- const size_t byte_position = VP8LBitWriterNumBytes(bw);
- int use_near_lossless = 0;
- int hdr_size = 0;
- int data_size = 0;
- int use_delta_palettization = 0;
-
- if (enc == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- // ---------------------------------------------------------------------------
- // Analyze image (entropy, num_palettes etc)
-
- if (!AnalyzeAndInit(enc)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- // Apply near-lossless preprocessing.
- use_near_lossless =
- (config->near_lossless < 100) && !enc->use_palette_ && !enc->use_predict_;
- if (use_near_lossless) {
- if (!VP8ApplyNearLossless(width, height, picture->argb,
- config->near_lossless)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- }
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (config->delta_palettization) {
- enc->use_predict_ = 1;
- enc->use_cross_color_ = 0;
- enc->use_subtract_green_ = 0;
- enc->use_palette_ = 1;
- err = MakeInputImageCopy(enc);
- if (err != VP8_ENC_OK) goto Error;
- err = WebPSearchOptimalDeltaPalette(enc);
- if (err != VP8_ENC_OK) goto Error;
- if (enc->use_palette_) {
- err = AllocateTransformBuffer(enc, width, height);
- if (err != VP8_ENC_OK) goto Error;
- err = EncodeDeltaPalettePredictorImage(bw, enc, quality);
- if (err != VP8_ENC_OK) goto Error;
- use_delta_palettization = 1;
- }
- }
-#endif // WEBP_EXPERIMENTAL_FEATURES
-
- // Encode palette
- if (enc->use_palette_) {
- err = EncodePalette(bw, enc);
- if (err != VP8_ENC_OK) goto Error;
- err = MapImageFromPalette(enc, use_delta_palettization);
- if (err != VP8_ENC_OK) goto Error;
- }
- if (!use_delta_palettization) {
- // In case image is not packed.
- if (enc->argb_ == NULL) {
- err = MakeInputImageCopy(enc);
- if (err != VP8_ENC_OK) goto Error;
- }
-
- // -------------------------------------------------------------------------
- // Apply transforms and write transform data.
-
- if (enc->use_subtract_green_) {
- ApplySubtractGreen(enc, enc->current_width_, height, bw);
- }
-
- if (enc->use_predict_) {
- err = ApplyPredictFilter(enc, enc->current_width_, height, quality,
- low_effort, enc->use_subtract_green_, bw);
- if (err != VP8_ENC_OK) goto Error;
- }
-
- if (enc->use_cross_color_) {
- err = ApplyCrossColorFilter(enc, enc->current_width_,
- height, quality, bw);
- if (err != VP8_ENC_OK) goto Error;
- }
- }
-
- VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms.
-
- // ---------------------------------------------------------------------------
- // Encode and write the transformed image.
- err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_,
- enc->current_width_, height, quality, low_effort,
- use_cache, &enc->cache_bits_, enc->histo_bits_,
- byte_position, &hdr_size, &data_size);
- if (err != VP8_ENC_OK) goto Error;
-
- if (picture->stats != NULL) {
- WebPAuxStats* const stats = picture->stats;
- stats->lossless_features = 0;
- if (enc->use_predict_) stats->lossless_features |= 1;
- if (enc->use_cross_color_) stats->lossless_features |= 2;
- if (enc->use_subtract_green_) stats->lossless_features |= 4;
- if (enc->use_palette_) stats->lossless_features |= 8;
- stats->histogram_bits = enc->histo_bits_;
- stats->transform_bits = enc->transform_bits_;
- stats->cache_bits = enc->cache_bits_;
- stats->palette_size = enc->palette_size_;
- stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position);
- stats->lossless_hdr_size = hdr_size;
- stats->lossless_data_size = data_size;
- }
-
- Error:
- VP8LEncoderDelete(enc);
- return err;
-}
-
-int VP8LEncodeImage(const WebPConfig* const config,
- const WebPPicture* const picture) {
- int width, height;
- int has_alpha;
- size_t coded_size;
- int percent = 0;
- int initial_size;
- WebPEncodingError err = VP8_ENC_OK;
- VP8LBitWriter bw;
-
- if (picture == NULL) return 0;
-
- if (config == NULL || picture->argb == NULL) {
- err = VP8_ENC_ERROR_NULL_PARAMETER;
- WebPEncodingSetError(picture, err);
- return 0;
- }
-
- width = picture->width;
- height = picture->height;
- // Initialize BitWriter with size corresponding to 16 bpp to photo images and
- // 8 bpp for graphical images.
- initial_size = (config->image_hint == WEBP_HINT_GRAPH) ?
- width * height : width * height * 2;
- if (!VP8LBitWriterInit(&bw, initial_size)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- if (!WebPReportProgress(picture, 1, &percent)) {
- UserAbort:
- err = VP8_ENC_ERROR_USER_ABORT;
- goto Error;
- }
- // Reset stats (for pure lossless coding)
- if (picture->stats != NULL) {
- WebPAuxStats* const stats = picture->stats;
- memset(stats, 0, sizeof(*stats));
- stats->PSNR[0] = 99.f;
- stats->PSNR[1] = 99.f;
- stats->PSNR[2] = 99.f;
- stats->PSNR[3] = 99.f;
- stats->PSNR[4] = 99.f;
- }
-
- // Write image size.
- if (!WriteImageSize(picture, &bw)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- has_alpha = WebPPictureHasTransparency(picture);
- // Write the non-trivial Alpha flag and lossless version.
- if (!WriteRealAlphaAndVersion(&bw, has_alpha)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort;
-
- // Encode main image stream.
- err = VP8LEncodeStream(config, picture, &bw, 1 /*use_cache*/);
- if (err != VP8_ENC_OK) goto Error;
-
- // TODO(skal): have a fine-grained progress report in VP8LEncodeStream().
- if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort;
-
- // Finish the RIFF chunk.
- err = WriteImage(picture, &bw, &coded_size);
- if (err != VP8_ENC_OK) goto Error;
-
- if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort;
-
- // Save size.
- if (picture->stats != NULL) {
- picture->stats->coded_size += (int)coded_size;
- picture->stats->lossless_size = (int)coded_size;
- }
-
- if (picture->extra_info != NULL) {
- const int mb_w = (width + 15) >> 4;
- const int mb_h = (height + 15) >> 4;
- memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info));
- }
-
- Error:
- if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- VP8LBitWriterWipeOut(&bw);
- if (err != VP8_ENC_OK) {
- WebPEncodingSetError(picture, err);
- return 0;
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/enc/vp8li.h b/drivers/webp/enc/vp8li.h
deleted file mode 100644
index 8e6b360d81..0000000000
--- a/drivers/webp/enc/vp8li.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Lossless encoder: internal header.
-//
-// Author: Vikas Arora (vikaas.arora@gmail.com)
-
-#ifndef WEBP_ENC_VP8LI_H_
-#define WEBP_ENC_VP8LI_H_
-
-#include "./backward_references.h"
-#include "./histogram.h"
-#include "../utils/bit_writer.h"
-#include "webp/encode.h"
-#include "webp/format_constants.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
- const WebPConfig* config_; // user configuration and parameters
- const WebPPicture* pic_; // input picture.
-
- uint32_t* argb_; // Transformed argb image data.
- uint32_t* argb_scratch_; // Scratch memory for argb rows
- // (used for prediction).
- uint32_t* transform_data_; // Scratch memory for transform data.
- uint32_t* transform_mem_; // Currently allocated memory.
- size_t transform_mem_size_; // Currently allocated memory size.
-
- int current_width_; // Corresponds to packed image width.
-
- // Encoding parameters derived from quality parameter.
- int histo_bits_;
- int transform_bits_;
- int cache_bits_; // If equal to 0, don't use color cache.
-
- // Encoding parameters derived from image characteristics.
- int use_cross_color_;
- int use_subtract_green_;
- int use_predict_;
- int use_palette_;
- int palette_size_;
- uint32_t palette_[MAX_PALETTE_SIZE];
-
- // Some 'scratch' (potentially large) objects.
- struct VP8LBackwardRefs refs_[2]; // Backward Refs array corresponding to
- // LZ77 & RLE coding.
- VP8LHashChain hash_chain_; // HashChain data for constructing
- // backward references.
-} VP8LEncoder;
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
-// Encodes the picture.
-// Returns 0 if config or picture is NULL or picture doesn't have valid argb
-// input.
-int VP8LEncodeImage(const WebPConfig* const config,
- const WebPPicture* const picture);
-
-// Encodes the main image stream using the supplied bit writer.
-// If 'use_cache' is false, disables the use of color cache.
-WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
- const WebPPicture* const picture,
- VP8LBitWriter* const bw, int use_cache);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_ENC_VP8LI_H_ */
diff --git a/drivers/webp/enc/webpenc.c b/drivers/webp/enc/webpenc.c
deleted file mode 100644
index a7d04ea2ce..0000000000
--- a/drivers/webp/enc/webpenc.c
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebP encoder: main entry point
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "./cost.h"
-#include "./vp8enci.h"
-#include "./vp8li.h"
-#include "../utils/utils.h"
-
-// #define PRINT_MEMORY_INFO
-
-#ifdef PRINT_MEMORY_INFO
-#include <stdio.h>
-#endif
-
-//------------------------------------------------------------------------------
-
-int WebPGetEncoderVersion(void) {
- return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION;
-}
-
-//------------------------------------------------------------------------------
-// VP8Encoder
-//------------------------------------------------------------------------------
-
-static void ResetSegmentHeader(VP8Encoder* const enc) {
- VP8EncSegmentHeader* const hdr = &enc->segment_hdr_;
- hdr->num_segments_ = enc->config_->segments;
- hdr->update_map_ = (hdr->num_segments_ > 1);
- hdr->size_ = 0;
-}
-
-static void ResetFilterHeader(VP8Encoder* const enc) {
- VP8EncFilterHeader* const hdr = &enc->filter_hdr_;
- hdr->simple_ = 1;
- hdr->level_ = 0;
- hdr->sharpness_ = 0;
- hdr->i4x4_lf_delta_ = 0;
-}
-
-static void ResetBoundaryPredictions(VP8Encoder* const enc) {
- // init boundary values once for all
- // Note: actually, initializing the preds_[] is only needed for intra4.
- int i;
- uint8_t* const top = enc->preds_ - enc->preds_w_;
- uint8_t* const left = enc->preds_ - 1;
- for (i = -1; i < 4 * enc->mb_w_; ++i) {
- top[i] = B_DC_PRED;
- }
- for (i = 0; i < 4 * enc->mb_h_; ++i) {
- left[i * enc->preds_w_] = B_DC_PRED;
- }
- enc->nz_[-1] = 0; // constant
-}
-
-// Mapping from config->method_ to coding tools used.
-//-------------------+---+---+---+---+---+---+---+
-// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 |
-//-------------------+---+---+---+---+---+---+---+
-// fast probe | x | | | x | | | |
-//-------------------+---+---+---+---+---+---+---+
-// dynamic proba | ~ | x | x | x | x | x | x |
-//-------------------+---+---+---+---+---+---+---+
-// fast mode analysis| | | | | x | x | x |
-//-------------------+---+---+---+---+---+---+---+
-// basic rd-opt | | | | x | x | x | x |
-//-------------------+---+---+---+---+---+---+---+
-// disto-refine i4/16| x | x | x | | | | |
-//-------------------+---+---+---+---+---+---+---+
-// disto-refine uv | | x | x | | | | |
-//-------------------+---+---+---+---+---+---+---+
-// rd-opt i4/16 | | | ~ | x | x | x | x |
-//-------------------+---+---+---+---+---+---+---+
-// token buffer (opt)| | | | x | x | x | x |
-//-------------------+---+---+---+---+---+---+---+
-// Trellis | | | | | | x |Ful|
-//-------------------+---+---+---+---+---+---+---+
-// full-SNS | | | | | x | x | x |
-//-------------------+---+---+---+---+---+---+---+
-
-static void MapConfigToTools(VP8Encoder* const enc) {
- const WebPConfig* const config = enc->config_;
- const int method = config->method;
- const int limit = 100 - config->partition_limit;
- enc->method_ = method;
- enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL
- : (method >= 5) ? RD_OPT_TRELLIS
- : (method >= 3) ? RD_OPT_BASIC
- : RD_OPT_NONE;
- enc->max_i4_header_bits_ =
- 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block
- (limit * limit) / (100 * 100); // ... modulated with a quadratic curve.
-
- // partition0 = 512k max.
- enc->mb_header_limit_ =
- (score_t)256 * 510 * 8 * 1024 / (enc->mb_w_ * enc->mb_h_);
-
- enc->thread_level_ = config->thread_level;
-
- enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0);
- if (!config->low_memory) {
-#if !defined(DISABLE_TOKEN_BUFFER)
- enc->use_tokens_ = (enc->rd_opt_level_ >= RD_OPT_BASIC); // need rd stats
-#endif
- if (enc->use_tokens_) {
- enc->num_parts_ = 1; // doesn't work with multi-partition
- }
- }
-}
-
-// Memory scaling with dimensions:
-// memory (bytes) ~= 2.25 * w + 0.0625 * w * h
-//
-// Typical memory footprint (614x440 picture)
-// encoder: 22111
-// info: 4368
-// preds: 17741
-// top samples: 1263
-// non-zero: 175
-// lf-stats: 0
-// total: 45658
-// Transient object sizes:
-// VP8EncIterator: 3360
-// VP8ModeScore: 872
-// VP8SegmentInfo: 732
-// VP8EncProba: 18352
-// LFStats: 2048
-// Picture size (yuv): 419328
-
-static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
- WebPPicture* const picture) {
- VP8Encoder* enc;
- const int use_filter =
- (config->filter_strength > 0) || (config->autofilter > 0);
- const int mb_w = (picture->width + 15) >> 4;
- const int mb_h = (picture->height + 15) >> 4;
- const int preds_w = 4 * mb_w + 1;
- const int preds_h = 4 * mb_h + 1;
- const size_t preds_size = preds_w * preds_h * sizeof(*enc->preds_);
- const int top_stride = mb_w * 16;
- const size_t nz_size = (mb_w + 1) * sizeof(*enc->nz_) + WEBP_ALIGN_CST;
- const size_t info_size = mb_w * mb_h * sizeof(*enc->mb_info_);
- const size_t samples_size =
- 2 * top_stride * sizeof(*enc->y_top_) // top-luma/u/v
- + WEBP_ALIGN_CST; // align all
- const size_t lf_stats_size =
- config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0;
- uint8_t* mem;
- const uint64_t size = (uint64_t)sizeof(*enc) // main struct
- + WEBP_ALIGN_CST // cache alignment
- + info_size // modes info
- + preds_size // prediction modes
- + samples_size // top/left samples
- + nz_size // coeff context bits
- + lf_stats_size; // autofilter stats
-
-#ifdef PRINT_MEMORY_INFO
- printf("===================================\n");
- printf("Memory used:\n"
- " encoder: %ld\n"
- " info: %ld\n"
- " preds: %ld\n"
- " top samples: %ld\n"
- " non-zero: %ld\n"
- " lf-stats: %ld\n"
- " total: %ld\n",
- sizeof(*enc) + WEBP_ALIGN_CST, info_size,
- preds_size, samples_size, nz_size, lf_stats_size, size);
- printf("Transient object sizes:\n"
- " VP8EncIterator: %ld\n"
- " VP8ModeScore: %ld\n"
- " VP8SegmentInfo: %ld\n"
- " VP8EncProba: %ld\n"
- " LFStats: %ld\n",
- sizeof(VP8EncIterator), sizeof(VP8ModeScore),
- sizeof(VP8SegmentInfo), sizeof(VP8EncProba),
- sizeof(LFStats));
- printf("Picture size (yuv): %ld\n",
- mb_w * mb_h * 384 * sizeof(uint8_t));
- printf("===================================\n");
-#endif
- mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem));
- if (mem == NULL) {
- WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- return NULL;
- }
- enc = (VP8Encoder*)mem;
- mem = (uint8_t*)WEBP_ALIGN(mem + sizeof(*enc));
- memset(enc, 0, sizeof(*enc));
- enc->num_parts_ = 1 << config->partitions;
- enc->mb_w_ = mb_w;
- enc->mb_h_ = mb_h;
- enc->preds_w_ = preds_w;
- enc->mb_info_ = (VP8MBInfo*)mem;
- mem += info_size;
- enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_;
- mem += preds_size;
- enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem);
- mem += nz_size;
- enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL;
- mem += lf_stats_size;
-
- // top samples (all 16-aligned)
- mem = (uint8_t*)WEBP_ALIGN(mem);
- enc->y_top_ = (uint8_t*)mem;
- enc->uv_top_ = enc->y_top_ + top_stride;
- mem += 2 * top_stride;
- assert(mem <= (uint8_t*)enc + size);
-
- enc->config_ = config;
- enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2;
- enc->pic_ = picture;
- enc->percent_ = 0;
-
- MapConfigToTools(enc);
- VP8EncDspInit();
- VP8DefaultProbas(enc);
- ResetSegmentHeader(enc);
- ResetFilterHeader(enc);
- ResetBoundaryPredictions(enc);
- VP8EncDspCostInit();
- VP8EncInitAlpha(enc);
-
- // lower quality means smaller output -> we modulate a little the page
- // size based on quality. This is just a crude 1rst-order prediction.
- {
- const float scale = 1.f + config->quality * 5.f / 100.f; // in [1,6]
- VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale));
- }
- return enc;
-}
-
-static int DeleteVP8Encoder(VP8Encoder* enc) {
- int ok = 1;
- if (enc != NULL) {
- ok = VP8EncDeleteAlpha(enc);
- VP8TBufferClear(&enc->tokens_);
- WebPSafeFree(enc);
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-
-static double GetPSNR(uint64_t err, uint64_t size) {
- return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.;
-}
-
-static void FinalizePSNR(const VP8Encoder* const enc) {
- WebPAuxStats* stats = enc->pic_->stats;
- const uint64_t size = enc->sse_count_;
- const uint64_t* const sse = enc->sse_;
- stats->PSNR[0] = (float)GetPSNR(sse[0], size);
- stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4);
- stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4);
- stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2);
- stats->PSNR[4] = (float)GetPSNR(sse[3], size);
-}
-
-static void StoreStats(VP8Encoder* const enc) {
- WebPAuxStats* const stats = enc->pic_->stats;
- if (stats != NULL) {
- int i, s;
- for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
- stats->segment_level[i] = enc->dqm_[i].fstrength_;
- stats->segment_quant[i] = enc->dqm_[i].quant_;
- for (s = 0; s <= 2; ++s) {
- stats->residual_bytes[s][i] = enc->residual_bytes_[s][i];
- }
- }
- FinalizePSNR(enc);
- stats->coded_size = enc->coded_size_;
- for (i = 0; i < 3; ++i) {
- stats->block_count[i] = enc->block_count_[i];
- }
- }
- WebPReportProgress(enc->pic_, 100, &enc->percent_); // done!
-}
-
-int WebPEncodingSetError(const WebPPicture* const pic,
- WebPEncodingError error) {
- assert((int)error < VP8_ENC_ERROR_LAST);
- assert((int)error >= VP8_ENC_OK);
- ((WebPPicture*)pic)->error_code = error;
- return 0;
-}
-
-int WebPReportProgress(const WebPPicture* const pic,
- int percent, int* const percent_store) {
- if (percent_store != NULL && percent != *percent_store) {
- *percent_store = percent;
- if (pic->progress_hook && !pic->progress_hook(percent, pic)) {
- // user abort requested
- WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT);
- return 0;
- }
- }
- return 1; // ok
-}
-//------------------------------------------------------------------------------
-
-int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
- int ok = 0;
-
- if (pic == NULL)
- return 0;
- WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far
- if (config == NULL) // bad params
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
- if (!WebPValidateConfig(config))
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION);
- if (pic->width <= 0 || pic->height <= 0)
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
- if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION)
- return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
-
- if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats));
-
- if (!config->lossless) {
- VP8Encoder* enc = NULL;
-
- if (!config->exact) {
- WebPCleanupTransparentArea(pic);
- }
-
- if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) {
- // Make sure we have YUVA samples.
- if (config->preprocessing & 4) {
- if (!WebPPictureSmartARGBToYUVA(pic)) {
- return 0;
- }
- } else {
- float dithering = 0.f;
- if (config->preprocessing & 2) {
- const float x = config->quality / 100.f;
- const float x2 = x * x;
- // slowly decreasing from max dithering at low quality (q->0)
- // to 0.5 dithering amplitude at high quality (q->100)
- dithering = 1.0f + (0.5f - 1.0f) * x2 * x2;
- }
- if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) {
- return 0;
- }
- }
- }
-
- enc = InitVP8Encoder(config, pic);
- if (enc == NULL) return 0; // pic->error is already set.
- // Note: each of the tasks below account for 20% in the progress report.
- ok = VP8EncAnalyze(enc);
-
- // Analysis is done, proceed to actual coding.
- ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel
- if (!enc->use_tokens_) {
- ok = ok && VP8EncLoop(enc);
- } else {
- ok = ok && VP8EncTokenLoop(enc);
- }
- ok = ok && VP8EncFinishAlpha(enc);
-
- ok = ok && VP8EncWrite(enc);
- StoreStats(enc);
- if (!ok) {
- VP8EncFreeBitWriters(enc);
- }
- ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok
- } else {
- // Make sure we have ARGB samples.
- if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) {
- return 0;
- }
-
- if (!config->exact) {
- WebPCleanupTransparentAreaLossless(pic);
- }
-
- ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
- }
-
- return ok;
-}
diff --git a/drivers/webp/encode.h b/drivers/webp/encode.h
deleted file mode 100644
index 9291b7195c..0000000000
--- a/drivers/webp/encode.h
+++ /dev/null
@@ -1,527 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// WebP encoder: main interface
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_WEBP_ENCODE_H_
-#define WEBP_WEBP_ENCODE_H_
-
-#include "./types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WEBP_ENCODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b)
-
-// Note: forward declaring enumerations is not allowed in (strict) C and C++,
-// the types are left here for reference.
-// typedef enum WebPImageHint WebPImageHint;
-// typedef enum WebPEncCSP WebPEncCSP;
-// typedef enum WebPPreset WebPPreset;
-// typedef enum WebPEncodingError WebPEncodingError;
-typedef struct WebPConfig WebPConfig;
-typedef struct WebPPicture WebPPicture; // main structure for I/O
-typedef struct WebPAuxStats WebPAuxStats;
-typedef struct WebPMemoryWriter WebPMemoryWriter;
-
-// Return the encoder's version number, packed in hexadecimal using 8bits for
-// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
-WEBP_EXTERN(int) WebPGetEncoderVersion(void);
-
-//------------------------------------------------------------------------------
-// One-stop-shop call! No questions asked:
-
-// Returns the size of the compressed data (pointed to by *output), or 0 if
-// an error occurred. The compressed data must be released by the caller
-// using the call 'WebPFree(*output)'.
-// These functions compress using the lossy format, and the quality_factor
-// can go from 0 (smaller output, lower quality) to 100 (best quality,
-// larger output).
-WEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb,
- int width, int height, int stride,
- float quality_factor, uint8_t** output);
-WEBP_EXTERN(size_t) WebPEncodeBGR(const uint8_t* bgr,
- int width, int height, int stride,
- float quality_factor, uint8_t** output);
-WEBP_EXTERN(size_t) WebPEncodeRGBA(const uint8_t* rgba,
- int width, int height, int stride,
- float quality_factor, uint8_t** output);
-WEBP_EXTERN(size_t) WebPEncodeBGRA(const uint8_t* bgra,
- int width, int height, int stride,
- float quality_factor, uint8_t** output);
-
-// These functions are the equivalent of the above, but compressing in a
-// lossless manner. Files are usually larger than lossy format, but will
-// not suffer any compression loss.
-WEBP_EXTERN(size_t) WebPEncodeLosslessRGB(const uint8_t* rgb,
- int width, int height, int stride,
- uint8_t** output);
-WEBP_EXTERN(size_t) WebPEncodeLosslessBGR(const uint8_t* bgr,
- int width, int height, int stride,
- uint8_t** output);
-WEBP_EXTERN(size_t) WebPEncodeLosslessRGBA(const uint8_t* rgba,
- int width, int height, int stride,
- uint8_t** output);
-WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra,
- int width, int height, int stride,
- uint8_t** output);
-
-// Releases memory returned by the WebPEncode*() functions above.
-WEBP_EXTERN(void) WebPFree(void* ptr);
-
-//------------------------------------------------------------------------------
-// Coding parameters
-
-// Image characteristics hint for the underlying encoder.
-typedef enum WebPImageHint {
- WEBP_HINT_DEFAULT = 0, // default preset.
- WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot
- WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting
- WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc).
- WEBP_HINT_LAST
-} WebPImageHint;
-
-// Compression parameters.
-struct WebPConfig {
- int lossless; // Lossless encoding (0=lossy(default), 1=lossless).
- float quality; // between 0 (smallest file) and 100 (biggest)
- int method; // quality/speed trade-off (0=fast, 6=slower-better)
-
- WebPImageHint image_hint; // Hint for image type (lossless only for now).
-
- // Parameters related to lossy compression only:
- int target_size; // if non-zero, set the desired target size in bytes.
- // Takes precedence over the 'compression' parameter.
- float target_PSNR; // if non-zero, specifies the minimal distortion to
- // try to achieve. Takes precedence over target_size.
- int segments; // maximum number of segments to use, in [1..4]
- int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum.
- int filter_strength; // range: [0 = off .. 100 = strongest]
- int filter_sharpness; // range: [0 = off .. 7 = least sharp]
- int filter_type; // filtering type: 0 = simple, 1 = strong (only used
- // if filter_strength > 0 or autofilter > 0)
- int autofilter; // Auto adjust filter's strength [0 = off, 1 = on]
- int alpha_compression; // Algorithm for encoding the alpha plane (0 = none,
- // 1 = compressed with WebP lossless). Default is 1.
- int alpha_filtering; // Predictive filtering method for alpha plane.
- // 0: none, 1: fast, 2: best. Default if 1.
- int alpha_quality; // Between 0 (smallest size) and 100 (lossless).
- // Default is 100.
- int pass; // number of entropy-analysis passes (in [1..10]).
-
- int show_compressed; // if true, export the compressed picture back.
- // In-loop filtering is not applied.
- int preprocessing; // preprocessing filter:
- // 0=none, 1=segment-smooth, 2=pseudo-random dithering
- int partitions; // log2(number of token partitions) in [0..3]. Default
- // is set to 0 for easier progressive decoding.
- int partition_limit; // quality degradation allowed to fit the 512k limit
- // on prediction modes coding (0: no degradation,
- // 100: maximum possible degradation).
- int emulate_jpeg_size; // If true, compression parameters will be remapped
- // to better match the expected output size from
- // JPEG compression. Generally, the output size will
- // be similar but the degradation will be lower.
- int thread_level; // If non-zero, try and use multi-threaded encoding.
- int low_memory; // If set, reduce memory usage (but increase CPU use).
-
- int near_lossless; // Near lossless encoding [0 = max loss .. 100 = off
- // (default)].
- int exact; // if non-zero, preserve the exact RGB values under
- // transparent area. Otherwise, discard this invisible
- // RGB information for better compression. The default
- // value is 0.
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- int delta_palettization;
- uint32_t pad[2]; // padding for later use
-#else
- uint32_t pad[3]; // padding for later use
-#endif // WEBP_EXPERIMENTAL_FEATURES
-};
-
-// Enumerate some predefined settings for WebPConfig, depending on the type
-// of source picture. These presets are used when calling WebPConfigPreset().
-typedef enum WebPPreset {
- WEBP_PRESET_DEFAULT = 0, // default preset.
- WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot
- WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting
- WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details
- WEBP_PRESET_ICON, // small-sized colorful images
- WEBP_PRESET_TEXT // text-like
-} WebPPreset;
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int);
-
-// Should always be called, to initialize a fresh WebPConfig structure before
-// modification. Returns false in case of version mismatch. WebPConfigInit()
-// must have succeeded before using the 'config' object.
-// Note that the default values are lossless=0 and quality=75.
-static WEBP_INLINE int WebPConfigInit(WebPConfig* config) {
- return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f,
- WEBP_ENCODER_ABI_VERSION);
-}
-
-// This function will initialize the configuration according to a predefined
-// set of parameters (referred to by 'preset') and a given quality factor.
-// This function can be called as a replacement to WebPConfigInit(). Will
-// return false in case of error.
-static WEBP_INLINE int WebPConfigPreset(WebPConfig* config,
- WebPPreset preset, float quality) {
- return WebPConfigInitInternal(config, preset, quality,
- WEBP_ENCODER_ABI_VERSION);
-}
-
-// Activate the lossless compression mode with the desired efficiency level
-// between 0 (fastest, lowest compression) and 9 (slower, best compression).
-// A good default level is '6', providing a fair tradeoff between compression
-// speed and final compressed size.
-// This function will overwrite several fields from config: 'method', 'quality'
-// and 'lossless'. Returns false in case of parameter error.
-WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level);
-
-// Returns true if 'config' is non-NULL and all configuration parameters are
-// within their valid ranges.
-WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config);
-
-//------------------------------------------------------------------------------
-// Input / Output
-// Structure for storing auxiliary statistics (mostly for lossy encoding).
-
-struct WebPAuxStats {
- int coded_size; // final size
-
- float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha
- int block_count[3]; // number of intra4/intra16/skipped macroblocks
- int header_bytes[2]; // approximate number of bytes spent for header
- // and mode-partition #0
- int residual_bytes[3][4]; // approximate number of bytes spent for
- // DC/AC/uv coefficients for each (0..3) segments.
- int segment_size[4]; // number of macroblocks in each segments
- int segment_quant[4]; // quantizer values for each segments
- int segment_level[4]; // filtering strength for each segments [0..63]
-
- int alpha_data_size; // size of the transparency data
- int layer_data_size; // size of the enhancement layer data
-
- // lossless encoder statistics
- uint32_t lossless_features; // bit0:predictor bit1:cross-color transform
- // bit2:subtract-green bit3:color indexing
- int histogram_bits; // number of precision bits of histogram
- int transform_bits; // precision bits for transform
- int cache_bits; // number of bits for color cache lookup
- int palette_size; // number of color in palette, if used
- int lossless_size; // final lossless size
- int lossless_hdr_size; // lossless header (transform, huffman etc) size
- int lossless_data_size; // lossless image data size
-
- uint32_t pad[2]; // padding for later use
-};
-
-// Signature for output function. Should return true if writing was successful.
-// data/data_size is the segment of data to write, and 'picture' is for
-// reference (and so one can make use of picture->custom_ptr).
-typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size,
- const WebPPicture* picture);
-
-// WebPMemoryWrite: a special WebPWriterFunction that writes to memory using
-// the following WebPMemoryWriter object (to be set as a custom_ptr).
-struct WebPMemoryWriter {
- uint8_t* mem; // final buffer (of size 'max_size', larger than 'size').
- size_t size; // final size
- size_t max_size; // total capacity
- uint32_t pad[1]; // padding for later use
-};
-
-// The following must be called first before any use.
-WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer);
-
-// The following must be called to deallocate writer->mem memory. The 'writer'
-// object itself is not deallocated.
-WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer);
-// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon
-// completion, writer.mem and writer.size will hold the coded data.
-// writer.mem must be freed by calling WebPMemoryWriterClear.
-WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size,
- const WebPPicture* picture);
-
-// Progress hook, called from time to time to report progress. It can return
-// false to request an abort of the encoding process, or true otherwise if
-// everything is OK.
-typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture);
-
-// Color spaces.
-typedef enum WebPEncCSP {
- // chroma sampling
- WEBP_YUV420 = 0, // 4:2:0
- WEBP_YUV420A = 4, // alpha channel variant
- WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors
- WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present
-} WebPEncCSP;
-
-// Encoding error conditions.
-typedef enum WebPEncodingError {
- VP8_ENC_OK = 0,
- VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects
- VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits
- VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL
- VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid
- VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height
- VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k
- VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M
- VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes
- VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G
- VP8_ENC_ERROR_USER_ABORT, // abort request by user
- VP8_ENC_ERROR_LAST // list terminator. always last.
-} WebPEncodingError;
-
-// maximum width/height allowed (inclusive), in pixels
-#define WEBP_MAX_DIMENSION 16383
-
-// Main exchange structure (input samples, output bytes, statistics)
-struct WebPPicture {
- // INPUT
- //////////////
- // Main flag for encoder selecting between ARGB or YUV input.
- // It is recommended to use ARGB input (*argb, argb_stride) for lossless
- // compression, and YUV input (*y, *u, *v, etc.) for lossy compression
- // since these are the respective native colorspace for these formats.
- int use_argb;
-
- // YUV input (mostly used for input to lossy compression)
- WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr).
- int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION)
- uint8_t *y, *u, *v; // pointers to luma/chroma planes.
- int y_stride, uv_stride; // luma/chroma strides.
- uint8_t* a; // pointer to the alpha plane
- int a_stride; // stride of the alpha plane
- uint32_t pad1[2]; // padding for later use
-
- // ARGB input (mostly used for input to lossless compression)
- uint32_t* argb; // Pointer to argb (32 bit) plane.
- int argb_stride; // This is stride in pixels units, not bytes.
- uint32_t pad2[3]; // padding for later use
-
- // OUTPUT
- ///////////////
- // Byte-emission hook, to store compressed bytes as they are ready.
- WebPWriterFunction writer; // can be NULL
- void* custom_ptr; // can be used by the writer.
-
- // map for extra information (only for lossy compression mode)
- int extra_info_type; // 1: intra type, 2: segment, 3: quant
- // 4: intra-16 prediction mode,
- // 5: chroma prediction mode,
- // 6: bit cost, 7: distortion
- uint8_t* extra_info; // if not NULL, points to an array of size
- // ((width + 15) / 16) * ((height + 15) / 16) that
- // will be filled with a macroblock map, depending
- // on extra_info_type.
-
- // STATS AND REPORTS
- ///////////////////////////
- // Pointer to side statistics (updated only if not NULL)
- WebPAuxStats* stats;
-
- // Error code for the latest error encountered during encoding
- WebPEncodingError error_code;
-
- // If not NULL, report progress during encoding.
- WebPProgressHook progress_hook;
-
- void* user_data; // this field is free to be set to any value and
- // used during callbacks (like progress-report e.g.).
-
- uint32_t pad3[3]; // padding for later use
-
- // Unused for now
- uint8_t *pad4, *pad5;
- uint32_t pad6[8]; // padding for later use
-
- // PRIVATE FIELDS
- ////////////////////
- void* memory_; // row chunk of memory for yuva planes
- void* memory_argb_; // and for argb too.
- void* pad7[2]; // padding for later use
-};
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(int) WebPPictureInitInternal(WebPPicture*, int);
-
-// Should always be called, to initialize the structure. Returns false in case
-// of version mismatch. WebPPictureInit() must have succeeded before using the
-// 'picture' object.
-// Note that, by default, use_argb is false and colorspace is WEBP_YUV420.
-static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) {
- return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION);
-}
-
-//------------------------------------------------------------------------------
-// WebPPicture utils
-
-// Convenience allocation / deallocation based on picture->width/height:
-// Allocate y/u/v buffers as per colorspace/width/height specification.
-// Note! This function will free the previous buffer if needed.
-// Returns false in case of memory error.
-WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture);
-
-// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*().
-// Note that this function does _not_ free the memory used by the 'picture'
-// object itself.
-// Besides memory (which is reclaimed) all other fields of 'picture' are
-// preserved.
-WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture);
-
-// Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst
-// will fully own the copied pixels (this is not a view). The 'dst' picture need
-// not be initialized as its content is overwritten.
-// Returns false in case of memory allocation error.
-WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst);
-
-// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results
-// are in dB, stored in result[] in the Y/U/V/Alpha/All or B/G/R/A/All order.
-// Returns false in case of error (src and ref don't have same dimension, ...)
-// Warning: this function is rather CPU-intensive.
-WEBP_EXTERN(int) WebPPictureDistortion(
- const WebPPicture* src, const WebPPicture* ref,
- int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM
- float result[5]);
-
-// self-crops a picture to the rectangle defined by top/left/width/height.
-// Returns false in case of memory allocation error, or if the rectangle is
-// outside of the source picture.
-// The rectangle for the view is defined by the top-left corner pixel
-// coordinates (left, top) as well as its width and height. This rectangle
-// must be fully be comprised inside the 'src' source picture. If the source
-// picture uses the YUV420 colorspace, the top and left coordinates will be
-// snapped to even values.
-WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture,
- int left, int top, int width, int height);
-
-// Extracts a view from 'src' picture into 'dst'. The rectangle for the view
-// is defined by the top-left corner pixel coordinates (left, top) as well
-// as its width and height. This rectangle must be fully be comprised inside
-// the 'src' source picture. If the source picture uses the YUV420 colorspace,
-// the top and left coordinates will be snapped to even values.
-// Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed
-// ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so,
-// the original dimension will be lost). Picture 'dst' need not be initialized
-// with WebPPictureInit() if it is different from 'src', since its content will
-// be overwritten.
-// Returns false in case of memory allocation error or invalid parameters.
-WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src,
- int left, int top, int width, int height,
- WebPPicture* dst);
-
-// Returns true if the 'picture' is actually a view and therefore does
-// not own the memory for pixels.
-WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture);
-
-// Rescale a picture to new dimension width x height.
-// If either 'width' or 'height' (but not both) is 0 the corresponding
-// dimension will be calculated preserving the aspect ratio.
-// No gamma correction is applied.
-// Returns false in case of error (invalid parameter or insufficient memory).
-WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height);
-
-// Colorspace conversion function to import RGB samples.
-// Previous buffer will be free'd, if any.
-// *rgb buffer should have a size of at least height * rgb_stride.
-// Returns false in case of memory error.
-WEBP_EXTERN(int) WebPPictureImportRGB(
- WebPPicture* picture, const uint8_t* rgb, int rgb_stride);
-// Same, but for RGBA buffer.
-WEBP_EXTERN(int) WebPPictureImportRGBA(
- WebPPicture* picture, const uint8_t* rgba, int rgba_stride);
-// Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format
-// input buffer ignoring the alpha channel. Avoids needing to copy the data
-// to a temporary 24-bit RGB buffer to import the RGB only.
-WEBP_EXTERN(int) WebPPictureImportRGBX(
- WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride);
-
-// Variants of the above, but taking BGR(A|X) input.
-WEBP_EXTERN(int) WebPPictureImportBGR(
- WebPPicture* picture, const uint8_t* bgr, int bgr_stride);
-WEBP_EXTERN(int) WebPPictureImportBGRA(
- WebPPicture* picture, const uint8_t* bgra, int bgra_stride);
-WEBP_EXTERN(int) WebPPictureImportBGRX(
- WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride);
-
-// Converts picture->argb data to the YUV420A format. The 'colorspace'
-// parameter is deprecated and should be equal to WEBP_YUV420.
-// Upon return, picture->use_argb is set to false. The presence of real
-// non-opaque transparent values is detected, and 'colorspace' will be
-// adjusted accordingly. Note that this method is lossy.
-// Returns false in case of error.
-WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
- WebPEncCSP /*colorspace = WEBP_YUV420*/);
-
-// Same as WebPPictureARGBToYUVA(), but the conversion is done using
-// pseudo-random dithering with a strength 'dithering' between
-// 0.0 (no dithering) and 1.0 (maximum dithering). This is useful
-// for photographic picture.
-WEBP_EXTERN(int) WebPPictureARGBToYUVADithered(
- WebPPicture* picture, WebPEncCSP colorspace, float dithering);
-
-// Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion.
-// Downsampling is handled with extra care in case of color clipping. This
-// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better
-// YUV representation.
-// Returns false in case of error.
-WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture);
-
-// Converts picture->yuv to picture->argb and sets picture->use_argb to true.
-// The input format must be YUV_420 or YUV_420A.
-// Note that the use of this method is discouraged if one has access to the
-// raw ARGB samples, since using YUV420 is comparatively lossy. Also, the
-// conversion from YUV420 to ARGB incurs a small loss too.
-// Returns false in case of error.
-WEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture);
-
-// Helper function: given a width x height plane of RGBA or YUV(A) samples
-// clean-up the YUV or RGB samples under fully transparent area, to help
-// compressibility (no guarantee, though).
-WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture);
-
-// Scan the picture 'picture' for the presence of non fully opaque alpha values.
-// Returns true in such case. Otherwise returns false (indicating that the
-// alpha plane can be ignored altogether e.g.).
-WEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture);
-
-// Remove the transparency information (if present) by blending the color with
-// the background color 'background_rgb' (specified as 24bit RGB triplet).
-// After this call, all alpha values are reset to 0xff.
-WEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb);
-
-//------------------------------------------------------------------------------
-// Main call
-
-// Main encoding call, after config and picture have been initialized.
-// 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION),
-// and the 'config' object must be a valid one.
-// Returns false in case of error, true otherwise.
-// In case of error, picture->error_code is updated accordingly.
-// 'picture' can hold the source samples in both YUV(A) or ARGB input, depending
-// on the value of 'picture->use_argb'. It is highly recommended to use
-// the former for lossy encoding, and the latter for lossless encoding
-// (when config.lossless is true). Automatic conversion from one format to
-// another is provided but they both incur some loss.
-WEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_WEBP_ENCODE_H_ */
diff --git a/drivers/webp/extras.h b/drivers/webp/extras.h
deleted file mode 100644
index 1c24be2e0c..0000000000
--- a/drivers/webp/extras.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-
-#ifndef WEBP_WEBP_EXTRAS_H_
-#define WEBP_WEBP_EXTRAS_H_
-
-#include "./types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "./encode.h"
-
-#define WEBP_EXTRAS_ABI_VERSION 0x0000 // MAJOR(8b) + MINOR(8b)
-
-//------------------------------------------------------------------------------
-
-// Returns the version number of the extras library, packed in hexadecimal using
-// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
-WEBP_EXTERN(int) WebPGetExtrasVersion(void);
-
-//------------------------------------------------------------------------------
-// Ad-hoc colorspace importers.
-
-// Import luma sample (gray scale image) into 'picture'. The 'picture'
-// width and height must be set prior to calling this function.
-WEBP_EXTERN(int) WebPImportGray(const uint8_t* gray, WebPPicture* picture);
-
-// Import rgb sample in RGB565 packed format into 'picture'. The 'picture'
-// width and height must be set prior to calling this function.
-WEBP_EXTERN(int) WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic);
-
-// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture'
-// width and height must be set prior to calling this function.
-WEBP_EXTERN(int) WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_WEBP_EXTRAS_H_ */
diff --git a/drivers/webp/format_constants.h b/drivers/webp/format_constants.h
deleted file mode 100644
index b6e78a643e..0000000000
--- a/drivers/webp/format_constants.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Internal header for constants related to WebP file format.
-//
-// Author: Urvang (urvang@google.com)
-
-#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_
-#define WEBP_WEBP_FORMAT_CONSTANTS_H_
-
-// Create fourcc of the chunk from the chunk tag characters.
-#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24)
-
-// VP8 related constants.
-#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data.
-#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition
-#define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition
-#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data.
-
-// VP8L related constants.
-#define VP8L_SIGNATURE_SIZE 1 // VP8L signature size.
-#define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte.
-#define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store
- // width and height.
-#define VP8L_VERSION_BITS 3 // 3 bits reserved for version.
-#define VP8L_VERSION 0 // version 0
-#define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header.
-
-#define MAX_PALETTE_SIZE 256
-#define MAX_CACHE_BITS 11
-#define HUFFMAN_CODES_PER_META_CODE 5
-#define ARGB_BLACK 0xff000000
-
-#define DEFAULT_CODE_LENGTH 8
-#define MAX_ALLOWED_CODE_LENGTH 15
-
-#define NUM_LITERAL_CODES 256
-#define NUM_LENGTH_CODES 24
-#define NUM_DISTANCE_CODES 40
-#define CODE_LENGTH_CODES 19
-
-#define MIN_HUFFMAN_BITS 2 // min number of Huffman bits
-#define MAX_HUFFMAN_BITS 9 // max number of Huffman bits
-
-#define TRANSFORM_PRESENT 1 // The bit to be written when next data
- // to be read is a transform.
-#define NUM_TRANSFORMS 4 // Maximum number of allowed transform
- // in a bitstream.
-typedef enum {
- PREDICTOR_TRANSFORM = 0,
- CROSS_COLOR_TRANSFORM = 1,
- SUBTRACT_GREEN = 2,
- COLOR_INDEXING_TRANSFORM = 3
-} VP8LImageTransformType;
-
-// Alpha related constants.
-#define ALPHA_HEADER_LEN 1
-#define ALPHA_NO_COMPRESSION 0
-#define ALPHA_LOSSLESS_COMPRESSION 1
-#define ALPHA_PREPROCESSED_LEVELS 1
-
-// Mux related constants.
-#define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L").
-#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size.
-#define CHUNK_HEADER_SIZE 8 // Size of a chunk header.
-#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP").
-#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk.
-#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk.
-#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk.
-#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.
-
-#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
-#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
-#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
-#define MAX_DURATION (1 << 24) // maximum duration
-#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/fragment x/y offset
-
-// Maximum chunk payload is such that adding the header and padding won't
-// overflow a uint32_t.
-#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1)
-
-#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */
diff --git a/drivers/webp/image_loader_webp.cpp b/drivers/webp/image_loader_webp.cpp
deleted file mode 100644
index 68bb857293..0000000000
--- a/drivers/webp/image_loader_webp.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*************************************************************************/
-/* image_loader_webp.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "image_loader_webp.h"
-
-#include "print_string.h"
-#include "os/os.h"
-#include "drivers/webp/decode.h"
-#include "drivers/webp/encode.h"
-#include "io/marshalls.h"
-#include <stdlib.h>
-
-static DVector<uint8_t> _webp_lossy_pack(const Image& p_image,float p_quality) {
-
- ERR_FAIL_COND_V(p_image.empty(),DVector<uint8_t>());
-
- Image img=p_image;
- if (img.detect_alpha())
- img.convert(Image::FORMAT_RGBA);
- else
- img.convert(Image::FORMAT_RGB);
-
- Size2 s(img.get_width(),img.get_height());
- DVector<uint8_t> data = img.get_data();
- DVector<uint8_t>::Read r = data.read();
-
- uint8_t *dst_buff=NULL;
- size_t dst_size=0;
- if (img.get_format()==Image::FORMAT_RGB) {
-
- dst_size = WebPEncodeRGB(r.ptr(),s.width,s.height,3*s.width,CLAMP(p_quality*100.0,0,100.0),&dst_buff);
- } else {
- dst_size = WebPEncodeRGBA(r.ptr(),s.width,s.height,4*s.width,CLAMP(p_quality*100.0,0,100.0),&dst_buff);
- }
-
- ERR_FAIL_COND_V(dst_size==0,DVector<uint8_t>());
- DVector<uint8_t> dst;
- dst.resize(4+dst_size);
- DVector<uint8_t>::Write w = dst.write();
- w[0]='W';
- w[1]='E';
- w[2]='B';
- w[3]='P';
- copymem(&w[4],dst_buff,dst_size);
- free(dst_buff);
- w=DVector<uint8_t>::Write();
- return dst;
-}
-
-static Image _webp_lossy_unpack(const DVector<uint8_t>& p_buffer) {
-
- int size = p_buffer.size()-4;
- ERR_FAIL_COND_V(size<=0,Image());
- DVector<uint8_t>::Read r = p_buffer.read();
-
- ERR_FAIL_COND_V(r[0]!='W' || r[1]!='E' || r[2]!='B' || r[3]!='P',Image());
- WebPBitstreamFeatures features;
- if (WebPGetFeatures(&r[4],size,&features)!=VP8_STATUS_OK) {
- ERR_EXPLAIN("Error unpacking WEBP image:");
- ERR_FAIL_V(Image());
- }
-
- //print_line("width: "+itos(features.width));
- //print_line("height: "+itos(features.height));
- //print_line("alpha: "+itos(features.has_alpha));
-
- DVector<uint8_t> dst_image;
- int datasize = features.width*features.height*(features.has_alpha?4:3);
- dst_image.resize(datasize);
-
- DVector<uint8_t>::Write dst_w = dst_image.write();
-
- bool errdec=false;
- if (features.has_alpha) {
- errdec = WebPDecodeRGBAInto(&r[4],size,dst_w.ptr(),datasize,4*features.width)==NULL;
- } else {
- errdec = WebPDecodeRGBInto(&r[4],size,dst_w.ptr(),datasize,3*features.width)==NULL;
-
- }
-
- //ERR_EXPLAIN("Error decoding webp! - "+p_file);
- ERR_FAIL_COND_V(errdec,Image());
-
- dst_w = DVector<uint8_t>::Write();
-
- return Image(features.width,features.height,0,features.has_alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB,dst_image);
-
-}
-
-
-Error ImageLoaderWEBP::load_image(Image *p_image,FileAccess *f) {
-
-
- uint32_t size = f->get_len();
- DVector<uint8_t> src_image;
- src_image.resize(size);
-
- WebPBitstreamFeatures features;
-
- DVector<uint8_t>::Write src_w = src_image.write();
- f->get_buffer(src_w.ptr(),size);
- ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_EOF);
-
- if (WebPGetFeatures(src_w.ptr(),size,&features)!=VP8_STATUS_OK) {
- f->close();
- //ERR_EXPLAIN("Error decoding WEBP image: "+p_file);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- print_line("width: "+itos(features.width));
- print_line("height: "+itos(features.height));
- print_line("alpha: "+itos(features.has_alpha));
-
- src_w = DVector<uint8_t>::Write();
-
- DVector<uint8_t> dst_image;
- int datasize = features.width*features.height*(features.has_alpha?4:3);
- dst_image.resize(datasize);
-
- DVector<uint8_t>::Read src_r = src_image.read();
- DVector<uint8_t>::Write dst_w = dst_image.write();
-
-
- bool errdec=false;
- if (features.has_alpha) {
- errdec = WebPDecodeRGBAInto(src_r.ptr(),size,dst_w.ptr(),datasize,4*features.width)==NULL;
- } else {
- errdec = WebPDecodeRGBInto(src_r.ptr(),size,dst_w.ptr(),datasize,3*features.width)==NULL;
-
- }
-
- //ERR_EXPLAIN("Error decoding webp! - "+p_file);
- ERR_FAIL_COND_V(errdec,ERR_FILE_CORRUPT);
-
- src_r = DVector<uint8_t>::Read();
- dst_w = DVector<uint8_t>::Write();
-
- *p_image = Image(features.width,features.height,0,features.has_alpha?Image::FORMAT_RGBA:Image::FORMAT_RGB,dst_image);
-
-
- return OK;
-
-}
-
-void ImageLoaderWEBP::get_recognized_extensions(List<String> *p_extensions) const {
-
- p_extensions->push_back("webp");
-}
-
-
-ImageLoaderWEBP::ImageLoaderWEBP() {
-
- Image::lossy_packer=_webp_lossy_pack;
- Image::lossy_unpacker=_webp_lossy_unpack;
-}
-
-
diff --git a/drivers/webp/image_loader_webp.h b/drivers/webp/image_loader_webp.h
deleted file mode 100644
index 24f79708db..0000000000
--- a/drivers/webp/image_loader_webp.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*************************************************************************/
-/* image_loader_webp.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef IMAGE_LOADER_WEBP_H
-#define IMAGE_LOADER_WEBP_H
-
-#include "io/image_loader.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class ImageLoaderWEBP : public ImageFormatLoader {
-
-
-public:
-
- virtual Error load_image(Image *p_image,FileAccess *f);
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- ImageLoaderWEBP();
-};
-
-
-
-#endif
diff --git a/drivers/webp/mux.h b/drivers/webp/mux.h
deleted file mode 100644
index b72658c741..0000000000
--- a/drivers/webp/mux.h
+++ /dev/null
@@ -1,530 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// RIFF container manipulation and encoding for WebP images.
-//
-// Authors: Urvang (urvang@google.com)
-// Vikas (vikasa@google.com)
-
-#ifndef WEBP_WEBP_MUX_H_
-#define WEBP_WEBP_MUX_H_
-
-#include "./mux_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WEBP_MUX_ABI_VERSION 0x0106 // MAJOR(8b) + MINOR(8b)
-
-//------------------------------------------------------------------------------
-// Mux API
-//
-// This API allows manipulation of WebP container images containing features
-// like color profile, metadata, animation and fragmented images.
-//
-// Code Example#1: Create a WebPMux object with image data, color profile and
-// XMP metadata.
-/*
- int copy_data = 0;
- WebPMux* mux = WebPMuxNew();
- // ... (Prepare image data).
- WebPMuxSetImage(mux, &image, copy_data);
- // ... (Prepare ICCP color profile data).
- WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
- // ... (Prepare XMP metadata).
- WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
- // Get data from mux in WebP RIFF format.
- WebPMuxAssemble(mux, &output_data);
- WebPMuxDelete(mux);
- // ... (Consume output_data; e.g. write output_data.bytes to file).
- WebPDataClear(&output_data);
-*/
-
-// Code Example#2: Get image and color profile data from a WebP file.
-/*
- int copy_data = 0;
- // ... (Read data from file).
- WebPMux* mux = WebPMuxCreate(&data, copy_data);
- WebPMuxGetFrame(mux, 1, &image);
- // ... (Consume image; e.g. call WebPDecode() to decode the data).
- WebPMuxGetChunk(mux, "ICCP", &icc_profile);
- // ... (Consume icc_data).
- WebPMuxDelete(mux);
- free(data);
-*/
-
-// Note: forward declaring enumerations is not allowed in (strict) C and C++,
-// the types are left here for reference.
-// typedef enum WebPMuxError WebPMuxError;
-// typedef enum WebPChunkId WebPChunkId;
-typedef struct WebPMux WebPMux; // main opaque object.
-typedef struct WebPMuxFrameInfo WebPMuxFrameInfo;
-typedef struct WebPMuxAnimParams WebPMuxAnimParams;
-typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions;
-
-// Error codes
-typedef enum WebPMuxError {
- WEBP_MUX_OK = 1,
- WEBP_MUX_NOT_FOUND = 0,
- WEBP_MUX_INVALID_ARGUMENT = -1,
- WEBP_MUX_BAD_DATA = -2,
- WEBP_MUX_MEMORY_ERROR = -3,
- WEBP_MUX_NOT_ENOUGH_DATA = -4
-} WebPMuxError;
-
-// IDs for different types of chunks.
-typedef enum WebPChunkId {
- WEBP_CHUNK_VP8X, // VP8X
- WEBP_CHUNK_ICCP, // ICCP
- WEBP_CHUNK_ANIM, // ANIM
- WEBP_CHUNK_ANMF, // ANMF
- WEBP_CHUNK_FRGM, // FRGM
- WEBP_CHUNK_ALPHA, // ALPH
- WEBP_CHUNK_IMAGE, // VP8/VP8L
- WEBP_CHUNK_EXIF, // EXIF
- WEBP_CHUNK_XMP, // XMP
- WEBP_CHUNK_UNKNOWN, // Other chunks.
- WEBP_CHUNK_NIL
-} WebPChunkId;
-
-//------------------------------------------------------------------------------
-
-// Returns the version number of the mux library, packed in hexadecimal using
-// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
-WEBP_EXTERN(int) WebPGetMuxVersion(void);
-
-//------------------------------------------------------------------------------
-// Life of a Mux object
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(WebPMux*) WebPNewInternal(int);
-
-// Creates an empty mux object.
-// Returns:
-// A pointer to the newly created empty mux object.
-// Or NULL in case of memory error.
-static WEBP_INLINE WebPMux* WebPMuxNew(void) {
- return WebPNewInternal(WEBP_MUX_ABI_VERSION);
-}
-
-// Deletes the mux object.
-// Parameters:
-// mux - (in/out) object to be deleted
-WEBP_EXTERN(void) WebPMuxDelete(WebPMux* mux);
-
-//------------------------------------------------------------------------------
-// Mux creation.
-
-// Internal, version-checked, entry point
-WEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int);
-
-// Creates a mux object from raw data given in WebP RIFF format.
-// Parameters:
-// bitstream - (in) the bitstream data in WebP RIFF format
-// copy_data - (in) value 1 indicates given data WILL be copied to the mux
-// object and value 0 indicates data will NOT be copied.
-// Returns:
-// A pointer to the mux object created from given data - on success.
-// NULL - In case of invalid data or memory error.
-static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream,
- int copy_data) {
- return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION);
-}
-
-//------------------------------------------------------------------------------
-// Non-image chunks.
-
-// Note: Only non-image related chunks should be managed through chunk APIs.
-// (Image related chunks are: "ANMF", "FRGM", "VP8 ", "VP8L" and "ALPH").
-// To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(),
-// WebPMuxGetFrame() and WebPMuxDeleteFrame().
-
-// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object.
-// Any existing chunk(s) with the same id will be removed.
-// Parameters:
-// mux - (in/out) object to which the chunk is to be added
-// fourcc - (in) a character array containing the fourcc of the given chunk;
-// e.g., "ICCP", "XMP ", "EXIF" etc.
-// chunk_data - (in) the chunk data to be added
-// copy_data - (in) value 1 indicates given data WILL be copied to the mux
-// object and value 0 indicates data will NOT be copied.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL
-// or if fourcc corresponds to an image chunk.
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk(
- WebPMux* mux, const char fourcc[4], const WebPData* chunk_data,
- int copy_data);
-
-// Gets a reference to the data of the chunk with id 'fourcc' in the mux object.
-// The caller should NOT free the returned data.
-// Parameters:
-// mux - (in) object from which the chunk data is to be fetched
-// fourcc - (in) a character array containing the fourcc of the chunk;
-// e.g., "ICCP", "XMP ", "EXIF" etc.
-// chunk_data - (out) returned chunk data
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL
-// or if fourcc corresponds to an image chunk.
-// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk(
- const WebPMux* mux, const char fourcc[4], WebPData* chunk_data);
-
-// Deletes the chunk with the given 'fourcc' from the mux object.
-// Parameters:
-// mux - (in/out) object from which the chunk is to be deleted
-// fourcc - (in) a character array containing the fourcc of the chunk;
-// e.g., "ICCP", "XMP ", "EXIF" etc.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL
-// or if fourcc corresponds to an image chunk.
-// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk(
- WebPMux* mux, const char fourcc[4]);
-
-//------------------------------------------------------------------------------
-// Images.
-
-// Encapsulates data about a single frame/fragment.
-struct WebPMuxFrameInfo {
- WebPData bitstream; // image data: can be a raw VP8/VP8L bitstream
- // or a single-image WebP file.
- int x_offset; // x-offset of the frame.
- int y_offset; // y-offset of the frame.
- int duration; // duration of the frame (in milliseconds).
-
- WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF,
- // WEBP_CHUNK_FRGM or WEBP_CHUNK_IMAGE
- WebPMuxAnimDispose dispose_method; // Disposal method for the frame.
- WebPMuxAnimBlend blend_method; // Blend operation for the frame.
- uint32_t pad[1]; // padding for later use
-};
-
-// Sets the (non-animated and non-fragmented) image in the mux object.
-// Note: Any existing images (including frames/fragments) will be removed.
-// Parameters:
-// mux - (in/out) object in which the image is to be set
-// bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image
-// WebP file (non-animated and non-fragmented)
-// copy_data - (in) value 1 indicates given data WILL be copied to the mux
-// object and value 0 indicates data will NOT be copied.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL.
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxSetImage(
- WebPMux* mux, const WebPData* bitstream, int copy_data);
-
-// Adds a frame at the end of the mux object.
-// Notes: (1) frame.id should be one of WEBP_CHUNK_ANMF or WEBP_CHUNK_FRGM
-// (2) For setting a non-animated non-fragmented image, use
-// WebPMuxSetImage() instead.
-// (3) Type of frame being pushed must be same as the frames in mux.
-// (4) As WebP only supports even offsets, any odd offset will be snapped
-// to an even location using: offset &= ~1
-// Parameters:
-// mux - (in/out) object to which the frame is to be added
-// frame - (in) frame data.
-// copy_data - (in) value 1 indicates given data WILL be copied to the mux
-// object and value 0 indicates data will NOT be copied.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL
-// or if content of 'frame' is invalid.
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame(
- WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data);
-
-// Gets the nth frame from the mux object.
-// The content of 'frame->bitstream' is allocated using malloc(), and NOT
-// owned by the 'mux' object. It MUST be deallocated by the caller by calling
-// WebPDataClear().
-// nth=0 has a special meaning - last position.
-// Parameters:
-// mux - (in) object from which the info is to be fetched
-// nth - (in) index of the frame in the mux object
-// frame - (out) data of the returned frame
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL.
-// WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object.
-// WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid.
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame(
- const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame);
-
-// Deletes a frame from the mux object.
-// nth=0 has a special meaning - last position.
-// Parameters:
-// mux - (in/out) object from which a frame is to be deleted
-// nth - (in) The position from which the frame is to be deleted
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL.
-// WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object
-// before deletion.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth);
-
-//------------------------------------------------------------------------------
-// Animation.
-
-// Animation parameters.
-struct WebPMuxAnimParams {
- uint32_t bgcolor; // Background color of the canvas stored (in MSB order) as:
- // Bits 00 to 07: Alpha.
- // Bits 08 to 15: Red.
- // Bits 16 to 23: Green.
- // Bits 24 to 31: Blue.
- int loop_count; // Number of times to repeat the animation [0 = infinite].
-};
-
-// Sets the animation parameters in the mux object. Any existing ANIM chunks
-// will be removed.
-// Parameters:
-// mux - (in/out) object in which ANIM chunk is to be set/added
-// params - (in) animation parameters.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL.
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxSetAnimationParams(
- WebPMux* mux, const WebPMuxAnimParams* params);
-
-// Gets the animation parameters from the mux object.
-// Parameters:
-// mux - (in) object from which the animation parameters to be fetched
-// params - (out) animation parameters extracted from the ANIM chunk
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL.
-// WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams(
- const WebPMux* mux, WebPMuxAnimParams* params);
-
-//------------------------------------------------------------------------------
-// Misc Utilities.
-
-// Sets the canvas size for the mux object. The width and height can be
-// specified explicitly or left as zero (0, 0).
-// * When width and height are specified explicitly, then this frame bound is
-// enforced during subsequent calls to WebPMuxAssemble() and an error is
-// reported if any animated frame does not completely fit within the canvas.
-// * When unspecified (0, 0), the constructed canvas will get the frame bounds
-// from the bounding-box over all frames after calling WebPMuxAssemble().
-// Parameters:
-// mux - (in) object to which the canvas size is to be set
-// width - (in) canvas width
-// height - (in) canvas height
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or
-// width or height are invalid or out of bounds
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxSetCanvasSize(WebPMux* mux,
- int width, int height);
-
-// Gets the canvas size from the mux object.
-// Note: This method assumes that the VP8X chunk, if present, is up-to-date.
-// That is, the mux object hasn't been modified since the last call to
-// WebPMuxAssemble() or WebPMuxCreate().
-// Parameters:
-// mux - (in) object from which the canvas size is to be fetched
-// width - (out) canvas width
-// height - (out) canvas height
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL.
-// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetCanvasSize(const WebPMux* mux,
- int* width, int* height);
-
-// Gets the feature flags from the mux object.
-// Note: This method assumes that the VP8X chunk, if present, is up-to-date.
-// That is, the mux object hasn't been modified since the last call to
-// WebPMuxAssemble() or WebPMuxCreate().
-// Parameters:
-// mux - (in) object from which the features are to be fetched
-// flags - (out) the flags specifying which features are present in the
-// mux object. This will be an OR of various flag values.
-// Enum 'WebPFeatureFlags' can be used to test individual flag values.
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL.
-// WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* mux,
- uint32_t* flags);
-
-// Gets number of chunks with the given 'id' in the mux object.
-// Parameters:
-// mux - (in) object from which the info is to be fetched
-// id - (in) chunk id specifying the type of chunk
-// num_elements - (out) number of chunks with the given chunk id
-// Returns:
-// WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux,
- WebPChunkId id, int* num_elements);
-
-// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'.
-// This function also validates the mux object.
-// Note: The content of 'assembled_data' will be ignored and overwritten.
-// Also, the content of 'assembled_data' is allocated using malloc(), and NOT
-// owned by the 'mux' object. It MUST be deallocated by the caller by calling
-// WebPDataClear(). It's always safe to call WebPDataClear() upon return,
-// even in case of error.
-// Parameters:
-// mux - (in/out) object whose chunks are to be assembled
-// assembled_data - (out) assembled WebP data
-// Returns:
-// WEBP_MUX_BAD_DATA - if mux object is invalid.
-// WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL.
-// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
-// WEBP_MUX_OK - on success.
-WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux,
- WebPData* assembled_data);
-
-//------------------------------------------------------------------------------
-// WebPAnimEncoder API
-//
-// This API allows encoding (possibly) animated WebP images.
-//
-// Code Example:
-/*
- WebPAnimEncoderOptions enc_options;
- WebPAnimEncoderOptionsInit(&enc_options);
- // Tune 'enc_options' as needed.
- WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options);
- while(<there are more frames>) {
- WebPConfig config;
- WebPConfigInit(&config);
- // Tune 'config' as needed.
- WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config);
- }
- WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL);
- WebPAnimEncoderAssemble(enc, webp_data);
- WebPAnimEncoderDelete(enc);
- // Write the 'webp_data' to a file, or re-mux it further.
-*/
-
-typedef struct WebPAnimEncoder WebPAnimEncoder; // Main opaque object.
-
-// Forward declarations. Defined in encode.h.
-struct WebPPicture;
-struct WebPConfig;
-
-// Global options.
-struct WebPAnimEncoderOptions {
- WebPMuxAnimParams anim_params; // Animation parameters.
- int minimize_size; // If true, minimize the output size (slow). Implicitly
- // disables key-frame insertion.
- int kmin;
- int kmax; // Minimum and maximum distance between consecutive key
- // frames in the output. The library may insert some key
- // frames as needed to satisfy this criteria.
- // Note that these conditions should hold: kmax > kmin
- // and kmin >= kmax / 2 + 1. Also, if kmin == 0, then
- // key-frame insertion is disabled; and if kmax == 0,
- // then all frames will be key-frames.
- int allow_mixed; // If true, use mixed compression mode; may choose
- // either lossy and lossless for each frame.
- int verbose; // If true, print info and warning messages to stderr.
-
- uint32_t padding[4]; // Padding for later use.
-};
-
-// Internal, version-checked, entry point.
-WEBP_EXTERN(int) WebPAnimEncoderOptionsInitInternal(
- WebPAnimEncoderOptions*, int);
-
-// Should always be called, to initialize a fresh WebPAnimEncoderOptions
-// structure before modification. Returns false in case of version mismatch.
-// WebPAnimEncoderOptionsInit() must have succeeded before using the
-// 'enc_options' object.
-static WEBP_INLINE int WebPAnimEncoderOptionsInit(
- WebPAnimEncoderOptions* enc_options) {
- return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION);
-}
-
-// Internal, version-checked, entry point.
-WEBP_EXTERN(WebPAnimEncoder*) WebPAnimEncoderNewInternal(
- int, int, const WebPAnimEncoderOptions*, int);
-
-// Creates and initializes a WebPAnimEncoder object.
-// Parameters:
-// width/height - (in) canvas width and height of the animation.
-// enc_options - (in) encoding options; can be passed NULL to pick
-// reasonable defaults.
-// Returns:
-// A pointer to the newly created WebPAnimEncoder object.
-// Or NULL in case of memory error.
-static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew(
- int width, int height, const WebPAnimEncoderOptions* enc_options) {
- return WebPAnimEncoderNewInternal(width, height, enc_options,
- WEBP_MUX_ABI_VERSION);
-}
-
-// Optimize the given frame for WebP, encode it and add it to the
-// WebPAnimEncoder object.
-// The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which
-// indicates that no more frames are to be added. This call is also used to
-// determine the duration of the last frame.
-// Parameters:
-// enc - (in/out) object to which the frame is to be added.
-// frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A)
-// format, it will be converted to ARGB, which incurs a small loss.
-// timestamp_ms - (in) timestamp of this frame in milliseconds.
-// Duration of a frame would be calculated as
-// "timestamp of next frame - timestamp of this frame".
-// Hence, timestamps should be in non-decreasing order.
-// config - (in) encoding options; can be passed NULL to pick
-// reasonable defaults.
-// Returns:
-// On error, returns false and frame->error_code is set appropriately.
-// Otherwise, returns true.
-WEBP_EXTERN(int) WebPAnimEncoderAdd(
- WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms,
- const struct WebPConfig* config);
-
-// Assemble all frames added so far into a WebP bitstream.
-// This call should be preceded by a call to 'WebPAnimEncoderAdd' with
-// frame = NULL; if not, the duration of the last frame will be internally
-// estimated.
-// Parameters:
-// enc - (in/out) object from which the frames are to be assembled.
-// webp_data - (out) generated WebP bitstream.
-// Returns:
-// True on success.
-WEBP_EXTERN(int) WebPAnimEncoderAssemble(WebPAnimEncoder* enc,
- WebPData* webp_data);
-
-// Get error string corresponding to the most recent call using 'enc'. The
-// returned string is owned by 'enc' and is valid only until the next call to
-// WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete().
-// Parameters:
-// enc - (in/out) object from which the error string is to be fetched.
-// Returns:
-// NULL if 'enc' is NULL. Otherwise, returns the error string if the last call
-// to 'enc' had an error, or an empty string if the last call was a success.
-WEBP_EXTERN(const char*) WebPAnimEncoderGetError(WebPAnimEncoder* enc);
-
-// Deletes the WebPAnimEncoder object.
-// Parameters:
-// enc - (in/out) object to be deleted
-WEBP_EXTERN(void) WebPAnimEncoderDelete(WebPAnimEncoder* enc);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_WEBP_MUX_H_ */
diff --git a/drivers/webp/mux/anim_encode.c b/drivers/webp/mux/anim_encode.c
deleted file mode 100644
index 2226febf13..0000000000
--- a/drivers/webp/mux/anim_encode.c
+++ /dev/null
@@ -1,1534 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// AnimEncoder implementation.
-//
-
-#include <assert.h>
-#include <limits.h>
-#include <math.h> // for pow()
-#include <stdio.h>
-#include <stdlib.h> // for abs()
-
-#include "../utils/utils.h"
-#include "webp/decode.h"
-#include "webp/encode.h"
-#include "webp/format_constants.h"
-#include "webp/mux.h"
-
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define snprintf _snprintf
-#endif
-
-#define ERROR_STR_MAX_LENGTH 100
-
-//------------------------------------------------------------------------------
-// Internal structs.
-
-// Stores frame rectangle dimensions.
-typedef struct {
- int x_offset_, y_offset_, width_, height_;
-} FrameRect;
-
-// Used to store two candidates of encoded data for an animation frame. One of
-// the two will be chosen later.
-typedef struct {
- WebPMuxFrameInfo sub_frame_; // Encoded frame rectangle.
- WebPMuxFrameInfo key_frame_; // Encoded frame if it is a key-frame.
- int is_key_frame_; // True if 'key_frame' has been chosen.
-} EncodedFrame;
-
-struct WebPAnimEncoder {
- const int canvas_width_; // Canvas width.
- const int canvas_height_; // Canvas height.
- const WebPAnimEncoderOptions options_; // Global encoding options.
-
- FrameRect prev_rect_; // Previous WebP frame rectangle.
- WebPConfig last_config_; // Cached in case a re-encode is needed.
- WebPConfig last_config_reversed_; // If 'last_config_' uses lossless, then
- // this config uses lossy and vice versa;
- // only valid if 'options_.allow_mixed'
- // is true.
-
- WebPPicture* curr_canvas_; // Only pointer; we don't own memory.
-
- // Canvas buffers.
- WebPPicture curr_canvas_copy_; // Possibly modified current canvas.
- int curr_canvas_copy_modified_; // True if pixels in 'curr_canvas_copy_'
- // differ from those in 'curr_canvas_'.
-
- WebPPicture prev_canvas_; // Previous canvas.
- WebPPicture prev_canvas_disposed_; // Previous canvas disposed to background.
-
- // Encoded data.
- EncodedFrame* encoded_frames_; // Array of encoded frames.
- size_t size_; // Number of allocated frames.
- size_t start_; // Frame start index.
- size_t count_; // Number of valid frames.
- size_t flush_count_; // If >0, 'flush_count' frames starting from
- // 'start' are ready to be added to mux.
-
- // key-frame related.
- int64_t best_delta_; // min(canvas size - frame size) over the frames.
- // Can be negative in certain cases due to
- // transparent pixels in a frame.
- int keyframe_; // Index of selected key-frame relative to 'start_'.
- int count_since_key_frame_; // Frames seen since the last key-frame.
-
- int first_timestamp_; // Timestamp of the first frame.
- int prev_timestamp_; // Timestamp of the last added frame.
- int prev_candidate_undecided_; // True if it's not yet decided if previous
- // frame would be a sub-frame or a key-frame.
-
- // Misc.
- int is_first_frame_; // True if first frame is yet to be added/being added.
- int got_null_frame_; // True if WebPAnimEncoderAdd() has already been called
- // with a NULL frame.
-
- size_t in_frame_count_; // Number of input frames processed so far.
- size_t out_frame_count_; // Number of frames added to mux so far. This may be
- // different from 'in_frame_count_' due to merging.
-
- WebPMux* mux_; // Muxer to assemble the WebP bitstream.
- char error_str_[ERROR_STR_MAX_LENGTH]; // Error string. Empty if no error.
-};
-
-// -----------------------------------------------------------------------------
-// Life of WebPAnimEncoder object.
-
-#define DELTA_INFINITY (1ULL << 32)
-#define KEYFRAME_NONE (-1)
-
-// Reset the counters in the WebPAnimEncoder.
-static void ResetCounters(WebPAnimEncoder* const enc) {
- enc->start_ = 0;
- enc->count_ = 0;
- enc->flush_count_ = 0;
- enc->best_delta_ = DELTA_INFINITY;
- enc->keyframe_ = KEYFRAME_NONE;
-}
-
-static void DisableKeyframes(WebPAnimEncoderOptions* const enc_options) {
- enc_options->kmax = INT_MAX;
- enc_options->kmin = enc_options->kmax - 1;
-}
-
-#define MAX_CACHED_FRAMES 30
-
-static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) {
- int print_warning = enc_options->verbose;
-
- if (enc_options->minimize_size) {
- DisableKeyframes(enc_options);
- }
-
- if (enc_options->kmin <= 0) {
- DisableKeyframes(enc_options);
- print_warning = 0;
- }
- if (enc_options->kmax <= 0) { // All frames will be key-frames.
- enc_options->kmin = 0;
- enc_options->kmax = 0;
- return;
- }
-
- if (enc_options->kmin >= enc_options->kmax) {
- enc_options->kmin = enc_options->kmax - 1;
- if (print_warning) {
- fprintf(stderr, "WARNING: Setting kmin = %d, so that kmin < kmax.\n",
- enc_options->kmin);
- }
- } else {
- const int kmin_limit = enc_options->kmax / 2 + 1;
- if (enc_options->kmin < kmin_limit && kmin_limit < enc_options->kmax) {
- // This ensures that enc.keyframe + kmin >= kmax is always true. So, we
- // can flush all the frames in the 'count_since_key_frame == kmax' case.
- enc_options->kmin = kmin_limit;
- if (print_warning) {
- fprintf(stderr,
- "WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n",
- enc_options->kmin);
- }
- }
- }
- // Limit the max number of frames that are allocated.
- if (enc_options->kmax - enc_options->kmin > MAX_CACHED_FRAMES) {
- enc_options->kmin = enc_options->kmax - MAX_CACHED_FRAMES;
- if (print_warning) {
- fprintf(stderr,
- "WARNING: Setting kmin = %d, so that kmax - kmin <= %d.\n",
- enc_options->kmin, MAX_CACHED_FRAMES);
- }
- }
- assert(enc_options->kmin < enc_options->kmax);
-}
-
-#undef MAX_CACHED_FRAMES
-
-static void DefaultEncoderOptions(WebPAnimEncoderOptions* const enc_options) {
- enc_options->anim_params.loop_count = 0;
- enc_options->anim_params.bgcolor = 0xffffffff; // White.
- enc_options->minimize_size = 0;
- DisableKeyframes(enc_options);
- enc_options->allow_mixed = 0;
- enc_options->verbose = 0;
-}
-
-int WebPAnimEncoderOptionsInitInternal(WebPAnimEncoderOptions* enc_options,
- int abi_version) {
- if (enc_options == NULL ||
- WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) {
- return 0;
- }
- DefaultEncoderOptions(enc_options);
- return 1;
-}
-
-// This starting value is more fit to WebPCleanupTransparentAreaLossless().
-#define TRANSPARENT_COLOR 0x00000000
-
-static void ClearRectangle(WebPPicture* const picture,
- int left, int top, int width, int height) {
- int j;
- for (j = top; j < top + height; ++j) {
- uint32_t* const dst = picture->argb + j * picture->argb_stride;
- int i;
- for (i = left; i < left + width; ++i) {
- dst[i] = TRANSPARENT_COLOR;
- }
- }
-}
-
-static void WebPUtilClearPic(WebPPicture* const picture,
- const FrameRect* const rect) {
- if (rect != NULL) {
- ClearRectangle(picture, rect->x_offset_, rect->y_offset_,
- rect->width_, rect->height_);
- } else {
- ClearRectangle(picture, 0, 0, picture->width, picture->height);
- }
-}
-
-static void MarkNoError(WebPAnimEncoder* const enc) {
- enc->error_str_[0] = '\0'; // Empty string.
-}
-
-static void MarkError(WebPAnimEncoder* const enc, const char* str) {
- if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s.", str) < 0) {
- assert(0); // FIX ME!
- }
-}
-
-static void MarkError2(WebPAnimEncoder* const enc,
- const char* str, int error_code) {
- if (snprintf(enc->error_str_, ERROR_STR_MAX_LENGTH, "%s: %d.", str,
- error_code) < 0) {
- assert(0); // FIX ME!
- }
-}
-
-WebPAnimEncoder* WebPAnimEncoderNewInternal(
- int width, int height, const WebPAnimEncoderOptions* enc_options,
- int abi_version) {
- WebPAnimEncoder* enc;
-
- if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) {
- return NULL;
- }
- if (width <= 0 || height <= 0 ||
- (width * (uint64_t)height) >= MAX_IMAGE_AREA) {
- return NULL;
- }
-
- enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc));
- if (enc == NULL) return NULL;
- // sanity inits, so we can call WebPAnimEncoderDelete():
- enc->encoded_frames_ = NULL;
- enc->mux_ = NULL;
- MarkNoError(enc);
-
- // Dimensions and options.
- *(int*)&enc->canvas_width_ = width;
- *(int*)&enc->canvas_height_ = height;
- if (enc_options != NULL) {
- *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options;
- SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_);
- } else {
- DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_);
- }
-
- // Canvas buffers.
- if (!WebPPictureInit(&enc->curr_canvas_copy_) ||
- !WebPPictureInit(&enc->prev_canvas_) ||
- !WebPPictureInit(&enc->prev_canvas_disposed_)) {
- goto Err;
- }
- enc->curr_canvas_copy_.width = width;
- enc->curr_canvas_copy_.height = height;
- enc->curr_canvas_copy_.use_argb = 1;
- if (!WebPPictureAlloc(&enc->curr_canvas_copy_) ||
- !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) ||
- !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) {
- goto Err;
- }
- WebPUtilClearPic(&enc->prev_canvas_, NULL);
- enc->curr_canvas_copy_modified_ = 1;
-
- // Encoded frames.
- ResetCounters(enc);
- // Note: one extra storage is for the previous frame.
- enc->size_ = enc->options_.kmax - enc->options_.kmin + 1;
- // We need space for at least 2 frames. But when kmin, kmax are both zero,
- // enc->size_ will be 1. So we handle that special case below.
- if (enc->size_ < 2) enc->size_ = 2;
- enc->encoded_frames_ =
- (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_));
- if (enc->encoded_frames_ == NULL) goto Err;
-
- enc->mux_ = WebPMuxNew();
- if (enc->mux_ == NULL) goto Err;
-
- enc->count_since_key_frame_ = 0;
- enc->first_timestamp_ = 0;
- enc->prev_timestamp_ = 0;
- enc->prev_candidate_undecided_ = 0;
- enc->is_first_frame_ = 1;
- enc->got_null_frame_ = 0;
-
- return enc; // All OK.
-
- Err:
- WebPAnimEncoderDelete(enc);
- return NULL;
-}
-
-// Release the data contained by 'encoded_frame'.
-static void FrameRelease(EncodedFrame* const encoded_frame) {
- if (encoded_frame != NULL) {
- WebPDataClear(&encoded_frame->sub_frame_.bitstream);
- WebPDataClear(&encoded_frame->key_frame_.bitstream);
- memset(encoded_frame, 0, sizeof(*encoded_frame));
- }
-}
-
-void WebPAnimEncoderDelete(WebPAnimEncoder* enc) {
- if (enc != NULL) {
- WebPPictureFree(&enc->curr_canvas_copy_);
- WebPPictureFree(&enc->prev_canvas_);
- WebPPictureFree(&enc->prev_canvas_disposed_);
- if (enc->encoded_frames_ != NULL) {
- size_t i;
- for (i = 0; i < enc->size_; ++i) {
- FrameRelease(&enc->encoded_frames_[i]);
- }
- WebPSafeFree(enc->encoded_frames_);
- }
- WebPMuxDelete(enc->mux_);
- WebPSafeFree(enc);
- }
-}
-
-// -----------------------------------------------------------------------------
-// Frame addition.
-
-// Returns cached frame at the given 'position'.
-static EncodedFrame* GetFrame(const WebPAnimEncoder* const enc,
- size_t position) {
- assert(enc->start_ + position < enc->size_);
- return &enc->encoded_frames_[enc->start_ + position];
-}
-
-typedef int (*ComparePixelsFunc)(const uint32_t*, int, const uint32_t*, int,
- int, int);
-
-// Returns true if 'length' number of pixels in 'src' and 'dst' are equal,
-// assuming the given step sizes between pixels.
-// 'max_allowed_diff' is unused and only there to allow function pointer use.
-static WEBP_INLINE int ComparePixelsLossless(const uint32_t* src, int src_step,
- const uint32_t* dst, int dst_step,
- int length, int max_allowed_diff) {
- (void)max_allowed_diff;
- assert(length > 0);
- while (length-- > 0) {
- if (*src != *dst) {
- return 0;
- }
- src += src_step;
- dst += dst_step;
- }
- return 1;
-}
-
-// Helper to check if each channel in 'src' and 'dst' is at most off by
-// 'max_allowed_diff'.
-static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst,
- int max_allowed_diff) {
- const int src_a = (src >> 24) & 0xff;
- const int src_r = (src >> 16) & 0xff;
- const int src_g = (src >> 8) & 0xff;
- const int src_b = (src >> 0) & 0xff;
- const int dst_a = (dst >> 24) & 0xff;
- const int dst_r = (dst >> 16) & 0xff;
- const int dst_g = (dst >> 8) & 0xff;
- const int dst_b = (dst >> 0) & 0xff;
-
- return (abs(src_r * src_a - dst_r * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_g * src_a - dst_g * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_b * src_a - dst_b * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_a - dst_a) <= max_allowed_diff);
-}
-
-// Returns true if 'length' number of pixels in 'src' and 'dst' are within an
-// error bound, assuming the given step sizes between pixels.
-static WEBP_INLINE int ComparePixelsLossy(const uint32_t* src, int src_step,
- const uint32_t* dst, int dst_step,
- int length, int max_allowed_diff) {
- assert(length > 0);
- while (length-- > 0) {
- if (!PixelsAreSimilar(*src, *dst, max_allowed_diff)) {
- return 0;
- }
- src += src_step;
- dst += dst_step;
- }
- return 1;
-}
-
-static int IsEmptyRect(const FrameRect* const rect) {
- return (rect->width_ == 0) || (rect->height_ == 0);
-}
-
-static int QualityToMaxDiff(float quality) {
- const double val = pow(quality / 100., 0.5);
- const double max_diff = 31 * (1 - val) + 1 * val;
- return (int)(max_diff + 0.5);
-}
-
-// Assumes that an initial valid guess of change rectangle 'rect' is passed.
-static void MinimizeChangeRectangle(const WebPPicture* const src,
- const WebPPicture* const dst,
- FrameRect* const rect,
- int is_lossless, float quality) {
- int i, j;
- const ComparePixelsFunc compare_pixels =
- is_lossless ? ComparePixelsLossless : ComparePixelsLossy;
- const int max_allowed_diff_lossy = QualityToMaxDiff(quality);
- const int max_allowed_diff = is_lossless ? 0 : max_allowed_diff_lossy;
-
- // Sanity checks.
- assert(src->width == dst->width && src->height == dst->height);
- assert(rect->x_offset_ + rect->width_ <= dst->width);
- assert(rect->y_offset_ + rect->height_ <= dst->height);
-
- // Left boundary.
- for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
- const uint32_t* const src_argb =
- &src->argb[rect->y_offset_ * src->argb_stride + i];
- const uint32_t* const dst_argb =
- &dst->argb[rect->y_offset_ * dst->argb_stride + i];
- if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride,
- rect->height_, max_allowed_diff)) {
- --rect->width_; // Redundant column.
- ++rect->x_offset_;
- } else {
- break;
- }
- }
- if (rect->width_ == 0) goto NoChange;
-
- // Right boundary.
- for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) {
- const uint32_t* const src_argb =
- &src->argb[rect->y_offset_ * src->argb_stride + i];
- const uint32_t* const dst_argb =
- &dst->argb[rect->y_offset_ * dst->argb_stride + i];
- if (compare_pixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride,
- rect->height_, max_allowed_diff)) {
- --rect->width_; // Redundant column.
- } else {
- break;
- }
- }
- if (rect->width_ == 0) goto NoChange;
-
- // Top boundary.
- for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
- const uint32_t* const src_argb =
- &src->argb[j * src->argb_stride + rect->x_offset_];
- const uint32_t* const dst_argb =
- &dst->argb[j * dst->argb_stride + rect->x_offset_];
- if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_,
- max_allowed_diff)) {
- --rect->height_; // Redundant row.
- ++rect->y_offset_;
- } else {
- break;
- }
- }
- if (rect->height_ == 0) goto NoChange;
-
- // Bottom boundary.
- for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) {
- const uint32_t* const src_argb =
- &src->argb[j * src->argb_stride + rect->x_offset_];
- const uint32_t* const dst_argb =
- &dst->argb[j * dst->argb_stride + rect->x_offset_];
- if (compare_pixels(src_argb, 1, dst_argb, 1, rect->width_,
- max_allowed_diff)) {
- --rect->height_; // Redundant row.
- } else {
- break;
- }
- }
- if (rect->height_ == 0) goto NoChange;
-
- if (IsEmptyRect(rect)) {
- NoChange:
- rect->x_offset_ = 0;
- rect->y_offset_ = 0;
- rect->width_ = 0;
- rect->height_ = 0;
- }
-}
-
-// Snap rectangle to even offsets (and adjust dimensions if needed).
-static WEBP_INLINE void SnapToEvenOffsets(FrameRect* const rect) {
- rect->width_ += (rect->x_offset_ & 1);
- rect->height_ += (rect->y_offset_ & 1);
- rect->x_offset_ &= ~1;
- rect->y_offset_ &= ~1;
-}
-
-typedef struct {
- int should_try_; // Should try this set of parameters.
- int empty_rect_allowed_; // Frame with empty rectangle can be skipped.
- FrameRect rect_ll_; // Frame rectangle for lossless compression.
- WebPPicture sub_frame_ll_; // Sub-frame pic for lossless compression.
- FrameRect rect_lossy_; // Frame rectangle for lossy compression.
- // Could be smaller than rect_ll_ as pixels
- // with small diffs can be ignored.
- WebPPicture sub_frame_lossy_; // Sub-frame pic for lossless compression.
-} SubFrameParams;
-
-static int SubFrameParamsInit(SubFrameParams* const params,
- int should_try, int empty_rect_allowed) {
- params->should_try_ = should_try;
- params->empty_rect_allowed_ = empty_rect_allowed;
- if (!WebPPictureInit(&params->sub_frame_ll_) ||
- !WebPPictureInit(&params->sub_frame_lossy_)) {
- return 0;
- }
- return 1;
-}
-
-static void SubFrameParamsFree(SubFrameParams* const params) {
- WebPPictureFree(&params->sub_frame_ll_);
- WebPPictureFree(&params->sub_frame_lossy_);
-}
-
-// Given previous and current canvas, picks the optimal rectangle for the
-// current frame based on 'is_lossless' and other parameters. Assumes that the
-// initial guess 'rect' is valid.
-static int GetSubRect(const WebPPicture* const prev_canvas,
- const WebPPicture* const curr_canvas, int is_key_frame,
- int is_first_frame, int empty_rect_allowed,
- int is_lossless, float quality, FrameRect* const rect,
- WebPPicture* const sub_frame) {
- if (!is_key_frame || is_first_frame) { // Optimize frame rectangle.
- // Note: This behaves as expected for first frame, as 'prev_canvas' is
- // initialized to a fully transparent canvas in the beginning.
- MinimizeChangeRectangle(prev_canvas, curr_canvas, rect,
- is_lossless, quality);
- }
-
- if (IsEmptyRect(rect)) {
- if (empty_rect_allowed) { // No need to get 'sub_frame'.
- return 1;
- } else { // Force a 1x1 rectangle.
- rect->width_ = 1;
- rect->height_ = 1;
- assert(rect->x_offset_ == 0);
- assert(rect->y_offset_ == 0);
- }
- }
-
- SnapToEvenOffsets(rect);
- return WebPPictureView(curr_canvas, rect->x_offset_, rect->y_offset_,
- rect->width_, rect->height_, sub_frame);
-}
-
-// Picks optimal frame rectangle for both lossless and lossy compression. The
-// initial guess for frame rectangles will be the full canvas.
-static int GetSubRects(const WebPPicture* const prev_canvas,
- const WebPPicture* const curr_canvas, int is_key_frame,
- int is_first_frame, float quality,
- SubFrameParams* const params) {
- // Lossless frame rectangle.
- params->rect_ll_.x_offset_ = 0;
- params->rect_ll_.y_offset_ = 0;
- params->rect_ll_.width_ = curr_canvas->width;
- params->rect_ll_.height_ = curr_canvas->height;
- if (!GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame,
- params->empty_rect_allowed_, 1, quality,
- &params->rect_ll_, &params->sub_frame_ll_)) {
- return 0;
- }
- // Lossy frame rectangle.
- params->rect_lossy_ = params->rect_ll_; // seed with lossless rect.
- return GetSubRect(prev_canvas, curr_canvas, is_key_frame, is_first_frame,
- params->empty_rect_allowed_, 0, quality,
- &params->rect_lossy_, &params->sub_frame_lossy_);
-}
-
-static void DisposeFrameRectangle(int dispose_method,
- const FrameRect* const rect,
- WebPPicture* const curr_canvas) {
- assert(rect != NULL);
- if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
- WebPUtilClearPic(curr_canvas, rect);
- }
-}
-
-static uint32_t RectArea(const FrameRect* const rect) {
- return (uint32_t)rect->width_ * rect->height_;
-}
-
-static int IsLosslessBlendingPossible(const WebPPicture* const src,
- const WebPPicture* const dst,
- const FrameRect* const rect) {
- int i, j;
- assert(src->width == dst->width && src->height == dst->height);
- assert(rect->x_offset_ + rect->width_ <= dst->width);
- assert(rect->y_offset_ + rect->height_ <= dst->height);
- for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
- for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
- const uint32_t src_pixel = src->argb[j * src->argb_stride + i];
- const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i];
- const uint32_t dst_alpha = dst_pixel >> 24;
- if (dst_alpha != 0xff && src_pixel != dst_pixel) {
- // In this case, if we use blending, we can't attain the desired
- // 'dst_pixel' value for this pixel. So, blending is not possible.
- return 0;
- }
- }
- }
- return 1;
-}
-
-static int IsLossyBlendingPossible(const WebPPicture* const src,
- const WebPPicture* const dst,
- const FrameRect* const rect,
- float quality) {
- const int max_allowed_diff_lossy = QualityToMaxDiff(quality);
- int i, j;
- assert(src->width == dst->width && src->height == dst->height);
- assert(rect->x_offset_ + rect->width_ <= dst->width);
- assert(rect->y_offset_ + rect->height_ <= dst->height);
- for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
- for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
- const uint32_t src_pixel = src->argb[j * src->argb_stride + i];
- const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i];
- const uint32_t dst_alpha = dst_pixel >> 24;
- if (dst_alpha != 0xff &&
- !PixelsAreSimilar(src_pixel, dst_pixel, max_allowed_diff_lossy)) {
- // In this case, if we use blending, we can't attain the desired
- // 'dst_pixel' value for this pixel. So, blending is not possible.
- return 0;
- }
- }
- }
- return 1;
-}
-
-// For pixels in 'rect', replace those pixels in 'dst' that are same as 'src' by
-// transparent pixels.
-// Returns true if at least one pixel gets modified.
-static int IncreaseTransparency(const WebPPicture* const src,
- const FrameRect* const rect,
- WebPPicture* const dst) {
- int i, j;
- int modified = 0;
- assert(src != NULL && dst != NULL && rect != NULL);
- assert(src->width == dst->width && src->height == dst->height);
- for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
- const uint32_t* const psrc = src->argb + j * src->argb_stride;
- uint32_t* const pdst = dst->argb + j * dst->argb_stride;
- for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
- if (psrc[i] == pdst[i] && pdst[i] != TRANSPARENT_COLOR) {
- pdst[i] = TRANSPARENT_COLOR;
- modified = 1;
- }
- }
- }
- return modified;
-}
-
-#undef TRANSPARENT_COLOR
-
-// Replace similar blocks of pixels by a 'see-through' transparent block
-// with uniform average color.
-// Assumes lossy compression is being used.
-// Returns true if at least one pixel gets modified.
-static int FlattenSimilarBlocks(const WebPPicture* const src,
- const FrameRect* const rect,
- WebPPicture* const dst, float quality) {
- const int max_allowed_diff_lossy = QualityToMaxDiff(quality);
- int i, j;
- int modified = 0;
- const int block_size = 8;
- const int y_start = (rect->y_offset_ + block_size) & ~(block_size - 1);
- const int y_end = (rect->y_offset_ + rect->height_) & ~(block_size - 1);
- const int x_start = (rect->x_offset_ + block_size) & ~(block_size - 1);
- const int x_end = (rect->x_offset_ + rect->width_) & ~(block_size - 1);
- assert(src != NULL && dst != NULL && rect != NULL);
- assert(src->width == dst->width && src->height == dst->height);
- assert((block_size & (block_size - 1)) == 0); // must be a power of 2
- // Iterate over each block and count similar pixels.
- for (j = y_start; j < y_end; j += block_size) {
- for (i = x_start; i < x_end; i += block_size) {
- int cnt = 0;
- int avg_r = 0, avg_g = 0, avg_b = 0;
- int x, y;
- const uint32_t* const psrc = src->argb + j * src->argb_stride + i;
- uint32_t* const pdst = dst->argb + j * dst->argb_stride + i;
- for (y = 0; y < block_size; ++y) {
- for (x = 0; x < block_size; ++x) {
- const uint32_t src_pixel = psrc[x + y * src->argb_stride];
- const int alpha = src_pixel >> 24;
- if (alpha == 0xff &&
- PixelsAreSimilar(src_pixel, pdst[x + y * dst->argb_stride],
- max_allowed_diff_lossy)) {
- ++cnt;
- avg_r += (src_pixel >> 16) & 0xff;
- avg_g += (src_pixel >> 8) & 0xff;
- avg_b += (src_pixel >> 0) & 0xff;
- }
- }
- }
- // If we have a fully similar block, we replace it with an
- // average transparent block. This compresses better in lossy mode.
- if (cnt == block_size * block_size) {
- const uint32_t color = (0x00 << 24) |
- ((avg_r / cnt) << 16) |
- ((avg_g / cnt) << 8) |
- ((avg_b / cnt) << 0);
- for (y = 0; y < block_size; ++y) {
- for (x = 0; x < block_size; ++x) {
- pdst[x + y * dst->argb_stride] = color;
- }
- }
- modified = 1;
- }
- }
- }
- return modified;
-}
-
-static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic,
- WebPMemoryWriter* const memory) {
- pic->use_argb = 1;
- pic->writer = WebPMemoryWrite;
- pic->custom_ptr = memory;
- if (!WebPEncode(config, pic)) {
- return 0;
- }
- return 1;
-}
-
-// Struct representing a candidate encoded frame including its metadata.
-typedef struct {
- WebPMemoryWriter mem_;
- WebPMuxFrameInfo info_;
- FrameRect rect_;
- int evaluate_; // True if this candidate should be evaluated.
-} Candidate;
-
-// Generates a candidate encoded frame given a picture and metadata.
-static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame,
- const FrameRect* const rect,
- const WebPConfig* const encoder_config,
- int use_blending,
- Candidate* const candidate) {
- WebPConfig config = *encoder_config;
- WebPEncodingError error_code = VP8_ENC_OK;
- assert(candidate != NULL);
- memset(candidate, 0, sizeof(*candidate));
-
- // Set frame rect and info.
- candidate->rect_ = *rect;
- candidate->info_.id = WEBP_CHUNK_ANMF;
- candidate->info_.x_offset = rect->x_offset_;
- candidate->info_.y_offset = rect->y_offset_;
- candidate->info_.dispose_method = WEBP_MUX_DISPOSE_NONE; // Set later.
- candidate->info_.blend_method =
- use_blending ? WEBP_MUX_BLEND : WEBP_MUX_NO_BLEND;
- candidate->info_.duration = 0; // Set in next call to WebPAnimEncoderAdd().
-
- // Encode picture.
- WebPMemoryWriterInit(&candidate->mem_);
-
- if (!config.lossless && use_blending) {
- // Disable filtering to avoid blockiness in reconstructed frames at the
- // time of decoding.
- config.autofilter = 0;
- config.filter_strength = 0;
- }
- if (!EncodeFrame(&config, sub_frame, &candidate->mem_)) {
- error_code = sub_frame->error_code;
- goto Err;
- }
-
- candidate->evaluate_ = 1;
- return error_code;
-
- Err:
- WebPMemoryWriterClear(&candidate->mem_);
- return error_code;
-}
-
-static void CopyCurrentCanvas(WebPAnimEncoder* const enc) {
- if (enc->curr_canvas_copy_modified_) {
- WebPCopyPixels(enc->curr_canvas_, &enc->curr_canvas_copy_);
- enc->curr_canvas_copy_.progress_hook = enc->curr_canvas_->progress_hook;
- enc->curr_canvas_copy_.user_data = enc->curr_canvas_->user_data;
- enc->curr_canvas_copy_modified_ = 0;
- }
-}
-
-enum {
- LL_DISP_NONE = 0,
- LL_DISP_BG,
- LOSSY_DISP_NONE,
- LOSSY_DISP_BG,
- CANDIDATE_COUNT
-};
-
-#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold.
-#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold.
-
-// Generates candidates for a given dispose method given pre-filled sub-frame
-// 'params'.
-static WebPEncodingError GenerateCandidates(
- WebPAnimEncoder* const enc, Candidate candidates[CANDIDATE_COUNT],
- WebPMuxAnimDispose dispose_method, int is_lossless, int is_key_frame,
- SubFrameParams* const params,
- const WebPConfig* const config_ll, const WebPConfig* const config_lossy) {
- WebPEncodingError error_code = VP8_ENC_OK;
- const int is_dispose_none = (dispose_method == WEBP_MUX_DISPOSE_NONE);
- Candidate* const candidate_ll =
- is_dispose_none ? &candidates[LL_DISP_NONE] : &candidates[LL_DISP_BG];
- Candidate* const candidate_lossy = is_dispose_none
- ? &candidates[LOSSY_DISP_NONE]
- : &candidates[LOSSY_DISP_BG];
- WebPPicture* const curr_canvas = &enc->curr_canvas_copy_;
- const WebPPicture* const prev_canvas =
- is_dispose_none ? &enc->prev_canvas_ : &enc->prev_canvas_disposed_;
- int use_blending_ll;
- int use_blending_lossy;
-
- CopyCurrentCanvas(enc);
- use_blending_ll =
- !is_key_frame &&
- IsLosslessBlendingPossible(prev_canvas, curr_canvas, &params->rect_ll_);
- use_blending_lossy =
- !is_key_frame &&
- IsLossyBlendingPossible(prev_canvas, curr_canvas, &params->rect_lossy_,
- config_lossy->quality);
-
- // Pick candidates to be tried.
- if (!enc->options_.allow_mixed) {
- candidate_ll->evaluate_ = is_lossless;
- candidate_lossy->evaluate_ = !is_lossless;
- } else { // Use a heuristic for trying lossless and/or lossy compression.
- const int num_colors = WebPGetColorPalette(&params->sub_frame_ll_, NULL);
- candidate_ll->evaluate_ = (num_colors < MAX_COLORS_LOSSLESS);
- candidate_lossy->evaluate_ = (num_colors >= MIN_COLORS_LOSSY);
- }
-
- // Generate candidates.
- if (candidate_ll->evaluate_) {
- CopyCurrentCanvas(enc);
- if (use_blending_ll) {
- enc->curr_canvas_copy_modified_ =
- IncreaseTransparency(prev_canvas, &params->rect_ll_, curr_canvas);
- }
- error_code = EncodeCandidate(&params->sub_frame_ll_, &params->rect_ll_,
- config_ll, use_blending_ll, candidate_ll);
- if (error_code != VP8_ENC_OK) return error_code;
- }
- if (candidate_lossy->evaluate_) {
- CopyCurrentCanvas(enc);
- if (use_blending_lossy) {
- enc->curr_canvas_copy_modified_ =
- FlattenSimilarBlocks(prev_canvas, &params->rect_lossy_, curr_canvas,
- config_lossy->quality);
- }
- error_code =
- EncodeCandidate(&params->sub_frame_lossy_, &params->rect_lossy_,
- config_lossy, use_blending_lossy, candidate_lossy);
- if (error_code != VP8_ENC_OK) return error_code;
- enc->curr_canvas_copy_modified_ = 1;
- }
- return error_code;
-}
-
-#undef MIN_COLORS_LOSSY
-#undef MAX_COLORS_LOSSLESS
-
-static void GetEncodedData(const WebPMemoryWriter* const memory,
- WebPData* const encoded_data) {
- encoded_data->bytes = memory->mem;
- encoded_data->size = memory->size;
-}
-
-// Sets dispose method of the previous frame to be 'dispose_method'.
-static void SetPreviousDisposeMethod(WebPAnimEncoder* const enc,
- WebPMuxAnimDispose dispose_method) {
- const size_t position = enc->count_ - 2;
- EncodedFrame* const prev_enc_frame = GetFrame(enc, position);
- assert(enc->count_ >= 2); // As current and previous frames are in enc.
-
- if (enc->prev_candidate_undecided_) {
- assert(dispose_method == WEBP_MUX_DISPOSE_NONE);
- prev_enc_frame->sub_frame_.dispose_method = dispose_method;
- prev_enc_frame->key_frame_.dispose_method = dispose_method;
- } else {
- WebPMuxFrameInfo* const prev_info = prev_enc_frame->is_key_frame_
- ? &prev_enc_frame->key_frame_
- : &prev_enc_frame->sub_frame_;
- prev_info->dispose_method = dispose_method;
- }
-}
-
-static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) {
- const size_t position = enc->count_ - 1;
- EncodedFrame* const prev_enc_frame = GetFrame(enc, position);
- int new_duration;
-
- assert(enc->count_ >= 1);
- assert(prev_enc_frame->sub_frame_.duration ==
- prev_enc_frame->key_frame_.duration);
- assert(prev_enc_frame->sub_frame_.duration ==
- (prev_enc_frame->sub_frame_.duration & (MAX_DURATION - 1)));
- assert(duration == (duration & (MAX_DURATION - 1)));
-
- new_duration = prev_enc_frame->sub_frame_.duration + duration;
- if (new_duration >= MAX_DURATION) { // Special case.
- // Separate out previous frame from earlier merged frames to avoid overflow.
- // We add a 1x1 transparent frame for the previous frame, with blending on.
- const FrameRect rect = { 0, 0, 1, 1 };
- const uint8_t lossless_1x1_bytes[] = {
- 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50,
- 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
- 0x10, 0x88, 0x88, 0x08
- };
- const WebPData lossless_1x1 = {
- lossless_1x1_bytes, sizeof(lossless_1x1_bytes)
- };
- const uint8_t lossy_1x1_bytes[] = {
- 0x52, 0x49, 0x46, 0x46, 0x40, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50,
- 0x56, 0x50, 0x38, 0x58, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x4c, 0x50, 0x48, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x56, 0x50, 0x38, 0x20, 0x18, 0x00, 0x00, 0x00,
- 0x30, 0x01, 0x00, 0x9d, 0x01, 0x2a, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00,
- 0x34, 0x25, 0xa4, 0x00, 0x03, 0x70, 0x00, 0xfe, 0xfb, 0xfd, 0x50, 0x00
- };
- const WebPData lossy_1x1 = { lossy_1x1_bytes, sizeof(lossy_1x1_bytes) };
- const int can_use_lossless =
- (enc->last_config_.lossless || enc->options_.allow_mixed);
- EncodedFrame* const curr_enc_frame = GetFrame(enc, enc->count_);
- curr_enc_frame->is_key_frame_ = 0;
- curr_enc_frame->sub_frame_.id = WEBP_CHUNK_ANMF;
- curr_enc_frame->sub_frame_.x_offset = 0;
- curr_enc_frame->sub_frame_.y_offset = 0;
- curr_enc_frame->sub_frame_.dispose_method = WEBP_MUX_DISPOSE_NONE;
- curr_enc_frame->sub_frame_.blend_method = WEBP_MUX_BLEND;
- curr_enc_frame->sub_frame_.duration = duration;
- if (!WebPDataCopy(can_use_lossless ? &lossless_1x1 : &lossy_1x1,
- &curr_enc_frame->sub_frame_.bitstream)) {
- return 0;
- }
- ++enc->count_;
- ++enc->count_since_key_frame_;
- enc->flush_count_ = enc->count_ - 1;
- enc->prev_candidate_undecided_ = 0;
- enc->prev_rect_ = rect;
- } else { // Regular case.
- // Increase duration of the previous frame by 'duration'.
- prev_enc_frame->sub_frame_.duration = new_duration;
- prev_enc_frame->key_frame_.duration = new_duration;
- }
- return 1;
-}
-
-// Pick the candidate encoded frame with smallest size and release other
-// candidates.
-// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should
-// also be a criteria, in addition to sizes.
-static void PickBestCandidate(WebPAnimEncoder* const enc,
- Candidate* const candidates, int is_key_frame,
- EncodedFrame* const encoded_frame) {
- int i;
- int best_idx = -1;
- size_t best_size = ~0;
- for (i = 0; i < CANDIDATE_COUNT; ++i) {
- if (candidates[i].evaluate_) {
- const size_t candidate_size = candidates[i].mem_.size;
- if (candidate_size < best_size) {
- best_idx = i;
- best_size = candidate_size;
- }
- }
- }
- assert(best_idx != -1);
- for (i = 0; i < CANDIDATE_COUNT; ++i) {
- if (candidates[i].evaluate_) {
- if (i == best_idx) {
- WebPMuxFrameInfo* const dst = is_key_frame
- ? &encoded_frame->key_frame_
- : &encoded_frame->sub_frame_;
- *dst = candidates[i].info_;
- GetEncodedData(&candidates[i].mem_, &dst->bitstream);
- if (!is_key_frame) {
- // Note: Previous dispose method only matters for non-keyframes.
- // Also, we don't want to modify previous dispose method that was
- // selected when a non key-frame was assumed.
- const WebPMuxAnimDispose prev_dispose_method =
- (best_idx == LL_DISP_NONE || best_idx == LOSSY_DISP_NONE)
- ? WEBP_MUX_DISPOSE_NONE
- : WEBP_MUX_DISPOSE_BACKGROUND;
- SetPreviousDisposeMethod(enc, prev_dispose_method);
- }
- enc->prev_rect_ = candidates[i].rect_; // save for next frame.
- } else {
- WebPMemoryWriterClear(&candidates[i].mem_);
- candidates[i].evaluate_ = 0;
- }
- }
- }
-}
-
-// Depending on the configuration, tries different compressions
-// (lossy/lossless), dispose methods, blending methods etc to encode the current
-// frame and outputs the best one in 'encoded_frame'.
-// 'frame_skipped' will be set to true if this frame should actually be skipped.
-static WebPEncodingError SetFrame(WebPAnimEncoder* const enc,
- const WebPConfig* const config,
- int is_key_frame,
- EncodedFrame* const encoded_frame,
- int* const frame_skipped) {
- int i;
- WebPEncodingError error_code = VP8_ENC_OK;
- const WebPPicture* const curr_canvas = &enc->curr_canvas_copy_;
- const WebPPicture* const prev_canvas = &enc->prev_canvas_;
- Candidate candidates[CANDIDATE_COUNT];
- const int is_lossless = config->lossless;
- const int is_first_frame = enc->is_first_frame_;
-
- // First frame cannot be skipped as there is no 'previous frame' to merge it
- // to. So, empty rectangle is not allowed for the first frame.
- const int empty_rect_allowed_none = !is_first_frame;
-
- // Even if there is exact pixel match between 'disposed previous canvas' and
- // 'current canvas', we can't skip current frame, as there may not be exact
- // pixel match between 'previous canvas' and 'current canvas'. So, we don't
- // allow empty rectangle in this case.
- const int empty_rect_allowed_bg = 0;
-
- // If current frame is a key-frame, dispose method of previous frame doesn't
- // matter, so we don't try dispose to background.
- // Also, if key-frame insertion is on, and previous frame could be picked as
- // either a sub-frame or a key-frame, then we can't be sure about what frame
- // rectangle would be disposed. In that case too, we don't try dispose to
- // background.
- const int dispose_bg_possible =
- !is_key_frame && !enc->prev_candidate_undecided_;
-
- SubFrameParams dispose_none_params;
- SubFrameParams dispose_bg_params;
-
- WebPConfig config_ll = *config;
- WebPConfig config_lossy = *config;
- config_ll.lossless = 1;
- config_lossy.lossless = 0;
- enc->last_config_ = *config;
- enc->last_config_reversed_ = config->lossless ? config_lossy : config_ll;
- *frame_skipped = 0;
-
- if (!SubFrameParamsInit(&dispose_none_params, 1, empty_rect_allowed_none) ||
- !SubFrameParamsInit(&dispose_bg_params, 0, empty_rect_allowed_bg)) {
- return VP8_ENC_ERROR_INVALID_CONFIGURATION;
- }
-
- for (i = 0; i < CANDIDATE_COUNT; ++i) {
- candidates[i].evaluate_ = 0;
- }
-
- // Change-rectangle assuming previous frame was DISPOSE_NONE.
- if (!GetSubRects(prev_canvas, curr_canvas, is_key_frame, is_first_frame,
- config_lossy.quality, &dispose_none_params)) {
- error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION;
- goto Err;
- }
-
- if ((is_lossless && IsEmptyRect(&dispose_none_params.rect_ll_)) ||
- (!is_lossless && IsEmptyRect(&dispose_none_params.rect_lossy_))) {
- // Don't encode the frame at all. Instead, the duration of the previous
- // frame will be increased later.
- assert(empty_rect_allowed_none);
- *frame_skipped = 1;
- goto End;
- }
-
- if (dispose_bg_possible) {
- // Change-rectangle assuming previous frame was DISPOSE_BACKGROUND.
- WebPPicture* const prev_canvas_disposed = &enc->prev_canvas_disposed_;
- WebPCopyPixels(prev_canvas, prev_canvas_disposed);
- DisposeFrameRectangle(WEBP_MUX_DISPOSE_BACKGROUND, &enc->prev_rect_,
- prev_canvas_disposed);
-
- if (!GetSubRects(prev_canvas_disposed, curr_canvas, is_key_frame,
- is_first_frame, config_lossy.quality,
- &dispose_bg_params)) {
- error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION;
- goto Err;
- }
- assert(!IsEmptyRect(&dispose_bg_params.rect_ll_));
- assert(!IsEmptyRect(&dispose_bg_params.rect_lossy_));
-
- if (enc->options_.minimize_size) { // Try both dispose methods.
- dispose_bg_params.should_try_ = 1;
- dispose_none_params.should_try_ = 1;
- } else if ((is_lossless &&
- RectArea(&dispose_bg_params.rect_ll_) <
- RectArea(&dispose_none_params.rect_ll_)) ||
- (!is_lossless &&
- RectArea(&dispose_bg_params.rect_lossy_) <
- RectArea(&dispose_none_params.rect_lossy_))) {
- dispose_bg_params.should_try_ = 1; // Pick DISPOSE_BACKGROUND.
- dispose_none_params.should_try_ = 0;
- }
- }
-
- if (dispose_none_params.should_try_) {
- error_code = GenerateCandidates(
- enc, candidates, WEBP_MUX_DISPOSE_NONE, is_lossless, is_key_frame,
- &dispose_none_params, &config_ll, &config_lossy);
- if (error_code != VP8_ENC_OK) goto Err;
- }
-
- if (dispose_bg_params.should_try_) {
- assert(!enc->is_first_frame_);
- assert(dispose_bg_possible);
- error_code = GenerateCandidates(
- enc, candidates, WEBP_MUX_DISPOSE_BACKGROUND, is_lossless, is_key_frame,
- &dispose_bg_params, &config_ll, &config_lossy);
- if (error_code != VP8_ENC_OK) goto Err;
- }
-
- PickBestCandidate(enc, candidates, is_key_frame, encoded_frame);
-
- goto End;
-
- Err:
- for (i = 0; i < CANDIDATE_COUNT; ++i) {
- if (candidates[i].evaluate_) {
- WebPMemoryWriterClear(&candidates[i].mem_);
- }
- }
-
- End:
- SubFrameParamsFree(&dispose_none_params);
- SubFrameParamsFree(&dispose_bg_params);
- return error_code;
-}
-
-// Calculate the penalty incurred if we encode given frame as a key frame
-// instead of a sub-frame.
-static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) {
- return ((int64_t)encoded_frame->key_frame_.bitstream.size -
- encoded_frame->sub_frame_.bitstream.size);
-}
-
-static int CacheFrame(WebPAnimEncoder* const enc,
- const WebPConfig* const config) {
- int ok = 0;
- int frame_skipped = 0;
- WebPEncodingError error_code = VP8_ENC_OK;
- const size_t position = enc->count_;
- EncodedFrame* const encoded_frame = GetFrame(enc, position);
-
- ++enc->count_;
-
- if (enc->is_first_frame_) { // Add this as a key-frame.
- error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped);
- if (error_code != VP8_ENC_OK) goto End;
- assert(frame_skipped == 0); // First frame can't be skipped, even if empty.
- assert(position == 0 && enc->count_ == 1);
- encoded_frame->is_key_frame_ = 1;
- enc->flush_count_ = 0;
- enc->count_since_key_frame_ = 0;
- enc->prev_candidate_undecided_ = 0;
- } else {
- ++enc->count_since_key_frame_;
- if (enc->count_since_key_frame_ <= enc->options_.kmin) {
- // Add this as a frame rectangle.
- error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped);
- if (error_code != VP8_ENC_OK) goto End;
- if (frame_skipped) goto Skip;
- encoded_frame->is_key_frame_ = 0;
- enc->flush_count_ = enc->count_ - 1;
- enc->prev_candidate_undecided_ = 0;
- } else {
- int64_t curr_delta;
-
- // Add this as a frame rectangle to enc.
- error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped);
- if (error_code != VP8_ENC_OK) goto End;
- if (frame_skipped) goto Skip;
-
- // Add this as a key-frame to enc, too.
- error_code = SetFrame(enc, config, 1, encoded_frame, &frame_skipped);
- if (error_code != VP8_ENC_OK) goto End;
- assert(frame_skipped == 0); // Key-frame cannot be an empty rectangle.
-
- // Analyze size difference of the two variants.
- curr_delta = KeyFramePenalty(encoded_frame);
- if (curr_delta <= enc->best_delta_) { // Pick this as the key-frame.
- if (enc->keyframe_ != KEYFRAME_NONE) {
- EncodedFrame* const old_keyframe = GetFrame(enc, enc->keyframe_);
- assert(old_keyframe->is_key_frame_);
- old_keyframe->is_key_frame_ = 0;
- }
- encoded_frame->is_key_frame_ = 1;
- enc->keyframe_ = (int)position;
- enc->best_delta_ = curr_delta;
- enc->flush_count_ = enc->count_ - 1; // We can flush previous frames.
- } else {
- encoded_frame->is_key_frame_ = 0;
- }
- // Note: We need '>=' below because when kmin and kmax are both zero,
- // count_since_key_frame will always be > kmax.
- if (enc->count_since_key_frame_ >= enc->options_.kmax) {
- enc->flush_count_ = enc->count_ - 1;
- enc->count_since_key_frame_ = 0;
- enc->keyframe_ = KEYFRAME_NONE;
- enc->best_delta_ = DELTA_INFINITY;
- }
- enc->prev_candidate_undecided_ = 1;
- }
- }
-
- // Update previous to previous and previous canvases for next call.
- WebPCopyPixels(enc->curr_canvas_, &enc->prev_canvas_);
- enc->is_first_frame_ = 0;
-
- Skip:
- ok = 1;
- ++enc->in_frame_count_;
-
- End:
- if (!ok || frame_skipped) {
- FrameRelease(encoded_frame);
- // We reset some counters, as the frame addition failed/was skipped.
- --enc->count_;
- if (!enc->is_first_frame_) --enc->count_since_key_frame_;
- if (!ok) {
- MarkError2(enc, "ERROR adding frame. WebPEncodingError", error_code);
- }
- }
- enc->curr_canvas_->error_code = error_code; // report error_code
- assert(ok || error_code != VP8_ENC_OK);
- return ok;
-}
-
-static int FlushFrames(WebPAnimEncoder* const enc) {
- while (enc->flush_count_ > 0) {
- WebPMuxError err;
- EncodedFrame* const curr = GetFrame(enc, 0);
- const WebPMuxFrameInfo* const info =
- curr->is_key_frame_ ? &curr->key_frame_ : &curr->sub_frame_;
- assert(enc->mux_ != NULL);
- err = WebPMuxPushFrame(enc->mux_, info, 1);
- if (err != WEBP_MUX_OK) {
- MarkError2(enc, "ERROR adding frame. WebPMuxError", err);
- return 0;
- }
- if (enc->options_.verbose) {
- fprintf(stderr, "INFO: Added frame. offset:%d,%d dispose:%d blend:%d\n",
- info->x_offset, info->y_offset, info->dispose_method,
- info->blend_method);
- }
- ++enc->out_frame_count_;
- FrameRelease(curr);
- ++enc->start_;
- --enc->flush_count_;
- --enc->count_;
- if (enc->keyframe_ != KEYFRAME_NONE) --enc->keyframe_;
- }
-
- if (enc->count_ == 1 && enc->start_ != 0) {
- // Move enc->start to index 0.
- const int enc_start_tmp = (int)enc->start_;
- EncodedFrame temp = enc->encoded_frames_[0];
- enc->encoded_frames_[0] = enc->encoded_frames_[enc_start_tmp];
- enc->encoded_frames_[enc_start_tmp] = temp;
- FrameRelease(&enc->encoded_frames_[enc_start_tmp]);
- enc->start_ = 0;
- }
- return 1;
-}
-
-#undef DELTA_INFINITY
-#undef KEYFRAME_NONE
-
-int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp,
- const WebPConfig* encoder_config) {
- WebPConfig config;
- int ok;
-
- if (enc == NULL) {
- return 0;
- }
- MarkNoError(enc);
-
- if (!enc->is_first_frame_) {
- // Make sure timestamps are non-decreasing (integer wrap-around is OK).
- const uint32_t prev_frame_duration =
- (uint32_t)timestamp - enc->prev_timestamp_;
- if (prev_frame_duration >= MAX_DURATION) {
- if (frame != NULL) {
- frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION;
- }
- MarkError(enc, "ERROR adding frame: timestamps must be non-decreasing");
- return 0;
- }
- if (!IncreasePreviousDuration(enc, (int)prev_frame_duration)) {
- return 0;
- }
- } else {
- enc->first_timestamp_ = timestamp;
- }
-
- if (frame == NULL) { // Special: last call.
- enc->got_null_frame_ = 1;
- enc->prev_timestamp_ = timestamp;
- return 1;
- }
-
- if (frame->width != enc->canvas_width_ ||
- frame->height != enc->canvas_height_) {
- frame->error_code = VP8_ENC_ERROR_INVALID_CONFIGURATION;
- MarkError(enc, "ERROR adding frame: Invalid frame dimensions");
- return 0;
- }
-
- if (!frame->use_argb) { // Convert frame from YUV(A) to ARGB.
- if (enc->options_.verbose) {
- fprintf(stderr, "WARNING: Converting frame from YUV(A) to ARGB format; "
- "this incurs a small loss.\n");
- }
- if (!WebPPictureYUVAToARGB(frame)) {
- MarkError(enc, "ERROR converting frame from YUV(A) to ARGB");
- return 0;
- }
- }
-
- if (encoder_config != NULL) {
- if (!WebPValidateConfig(encoder_config)) {
- MarkError(enc, "ERROR adding frame: Invalid WebPConfig");
- return 0;
- }
- config = *encoder_config;
- } else {
- WebPConfigInit(&config);
- config.lossless = 1;
- }
- assert(enc->curr_canvas_ == NULL);
- enc->curr_canvas_ = frame; // Store reference.
- assert(enc->curr_canvas_copy_modified_ == 1);
- CopyCurrentCanvas(enc);
-
- ok = CacheFrame(enc, &config) && FlushFrames(enc);
-
- enc->curr_canvas_ = NULL;
- enc->curr_canvas_copy_modified_ = 1;
- if (ok) {
- enc->prev_timestamp_ = timestamp;
- }
- return ok;
-}
-
-// -----------------------------------------------------------------------------
-// Bitstream assembly.
-
-static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame,
- WebPPicture* const canvas) {
- const WebPData* const image = &frame->bitstream;
- WebPPicture sub_image;
- WebPDecoderConfig config;
- WebPInitDecoderConfig(&config);
- WebPUtilClearPic(canvas, NULL);
- if (WebPGetFeatures(image->bytes, image->size, &config.input) !=
- VP8_STATUS_OK) {
- return 0;
- }
- if (!WebPPictureView(canvas, frame->x_offset, frame->y_offset,
- config.input.width, config.input.height, &sub_image)) {
- return 0;
- }
- config.output.is_external_memory = 1;
- config.output.colorspace = MODE_BGRA;
- config.output.u.RGBA.rgba = (uint8_t*)sub_image.argb;
- config.output.u.RGBA.stride = sub_image.argb_stride * 4;
- config.output.u.RGBA.size = config.output.u.RGBA.stride * sub_image.height;
-
- if (WebPDecode(image->bytes, image->size, &config) != VP8_STATUS_OK) {
- return 0;
- }
- return 1;
-}
-
-static int FrameToFullCanvas(WebPAnimEncoder* const enc,
- const WebPMuxFrameInfo* const frame,
- WebPData* const full_image) {
- WebPPicture* const canvas_buf = &enc->curr_canvas_copy_;
- WebPMemoryWriter mem1, mem2;
- WebPMemoryWriterInit(&mem1);
- WebPMemoryWriterInit(&mem2);
-
- if (!DecodeFrameOntoCanvas(frame, canvas_buf)) goto Err;
- if (!EncodeFrame(&enc->last_config_, canvas_buf, &mem1)) goto Err;
- GetEncodedData(&mem1, full_image);
-
- if (enc->options_.allow_mixed) {
- if (!EncodeFrame(&enc->last_config_reversed_, canvas_buf, &mem2)) goto Err;
- if (mem2.size < mem1.size) {
- GetEncodedData(&mem2, full_image);
- WebPMemoryWriterClear(&mem1);
- } else {
- WebPMemoryWriterClear(&mem2);
- }
- }
- return 1;
-
- Err:
- WebPMemoryWriterClear(&mem1);
- WebPMemoryWriterClear(&mem2);
- return 0;
-}
-
-// Convert a single-frame animation to a non-animated image if appropriate.
-// TODO(urvang): Can we pick one of the two heuristically (based on frame
-// rectangle and/or presence of alpha)?
-static WebPMuxError OptimizeSingleFrame(WebPAnimEncoder* const enc,
- WebPData* const webp_data) {
- WebPMuxError err = WEBP_MUX_OK;
- int canvas_width, canvas_height;
- WebPMuxFrameInfo frame;
- WebPData full_image;
- WebPData webp_data2;
- WebPMux* const mux = WebPMuxCreate(webp_data, 0);
- if (mux == NULL) return WEBP_MUX_BAD_DATA;
- assert(enc->out_frame_count_ == 1);
- WebPDataInit(&frame.bitstream);
- WebPDataInit(&full_image);
- WebPDataInit(&webp_data2);
-
- err = WebPMuxGetFrame(mux, 1, &frame);
- if (err != WEBP_MUX_OK) goto End;
- if (frame.id != WEBP_CHUNK_ANMF) goto End; // Non-animation: nothing to do.
- err = WebPMuxGetCanvasSize(mux, &canvas_width, &canvas_height);
- if (err != WEBP_MUX_OK) goto End;
- if (!FrameToFullCanvas(enc, &frame, &full_image)) {
- err = WEBP_MUX_BAD_DATA;
- goto End;
- }
- err = WebPMuxSetImage(mux, &full_image, 1);
- if (err != WEBP_MUX_OK) goto End;
- err = WebPMuxAssemble(mux, &webp_data2);
- if (err != WEBP_MUX_OK) goto End;
-
- if (webp_data2.size < webp_data->size) { // Pick 'webp_data2' if smaller.
- WebPDataClear(webp_data);
- *webp_data = webp_data2;
- WebPDataInit(&webp_data2);
- }
-
- End:
- WebPDataClear(&frame.bitstream);
- WebPDataClear(&full_image);
- WebPMuxDelete(mux);
- WebPDataClear(&webp_data2);
- return err;
-}
-
-int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) {
- WebPMux* mux;
- WebPMuxError err;
-
- if (enc == NULL) {
- return 0;
- }
- MarkNoError(enc);
-
- if (webp_data == NULL) {
- MarkError(enc, "ERROR assembling: NULL input");
- return 0;
- }
-
- if (enc->in_frame_count_ == 0) {
- MarkError(enc, "ERROR: No frames to assemble");
- return 0;
- }
-
- if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) {
- // set duration of the last frame to be avg of durations of previous frames.
- const double delta_time = enc->prev_timestamp_ - enc->first_timestamp_;
- const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1));
- if (!IncreasePreviousDuration(enc, average_duration)) {
- return 0;
- }
- }
-
- // Flush any remaining frames.
- enc->flush_count_ = enc->count_;
- if (!FlushFrames(enc)) {
- return 0;
- }
-
- // Set definitive canvas size.
- mux = enc->mux_;
- err = WebPMuxSetCanvasSize(mux, enc->canvas_width_, enc->canvas_height_);
- if (err != WEBP_MUX_OK) goto Err;
-
- err = WebPMuxSetAnimationParams(mux, &enc->options_.anim_params);
- if (err != WEBP_MUX_OK) goto Err;
-
- // Assemble into a WebP bitstream.
- err = WebPMuxAssemble(mux, webp_data);
- if (err != WEBP_MUX_OK) goto Err;
-
- if (enc->out_frame_count_ == 1) {
- err = OptimizeSingleFrame(enc, webp_data);
- if (err != WEBP_MUX_OK) goto Err;
- }
- return 1;
-
- Err:
- MarkError2(enc, "ERROR assembling WebP", err);
- return 0;
-}
-
-const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) {
- if (enc == NULL) return NULL;
- return enc->error_str_;
-}
-
-// -----------------------------------------------------------------------------
diff --git a/drivers/webp/mux/muxedit.c b/drivers/webp/mux/muxedit.c
deleted file mode 100644
index 9bbed42b1a..0000000000
--- a/drivers/webp/mux/muxedit.c
+++ /dev/null
@@ -1,696 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Set and delete APIs for mux.
-//
-// Authors: Urvang (urvang@google.com)
-// Vikas (vikasa@google.com)
-
-#include <assert.h>
-#include "./muxi.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// Life of a mux object.
-
-static void MuxInit(WebPMux* const mux) {
- assert(mux != NULL);
- memset(mux, 0, sizeof(*mux));
- mux->canvas_width_ = 0; // just to be explicit
- mux->canvas_height_ = 0;
-}
-
-WebPMux* WebPNewInternal(int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) {
- return NULL;
- } else {
- WebPMux* const mux = (WebPMux*)WebPSafeMalloc(1ULL, sizeof(WebPMux));
- if (mux != NULL) MuxInit(mux);
- return mux;
- }
-}
-
-// Delete all images in 'wpi_list'.
-static void DeleteAllImages(WebPMuxImage** const wpi_list) {
- while (*wpi_list != NULL) {
- *wpi_list = MuxImageDelete(*wpi_list);
- }
-}
-
-static void MuxRelease(WebPMux* const mux) {
- assert(mux != NULL);
- DeleteAllImages(&mux->images_);
- ChunkListDelete(&mux->vp8x_);
- ChunkListDelete(&mux->iccp_);
- ChunkListDelete(&mux->anim_);
- ChunkListDelete(&mux->exif_);
- ChunkListDelete(&mux->xmp_);
- ChunkListDelete(&mux->unknown_);
-}
-
-void WebPMuxDelete(WebPMux* mux) {
- if (mux != NULL) {
- MuxRelease(mux);
- WebPSafeFree(mux);
- }
-}
-
-//------------------------------------------------------------------------------
-// Helper method(s).
-
-// Handy MACRO, makes MuxSet() very symmetric to MuxGet().
-#define SWITCH_ID_LIST(INDEX, LIST) \
- if (idx == (INDEX)) { \
- err = ChunkAssignData(&chunk, data, copy_data, tag); \
- if (err == WEBP_MUX_OK) { \
- err = ChunkSetNth(&chunk, (LIST), nth); \
- } \
- return err; \
- }
-
-static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
- const WebPData* const data, int copy_data) {
- WebPChunk chunk;
- WebPMuxError err = WEBP_MUX_NOT_FOUND;
- const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag);
- assert(mux != NULL);
- assert(!IsWPI(kChunks[idx].id));
-
- ChunkInit(&chunk);
- SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_);
- SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_);
- SWITCH_ID_LIST(IDX_ANIM, &mux->anim_);
- SWITCH_ID_LIST(IDX_EXIF, &mux->exif_);
- SWITCH_ID_LIST(IDX_XMP, &mux->xmp_);
- SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown_);
- return err;
-}
-#undef SWITCH_ID_LIST
-
-// Create data for frame/fragment given image data, offsets and duration.
-static WebPMuxError CreateFrameFragmentData(
- int width, int height, const WebPMuxFrameInfo* const info, int is_frame,
- WebPData* const frame_frgm) {
- uint8_t* frame_frgm_bytes;
- const size_t frame_frgm_size = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].size;
-
- assert(width > 0 && height > 0 && info->duration >= 0);
- assert(info->dispose_method == (info->dispose_method & 1));
- // Note: assertion on upper bounds is done in PutLE24().
-
- frame_frgm_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_frgm_size);
- if (frame_frgm_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
-
- PutLE24(frame_frgm_bytes + 0, info->x_offset / 2);
- PutLE24(frame_frgm_bytes + 3, info->y_offset / 2);
-
- if (is_frame) {
- PutLE24(frame_frgm_bytes + 6, width - 1);
- PutLE24(frame_frgm_bytes + 9, height - 1);
- PutLE24(frame_frgm_bytes + 12, info->duration);
- frame_frgm_bytes[15] =
- (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) |
- (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0);
- }
-
- frame_frgm->bytes = frame_frgm_bytes;
- frame_frgm->size = frame_frgm_size;
- return WEBP_MUX_OK;
-}
-
-// Outputs image data given a bitstream. The bitstream can either be a
-// single-image WebP file or raw VP8/VP8L data.
-// Also outputs 'is_lossless' to be true if the given bitstream is lossless.
-static WebPMuxError GetImageData(const WebPData* const bitstream,
- WebPData* const image, WebPData* const alpha,
- int* const is_lossless) {
- WebPDataInit(alpha); // Default: no alpha.
- if (bitstream->size < TAG_SIZE ||
- memcmp(bitstream->bytes, "RIFF", TAG_SIZE)) {
- // It is NOT webp file data. Return input data as is.
- *image = *bitstream;
- } else {
- // It is webp file data. Extract image data from it.
- const WebPMuxImage* wpi;
- WebPMux* const mux = WebPMuxCreate(bitstream, 0);
- if (mux == NULL) return WEBP_MUX_BAD_DATA;
- wpi = mux->images_;
- assert(wpi != NULL && wpi->img_ != NULL);
- *image = wpi->img_->data_;
- if (wpi->alpha_ != NULL) {
- *alpha = wpi->alpha_->data_;
- }
- WebPMuxDelete(mux);
- }
- *is_lossless = VP8LCheckSignature(image->bytes, image->size);
- return WEBP_MUX_OK;
-}
-
-static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) {
- WebPMuxError err = WEBP_MUX_NOT_FOUND;
- assert(chunk_list);
- while (*chunk_list) {
- WebPChunk* const chunk = *chunk_list;
- if (chunk->tag_ == tag) {
- *chunk_list = ChunkDelete(chunk);
- err = WEBP_MUX_OK;
- } else {
- chunk_list = &chunk->next_;
- }
- }
- return err;
-}
-
-static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) {
- const WebPChunkId id = ChunkGetIdFromTag(tag);
- assert(mux != NULL);
- if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT;
- return DeleteChunks(MuxGetChunkListFromId(mux, id), tag);
-}
-
-//------------------------------------------------------------------------------
-// Set API(s).
-
-WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4],
- const WebPData* chunk_data, int copy_data) {
- uint32_t tag;
- WebPMuxError err;
- if (mux == NULL || fourcc == NULL || chunk_data == NULL ||
- chunk_data->bytes == NULL || chunk_data->size > MAX_CHUNK_PAYLOAD) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- tag = ChunkGetTagFromFourCC(fourcc);
-
- // Delete existing chunk(s) with the same 'fourcc'.
- err = MuxDeleteAllNamedData(mux, tag);
- if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
-
- // Add the given chunk.
- return MuxSet(mux, tag, 1, chunk_data, copy_data);
-}
-
-// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'.
-static WebPMuxError AddDataToChunkList(
- const WebPData* const data, int copy_data, uint32_t tag,
- WebPChunk** chunk_list) {
- WebPChunk chunk;
- WebPMuxError err;
- ChunkInit(&chunk);
- err = ChunkAssignData(&chunk, data, copy_data, tag);
- if (err != WEBP_MUX_OK) goto Err;
- err = ChunkSetNth(&chunk, chunk_list, 1);
- if (err != WEBP_MUX_OK) goto Err;
- return WEBP_MUX_OK;
- Err:
- ChunkRelease(&chunk);
- return err;
-}
-
-// Extracts image & alpha data from the given bitstream and then sets wpi.alpha_
-// and wpi.img_ appropriately.
-static WebPMuxError SetAlphaAndImageChunks(
- const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) {
- int is_lossless = 0;
- WebPData image, alpha;
- WebPMuxError err = GetImageData(bitstream, &image, &alpha, &is_lossless);
- const int image_tag =
- is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag;
- if (err != WEBP_MUX_OK) return err;
- if (alpha.bytes != NULL) {
- err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag,
- &wpi->alpha_);
- if (err != WEBP_MUX_OK) return err;
- }
- err = AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_);
- if (err != WEBP_MUX_OK) return err;
- return MuxImageFinalize(wpi) ? WEBP_MUX_OK : WEBP_MUX_INVALID_ARGUMENT;
-}
-
-WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream,
- int copy_data) {
- WebPMuxImage wpi;
- WebPMuxError err;
-
- // Sanity checks.
- if (mux == NULL || bitstream == NULL || bitstream->bytes == NULL ||
- bitstream->size > MAX_CHUNK_PAYLOAD) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- if (mux->images_ != NULL) {
- // Only one 'simple image' can be added in mux. So, remove present images.
- DeleteAllImages(&mux->images_);
- }
-
- MuxImageInit(&wpi);
- err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi);
- if (err != WEBP_MUX_OK) goto Err;
-
- // Add this WebPMuxImage to mux.
- err = MuxImagePush(&wpi, &mux->images_);
- if (err != WEBP_MUX_OK) goto Err;
-
- // All is well.
- return WEBP_MUX_OK;
-
- Err: // Something bad happened.
- MuxImageRelease(&wpi);
- return err;
-}
-
-WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
- int copy_data) {
- WebPMuxImage wpi;
- WebPMuxError err;
- int is_frame;
- const WebPData* const bitstream = &frame->bitstream;
-
- // Sanity checks.
- if (mux == NULL || frame == NULL) return WEBP_MUX_INVALID_ARGUMENT;
-
- is_frame = (frame->id == WEBP_CHUNK_ANMF);
- if (!(is_frame || (frame->id == WEBP_CHUNK_FRGM))) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- if (frame->id == WEBP_CHUNK_FRGM) { // Dead experiment.
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- if (mux->images_ != NULL) {
- const WebPMuxImage* const image = mux->images_;
- const uint32_t image_id = (image->header_ != NULL) ?
- ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE;
- if (image_id != frame->id) {
- return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types.
- }
- }
-
- MuxImageInit(&wpi);
- err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi);
- if (err != WEBP_MUX_OK) goto Err;
- assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful.
-
- {
- WebPData frame_frgm;
- const uint32_t tag = kChunks[is_frame ? IDX_ANMF : IDX_FRGM].tag;
- WebPMuxFrameInfo tmp = *frame;
- tmp.x_offset &= ~1; // Snap offsets to even.
- tmp.y_offset &= ~1;
- if (!is_frame) { // Reset unused values.
- tmp.duration = 1;
- tmp.dispose_method = WEBP_MUX_DISPOSE_NONE;
- tmp.blend_method = WEBP_MUX_BLEND;
- }
- if (tmp.x_offset < 0 || tmp.x_offset >= MAX_POSITION_OFFSET ||
- tmp.y_offset < 0 || tmp.y_offset >= MAX_POSITION_OFFSET ||
- (tmp.duration < 0 || tmp.duration >= MAX_DURATION) ||
- tmp.dispose_method != (tmp.dispose_method & 1)) {
- err = WEBP_MUX_INVALID_ARGUMENT;
- goto Err;
- }
- err = CreateFrameFragmentData(wpi.width_, wpi.height_, &tmp, is_frame,
- &frame_frgm);
- if (err != WEBP_MUX_OK) goto Err;
- // Add frame/fragment chunk (with copy_data = 1).
- err = AddDataToChunkList(&frame_frgm, 1, tag, &wpi.header_);
- WebPDataClear(&frame_frgm); // frame_frgm owned by wpi.header_ now.
- if (err != WEBP_MUX_OK) goto Err;
- }
-
- // Add this WebPMuxImage to mux.
- err = MuxImagePush(&wpi, &mux->images_);
- if (err != WEBP_MUX_OK) goto Err;
-
- // All is well.
- return WEBP_MUX_OK;
-
- Err: // Something bad happened.
- MuxImageRelease(&wpi);
- return err;
-}
-
-WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux,
- const WebPMuxAnimParams* params) {
- WebPMuxError err;
- uint8_t data[ANIM_CHUNK_SIZE];
- const WebPData anim = { data, ANIM_CHUNK_SIZE };
-
- if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- if (params->loop_count < 0 || params->loop_count >= MAX_LOOP_COUNT) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- // Delete any existing ANIM chunk(s).
- err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag);
- if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
-
- // Set the animation parameters.
- PutLE32(data, params->bgcolor);
- PutLE16(data + 4, params->loop_count);
- return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1);
-}
-
-WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux,
- int width, int height) {
- WebPMuxError err;
- if (mux == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- if (width < 0 || height < 0 ||
- width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- if (width * (uint64_t)height >= MAX_IMAGE_AREA) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- if ((width * height) == 0 && (width | height) != 0) {
- // one of width / height is zero, but not both -> invalid!
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- // If we already assembled a VP8X chunk, invalidate it.
- err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag);
- if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
-
- mux->canvas_width_ = width;
- mux->canvas_height_ = height;
- return WEBP_MUX_OK;
-}
-
-//------------------------------------------------------------------------------
-// Delete API(s).
-
-WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) {
- if (mux == NULL || fourcc == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc));
-}
-
-WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) {
- if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- return MuxImageDeleteNth(&mux->images_, nth);
-}
-
-//------------------------------------------------------------------------------
-// Assembly of the WebP RIFF file.
-
-static WebPMuxError GetFrameFragmentInfo(
- const WebPChunk* const frame_frgm_chunk,
- int* const x_offset, int* const y_offset, int* const duration) {
- const uint32_t tag = frame_frgm_chunk->tag_;
- const int is_frame = (tag == kChunks[IDX_ANMF].tag);
- const WebPData* const data = &frame_frgm_chunk->data_;
- const size_t expected_data_size =
- is_frame ? ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
- assert(frame_frgm_chunk != NULL);
- assert(tag == kChunks[IDX_ANMF].tag || tag == kChunks[IDX_FRGM].tag);
- if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT;
-
- *x_offset = 2 * GetLE24(data->bytes + 0);
- *y_offset = 2 * GetLE24(data->bytes + 3);
- if (is_frame) *duration = GetLE24(data->bytes + 12);
- return WEBP_MUX_OK;
-}
-
-static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
- int* const x_offset, int* const y_offset,
- int* const duration,
- int* const width, int* const height) {
- const WebPChunk* const frame_frgm_chunk = wpi->header_;
- WebPMuxError err;
- assert(wpi != NULL);
- assert(frame_frgm_chunk != NULL);
-
- // Get offsets and duration from ANMF/FRGM chunk.
- err = GetFrameFragmentInfo(frame_frgm_chunk, x_offset, y_offset, duration);
- if (err != WEBP_MUX_OK) return err;
-
- // Get width and height from VP8/VP8L chunk.
- if (width != NULL) *width = wpi->width_;
- if (height != NULL) *height = wpi->height_;
- return WEBP_MUX_OK;
-}
-
-// Returns the tightest dimension for the canvas considering the image list.
-static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
- uint32_t flags,
- int* const width, int* const height) {
- WebPMuxImage* wpi = NULL;
- assert(mux != NULL);
- assert(width != NULL && height != NULL);
-
- wpi = mux->images_;
- assert(wpi != NULL);
- assert(wpi->img_ != NULL);
-
- if (wpi->next_ != NULL) {
- int max_x = 0;
- int max_y = 0;
- int64_t image_area = 0;
- // if we have a chain of wpi's, header_ is necessarily set
- assert(wpi->header_ != NULL);
- // Aggregate the bounding box for animation frames & fragmented images.
- for (; wpi != NULL; wpi = wpi->next_) {
- int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0;
- const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset,
- &duration, &w, &h);
- const int max_x_pos = x_offset + w;
- const int max_y_pos = y_offset + h;
- if (err != WEBP_MUX_OK) return err;
- assert(x_offset < MAX_POSITION_OFFSET);
- assert(y_offset < MAX_POSITION_OFFSET);
-
- if (max_x_pos > max_x) max_x = max_x_pos;
- if (max_y_pos > max_y) max_y = max_y_pos;
- image_area += w * h;
- }
- *width = max_x;
- *height = max_y;
- // Crude check to validate that there are no image overlaps/holes for
- // fragmented images. Check that the aggregated image area for individual
- // fragments exactly matches the image area of the constructed canvas.
- // However, the area-match is necessary but not sufficient condition.
- if ((flags & FRAGMENTS_FLAG) && (image_area != (max_x * max_y))) {
- *width = 0;
- *height = 0;
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- } else {
- // For a single image, canvas dimensions are same as image dimensions.
- *width = wpi->width_;
- *height = wpi->height_;
- }
- return WEBP_MUX_OK;
-}
-
-// VP8X format:
-// Total Size : 10,
-// Flags : 4 bytes,
-// Width : 3 bytes,
-// Height : 3 bytes.
-static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
- WebPMuxError err = WEBP_MUX_OK;
- uint32_t flags = 0;
- int width = 0;
- int height = 0;
- uint8_t data[VP8X_CHUNK_SIZE];
- const WebPData vp8x = { data, VP8X_CHUNK_SIZE };
- const WebPMuxImage* images = NULL;
-
- assert(mux != NULL);
- images = mux->images_; // First image.
- if (images == NULL || images->img_ == NULL ||
- images->img_->data_.bytes == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- // If VP8X chunk(s) is(are) already present, remove them (and later add new
- // VP8X chunk with updated flags).
- err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag);
- if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
-
- // Set flags.
- if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) {
- flags |= ICCP_FLAG;
- }
- if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) {
- flags |= EXIF_FLAG;
- }
- if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) {
- flags |= XMP_FLAG;
- }
- if (images->header_ != NULL) {
- if (images->header_->tag_ == kChunks[IDX_FRGM].tag) {
- // This is a fragmented image.
- flags |= FRAGMENTS_FLAG;
- } else if (images->header_->tag_ == kChunks[IDX_ANMF].tag) {
- // This is an image with animation.
- flags |= ANIMATION_FLAG;
- }
- }
- if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) {
- flags |= ALPHA_FLAG; // Some images have an alpha channel.
- }
-
- err = GetAdjustedCanvasSize(mux, flags, &width, &height);
- if (err != WEBP_MUX_OK) return err;
-
- if (width <= 0 || height <= 0) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- if (width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- if (mux->canvas_width_ != 0 || mux->canvas_height_ != 0) {
- if (width > mux->canvas_width_ || height > mux->canvas_height_) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- width = mux->canvas_width_;
- height = mux->canvas_height_;
- }
-
- if (flags == 0 && mux->unknown_ == NULL) {
- // For simple file format, VP8X chunk should not be added.
- return WEBP_MUX_OK;
- }
-
- if (MuxHasAlpha(images)) {
- // This means some frames explicitly/implicitly contain alpha.
- // Note: This 'flags' update must NOT be done for a lossless image
- // without a VP8X chunk!
- flags |= ALPHA_FLAG;
- }
-
- PutLE32(data + 0, flags); // VP8X chunk flags.
- PutLE24(data + 4, width - 1); // canvas width.
- PutLE24(data + 7, height - 1); // canvas height.
-
- return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1);
-}
-
-// Cleans up 'mux' by removing any unnecessary chunks.
-static WebPMuxError MuxCleanup(WebPMux* const mux) {
- int num_frames;
- int num_fragments;
- int num_anim_chunks;
-
- // If we have an image with a single fragment or frame, and its rectangle
- // covers the whole canvas, convert it to a non-animated non-fragmented image
- // (to avoid writing FRGM/ANMF chunk unnecessarily).
- WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames);
- if (err != WEBP_MUX_OK) return err;
- err = WebPMuxNumChunks(mux, kChunks[IDX_FRGM].id, &num_fragments);
- if (err != WEBP_MUX_OK) return err;
- if (num_frames == 1 || num_fragments == 1) {
- WebPMuxImage* frame_frag;
- err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame_frag);
- assert(err == WEBP_MUX_OK); // We know that one frame/fragment does exist.
- assert(frame_frag != NULL);
- if (frame_frag->header_ != NULL &&
- ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) ||
- (frame_frag->width_ == mux->canvas_width_ &&
- frame_frag->height_ == mux->canvas_height_))) {
- assert(frame_frag->header_->tag_ == kChunks[IDX_ANMF].tag ||
- frame_frag->header_->tag_ == kChunks[IDX_FRGM].tag);
- ChunkDelete(frame_frag->header_); // Removes ANMF/FRGM chunk.
- frame_frag->header_ = NULL;
- num_frames = 0;
- num_fragments = 0;
- }
- }
- // Remove ANIM chunk if this is a non-animated image.
- err = WebPMuxNumChunks(mux, kChunks[IDX_ANIM].id, &num_anim_chunks);
- if (err != WEBP_MUX_OK) return err;
- if (num_anim_chunks >= 1 && num_frames == 0) {
- err = MuxDeleteAllNamedData(mux, kChunks[IDX_ANIM].tag);
- if (err != WEBP_MUX_OK) return err;
- }
- return WEBP_MUX_OK;
-}
-
-// Total size of a list of images.
-static size_t ImageListDiskSize(const WebPMuxImage* wpi_list) {
- size_t size = 0;
- while (wpi_list != NULL) {
- size += MuxImageDiskSize(wpi_list);
- wpi_list = wpi_list->next_;
- }
- return size;
-}
-
-// Write out the given list of images into 'dst'.
-static uint8_t* ImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
- while (wpi_list != NULL) {
- dst = MuxImageEmit(wpi_list, dst);
- wpi_list = wpi_list->next_;
- }
- return dst;
-}
-
-WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) {
- size_t size = 0;
- uint8_t* data = NULL;
- uint8_t* dst = NULL;
- WebPMuxError err;
-
- if (assembled_data == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- // Clean up returned data, in case something goes wrong.
- memset(assembled_data, 0, sizeof(*assembled_data));
-
- if (mux == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- // Finalize mux.
- err = MuxCleanup(mux);
- if (err != WEBP_MUX_OK) return err;
- err = CreateVP8XChunk(mux);
- if (err != WEBP_MUX_OK) return err;
-
- // Allocate data.
- size = ChunkListDiskSize(mux->vp8x_) + ChunkListDiskSize(mux->iccp_)
- + ChunkListDiskSize(mux->anim_) + ImageListDiskSize(mux->images_)
- + ChunkListDiskSize(mux->exif_) + ChunkListDiskSize(mux->xmp_)
- + ChunkListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE;
-
- data = (uint8_t*)WebPSafeMalloc(1ULL, size);
- if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
-
- // Emit header & chunks.
- dst = MuxEmitRiffHeader(data, size);
- dst = ChunkListEmit(mux->vp8x_, dst);
- dst = ChunkListEmit(mux->iccp_, dst);
- dst = ChunkListEmit(mux->anim_, dst);
- dst = ImageListEmit(mux->images_, dst);
- dst = ChunkListEmit(mux->exif_, dst);
- dst = ChunkListEmit(mux->xmp_, dst);
- dst = ChunkListEmit(mux->unknown_, dst);
- assert(dst == data + size);
-
- // Validate mux.
- err = MuxValidate(mux);
- if (err != WEBP_MUX_OK) {
- WebPSafeFree(data);
- data = NULL;
- size = 0;
- }
-
- // Finalize data.
- assembled_data->bytes = data;
- assembled_data->size = size;
-
- return err;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/mux/muxi.h b/drivers/webp/mux/muxi.h
deleted file mode 100644
index 3f6428c4df..0000000000
--- a/drivers/webp/mux/muxi.h
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Internal header for mux library.
-//
-// Author: Urvang (urvang@google.com)
-
-#ifndef WEBP_MUX_MUXI_H_
-#define WEBP_MUX_MUXI_H_
-
-#include <stdlib.h>
-#include "../dec/vp8i.h"
-#include "../dec/vp8li.h"
-#include "webp/mux.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Defines and constants.
-
-#define MUX_MAJ_VERSION 0
-#define MUX_MIN_VERSION 3
-#define MUX_REV_VERSION 1
-
-// Chunk object.
-typedef struct WebPChunk WebPChunk;
-struct WebPChunk {
- uint32_t tag_;
- int owner_; // True if *data_ memory is owned internally.
- // VP8X, ANIM, and other internally created chunks
- // like ANMF/FRGM are always owned.
- WebPData data_;
- WebPChunk* next_;
-};
-
-// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH
-// chunk and VP8/VP8L chunk),
-typedef struct WebPMuxImage WebPMuxImage;
-struct WebPMuxImage {
- WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM.
- WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA.
- WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE.
- WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN.
- int width_;
- int height_;
- int has_alpha_; // Through ALPH chunk or as part of VP8L.
- int is_partial_; // True if only some of the chunks are filled.
- WebPMuxImage* next_;
-};
-
-// Main mux object. Stores data chunks.
-struct WebPMux {
- WebPMuxImage* images_;
- WebPChunk* iccp_;
- WebPChunk* exif_;
- WebPChunk* xmp_;
- WebPChunk* anim_;
- WebPChunk* vp8x_;
-
- WebPChunk* unknown_;
- int canvas_width_;
- int canvas_height_;
-};
-
-// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only.
-// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to
-// allow two different chunks to have the same id (e.g. WebPChunkId
-// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L').
-typedef enum {
- IDX_VP8X = 0,
- IDX_ICCP,
- IDX_ANIM,
- IDX_ANMF,
- IDX_FRGM,
- IDX_ALPHA,
- IDX_VP8,
- IDX_VP8L,
- IDX_EXIF,
- IDX_XMP,
- IDX_UNKNOWN,
-
- IDX_NIL,
- IDX_LAST_CHUNK
-} CHUNK_INDEX;
-
-#define NIL_TAG 0x00000000u // To signal void chunk.
-
-typedef struct {
- uint32_t tag;
- WebPChunkId id;
- uint32_t size;
-} ChunkInfo;
-
-extern const ChunkInfo kChunks[IDX_LAST_CHUNK];
-
-//------------------------------------------------------------------------------
-// Chunk object management.
-
-// Initialize.
-void ChunkInit(WebPChunk* const chunk);
-
-// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found.
-CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag);
-
-// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found.
-WebPChunkId ChunkGetIdFromTag(uint32_t tag);
-
-// Convert a fourcc string to a tag.
-uint32_t ChunkGetTagFromFourCC(const char fourcc[4]);
-
-// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown.
-CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]);
-
-// Search for nth chunk with given 'tag' in the chunk list.
-// nth = 0 means "last of the list".
-WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag);
-
-// Fill the chunk with the given data.
-WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
- int copy_data, uint32_t tag);
-
-// Sets 'chunk' at nth position in the 'chunk_list'.
-// nth = 0 has the special meaning "last of the list".
-// On success ownership is transferred from 'chunk' to the 'chunk_list'.
-WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
- uint32_t nth);
-
-// Releases chunk and returns chunk->next_.
-WebPChunk* ChunkRelease(WebPChunk* const chunk);
-
-// Deletes given chunk & returns chunk->next_.
-WebPChunk* ChunkDelete(WebPChunk* const chunk);
-
-// Deletes all chunks in the given chunk list.
-void ChunkListDelete(WebPChunk** const chunk_list);
-
-// Returns size of the chunk including chunk header and padding byte (if any).
-static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
- return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
-}
-
-// Size of a chunk including header and padding.
-static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
- const size_t data_size = chunk->data_.size;
- assert(data_size < MAX_CHUNK_PAYLOAD);
- return SizeWithPadding(data_size);
-}
-
-// Total size of a list of chunks.
-size_t ChunkListDiskSize(const WebPChunk* chunk_list);
-
-// Write out the given list of chunks into 'dst'.
-uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst);
-
-//------------------------------------------------------------------------------
-// MuxImage object management.
-
-// Initialize.
-void MuxImageInit(WebPMuxImage* const wpi);
-
-// Releases image 'wpi' and returns wpi->next.
-WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi);
-
-// Delete image 'wpi' and return the next image in the list or NULL.
-// 'wpi' can be NULL.
-WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi);
-
-// Count number of images matching the given tag id in the 'wpi_list'.
-// If id == WEBP_CHUNK_NIL, all images will be matched.
-int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id);
-
-// Update width/height/has_alpha info from chunks within wpi.
-// Also remove ALPH chunk if not needed.
-int MuxImageFinalize(WebPMuxImage* const wpi);
-
-// Check if given ID corresponds to an image related chunk.
-static WEBP_INLINE int IsWPI(WebPChunkId id) {
- switch (id) {
- case WEBP_CHUNK_ANMF:
- case WEBP_CHUNK_FRGM:
- case WEBP_CHUNK_ALPHA:
- case WEBP_CHUNK_IMAGE: return 1;
- default: return 0;
- }
-}
-
-// Pushes 'wpi' at the end of 'wpi_list'.
-WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list);
-
-// Delete nth image in the image list.
-WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth);
-
-// Get nth image in the image list.
-WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth,
- WebPMuxImage** wpi);
-
-// Total size of the given image.
-size_t MuxImageDiskSize(const WebPMuxImage* const wpi);
-
-// Write out the given image into 'dst'.
-uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst);
-
-//------------------------------------------------------------------------------
-// Helper methods for mux.
-
-// Checks if the given image list contains at least one image with alpha.
-int MuxHasAlpha(const WebPMuxImage* images);
-
-// Write out RIFF header into 'data', given total data size 'size'.
-uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size);
-
-// Returns the list where chunk with given ID is to be inserted in mux.
-WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id);
-
-// Validates the given mux object.
-WebPMuxError MuxValidate(const WebPMux* const mux);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_MUX_MUXI_H_ */
diff --git a/drivers/webp/mux/muxinternal.c b/drivers/webp/mux/muxinternal.c
deleted file mode 100644
index 4babbe82fc..0000000000
--- a/drivers/webp/mux/muxinternal.c
+++ /dev/null
@@ -1,551 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Internal objects and utils for mux.
-//
-// Authors: Urvang (urvang@google.com)
-// Vikas (vikasa@google.com)
-
-#include <assert.h>
-#include "./muxi.h"
-#include "../utils/utils.h"
-
-#define UNDEFINED_CHUNK_SIZE (-1)
-
-const ChunkInfo kChunks[] = {
- { MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE },
- { MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE },
- { MKFOURCC('A', 'N', 'I', 'M'), WEBP_CHUNK_ANIM, ANIM_CHUNK_SIZE },
- { MKFOURCC('A', 'N', 'M', 'F'), WEBP_CHUNK_ANMF, ANMF_CHUNK_SIZE },
- { MKFOURCC('F', 'R', 'G', 'M'), WEBP_CHUNK_FRGM, FRGM_CHUNK_SIZE },
- { MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE },
- { MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
- { MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
- { MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE },
- { MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE },
- { NIL_TAG, WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
-
- { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE }
-};
-
-//------------------------------------------------------------------------------
-
-int WebPGetMuxVersion(void) {
- return (MUX_MAJ_VERSION << 16) | (MUX_MIN_VERSION << 8) | MUX_REV_VERSION;
-}
-
-//------------------------------------------------------------------------------
-// Life of a chunk object.
-
-void ChunkInit(WebPChunk* const chunk) {
- assert(chunk);
- memset(chunk, 0, sizeof(*chunk));
- chunk->tag_ = NIL_TAG;
-}
-
-WebPChunk* ChunkRelease(WebPChunk* const chunk) {
- WebPChunk* next;
- if (chunk == NULL) return NULL;
- if (chunk->owner_) {
- WebPDataClear(&chunk->data_);
- }
- next = chunk->next_;
- ChunkInit(chunk);
- return next;
-}
-
-//------------------------------------------------------------------------------
-// Chunk misc methods.
-
-CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) {
- int i;
- for (i = 0; kChunks[i].tag != NIL_TAG; ++i) {
- if (tag == kChunks[i].tag) return (CHUNK_INDEX)i;
- }
- return IDX_UNKNOWN;
-}
-
-WebPChunkId ChunkGetIdFromTag(uint32_t tag) {
- int i;
- for (i = 0; kChunks[i].tag != NIL_TAG; ++i) {
- if (tag == kChunks[i].tag) return kChunks[i].id;
- }
- return WEBP_CHUNK_UNKNOWN;
-}
-
-uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) {
- return MKFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
-}
-
-CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) {
- const uint32_t tag = ChunkGetTagFromFourCC(fourcc);
- return ChunkGetIndexFromTag(tag);
-}
-
-//------------------------------------------------------------------------------
-// Chunk search methods.
-
-// Returns next chunk in the chunk list with the given tag.
-static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
- while (chunk != NULL && chunk->tag_ != tag) {
- chunk = chunk->next_;
- }
- return chunk;
-}
-
-WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
- uint32_t iter = nth;
- first = ChunkSearchNextInList(first, tag);
- if (first == NULL) return NULL;
-
- while (--iter != 0) {
- WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag);
- if (next_chunk == NULL) break;
- first = next_chunk;
- }
- return ((nth > 0) && (iter > 0)) ? NULL : first;
-}
-
-// Outputs a pointer to 'prev_chunk->next_',
-// where 'prev_chunk' is the pointer to the chunk at position (nth - 1).
-// Returns true if nth chunk was found.
-static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
- WebPChunk*** const location) {
- uint32_t count = 0;
- assert(chunk_list != NULL);
- *location = chunk_list;
-
- while (*chunk_list != NULL) {
- WebPChunk* const cur_chunk = *chunk_list;
- ++count;
- if (count == nth) return 1; // Found.
- chunk_list = &cur_chunk->next_;
- *location = chunk_list;
- }
-
- // *chunk_list is ok to be NULL if adding at last location.
- return (nth == 0 || (count == nth - 1)) ? 1 : 0;
-}
-
-//------------------------------------------------------------------------------
-// Chunk writer methods.
-
-WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
- int copy_data, uint32_t tag) {
- // For internally allocated chunks, always copy data & make it owner of data.
- if (tag == kChunks[IDX_VP8X].tag || tag == kChunks[IDX_ANIM].tag) {
- copy_data = 1;
- }
-
- ChunkRelease(chunk);
-
- if (data != NULL) {
- if (copy_data) { // Copy data.
- if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR;
- chunk->owner_ = 1; // Chunk is owner of data.
- } else { // Don't copy data.
- chunk->data_ = *data;
- }
- }
- chunk->tag_ = tag;
- return WEBP_MUX_OK;
-}
-
-WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
- uint32_t nth) {
- WebPChunk* new_chunk;
-
- if (!ChunkSearchListToSet(chunk_list, nth, &chunk_list)) {
- return WEBP_MUX_NOT_FOUND;
- }
-
- new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk));
- if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
- *new_chunk = *chunk;
- chunk->owner_ = 0;
- new_chunk->next_ = *chunk_list;
- *chunk_list = new_chunk;
- return WEBP_MUX_OK;
-}
-
-//------------------------------------------------------------------------------
-// Chunk deletion method(s).
-
-WebPChunk* ChunkDelete(WebPChunk* const chunk) {
- WebPChunk* const next = ChunkRelease(chunk);
- WebPSafeFree(chunk);
- return next;
-}
-
-void ChunkListDelete(WebPChunk** const chunk_list) {
- while (*chunk_list != NULL) {
- *chunk_list = ChunkDelete(*chunk_list);
- }
-}
-
-//------------------------------------------------------------------------------
-// Chunk serialization methods.
-
-static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) {
- const size_t chunk_size = chunk->data_.size;
- assert(chunk);
- assert(chunk->tag_ != NIL_TAG);
- PutLE32(dst + 0, chunk->tag_);
- PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size);
- assert(chunk_size == (uint32_t)chunk_size);
- memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes, chunk_size);
- if (chunk_size & 1)
- dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding.
- return dst + ChunkDiskSize(chunk);
-}
-
-uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) {
- while (chunk_list != NULL) {
- dst = ChunkEmit(chunk_list, dst);
- chunk_list = chunk_list->next_;
- }
- return dst;
-}
-
-size_t ChunkListDiskSize(const WebPChunk* chunk_list) {
- size_t size = 0;
- while (chunk_list != NULL) {
- size += ChunkDiskSize(chunk_list);
- chunk_list = chunk_list->next_;
- }
- return size;
-}
-
-//------------------------------------------------------------------------------
-// Life of a MuxImage object.
-
-void MuxImageInit(WebPMuxImage* const wpi) {
- assert(wpi);
- memset(wpi, 0, sizeof(*wpi));
-}
-
-WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
- WebPMuxImage* next;
- if (wpi == NULL) return NULL;
- ChunkDelete(wpi->header_);
- ChunkDelete(wpi->alpha_);
- ChunkDelete(wpi->img_);
- ChunkListDelete(&wpi->unknown_);
-
- next = wpi->next_;
- MuxImageInit(wpi);
- return next;
-}
-
-//------------------------------------------------------------------------------
-// MuxImage search methods.
-
-// Get a reference to appropriate chunk list within an image given chunk tag.
-static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi,
- WebPChunkId id) {
- assert(wpi != NULL);
- switch (id) {
- case WEBP_CHUNK_ANMF:
- case WEBP_CHUNK_FRGM: return (WebPChunk**)&wpi->header_;
- case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_;
- case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_;
- default: return NULL;
- }
-}
-
-int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) {
- int count = 0;
- const WebPMuxImage* current;
- for (current = wpi_list; current != NULL; current = current->next_) {
- if (id == WEBP_CHUNK_NIL) {
- ++count; // Special case: count all images.
- } else {
- const WebPChunk* const wpi_chunk = *GetChunkListFromId(current, id);
- if (wpi_chunk != NULL) {
- const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_);
- if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'.
- }
- }
- }
- return count;
-}
-
-// Outputs a pointer to 'prev_wpi->next_',
-// where 'prev_wpi' is the pointer to the image at position (nth - 1).
-// Returns true if nth image was found.
-static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth,
- WebPMuxImage*** const location) {
- uint32_t count = 0;
- assert(wpi_list);
- *location = wpi_list;
-
- if (nth == 0) {
- nth = MuxImageCount(*wpi_list, WEBP_CHUNK_NIL);
- if (nth == 0) return 0; // Not found.
- }
-
- while (*wpi_list != NULL) {
- WebPMuxImage* const cur_wpi = *wpi_list;
- ++count;
- if (count == nth) return 1; // Found.
- wpi_list = &cur_wpi->next_;
- *location = wpi_list;
- }
- return 0; // Not found.
-}
-
-//------------------------------------------------------------------------------
-// MuxImage writer methods.
-
-WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) {
- WebPMuxImage* new_wpi;
-
- while (*wpi_list != NULL) {
- WebPMuxImage* const cur_wpi = *wpi_list;
- if (cur_wpi->next_ == NULL) break;
- wpi_list = &cur_wpi->next_;
- }
-
- new_wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*new_wpi));
- if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR;
- *new_wpi = *wpi;
- new_wpi->next_ = NULL;
-
- if (*wpi_list != NULL) {
- (*wpi_list)->next_ = new_wpi;
- } else {
- *wpi_list = new_wpi;
- }
- return WEBP_MUX_OK;
-}
-
-//------------------------------------------------------------------------------
-// MuxImage deletion methods.
-
-WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) {
- // Delete the components of wpi. If wpi is NULL this is a noop.
- WebPMuxImage* const next = MuxImageRelease(wpi);
- WebPSafeFree(wpi);
- return next;
-}
-
-WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth) {
- assert(wpi_list);
- if (!SearchImageToGetOrDelete(wpi_list, nth, &wpi_list)) {
- return WEBP_MUX_NOT_FOUND;
- }
- *wpi_list = MuxImageDelete(*wpi_list);
- return WEBP_MUX_OK;
-}
-
-//------------------------------------------------------------------------------
-// MuxImage reader methods.
-
-WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth,
- WebPMuxImage** wpi) {
- assert(wpi_list);
- assert(wpi);
- if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth,
- (WebPMuxImage***)&wpi_list)) {
- return WEBP_MUX_NOT_FOUND;
- }
- *wpi = (WebPMuxImage*)*wpi_list;
- return WEBP_MUX_OK;
-}
-
-//------------------------------------------------------------------------------
-// MuxImage serialization methods.
-
-// Size of an image.
-size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
- size_t size = 0;
- if (wpi->header_ != NULL) size += ChunkDiskSize(wpi->header_);
- if (wpi->alpha_ != NULL) size += ChunkDiskSize(wpi->alpha_);
- if (wpi->img_ != NULL) size += ChunkDiskSize(wpi->img_);
- if (wpi->unknown_ != NULL) size += ChunkListDiskSize(wpi->unknown_);
- return size;
-}
-
-// Special case as ANMF/FRGM chunk encapsulates other image chunks.
-static uint8_t* ChunkEmitSpecial(const WebPChunk* const header,
- size_t total_size, uint8_t* dst) {
- const size_t header_size = header->data_.size;
- const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE;
- assert(header->tag_ == kChunks[IDX_ANMF].tag ||
- header->tag_ == kChunks[IDX_FRGM].tag);
- PutLE32(dst + 0, header->tag_);
- PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next);
- assert(header_size == (uint32_t)header_size);
- memcpy(dst + CHUNK_HEADER_SIZE, header->data_.bytes, header_size);
- if (header_size & 1) {
- dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding.
- }
- return dst + ChunkDiskSize(header);
-}
-
-uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
- // Ordering of chunks to be emitted is strictly as follows:
- // 1. ANMF/FRGM chunk (if present).
- // 2. ALPH chunk (if present).
- // 3. VP8/VP8L chunk.
- assert(wpi);
- if (wpi->header_ != NULL) {
- dst = ChunkEmitSpecial(wpi->header_, MuxImageDiskSize(wpi), dst);
- }
- if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst);
- if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst);
- if (wpi->unknown_ != NULL) dst = ChunkListEmit(wpi->unknown_, dst);
- return dst;
-}
-
-//------------------------------------------------------------------------------
-// Helper methods for mux.
-
-int MuxHasAlpha(const WebPMuxImage* images) {
- while (images != NULL) {
- if (images->has_alpha_) return 1;
- images = images->next_;
- }
- return 0;
-}
-
-uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) {
- PutLE32(data + 0, MKFOURCC('R', 'I', 'F', 'F'));
- PutLE32(data + TAG_SIZE, (uint32_t)size - CHUNK_HEADER_SIZE);
- assert(size == (uint32_t)size);
- PutLE32(data + TAG_SIZE + CHUNK_SIZE_BYTES, MKFOURCC('W', 'E', 'B', 'P'));
- return data + RIFF_HEADER_SIZE;
-}
-
-WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) {
- assert(mux != NULL);
- switch (id) {
- case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_;
- case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_;
- case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_;
- case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_;
- case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_;
- default: return (WebPChunk**)&mux->unknown_;
- }
-}
-
-static int IsNotCompatible(int feature, int num_items) {
- return (feature != 0) != (num_items > 0);
-}
-
-#define NO_FLAG 0
-
-// Test basic constraints:
-// retrieval, maximum number of chunks by index (use -1 to skip)
-// and feature incompatibility (use NO_FLAG to skip).
-// On success returns WEBP_MUX_OK and stores the chunk count in *num.
-static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx,
- WebPFeatureFlags feature,
- uint32_t vp8x_flags,
- int max, int* num) {
- const WebPMuxError err =
- WebPMuxNumChunks(mux, kChunks[idx].id, num);
- if (err != WEBP_MUX_OK) return err;
- if (max > -1 && *num > max) return WEBP_MUX_INVALID_ARGUMENT;
- if (feature != NO_FLAG && IsNotCompatible(vp8x_flags & feature, *num)) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- return WEBP_MUX_OK;
-}
-
-WebPMuxError MuxValidate(const WebPMux* const mux) {
- int num_iccp;
- int num_exif;
- int num_xmp;
- int num_anim;
- int num_frames;
- int num_fragments;
- int num_vp8x;
- int num_images;
- int num_alpha;
- uint32_t flags;
- WebPMuxError err;
-
- // Verify mux is not NULL.
- if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
-
- // Verify mux has at least one image.
- if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT;
-
- err = WebPMuxGetFeatures(mux, &flags);
- if (err != WEBP_MUX_OK) return err;
-
- // At most one color profile chunk.
- err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp);
- if (err != WEBP_MUX_OK) return err;
-
- // At most one EXIF metadata.
- err = ValidateChunk(mux, IDX_EXIF, EXIF_FLAG, flags, 1, &num_exif);
- if (err != WEBP_MUX_OK) return err;
-
- // At most one XMP metadata.
- err = ValidateChunk(mux, IDX_XMP, XMP_FLAG, flags, 1, &num_xmp);
- if (err != WEBP_MUX_OK) return err;
-
- // Animation: ANIMATION_FLAG, ANIM chunk and ANMF chunk(s) are consistent.
- // At most one ANIM chunk.
- err = ValidateChunk(mux, IDX_ANIM, NO_FLAG, flags, 1, &num_anim);
- if (err != WEBP_MUX_OK) return err;
- err = ValidateChunk(mux, IDX_ANMF, NO_FLAG, flags, -1, &num_frames);
- if (err != WEBP_MUX_OK) return err;
-
- {
- const int has_animation = !!(flags & ANIMATION_FLAG);
- if (has_animation && (num_anim == 0 || num_frames == 0)) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- if (!has_animation && (num_anim == 1 || num_frames > 0)) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- }
-
- // Fragmentation: FRAGMENTS_FLAG and FRGM chunk(s) are consistent.
- err = ValidateChunk(mux, IDX_FRGM, FRAGMENTS_FLAG, flags, -1, &num_fragments);
- if (err != WEBP_MUX_OK) return err;
-
- // Verify either VP8X chunk is present OR there is only one elem in
- // mux->images_.
- err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x);
- if (err != WEBP_MUX_OK) return err;
- err = ValidateChunk(mux, IDX_VP8, NO_FLAG, flags, -1, &num_images);
- if (err != WEBP_MUX_OK) return err;
- if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT;
-
- // ALPHA_FLAG & alpha chunk(s) are consistent.
- if (MuxHasAlpha(mux->images_)) {
- if (num_vp8x > 0) {
- // VP8X chunk is present, so it should contain ALPHA_FLAG.
- if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT;
- } else {
- // VP8X chunk is not present, so ALPH chunks should NOT be present either.
- err = WebPMuxNumChunks(mux, WEBP_CHUNK_ALPHA, &num_alpha);
- if (err != WEBP_MUX_OK) return err;
- if (num_alpha > 0) return WEBP_MUX_INVALID_ARGUMENT;
- }
- } else { // Mux doesn't need alpha. So, ALPHA_FLAG should NOT be present.
- if (flags & ALPHA_FLAG) return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- // num_fragments & num_images are consistent.
- if (num_fragments > 0 && num_images != num_fragments) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- return WEBP_MUX_OK;
-}
-
-#undef NO_FLAG
-
-//------------------------------------------------------------------------------
-
diff --git a/drivers/webp/mux/muxread.c b/drivers/webp/mux/muxread.c
deleted file mode 100644
index 8957a1e46e..0000000000
--- a/drivers/webp/mux/muxread.c
+++ /dev/null
@@ -1,544 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Read APIs for mux.
-//
-// Authors: Urvang (urvang@google.com)
-// Vikas (vikasa@google.com)
-
-#include <assert.h>
-#include "./muxi.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// Helper method(s).
-
-// Handy MACRO.
-#define SWITCH_ID_LIST(INDEX, LIST) \
- if (idx == (INDEX)) { \
- const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \
- kChunks[(INDEX)].tag); \
- if (chunk) { \
- *data = chunk->data_; \
- return WEBP_MUX_OK; \
- } else { \
- return WEBP_MUX_NOT_FOUND; \
- } \
- }
-
-static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx,
- uint32_t nth, WebPData* const data) {
- assert(mux != NULL);
- assert(!IsWPI(kChunks[idx].id));
- WebPDataInit(data);
-
- SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_);
- SWITCH_ID_LIST(IDX_ICCP, mux->iccp_);
- SWITCH_ID_LIST(IDX_ANIM, mux->anim_);
- SWITCH_ID_LIST(IDX_EXIF, mux->exif_);
- SWITCH_ID_LIST(IDX_XMP, mux->xmp_);
- SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_);
- return WEBP_MUX_NOT_FOUND;
-}
-#undef SWITCH_ID_LIST
-
-// Fill the chunk with the given data (includes chunk header bytes), after some
-// verifications.
-static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
- const uint8_t* data, size_t data_size,
- size_t riff_size, int copy_data) {
- uint32_t chunk_size;
- WebPData chunk_data;
-
- // Sanity checks.
- if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
- chunk_size = GetLE32(data + TAG_SIZE);
-
- {
- const size_t chunk_disk_size = SizeWithPadding(chunk_size);
- if (chunk_disk_size > riff_size) return WEBP_MUX_BAD_DATA;
- if (chunk_disk_size > data_size) return WEBP_MUX_NOT_ENOUGH_DATA;
- }
-
- // Data assignment.
- chunk_data.bytes = data + CHUNK_HEADER_SIZE;
- chunk_data.size = chunk_size;
- return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0));
-}
-
-int MuxImageFinalize(WebPMuxImage* const wpi) {
- const WebPChunk* const img = wpi->img_;
- const WebPData* const image = &img->data_;
- const int is_lossless = (img->tag_ == kChunks[IDX_VP8L].tag);
- int w, h;
- int vp8l_has_alpha = 0;
- const int ok = is_lossless ?
- VP8LGetInfo(image->bytes, image->size, &w, &h, &vp8l_has_alpha) :
- VP8GetInfo(image->bytes, image->size, image->size, &w, &h);
- assert(img != NULL);
- if (ok) {
- // Ignore ALPH chunk accompanying VP8L.
- if (is_lossless && (wpi->alpha_ != NULL)) {
- ChunkDelete(wpi->alpha_);
- wpi->alpha_ = NULL;
- }
- wpi->width_ = w;
- wpi->height_ = h;
- wpi->has_alpha_ = vp8l_has_alpha || (wpi->alpha_ != NULL);
- }
- return ok;
-}
-
-static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
- WebPMuxImage* const wpi) {
- const uint8_t* bytes = chunk->data_.bytes;
- size_t size = chunk->data_.size;
- const uint8_t* const last = bytes + size;
- WebPChunk subchunk;
- size_t subchunk_size;
- ChunkInit(&subchunk);
-
- assert(chunk->tag_ == kChunks[IDX_ANMF].tag ||
- chunk->tag_ == kChunks[IDX_FRGM].tag);
- assert(!wpi->is_partial_);
-
- // ANMF/FRGM.
- {
- const size_t hdr_size = (chunk->tag_ == kChunks[IDX_ANMF].tag) ?
- ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
- const WebPData temp = { bytes, hdr_size };
- // Each of ANMF and FRGM chunk contain a header at the beginning. So, its
- // size should at least be 'hdr_size'.
- if (size < hdr_size) goto Fail;
- ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
- }
- ChunkSetNth(&subchunk, &wpi->header_, 1);
- wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks.
-
- // Rest of the chunks.
- subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE;
- bytes += subchunk_size;
- size -= subchunk_size;
-
- while (bytes != last) {
- ChunkInit(&subchunk);
- if (ChunkVerifyAndAssign(&subchunk, bytes, size, size,
- copy_data) != WEBP_MUX_OK) {
- goto Fail;
- }
- switch (ChunkGetIdFromTag(subchunk.tag_)) {
- case WEBP_CHUNK_ALPHA:
- if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks.
- if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail;
- wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
- break;
- case WEBP_CHUNK_IMAGE:
- if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail;
- if (!MuxImageFinalize(wpi)) goto Fail;
- wpi->is_partial_ = 0; // wpi is completely filled.
- break;
- case WEBP_CHUNK_UNKNOWN:
- if (wpi->is_partial_) goto Fail; // Encountered an unknown chunk
- // before some image chunks.
- if (ChunkSetNth(&subchunk, &wpi->unknown_, 0) != WEBP_MUX_OK) goto Fail;
- break;
- default:
- goto Fail;
- break;
- }
- subchunk_size = ChunkDiskSize(&subchunk);
- bytes += subchunk_size;
- size -= subchunk_size;
- }
- if (wpi->is_partial_) goto Fail;
- return 1;
-
- Fail:
- ChunkRelease(&subchunk);
- return 0;
-}
-
-//------------------------------------------------------------------------------
-// Create a mux object from WebP-RIFF data.
-
-WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
- int version) {
- size_t riff_size;
- uint32_t tag;
- const uint8_t* end;
- WebPMux* mux = NULL;
- WebPMuxImage* wpi = NULL;
- const uint8_t* data;
- size_t size;
- WebPChunk chunk;
- ChunkInit(&chunk);
-
- // Sanity checks.
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) {
- return NULL; // version mismatch
- }
- if (bitstream == NULL) return NULL;
-
- data = bitstream->bytes;
- size = bitstream->size;
-
- if (data == NULL) return NULL;
- if (size < RIFF_HEADER_SIZE) return NULL;
- if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') ||
- GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) {
- return NULL;
- }
-
- mux = WebPMuxNew();
- if (mux == NULL) return NULL;
-
- if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err;
-
- tag = GetLE32(data + RIFF_HEADER_SIZE);
- if (tag != kChunks[IDX_VP8].tag &&
- tag != kChunks[IDX_VP8L].tag &&
- tag != kChunks[IDX_VP8X].tag) {
- goto Err; // First chunk should be VP8, VP8L or VP8X.
- }
-
- riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE));
- if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) {
- goto Err;
- } else {
- if (riff_size < size) { // Redundant data after last chunk.
- size = riff_size; // To make sure we don't read any data beyond mux_size.
- }
- }
-
- end = data + size;
- data += RIFF_HEADER_SIZE;
- size -= RIFF_HEADER_SIZE;
-
- wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*wpi));
- if (wpi == NULL) goto Err;
- MuxImageInit(wpi);
-
- // Loop over chunks.
- while (data != end) {
- size_t data_size;
- WebPChunkId id;
- WebPChunk** chunk_list;
- if (ChunkVerifyAndAssign(&chunk, data, size, riff_size,
- copy_data) != WEBP_MUX_OK) {
- goto Err;
- }
- data_size = ChunkDiskSize(&chunk);
- id = ChunkGetIdFromTag(chunk.tag_);
- switch (id) {
- case WEBP_CHUNK_ALPHA:
- if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks.
- if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err;
- wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
- break;
- case WEBP_CHUNK_IMAGE:
- if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err;
- if (!MuxImageFinalize(wpi)) goto Err;
- wpi->is_partial_ = 0; // wpi is completely filled.
- PushImage:
- // Add this to mux->images_ list.
- if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err;
- MuxImageInit(wpi); // Reset for reading next image.
- break;
- case WEBP_CHUNK_ANMF:
- if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete.
- if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err;
- ChunkRelease(&chunk);
- goto PushImage;
- break;
- default: // A non-image chunk.
- if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
- // getting all chunks of an image.
- chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk.
- if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
- if (id == WEBP_CHUNK_VP8X) { // grab global specs
- mux->canvas_width_ = GetLE24(data + 12) + 1;
- mux->canvas_height_ = GetLE24(data + 15) + 1;
- }
- break;
- }
- data += data_size;
- size -= data_size;
- ChunkInit(&chunk);
- }
-
- // Validate mux if complete.
- if (MuxValidate(mux) != WEBP_MUX_OK) goto Err;
-
- MuxImageDelete(wpi);
- return mux; // All OK;
-
- Err: // Something bad happened.
- ChunkRelease(&chunk);
- MuxImageDelete(wpi);
- WebPMuxDelete(mux);
- return NULL;
-}
-
-//------------------------------------------------------------------------------
-// Get API(s).
-
-// Validates that the given mux has a single image.
-static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) {
- const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE);
- const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF);
- const int num_fragments = MuxImageCount(mux->images_, WEBP_CHUNK_FRGM);
-
- if (num_images == 0) {
- // No images in mux.
- return WEBP_MUX_NOT_FOUND;
- } else if (num_images == 1 && num_frames == 0 && num_fragments == 0) {
- // Valid case (single image).
- return WEBP_MUX_OK;
- } else {
- // Frame/Fragment case OR an invalid mux.
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-}
-
-// Get the canvas width, height and flags after validating that VP8X/VP8/VP8L
-// chunk and canvas size are valid.
-static WebPMuxError MuxGetCanvasInfo(const WebPMux* const mux,
- int* width, int* height, uint32_t* flags) {
- int w, h;
- uint32_t f = 0;
- WebPData data;
- assert(mux != NULL);
-
- // Check if VP8X chunk is present.
- if (MuxGet(mux, IDX_VP8X, 1, &data) == WEBP_MUX_OK) {
- if (data.size < VP8X_CHUNK_SIZE) return WEBP_MUX_BAD_DATA;
- f = GetLE32(data.bytes + 0);
- w = GetLE24(data.bytes + 4) + 1;
- h = GetLE24(data.bytes + 7) + 1;
- } else {
- const WebPMuxImage* const wpi = mux->images_;
- // Grab user-forced canvas size as default.
- w = mux->canvas_width_;
- h = mux->canvas_height_;
- if (w == 0 && h == 0 && ValidateForSingleImage(mux) == WEBP_MUX_OK) {
- // single image and not forced canvas size => use dimension of first frame
- assert(wpi != NULL);
- w = wpi->width_;
- h = wpi->height_;
- }
- if (wpi != NULL) {
- if (wpi->has_alpha_) f |= ALPHA_FLAG;
- }
- }
- if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA;
-
- if (width != NULL) *width = w;
- if (height != NULL) *height = h;
- if (flags != NULL) *flags = f;
- return WEBP_MUX_OK;
-}
-
-WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, int* width, int* height) {
- if (mux == NULL || width == NULL || height == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- return MuxGetCanvasInfo(mux, width, height, NULL);
-}
-
-WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) {
- if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- return MuxGetCanvasInfo(mux, NULL, NULL, flags);
-}
-
-static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width,
- int height, uint32_t flags) {
- const size_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
- assert(width >= 1 && height >= 1);
- assert(width <= MAX_CANVAS_SIZE && height <= MAX_CANVAS_SIZE);
- assert(width * (uint64_t)height < MAX_IMAGE_AREA);
- PutLE32(dst, MKFOURCC('V', 'P', '8', 'X'));
- PutLE32(dst + TAG_SIZE, VP8X_CHUNK_SIZE);
- PutLE32(dst + CHUNK_HEADER_SIZE, flags);
- PutLE24(dst + CHUNK_HEADER_SIZE + 4, width - 1);
- PutLE24(dst + CHUNK_HEADER_SIZE + 7, height - 1);
- return dst + vp8x_size;
-}
-
-// Assemble a single image WebP bitstream from 'wpi'.
-static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
- WebPData* const bitstream) {
- uint8_t* dst;
-
- // Allocate data.
- const int need_vp8x = (wpi->alpha_ != NULL);
- const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0;
- const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0;
- // Note: No need to output ANMF/FRGM chunk for a single image.
- const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size +
- ChunkDiskSize(wpi->img_);
- uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
- if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
-
- // Main RIFF header.
- dst = MuxEmitRiffHeader(data, size);
-
- if (need_vp8x) {
- dst = EmitVP8XChunk(dst, wpi->width_, wpi->height_, ALPHA_FLAG); // VP8X.
- dst = ChunkListEmit(wpi->alpha_, dst); // ALPH.
- }
-
- // Bitstream.
- dst = ChunkListEmit(wpi->img_, dst);
- assert(dst == data + size);
-
- // Output.
- bitstream->bytes = data;
- bitstream->size = size;
- return WEBP_MUX_OK;
-}
-
-WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4],
- WebPData* chunk_data) {
- CHUNK_INDEX idx;
- if (mux == NULL || fourcc == NULL || chunk_data == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- idx = ChunkGetIndexFromFourCC(fourcc);
- if (IsWPI(kChunks[idx].id)) { // An image chunk.
- return WEBP_MUX_INVALID_ARGUMENT;
- } else if (idx != IDX_UNKNOWN) { // A known chunk type.
- return MuxGet(mux, idx, 1, chunk_data);
- } else { // An unknown chunk type.
- const WebPChunk* const chunk =
- ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc));
- if (chunk == NULL) return WEBP_MUX_NOT_FOUND;
- *chunk_data = chunk->data_;
- return WEBP_MUX_OK;
- }
-}
-
-static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi,
- WebPMuxFrameInfo* const info) {
- // Set some defaults for unrelated fields.
- info->x_offset = 0;
- info->y_offset = 0;
- info->duration = 1;
- info->dispose_method = WEBP_MUX_DISPOSE_NONE;
- info->blend_method = WEBP_MUX_BLEND;
- // Extract data for related fields.
- info->id = ChunkGetIdFromTag(wpi->img_->tag_);
- return SynthesizeBitstream(wpi, &info->bitstream);
-}
-
-static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi,
- WebPMuxFrameInfo* const frame) {
- const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag);
- const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM;
- const WebPData* frame_frgm_data;
- if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT;
- assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame().
- // Get frame/fragment chunk.
- frame_frgm_data = &wpi->header_->data_;
- if (frame_frgm_data->size < kChunks[idx].size) return WEBP_MUX_BAD_DATA;
- // Extract info.
- frame->x_offset = 2 * GetLE24(frame_frgm_data->bytes + 0);
- frame->y_offset = 2 * GetLE24(frame_frgm_data->bytes + 3);
- if (is_frame) {
- const uint8_t bits = frame_frgm_data->bytes[15];
- frame->duration = GetLE24(frame_frgm_data->bytes + 12);
- frame->dispose_method =
- (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
- frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
- } else { // Defaults for unused values.
- frame->duration = 1;
- frame->dispose_method = WEBP_MUX_DISPOSE_NONE;
- frame->blend_method = WEBP_MUX_BLEND;
- }
- frame->id = ChunkGetIdFromTag(wpi->header_->tag_);
- return SynthesizeBitstream(wpi, &frame->bitstream);
-}
-
-WebPMuxError WebPMuxGetFrame(
- const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) {
- WebPMuxError err;
- WebPMuxImage* wpi;
-
- // Sanity checks.
- if (mux == NULL || frame == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- // Get the nth WebPMuxImage.
- err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi);
- if (err != WEBP_MUX_OK) return err;
-
- // Get frame info.
- if (wpi->header_ == NULL) {
- return MuxGetImageInternal(wpi, frame);
- } else {
- return MuxGetFrameFragmentInternal(wpi, frame);
- }
-}
-
-WebPMuxError WebPMuxGetAnimationParams(const WebPMux* mux,
- WebPMuxAnimParams* params) {
- WebPData anim;
- WebPMuxError err;
-
- if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT;
-
- err = MuxGet(mux, IDX_ANIM, 1, &anim);
- if (err != WEBP_MUX_OK) return err;
- if (anim.size < kChunks[WEBP_CHUNK_ANIM].size) return WEBP_MUX_BAD_DATA;
- params->bgcolor = GetLE32(anim.bytes);
- params->loop_count = GetLE16(anim.bytes + 4);
-
- return WEBP_MUX_OK;
-}
-
-// Get chunk index from chunk id. Returns IDX_NIL if not found.
-static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) {
- int i;
- for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) {
- if (id == kChunks[i].id) return (CHUNK_INDEX)i;
- }
- return IDX_NIL;
-}
-
-// Count number of chunks matching 'tag' in the 'chunk_list'.
-// If tag == NIL_TAG, any tag will be matched.
-static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) {
- int count = 0;
- const WebPChunk* current;
- for (current = chunk_list; current != NULL; current = current->next_) {
- if (tag == NIL_TAG || current->tag_ == tag) {
- count++; // Count chunks whose tags match.
- }
- }
- return count;
-}
-
-WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
- WebPChunkId id, int* num_elements) {
- if (mux == NULL || num_elements == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
- if (IsWPI(id)) {
- *num_elements = MuxImageCount(mux->images_, id);
- } else {
- WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id);
- const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
- *num_elements = CountChunks(*chunk_list, kChunks[idx].tag);
- }
-
- return WEBP_MUX_OK;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/mux_types.h b/drivers/webp/mux_types.h
deleted file mode 100644
index c94043a3c0..0000000000
--- a/drivers/webp/mux_types.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Data-types common to the mux and demux libraries.
-//
-// Author: Urvang (urvang@google.com)
-
-#ifndef WEBP_WEBP_MUX_TYPES_H_
-#define WEBP_WEBP_MUX_TYPES_H_
-
-#include <stdlib.h> // free()
-#include <string.h> // memset()
-#include "./types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Note: forward declaring enumerations is not allowed in (strict) C and C++,
-// the types are left here for reference.
-// typedef enum WebPFeatureFlags WebPFeatureFlags;
-// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose;
-// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend;
-typedef struct WebPData WebPData;
-
-// VP8X Feature Flags.
-typedef enum WebPFeatureFlags {
- FRAGMENTS_FLAG = 0x00000001,
- ANIMATION_FLAG = 0x00000002,
- XMP_FLAG = 0x00000004,
- EXIF_FLAG = 0x00000008,
- ALPHA_FLAG = 0x00000010,
- ICCP_FLAG = 0x00000020
-} WebPFeatureFlags;
-
-// Dispose method (animation only). Indicates how the area used by the current
-// frame is to be treated before rendering the next frame on the canvas.
-typedef enum WebPMuxAnimDispose {
- WEBP_MUX_DISPOSE_NONE, // Do not dispose.
- WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color.
-} WebPMuxAnimDispose;
-
-// Blend operation (animation only). Indicates how transparent pixels of the
-// current frame are blended with those of the previous canvas.
-typedef enum WebPMuxAnimBlend {
- WEBP_MUX_BLEND, // Blend.
- WEBP_MUX_NO_BLEND // Do not blend.
-} WebPMuxAnimBlend;
-
-// Data type used to describe 'raw' data, e.g., chunk data
-// (ICC profile, metadata) and WebP compressed image data.
-struct WebPData {
- const uint8_t* bytes;
- size_t size;
-};
-
-// Initializes the contents of the 'webp_data' object with default values.
-static WEBP_INLINE void WebPDataInit(WebPData* webp_data) {
- if (webp_data != NULL) {
- memset(webp_data, 0, sizeof(*webp_data));
- }
-}
-
-// Clears the contents of the 'webp_data' object by calling free(). Does not
-// deallocate the object itself.
-static WEBP_INLINE void WebPDataClear(WebPData* webp_data) {
- if (webp_data != NULL) {
- free((void*)webp_data->bytes);
- WebPDataInit(webp_data);
- }
-}
-
-// Allocates necessary storage for 'dst' and copies the contents of 'src'.
-// Returns true on success.
-static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
- if (src == NULL || dst == NULL) return 0;
- WebPDataInit(dst);
- if (src->bytes != NULL && src->size != 0) {
- dst->bytes = (uint8_t*)malloc(src->size);
- if (dst->bytes == NULL) return 0;
- memcpy((void*)dst->bytes, src->bytes, src->size);
- dst->size = src->size;
- }
- return 1;
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_WEBP_MUX_TYPES_H_ */
diff --git a/drivers/webp/types.h b/drivers/webp/types.h
deleted file mode 100644
index 98fff35a11..0000000000
--- a/drivers/webp/types.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Common types
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_WEBP_TYPES_H_
-#define WEBP_WEBP_TYPES_H_
-
-#include <stddef.h> // for size_t
-
-#ifndef _MSC_VER
-#include <inttypes.h>
-#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \
- (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
-#define WEBP_INLINE inline
-#else
-#define WEBP_INLINE
-#endif
-#else
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef signed short int16_t;
-typedef unsigned short uint16_t;
-typedef signed int int32_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long int uint64_t;
-typedef long long int int64_t;
-#define WEBP_INLINE __forceinline
-#endif /* _MSC_VER */
-
-#ifndef WEBP_EXTERN
-// This explicitly marks library functions and allows for changing the
-// signature for e.g., Windows DLL builds.
-# if defined(__GNUC__) && __GNUC__ >= 4
-# define WEBP_EXTERN(type) extern __attribute__ ((visibility ("default"))) type
-# else
-# define WEBP_EXTERN(type) extern type
-# endif /* __GNUC__ >= 4 */
-#endif /* WEBP_EXTERN */
-
-// Macro to check ABI compatibility (same major revision number)
-#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
-
-#endif /* WEBP_WEBP_TYPES_H_ */
diff --git a/drivers/webp/utils/bit_reader.c b/drivers/webp/utils/bit_reader.c
deleted file mode 100644
index 13c6cf316e..0000000000
--- a/drivers/webp/utils/bit_reader.c
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Boolean decoder non-inlined methods
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifdef HAVE_CONFIG_H
-#include "webp/config.h"
-#endif
-
-#include "./bit_reader_inl.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// VP8BitReader
-
-void VP8BitReaderSetBuffer(VP8BitReader* const br,
- const uint8_t* const start,
- size_t size) {
- br->buf_ = start;
- br->buf_end_ = start + size;
- br->buf_max_ =
- (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1
- : start;
-}
-
-void VP8InitBitReader(VP8BitReader* const br,
- const uint8_t* const start, size_t size) {
- assert(br != NULL);
- assert(start != NULL);
- assert(size < (1u << 31)); // limit ensured by format and upstream checks
- br->range_ = 255 - 1;
- br->value_ = 0;
- br->bits_ = -8; // to load the very first 8bits
- br->eof_ = 0;
- VP8BitReaderSetBuffer(br, start, size);
-#ifdef JAVASCRIPT_ENABLED // html5 required aligned reads
- while(((uintptr_t)br->buf_ & 1) != 0 && !br->eof_)
- VP8LoadFinalBytes(br);
-#else
- VP8LoadNewBytes(br);
-#endif
-}
-
-void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {
- if (br->buf_ != NULL) {
- br->buf_ += offset;
- br->buf_end_ += offset;
- br->buf_max_ += offset;
- }
-}
-
-const uint8_t kVP8Log2Range[128] = {
- 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0
-};
-
-// range = ((range - 1) << kVP8Log2Range[range]) + 1
-const uint8_t kVP8NewRange[128] = {
- 127, 127, 191, 127, 159, 191, 223, 127,
- 143, 159, 175, 191, 207, 223, 239, 127,
- 135, 143, 151, 159, 167, 175, 183, 191,
- 199, 207, 215, 223, 231, 239, 247, 127,
- 131, 135, 139, 143, 147, 151, 155, 159,
- 163, 167, 171, 175, 179, 183, 187, 191,
- 195, 199, 203, 207, 211, 215, 219, 223,
- 227, 231, 235, 239, 243, 247, 251, 127,
- 129, 131, 133, 135, 137, 139, 141, 143,
- 145, 147, 149, 151, 153, 155, 157, 159,
- 161, 163, 165, 167, 169, 171, 173, 175,
- 177, 179, 181, 183, 185, 187, 189, 191,
- 193, 195, 197, 199, 201, 203, 205, 207,
- 209, 211, 213, 215, 217, 219, 221, 223,
- 225, 227, 229, 231, 233, 235, 237, 239,
- 241, 243, 245, 247, 249, 251, 253, 127
-};
-
-void VP8LoadFinalBytes(VP8BitReader* const br) {
- assert(br != NULL && br->buf_ != NULL);
- // Only read 8bits at a time
- if (br->buf_ < br->buf_end_) {
- br->bits_ += 8;
- br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8);
- } else if (!br->eof_) {
- br->value_ <<= 8;
- br->bits_ += 8;
- br->eof_ = 1;
- } else {
- br->bits_ = 0; // This is to avoid undefined behaviour with shifts.
- }
-}
-
-//------------------------------------------------------------------------------
-// Higher-level calls
-
-uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
- uint32_t v = 0;
- while (bits-- > 0) {
- v |= VP8GetBit(br, 0x80) << bits;
- }
- return v;
-}
-
-int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
- const int value = VP8GetValue(br, bits);
- return VP8Get(br) ? -value : value;
-}
-
-//------------------------------------------------------------------------------
-// VP8LBitReader
-
-#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits.
-
-#if defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
- defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64__) || defined(_M_X64)
-#define VP8L_USE_FAST_LOAD
-#endif
-
-static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = {
- 0,
- 0x000001, 0x000003, 0x000007, 0x00000f,
- 0x00001f, 0x00003f, 0x00007f, 0x0000ff,
- 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff,
- 0x001fff, 0x003fff, 0x007fff, 0x00ffff,
- 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff,
- 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff
-};
-
-void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start,
- size_t length) {
- size_t i;
- vp8l_val_t value = 0;
- assert(br != NULL);
- assert(start != NULL);
- assert(length < 0xfffffff8u); // can't happen with a RIFF chunk.
-
- br->len_ = length;
- br->val_ = 0;
- br->bit_pos_ = 0;
- br->eos_ = 0;
-
- if (length > sizeof(br->val_)) {
- length = sizeof(br->val_);
- }
- for (i = 0; i < length; ++i) {
- value |= (vp8l_val_t)start[i] << (8 * i);
- }
- br->val_ = value;
- br->pos_ = length;
- br->buf_ = start;
-}
-
-void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
- const uint8_t* const buf, size_t len) {
- assert(br != NULL);
- assert(buf != NULL);
- assert(len < 0xfffffff8u); // can't happen with a RIFF chunk.
- br->buf_ = buf;
- br->len_ = len;
- // pos_ > len_ should be considered a param error.
- br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br);
-}
-
-static void VP8LSetEndOfStream(VP8LBitReader* const br) {
- br->eos_ = 1;
- br->bit_pos_ = 0; // To avoid undefined behaviour with shifts.
-}
-
-// If not at EOS, reload up to VP8L_LBITS byte-by-byte
-static void ShiftBytes(VP8LBitReader* const br) {
- while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
- br->val_ >>= 8;
- br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);
- ++br->pos_;
- br->bit_pos_ -= 8;
- }
- if (VP8LIsEndOfStream(br)) {
- VP8LSetEndOfStream(br);
- }
-}
-
-void VP8LDoFillBitWindow(VP8LBitReader* const br) {
- assert(br->bit_pos_ >= VP8L_WBITS);
-#if defined(VP8L_USE_FAST_LOAD)
- if (br->pos_ + sizeof(br->val_) < br->len_) {
- br->val_ >>= VP8L_WBITS;
- br->bit_pos_ -= VP8L_WBITS;
- br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) <<
- (VP8L_LBITS - VP8L_WBITS);
- br->pos_ += VP8L_LOG8_WBITS;
- return;
- }
-#endif
- ShiftBytes(br); // Slow path.
-}
-
-uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
- assert(n_bits >= 0);
- // Flag an error if end_of_stream or n_bits is more than allowed limit.
- if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) {
- const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits];
- const int new_bits = br->bit_pos_ + n_bits;
- br->bit_pos_ = new_bits;
- ShiftBytes(br);
- return val;
- } else {
- VP8LSetEndOfStream(br);
- return 0;
- }
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/utils/bit_reader.h b/drivers/webp/utils/bit_reader.h
deleted file mode 100644
index c2dcc711c0..0000000000
--- a/drivers/webp/utils/bit_reader.h
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Boolean decoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-// Vikas Arora (vikaas.arora@gmail.com)
-
-#ifndef WEBP_UTILS_BIT_READER_H_
-#define WEBP_UTILS_BIT_READER_H_
-
-#include <assert.h>
-#ifdef _MSC_VER
-#include <stdlib.h> // _byteswap_ulong
-#endif
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// The Boolean decoder needs to maintain infinite precision on the value_ field.
-// However, since range_ is only 8bit, we only need an active window of 8 bits
-// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls
-// below 128, range_ is updated, and fresh bits read from the bitstream are
-// brought in as LSB. To avoid reading the fresh bits one by one (slow), we
-// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a
-// natural register (with type bit_t). To fetch BITS bits from bitstream we
-// use a type lbit_t.
-//
-// BITS can be any multiple of 8 from 8 to 56 (inclusive).
-// Pick values that fit natural register size.
-
-#ifdef JAVASCRIPT_ENABLED
-
-#define BITS 16
-
-#else
-
-#if defined(__i386__) || defined(_M_IX86) // x86 32bit
-#define BITS 24
-#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit
-#define BITS 56
-#elif defined(__arm__) || defined(_M_ARM) // ARM
-#define BITS 24
-#elif defined(__aarch64__) // ARM 64bit
-#define BITS 56
-#elif defined(__mips__) // MIPS
-#define BITS 24
-#else // reasonable default
-#define BITS 24
-#endif
-
-#endif
-
-//------------------------------------------------------------------------------
-// Derived types and constants:
-// bit_t = natural register type for storing 'value_' (which is BITS+8 bits)
-// range_t = register for 'range_' (which is 8bits only)
-
-#if (BITS > 24)
-typedef uint64_t bit_t;
-#else
-typedef uint32_t bit_t;
-#endif
-
-typedef uint32_t range_t;
-
-//------------------------------------------------------------------------------
-// Bitreader
-
-typedef struct VP8BitReader VP8BitReader;
-struct VP8BitReader {
- // boolean decoder (keep the field ordering as is!)
- bit_t value_; // current value
- range_t range_; // current range minus 1. In [127, 254] interval.
- int bits_; // number of valid bits left
- // read buffer
- const uint8_t* buf_; // next byte to be read
- const uint8_t* buf_end_; // end of read buffer
- const uint8_t* buf_max_; // max packed-read position on buffer
- int eof_; // true if input is exhausted
-};
-
-// Initialize the bit reader and the boolean decoder.
-void VP8InitBitReader(VP8BitReader* const br,
- const uint8_t* const start, size_t size);
-// Sets the working read buffer.
-void VP8BitReaderSetBuffer(VP8BitReader* const br,
- const uint8_t* const start, size_t size);
-
-// Update internal pointers to displace the byte buffer by the
-// relative offset 'offset'.
-void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset);
-
-// return the next value made of 'num_bits' bits
-uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
-static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) {
- return VP8GetValue(br, 1);
-}
-
-// return the next value with sign-extension.
-int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
-
-// bit_reader_inl.h will implement the following methods:
-// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob)
-// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v)
-// and should be included by the .c files that actually need them.
-// This is to avoid recompiling the whole library whenever this file is touched,
-// and also allowing platform-specific ad-hoc hacks.
-
-// -----------------------------------------------------------------------------
-// Bitreader for lossless format
-
-// maximum number of bits (inclusive) the bit-reader can handle:
-#define VP8L_MAX_NUM_BIT_READ 24
-
-#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t).
-#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow.
-
-typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit.
-
-typedef struct {
- vp8l_val_t val_; // pre-fetched bits
- const uint8_t* buf_; // input byte buffer
- size_t len_; // buffer length
- size_t pos_; // byte position in buf_
- int bit_pos_; // current bit-reading position in val_
- int eos_; // true if a bit was read past the end of buffer
-} VP8LBitReader;
-
-void VP8LInitBitReader(VP8LBitReader* const br,
- const uint8_t* const start,
- size_t length);
-
-// Sets a new data buffer.
-void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
- const uint8_t* const buffer, size_t length);
-
-// Reads the specified number of bits from read buffer.
-// Flags an error in case end_of_stream or n_bits is more than the allowed limit
-// of VP8L_MAX_NUM_BIT_READ (inclusive).
-// Flags eos_ if this read attempt is going to cross the read buffer.
-uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits);
-
-// Return the prefetched bits, so they can be looked up.
-static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) {
- return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1)));
-}
-
-// Returns true if there was an attempt at reading bit past the end of
-// the buffer. Doesn't set br->eos_ flag.
-static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) {
- assert(br->pos_ <= br->len_);
- return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS));
-}
-
-// For jumping over a number of bits in the bit stream when accessed with
-// VP8LPrefetchBits and VP8LFillBitWindow.
-static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) {
- br->bit_pos_ = val;
- br->eos_ = VP8LIsEndOfStream(br);
-}
-
-// Advances the read buffer by 4 bytes to make room for reading next 32 bits.
-// Speed critical, but infrequent part of the code can be non-inlined.
-extern void VP8LDoFillBitWindow(VP8LBitReader* const br);
-static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
- if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br);
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_BIT_READER_H_ */
diff --git a/drivers/webp/utils/bit_reader_inl.h b/drivers/webp/utils/bit_reader_inl.h
deleted file mode 100644
index 21faf14d83..0000000000
--- a/drivers/webp/utils/bit_reader_inl.h
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Specific inlined methods for boolean decoder [VP8GetBit() ...]
-// This file should be included by the .c sources that actually need to call
-// these methods.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_UTILS_BIT_READER_INL_H_
-#define WEBP_UTILS_BIT_READER_INL_H_
-
-#ifdef HAVE_CONFIG_H
-#include "webp/config.h"
-#endif
-
-#ifdef WEBP_FORCE_ALIGNED
-#include <string.h> // memcpy
-#endif
-
-#include "../dsp/dsp.h"
-#include "./bit_reader.h"
-#include "./endian_inl.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Derived type lbit_t = natural type for memory I/O
-
-#if (BITS > 32)
-typedef uint64_t lbit_t;
-#elif (BITS > 16)
-typedef uint32_t lbit_t;
-#elif (BITS > 8)
-typedef uint16_t lbit_t;
-#else
-typedef uint8_t lbit_t;
-#endif
-
-extern const uint8_t kVP8Log2Range[128];
-extern const uint8_t kVP8NewRange[128];
-
-// special case for the tail byte-reading
-void VP8LoadFinalBytes(VP8BitReader* const br);
-
-//------------------------------------------------------------------------------
-// Inlined critical functions
-
-// makes sure br->value_ has at least BITS bits worth of data
-static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE
-void VP8LoadNewBytes(VP8BitReader* const br) {
- assert(br != NULL && br->buf_ != NULL);
- // Read 'BITS' bits at a time if possible.
- if (br->buf_ < br->buf_max_) {
- // convert memory type to register type (with some zero'ing!)
- bit_t bits;
-#if defined(WEBP_FORCE_ALIGNED)
- lbit_t in_bits;
- memcpy(&in_bits, br->buf_, sizeof(in_bits));
-#elif defined(WEBP_USE_MIPS32)
- // This is needed because of un-aligned read.
- lbit_t in_bits;
- lbit_t* p_buf_ = (lbit_t*)br->buf_;
- __asm__ volatile(
- ".set push \n\t"
- ".set at \n\t"
- ".set macro \n\t"
- "ulw %[in_bits], 0(%[p_buf_]) \n\t"
- ".set pop \n\t"
- : [in_bits]"=r"(in_bits)
- : [p_buf_]"r"(p_buf_)
- : "memory", "at"
- );
-#else
- const lbit_t in_bits = *(const lbit_t*)br->buf_;
-#endif
- br->buf_ += BITS >> 3;
-#if !defined(WORDS_BIGENDIAN)
-#if (BITS > 32)
- bits = BSwap64(in_bits);
- bits >>= 64 - BITS;
-#elif (BITS >= 24)
- bits = BSwap32(in_bits);
- bits >>= (32 - BITS);
-#elif (BITS == 16)
- bits = BSwap16(in_bits);
-#else // BITS == 8
- bits = (bit_t)in_bits;
-#endif // BITS > 32
-#else // WORDS_BIGENDIAN
- bits = (bit_t)in_bits;
- if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS);
-#endif
- br->value_ = bits | (br->value_ << BITS);
- br->bits_ += BITS;
- } else {
- VP8LoadFinalBytes(br); // no need to be inlined
- }
-}
-
-// Read a bit with proba 'prob'. Speed-critical function!
-static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
- // Don't move this declaration! It makes a big speed difference to store
- // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't
- // alter br->range_ value.
- range_t range = br->range_;
- if (br->bits_ < 0) {
- VP8LoadNewBytes(br);
- }
- {
- const int pos = br->bits_;
- const range_t split = (range * prob) >> 8;
- const range_t value = (range_t)(br->value_ >> pos);
-#if defined(__arm__) || defined(_M_ARM) // ARM-specific
- const int bit = ((int)(split - value) >> 31) & 1;
- if (value > split) {
- range -= split + 1;
- br->value_ -= (bit_t)(split + 1) << pos;
- } else {
- range = split;
- }
-#else // faster version on x86
- int bit; // Don't use 'const int bit = (value > split);", it's slower.
- if (value > split) {
- range -= split + 1;
- br->value_ -= (bit_t)(split + 1) << pos;
- bit = 1;
- } else {
- range = split;
- bit = 0;
- }
-#endif
- if (range <= (range_t)0x7e) {
- const int shift = kVP8Log2Range[range];
- range = kVP8NewRange[range];
- br->bits_ -= shift;
- }
- br->range_ = range;
- return bit;
- }
-}
-
-// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here)
-static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
- if (br->bits_ < 0) {
- VP8LoadNewBytes(br);
- }
- {
- const int pos = br->bits_;
- const range_t split = br->range_ >> 1;
- const range_t value = (range_t)(br->value_ >> pos);
- const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0
- br->bits_ -= 1;
- br->range_ += mask;
- br->range_ |= 1;
- br->value_ -= (bit_t)((split + 1) & mask) << pos;
- return (v ^ mask) - mask;
- }
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // WEBP_UTILS_BIT_READER_INL_H_
diff --git a/drivers/webp/utils/bit_writer.c b/drivers/webp/utils/bit_writer.c
deleted file mode 100644
index 064428691b..0000000000
--- a/drivers/webp/utils/bit_writer.c
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Bit writing and boolean coder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-// Vikas Arora (vikaas.arora@gmail.com)
-
-#include <assert.h>
-#include <string.h> // for memcpy()
-#include <stdlib.h>
-
-#include "./bit_writer.h"
-#include "./endian_inl.h"
-#include "./utils.h"
-
-//------------------------------------------------------------------------------
-// VP8BitWriter
-
-static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) {
- uint8_t* new_buf;
- size_t new_size;
- const uint64_t needed_size_64b = (uint64_t)bw->pos_ + extra_size;
- const size_t needed_size = (size_t)needed_size_64b;
- if (needed_size_64b != needed_size) {
- bw->error_ = 1;
- return 0;
- }
- if (needed_size <= bw->max_pos_) return 1;
- // If the following line wraps over 32bit, the test just after will catch it.
- new_size = 2 * bw->max_pos_;
- if (new_size < needed_size) new_size = needed_size;
- if (new_size < 1024) new_size = 1024;
- new_buf = (uint8_t*)WebPSafeMalloc(1ULL, new_size);
- if (new_buf == NULL) {
- bw->error_ = 1;
- return 0;
- }
- if (bw->pos_ > 0) {
- assert(bw->buf_ != NULL);
- memcpy(new_buf, bw->buf_, bw->pos_);
- }
- WebPSafeFree(bw->buf_);
- bw->buf_ = new_buf;
- bw->max_pos_ = new_size;
- return 1;
-}
-
-static void Flush(VP8BitWriter* const bw) {
- const int s = 8 + bw->nb_bits_;
- const int32_t bits = bw->value_ >> s;
- assert(bw->nb_bits_ >= 0);
- bw->value_ -= bits << s;
- bw->nb_bits_ -= 8;
- if ((bits & 0xff) != 0xff) {
- size_t pos = bw->pos_;
- if (!BitWriterResize(bw, bw->run_ + 1)) {
- return;
- }
- if (bits & 0x100) { // overflow -> propagate carry over pending 0xff's
- if (pos > 0) bw->buf_[pos - 1]++;
- }
- if (bw->run_ > 0) {
- const int value = (bits & 0x100) ? 0x00 : 0xff;
- for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value;
- }
- bw->buf_[pos++] = bits;
- bw->pos_ = pos;
- } else {
- bw->run_++; // delay writing of bytes 0xff, pending eventual carry.
- }
-}
-
-//------------------------------------------------------------------------------
-// renormalization
-
-static const uint8_t kNorm[128] = { // renorm_sizes[i] = 8 - log2(i)
- 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0
-};
-
-// range = ((range + 1) << kVP8Log2Range[range]) - 1
-static const uint8_t kNewRange[128] = {
- 127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239,
- 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239,
- 247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179,
- 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239,
- 243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149,
- 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179,
- 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209,
- 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239,
- 241, 243, 245, 247, 249, 251, 253, 127
-};
-
-int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) {
- const int split = (bw->range_ * prob) >> 8;
- if (bit) {
- bw->value_ += split + 1;
- bw->range_ -= split + 1;
- } else {
- bw->range_ = split;
- }
- if (bw->range_ < 127) { // emit 'shift' bits out and renormalize
- const int shift = kNorm[bw->range_];
- bw->range_ = kNewRange[bw->range_];
- bw->value_ <<= shift;
- bw->nb_bits_ += shift;
- if (bw->nb_bits_ > 0) Flush(bw);
- }
- return bit;
-}
-
-int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
- const int split = bw->range_ >> 1;
- if (bit) {
- bw->value_ += split + 1;
- bw->range_ -= split + 1;
- } else {
- bw->range_ = split;
- }
- if (bw->range_ < 127) {
- bw->range_ = kNewRange[bw->range_];
- bw->value_ <<= 1;
- bw->nb_bits_ += 1;
- if (bw->nb_bits_ > 0) Flush(bw);
- }
- return bit;
-}
-
-void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) {
- uint32_t mask;
- assert(nb_bits > 0 && nb_bits < 32);
- for (mask = 1u << (nb_bits - 1); mask; mask >>= 1)
- VP8PutBitUniform(bw, value & mask);
-}
-
-void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) {
- if (!VP8PutBitUniform(bw, value != 0))
- return;
- if (value < 0) {
- VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1);
- } else {
- VP8PutBits(bw, value << 1, nb_bits + 1);
- }
-}
-
-//------------------------------------------------------------------------------
-
-int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) {
- bw->range_ = 255 - 1;
- bw->value_ = 0;
- bw->run_ = 0;
- bw->nb_bits_ = -8;
- bw->pos_ = 0;
- bw->max_pos_ = 0;
- bw->error_ = 0;
- bw->buf_ = NULL;
- return (expected_size > 0) ? BitWriterResize(bw, expected_size) : 1;
-}
-
-uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) {
- VP8PutBits(bw, 0, 9 - bw->nb_bits_);
- bw->nb_bits_ = 0; // pad with zeroes
- Flush(bw);
- return bw->buf_;
-}
-
-int VP8BitWriterAppend(VP8BitWriter* const bw,
- const uint8_t* data, size_t size) {
- assert(data != NULL);
- if (bw->nb_bits_ != -8) return 0; // Flush() must have been called
- if (!BitWriterResize(bw, size)) return 0;
- memcpy(bw->buf_ + bw->pos_, data, size);
- bw->pos_ += size;
- return 1;
-}
-
-void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
- if (bw != NULL) {
- WebPSafeFree(bw->buf_);
- memset(bw, 0, sizeof(*bw));
- }
-}
-
-//------------------------------------------------------------------------------
-// VP8LBitWriter
-
-// This is the minimum amount of size the memory buffer is guaranteed to grow
-// when extra space is needed.
-#define MIN_EXTRA_SIZE (32768ULL)
-
-// Returns 1 on success.
-static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) {
- uint8_t* allocated_buf;
- size_t allocated_size;
- const size_t max_bytes = bw->end_ - bw->buf_;
- const size_t current_size = bw->cur_ - bw->buf_;
- const uint64_t size_required_64b = (uint64_t)current_size + extra_size;
- const size_t size_required = (size_t)size_required_64b;
- if (size_required != size_required_64b) {
- bw->error_ = 1;
- return 0;
- }
- if (max_bytes > 0 && size_required <= max_bytes) return 1;
- allocated_size = (3 * max_bytes) >> 1;
- if (allocated_size < size_required) allocated_size = size_required;
- // make allocated size multiple of 1k
- allocated_size = (((allocated_size >> 10) + 1) << 10);
- allocated_buf = (uint8_t*)WebPSafeMalloc(1ULL, allocated_size);
- if (allocated_buf == NULL) {
- bw->error_ = 1;
- return 0;
- }
- if (current_size > 0) {
- memcpy(allocated_buf, bw->buf_, current_size);
- }
- WebPSafeFree(bw->buf_);
- bw->buf_ = allocated_buf;
- bw->cur_ = bw->buf_ + current_size;
- bw->end_ = bw->buf_ + allocated_size;
- return 1;
-}
-
-int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) {
- memset(bw, 0, sizeof(*bw));
- return VP8LBitWriterResize(bw, expected_size);
-}
-
-void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) {
- if (bw != NULL) {
- WebPSafeFree(bw->buf_);
- memset(bw, 0, sizeof(*bw));
- }
-}
-
-void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) {
- // If needed, make some room by flushing some bits out.
- if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) {
- const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE;
- if (extra_size != (size_t)extra_size ||
- !VP8LBitWriterResize(bw, (size_t)extra_size)) {
- bw->cur_ = bw->buf_;
- bw->error_ = 1;
- return;
- }
- }
- *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)bw->bits_);
- bw->cur_ += VP8L_WRITER_BYTES;
- bw->bits_ >>= VP8L_WRITER_BITS;
- bw->used_ -= VP8L_WRITER_BITS;
-}
-
-void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) {
- assert(n_bits <= 32);
- // That's the max we can handle:
- assert(sizeof(vp8l_wtype_t) == 2);
- if (n_bits > 0) {
- vp8l_atype_t lbits = bw->bits_;
- int used = bw->used_;
- // Special case of overflow handling for 32bit accumulator (2-steps flush).
-#if VP8L_WRITER_BITS == 16
- if (used + n_bits >= VP8L_WRITER_MAX_BITS) {
- // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below.
- const int shift = VP8L_WRITER_MAX_BITS - used;
- lbits |= (vp8l_atype_t)bits << used;
- used = VP8L_WRITER_MAX_BITS;
- n_bits -= shift;
- bits >>= shift;
- assert(n_bits <= VP8L_WRITER_MAX_BITS);
- }
-#endif
- // If needed, make some room by flushing some bits out.
- while (used >= VP8L_WRITER_BITS) {
- if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) {
- const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE;
- if (extra_size != (size_t)extra_size ||
- !VP8LBitWriterResize(bw, (size_t)extra_size)) {
- bw->cur_ = bw->buf_;
- bw->error_ = 1;
- return;
- }
- }
- *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)lbits);
- bw->cur_ += VP8L_WRITER_BYTES;
- lbits >>= VP8L_WRITER_BITS;
- used -= VP8L_WRITER_BITS;
- }
- bw->bits_ = lbits | ((vp8l_atype_t)bits << used);
- bw->used_ = used + n_bits;
- }
-}
-
-uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) {
- // flush leftover bits
- if (VP8LBitWriterResize(bw, (bw->used_ + 7) >> 3)) {
- while (bw->used_ > 0) {
- *bw->cur_++ = (uint8_t)bw->bits_;
- bw->bits_ >>= 8;
- bw->used_ -= 8;
- }
- bw->used_ = 0;
- }
- return bw->buf_;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/utils/bit_writer.h b/drivers/webp/utils/bit_writer.h
deleted file mode 100644
index 867a5ee055..0000000000
--- a/drivers/webp/utils/bit_writer.h
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Bit writing and boolean coder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_UTILS_BIT_WRITER_H_
-#define WEBP_UTILS_BIT_WRITER_H_
-
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Bit-writing
-
-typedef struct VP8BitWriter VP8BitWriter;
-struct VP8BitWriter {
- int32_t range_; // range-1
- int32_t value_;
- int run_; // number of outstanding bits
- int nb_bits_; // number of pending bits
- uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned.
- size_t pos_;
- size_t max_pos_;
- int error_; // true in case of error
-};
-
-// Initialize the object. Allocates some initial memory based on expected_size.
-int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size);
-// Finalize the bitstream coding. Returns a pointer to the internal buffer.
-uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw);
-// Release any pending memory and zeroes the object. Not a mandatory call.
-// Only useful in case of error, when the internal buffer hasn't been grabbed!
-void VP8BitWriterWipeOut(VP8BitWriter* const bw);
-
-int VP8PutBit(VP8BitWriter* const bw, int bit, int prob);
-int VP8PutBitUniform(VP8BitWriter* const bw, int bit);
-void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits);
-void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits);
-
-// Appends some bytes to the internal buffer. Data is copied.
-int VP8BitWriterAppend(VP8BitWriter* const bw,
- const uint8_t* data, size_t size);
-
-// return approximate write position (in bits)
-static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
- return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_;
-}
-
-// Returns a pointer to the internal buffer.
-static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) {
- return bw->buf_;
-}
-// Returns the size of the internal buffer.
-static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) {
- return bw->pos_;
-}
-
-//------------------------------------------------------------------------------
-// VP8LBitWriter
-
-#if defined(__x86_64__) || defined(_M_X64) // 64bit
-typedef uint64_t vp8l_atype_t; // accumulator type
-typedef uint32_t vp8l_wtype_t; // writing type
-#define WSWAP HToLE32
-#define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t)
-#define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t)
-#define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t)
-#else
-typedef uint32_t vp8l_atype_t;
-typedef uint16_t vp8l_wtype_t;
-#define WSWAP HToLE16
-#define VP8L_WRITER_BYTES 2
-#define VP8L_WRITER_BITS 16
-#define VP8L_WRITER_MAX_BITS 32
-#endif
-
-typedef struct {
- vp8l_atype_t bits_; // bit accumulator
- int used_; // number of bits used in accumulator
- uint8_t* buf_; // start of buffer
- uint8_t* cur_; // current write position
- uint8_t* end_; // end of buffer
-
- // After all bits are written (VP8LBitWriterFinish()), the caller must observe
- // the state of error_. A value of 1 indicates that a memory allocation
- // failure has happened during bit writing. A value of 0 indicates successful
- // writing of bits.
- int error_;
-} VP8LBitWriter;
-
-static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) {
- return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3);
-}
-
-// Returns false in case of memory allocation error.
-int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size);
-// Finalize the bitstream coding. Returns a pointer to the internal buffer.
-uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw);
-// Release any pending memory and zeroes the object.
-void VP8LBitWriterWipeOut(VP8LBitWriter* const bw);
-
-// Internal function for VP8LPutBits flushing 32 bits from the written state.
-void VP8LPutBitsFlushBits(VP8LBitWriter* const bw);
-
-// PutBits internal function used in the 16 bit vp8l_wtype_t case.
-void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits);
-
-// This function writes bits into bytes in increasing addresses (little endian),
-// and within a byte least-significant-bit first.
-// This function can write up to 32 bits in one go, but VP8LBitReader can only
-// read 24 bits max (VP8L_MAX_NUM_BIT_READ).
-// VP8LBitWriter's error_ flag is set in case of memory allocation error.
-static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw,
- uint32_t bits, int n_bits) {
- if (sizeof(vp8l_wtype_t) == 4) {
- if (n_bits > 0) {
- if (bw->used_ >= 32) {
- VP8LPutBitsFlushBits(bw);
- }
- bw->bits_ |= (vp8l_atype_t)bits << bw->used_;
- bw->used_ += n_bits;
- }
- } else {
- VP8LPutBitsInternal(bw, bits, n_bits);
- }
-}
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_BIT_WRITER_H_ */
diff --git a/drivers/webp/utils/color_cache.c b/drivers/webp/utils/color_cache.c
deleted file mode 100644
index c34b2e7f1a..0000000000
--- a/drivers/webp/utils/color_cache.c
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Color Cache for WebP Lossless
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "./color_cache.h"
-#include "./utils.h"
-
-//------------------------------------------------------------------------------
-// VP8LColorCache.
-
-int VP8LColorCacheInit(VP8LColorCache* const cc, int hash_bits) {
- const int hash_size = 1 << hash_bits;
- assert(cc != NULL);
- assert(hash_bits > 0);
- cc->colors_ = (uint32_t*)WebPSafeCalloc((uint64_t)hash_size,
- sizeof(*cc->colors_));
- if (cc->colors_ == NULL) return 0;
- cc->hash_shift_ = 32 - hash_bits;
- cc->hash_bits_ = hash_bits;
- return 1;
-}
-
-void VP8LColorCacheClear(VP8LColorCache* const cc) {
- if (cc != NULL) {
- WebPSafeFree(cc->colors_);
- cc->colors_ = NULL;
- }
-}
-
-void VP8LColorCacheCopy(const VP8LColorCache* const src,
- VP8LColorCache* const dst) {
- assert(src != NULL);
- assert(dst != NULL);
- assert(src->hash_bits_ == dst->hash_bits_);
- memcpy(dst->colors_, src->colors_,
- ((size_t)1u << dst->hash_bits_) * sizeof(*dst->colors_));
-}
diff --git a/drivers/webp/utils/color_cache.h b/drivers/webp/utils/color_cache.h
deleted file mode 100644
index 34299e4c4e..0000000000
--- a/drivers/webp/utils/color_cache.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Color Cache for WebP Lossless
-//
-// Authors: Jyrki Alakuijala (jyrki@google.com)
-// Urvang Joshi (urvang@google.com)
-
-#ifndef WEBP_UTILS_COLOR_CACHE_H_
-#define WEBP_UTILS_COLOR_CACHE_H_
-
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Main color cache struct.
-typedef struct {
- uint32_t *colors_; // color entries
- int hash_shift_; // Hash shift: 32 - hash_bits_.
- int hash_bits_;
-} VP8LColorCache;
-
-static const uint32_t kHashMul = 0x1e35a7bd;
-
-static WEBP_INLINE uint32_t VP8LColorCacheLookup(
- const VP8LColorCache* const cc, uint32_t key) {
- assert((key >> cc->hash_bits_) == 0u);
- return cc->colors_[key];
-}
-
-static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc,
- uint32_t key, uint32_t argb) {
- assert((key >> cc->hash_bits_) == 0u);
- cc->colors_[key] = argb;
-}
-
-static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc,
- uint32_t argb) {
- const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
- cc->colors_[key] = argb;
-}
-
-static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc,
- uint32_t argb) {
- return (kHashMul * argb) >> cc->hash_shift_;
-}
-
-static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc,
- uint32_t argb) {
- const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
- return (cc->colors_[key] == argb);
-}
-
-//------------------------------------------------------------------------------
-
-// Initializes the color cache with 'hash_bits' bits for the keys.
-// Returns false in case of memory error.
-int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits);
-
-void VP8LColorCacheCopy(const VP8LColorCache* const src,
- VP8LColorCache* const dst);
-
-// Delete the memory associated to color cache.
-void VP8LColorCacheClear(VP8LColorCache* const color_cache);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // WEBP_UTILS_COLOR_CACHE_H_
diff --git a/drivers/webp/utils/endian_inl.h b/drivers/webp/utils/endian_inl.h
deleted file mode 100644
index e11260ff7d..0000000000
--- a/drivers/webp/utils/endian_inl.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Endian related functions.
-
-#ifndef WEBP_UTILS_ENDIAN_INL_H_
-#define WEBP_UTILS_ENDIAN_INL_H_
-
-#ifdef HAVE_CONFIG_H
-#include "../webp/config.h"
-#endif
-
-#include "../dsp/dsp.h"
-#include "../webp/types.h"
-
-// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
-#if !defined(WORDS_BIGENDIAN) && \
- (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \
- (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
-#define WORDS_BIGENDIAN
-#endif
-
-#if defined(WORDS_BIGENDIAN)
-#define HToLE32 BSwap32
-#define HToLE16 BSwap16
-#else
-#define HToLE32(x) (x)
-#define HToLE16(x) (x)
-#endif
-
-#if !defined(HAVE_CONFIG_H)
-#if LOCAL_GCC_PREREQ(4,8) || __has_builtin(__builtin_bswap16)
-#define HAVE_BUILTIN_BSWAP16
-#endif
-#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap32)
-#define HAVE_BUILTIN_BSWAP32
-#endif
-#if LOCAL_GCC_PREREQ(4,3) || __has_builtin(__builtin_bswap64)
-#define HAVE_BUILTIN_BSWAP64
-#endif
-#endif // !HAVE_CONFIG_H
-
-static WEBP_INLINE uint16_t BSwap16(uint16_t x) {
-#if defined(HAVE_BUILTIN_BSWAP16)
- return __builtin_bswap16(x);
-#elif defined(_MSC_VER)
- return _byteswap_ushort(x);
-#else
- // gcc will recognize a 'rorw $8, ...' here:
- return (x >> 8) | ((x & 0xff) << 8);
-#endif // HAVE_BUILTIN_BSWAP16
-}
-
-static WEBP_INLINE uint32_t BSwap32(uint32_t x) {
-#if defined(WEBP_USE_MIPS32_R2)
- uint32_t ret;
- __asm__ volatile (
- "wsbh %[ret], %[x] \n\t"
- "rotr %[ret], %[ret], 16 \n\t"
- : [ret]"=r"(ret)
- : [x]"r"(x)
- );
- return ret;
-#elif defined(HAVE_BUILTIN_BSWAP32)
- return __builtin_bswap32(x);
-#elif defined(__i386__) || defined(__x86_64__)
- uint32_t swapped_bytes;
- __asm__ volatile("bswap %0" : "=r"(swapped_bytes) : "0"(x));
- return swapped_bytes;
-#elif defined(_MSC_VER)
- return (uint32_t)_byteswap_ulong(x);
-#else
- return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
-#endif // HAVE_BUILTIN_BSWAP32
-}
-
-static WEBP_INLINE uint64_t BSwap64(uint64_t x) {
-#if defined(HAVE_BUILTIN_BSWAP64)
- return __builtin_bswap64(x);
-#elif defined(__x86_64__)
- uint64_t swapped_bytes;
- __asm__ volatile("bswapq %0" : "=r"(swapped_bytes) : "0"(x));
- return swapped_bytes;
-#elif defined(_MSC_VER)
- return (uint64_t)_byteswap_uint64(x);
-#else // generic code for swapping 64-bit values (suggested by bdb@)
- x = ((x & 0xffffffff00000000ull) >> 32) | ((x & 0x00000000ffffffffull) << 32);
- x = ((x & 0xffff0000ffff0000ull) >> 16) | ((x & 0x0000ffff0000ffffull) << 16);
- x = ((x & 0xff00ff00ff00ff00ull) >> 8) | ((x & 0x00ff00ff00ff00ffull) << 8);
- return x;
-#endif // HAVE_BUILTIN_BSWAP64
-}
-
-#endif // WEBP_UTILS_ENDIAN_INL_H_
diff --git a/drivers/webp/utils/filters.c b/drivers/webp/utils/filters.c
deleted file mode 100644
index 15543b1271..0000000000
--- a/drivers/webp/utils/filters.c
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// filter estimation
-//
-// Author: Urvang (urvang@google.com)
-
-#include "./filters.h"
-#include <stdlib.h>
-#include <string.h>
-
-// -----------------------------------------------------------------------------
-// Quick estimate of a potentially interesting filter mode to try.
-
-#define SMAX 16
-#define SDIFF(a, b) (abs((a) - (b)) >> 4) // Scoring diff, in [0..SMAX)
-
-static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
- const int g = a + b - c;
- return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
-}
-
-WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data,
- int width, int height, int stride) {
- int i, j;
- int bins[WEBP_FILTER_LAST][SMAX];
- memset(bins, 0, sizeof(bins));
-
- // We only sample every other pixels. That's enough.
- for (j = 2; j < height - 1; j += 2) {
- const uint8_t* const p = data + j * stride;
- int mean = p[0];
- for (i = 2; i < width - 1; i += 2) {
- const int diff0 = SDIFF(p[i], mean);
- const int diff1 = SDIFF(p[i], p[i - 1]);
- const int diff2 = SDIFF(p[i], p[i - width]);
- const int grad_pred =
- GradientPredictor(p[i - 1], p[i - width], p[i - width - 1]);
- const int diff3 = SDIFF(p[i], grad_pred);
- bins[WEBP_FILTER_NONE][diff0] = 1;
- bins[WEBP_FILTER_HORIZONTAL][diff1] = 1;
- bins[WEBP_FILTER_VERTICAL][diff2] = 1;
- bins[WEBP_FILTER_GRADIENT][diff3] = 1;
- mean = (3 * mean + p[i] + 2) >> 2;
- }
- }
- {
- int filter;
- WEBP_FILTER_TYPE best_filter = WEBP_FILTER_NONE;
- int best_score = 0x7fffffff;
- for (filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; ++filter) {
- int score = 0;
- for (i = 0; i < SMAX; ++i) {
- if (bins[filter][i] > 0) {
- score += i;
- }
- }
- if (score < best_score) {
- best_score = score;
- best_filter = (WEBP_FILTER_TYPE)filter;
- }
- }
- return best_filter;
- }
-}
-
-#undef SMAX
-#undef SDIFF
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/utils/filters.h b/drivers/webp/utils/filters.h
deleted file mode 100644
index 4aba3fd3b7..0000000000
--- a/drivers/webp/utils/filters.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Spatial prediction using various filters
-//
-// Author: Urvang (urvang@google.com)
-
-#ifndef WEBP_UTILS_FILTERS_H_
-#define WEBP_UTILS_FILTERS_H_
-
-#include "webp/types.h"
-#include "../dsp/dsp.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Fast estimate of a potentially good filter.
-WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data,
- int width, int height, int stride);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_FILTERS_H_ */
diff --git a/drivers/webp/utils/huffman.c b/drivers/webp/utils/huffman.c
deleted file mode 100644
index 7c9d83db9a..0000000000
--- a/drivers/webp/utils/huffman.c
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Utilities for building and looking up Huffman trees.
-//
-// Author: Urvang Joshi (urvang@google.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "./huffman.h"
-#include "webp/format_constants.h"
-#include "./utils.h"
-
-// Huffman data read via DecodeImageStream is represented in two (red and green)
-// bytes.
-#define MAX_HTREE_GROUPS 0x10000
-
-HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) {
- HTreeGroup* const htree_groups =
- (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups));
- if (htree_groups == NULL) {
- return NULL;
- }
- assert(num_htree_groups <= MAX_HTREE_GROUPS);
- return htree_groups;
-}
-
-void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) {
- if (htree_groups != NULL) {
- WebPSafeFree(htree_groups);
- }
-}
-
-// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the
-// bit-wise reversal of the len least significant bits of key.
-static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) {
- uint32_t step = 1 << (len - 1);
- while (key & step) {
- step >>= 1;
- }
- return (key & (step - 1)) + step;
-}
-
-// Stores code in table[0], table[step], table[2*step], ..., table[end].
-// Assumes that end is an integer multiple of step.
-static WEBP_INLINE void ReplicateValue(HuffmanCode* table,
- int step, int end,
- HuffmanCode code) {
- assert(end % step == 0);
- do {
- end -= step;
- table[end] = code;
- } while (end > 0);
-}
-
-// Returns the table width of the next 2nd level table. count is the histogram
-// of bit lengths for the remaining symbols, len is the code length of the next
-// processed symbol
-static WEBP_INLINE int NextTableBitSize(const int* const count,
- int len, int root_bits) {
- int left = 1 << (len - root_bits);
- while (len < MAX_ALLOWED_CODE_LENGTH) {
- left -= count[len];
- if (left <= 0) break;
- ++len;
- left <<= 1;
- }
- return len - root_bits;
-}
-
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
- const int code_lengths[], int code_lengths_size) {
- HuffmanCode* table = root_table; // next available space in table
- int total_size = 1 << root_bits; // total size root table + 2nd level table
- int* sorted = NULL; // symbols sorted by code length
- int len; // current code length
- int symbol; // symbol index in original or sorted table
- // number of codes of each length:
- int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
- // offsets in sorted table for each length:
- int offset[MAX_ALLOWED_CODE_LENGTH + 1];
-
- assert(code_lengths_size != 0);
- assert(code_lengths != NULL);
- assert(root_table != NULL);
- assert(root_bits > 0);
-
- // Build histogram of code lengths.
- for (symbol = 0; symbol < code_lengths_size; ++symbol) {
- if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) {
- return 0;
- }
- ++count[code_lengths[symbol]];
- }
-
- // Error, all code lengths are zeros.
- if (count[0] == code_lengths_size) {
- return 0;
- }
-
- // Generate offsets into sorted symbol table by code length.
- offset[1] = 0;
- for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) {
- if (count[len] > (1 << len)) {
- return 0;
- }
- offset[len + 1] = offset[len] + count[len];
- }
-
- sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
- if (sorted == NULL) {
- return 0;
- }
-
- // Sort symbols by length, by symbol order within each length.
- for (symbol = 0; symbol < code_lengths_size; ++symbol) {
- const int symbol_code_length = code_lengths[symbol];
- if (code_lengths[symbol] > 0) {
- sorted[offset[symbol_code_length]++] = symbol;
- }
- }
-
- // Special case code with only one value.
- if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {
- HuffmanCode code;
- code.bits = 0;
- code.value = (uint16_t)sorted[0];
- ReplicateValue(table, 1, total_size, code);
- WebPSafeFree(sorted);
- return total_size;
- }
-
- {
- int step; // step size to replicate values in current table
- uint32_t low = -1; // low bits for current root entry
- uint32_t mask = total_size - 1; // mask for low bits
- uint32_t key = 0; // reversed prefix code
- int num_nodes = 1; // number of Huffman tree nodes
- int num_open = 1; // number of open branches in current tree level
- int table_bits = root_bits; // key length of current table
- int table_size = 1 << table_bits; // size of current table
- symbol = 0;
- // Fill in root table.
- for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) {
- num_open <<= 1;
- num_nodes += num_open;
- num_open -= count[len];
- if (num_open < 0) {
- WebPSafeFree(sorted);
- return 0;
- }
- for (; count[len] > 0; --count[len]) {
- HuffmanCode code;
- code.bits = (uint8_t)len;
- code.value = (uint16_t)sorted[symbol++];
- ReplicateValue(&table[key], step, table_size, code);
- key = GetNextKey(key, len);
- }
- }
-
- // Fill in 2nd level tables and add pointers to root table.
- for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH;
- ++len, step <<= 1) {
- num_open <<= 1;
- num_nodes += num_open;
- num_open -= count[len];
- if (num_open < 0) {
- WebPSafeFree(sorted);
- return 0;
- }
- for (; count[len] > 0; --count[len]) {
- HuffmanCode code;
- if ((key & mask) != low) {
- table += table_size;
- table_bits = NextTableBitSize(count, len, root_bits);
- table_size = 1 << table_bits;
- total_size += table_size;
- low = key & mask;
- root_table[low].bits = (uint8_t)(table_bits + root_bits);
- root_table[low].value = (uint16_t)((table - root_table) - low);
- }
- code.bits = (uint8_t)(len - root_bits);
- code.value = (uint16_t)sorted[symbol++];
- ReplicateValue(&table[key >> root_bits], step, table_size, code);
- key = GetNextKey(key, len);
- }
- }
-
- // Check if tree is full.
- if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
- WebPSafeFree(sorted);
- return 0;
- }
- }
-
- WebPSafeFree(sorted);
- return total_size;
-}
diff --git a/drivers/webp/utils/huffman.h b/drivers/webp/utils/huffman.h
deleted file mode 100644
index a8cc0da1c3..0000000000
--- a/drivers/webp/utils/huffman.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Utilities for building and looking up Huffman trees.
-//
-// Author: Urvang Joshi (urvang@google.com)
-
-#ifndef WEBP_UTILS_HUFFMAN_H_
-#define WEBP_UTILS_HUFFMAN_H_
-
-#include <assert.h>
-#include "webp/format_constants.h"
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define HUFFMAN_TABLE_BITS 8
-#define HUFFMAN_TABLE_MASK ((1 << HUFFMAN_TABLE_BITS) - 1)
-
-#define LENGTHS_TABLE_BITS 7
-#define LENGTHS_TABLE_MASK ((1 << LENGTHS_TABLE_BITS) - 1)
-
-
-// Huffman lookup table entry
-typedef struct {
- uint8_t bits; // number of bits used for this symbol
- uint16_t value; // symbol value or table offset
-} HuffmanCode;
-
-// long version for holding 32b values
-typedef struct {
- int bits; // number of bits used for this symbol,
- // or an impossible value if not a literal code.
- uint32_t value; // 32b packed ARGB value if literal,
- // or non-literal symbol otherwise
-} HuffmanCode32;
-
-#define HUFFMAN_PACKED_BITS 6
-#define HUFFMAN_PACKED_TABLE_SIZE (1u << HUFFMAN_PACKED_BITS)
-
-// Huffman table group.
-// Includes special handling for the following cases:
-// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN)
-// - is_trivial_code: only 1 code (no bit is read from bitstream)
-// - use_packed_table: few enough literal symbols, so all the bit codes
-// can fit into a small look-up table packed_table[]
-// The common literal base, if applicable, is stored in 'literal_arb'.
-typedef struct HTreeGroup HTreeGroup;
-struct HTreeGroup {
- HuffmanCode* htrees[HUFFMAN_CODES_PER_META_CODE];
- int is_trivial_literal; // True, if huffman trees for Red, Blue & Alpha
- // Symbols are trivial (have a single code).
- uint32_t literal_arb; // If is_trivial_literal is true, this is the
- // ARGB value of the pixel, with Green channel
- // being set to zero.
- int is_trivial_code; // true if is_trivial_literal with only one code
- int use_packed_table; // use packed table below for short literal code
- // table mapping input bits to a packed values, or escape case to literal code
- HuffmanCode32 packed_table[HUFFMAN_PACKED_TABLE_SIZE];
-};
-
-// Creates the instance of HTreeGroup with specified number of tree-groups.
-HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups);
-
-// Releases the memory allocated for HTreeGroup.
-void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups);
-
-// Builds Huffman lookup table assuming code lengths are in symbol order.
-// The 'code_lengths' is pre-allocated temporary memory buffer used for creating
-// the huffman table.
-// Returns built table size or 0 in case of error (invalid tree or
-// memory error).
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
- const int code_lengths[], int code_lengths_size);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // WEBP_UTILS_HUFFMAN_H_
diff --git a/drivers/webp/utils/huffman_encode.c b/drivers/webp/utils/huffman_encode.c
deleted file mode 100644
index 0be414a8f8..0000000000
--- a/drivers/webp/utils/huffman_encode.c
+++ /dev/null
@@ -1,417 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-//
-// Entropy encoding (Huffman) for webp lossless.
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "./huffman_encode.h"
-#include "webp/format_constants.h"
-#include "./utils.h"
-
-// -----------------------------------------------------------------------------
-// Util function to optimize the symbol map for RLE coding
-
-// Heuristics for selecting the stride ranges to collapse.
-static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) {
- return abs(a - b) < 4;
-}
-
-// Change the population counts in a way that the consequent
-// Huffman tree compression, especially its RLE-part, give smaller output.
-static void OptimizeHuffmanForRle(int length, uint8_t* const good_for_rle,
- uint32_t* const counts) {
- // 1) Let's make the Huffman code more compatible with rle encoding.
- int i;
- for (; length >= 0; --length) {
- if (length == 0) {
- return; // All zeros.
- }
- if (counts[length - 1] != 0) {
- // Now counts[0..length - 1] does not have trailing zeros.
- break;
- }
- }
- // 2) Let's mark all population counts that already can be encoded
- // with an rle code.
- {
- // Let's not spoil any of the existing good rle codes.
- // Mark any seq of 0's that is longer as 5 as a good_for_rle.
- // Mark any seq of non-0's that is longer as 7 as a good_for_rle.
- uint32_t symbol = counts[0];
- int stride = 0;
- for (i = 0; i < length + 1; ++i) {
- if (i == length || counts[i] != symbol) {
- if ((symbol == 0 && stride >= 5) ||
- (symbol != 0 && stride >= 7)) {
- int k;
- for (k = 0; k < stride; ++k) {
- good_for_rle[i - k - 1] = 1;
- }
- }
- stride = 1;
- if (i != length) {
- symbol = counts[i];
- }
- } else {
- ++stride;
- }
- }
- }
- // 3) Let's replace those population counts that lead to more rle codes.
- {
- uint32_t stride = 0;
- uint32_t limit = counts[0];
- uint32_t sum = 0;
- for (i = 0; i < length + 1; ++i) {
- if (i == length || good_for_rle[i] ||
- (i != 0 && good_for_rle[i - 1]) ||
- !ValuesShouldBeCollapsedToStrideAverage(counts[i], limit)) {
- if (stride >= 4 || (stride >= 3 && sum == 0)) {
- uint32_t k;
- // The stride must end, collapse what we have, if we have enough (4).
- uint32_t count = (sum + stride / 2) / stride;
- if (count < 1) {
- count = 1;
- }
- if (sum == 0) {
- // Don't make an all zeros stride to be upgraded to ones.
- count = 0;
- }
- for (k = 0; k < stride; ++k) {
- // We don't want to change value at counts[i],
- // that is already belonging to the next stride. Thus - 1.
- counts[i - k - 1] = count;
- }
- }
- stride = 0;
- sum = 0;
- if (i < length - 3) {
- // All interesting strides have a count of at least 4,
- // at least when non-zeros.
- limit = (counts[i] + counts[i + 1] +
- counts[i + 2] + counts[i + 3] + 2) / 4;
- } else if (i < length) {
- limit = counts[i];
- } else {
- limit = 0;
- }
- }
- ++stride;
- if (i != length) {
- sum += counts[i];
- if (stride >= 4) {
- limit = (sum + stride / 2) / stride;
- }
- }
- }
- }
-}
-
-// A comparer function for two Huffman trees: sorts first by 'total count'
-// (more comes first), and then by 'value' (more comes first).
-static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) {
- const HuffmanTree* const t1 = (const HuffmanTree*)ptr1;
- const HuffmanTree* const t2 = (const HuffmanTree*)ptr2;
- if (t1->total_count_ > t2->total_count_) {
- return -1;
- } else if (t1->total_count_ < t2->total_count_) {
- return 1;
- } else {
- assert(t1->value_ != t2->value_);
- return (t1->value_ < t2->value_) ? -1 : 1;
- }
-}
-
-static void SetBitDepths(const HuffmanTree* const tree,
- const HuffmanTree* const pool,
- uint8_t* const bit_depths, int level) {
- if (tree->pool_index_left_ >= 0) {
- SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1);
- SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1);
- } else {
- bit_depths[tree->value_] = level;
- }
-}
-
-// Create an optimal Huffman tree.
-//
-// (data,length): population counts.
-// tree_limit: maximum bit depth (inclusive) of the codes.
-// bit_depths[]: how many bits are used for the symbol.
-//
-// Returns 0 when an error has occurred.
-//
-// The catch here is that the tree cannot be arbitrarily deep
-//
-// count_limit is the value that is to be faked as the minimum value
-// and this minimum value is raised until the tree matches the
-// maximum length requirement.
-//
-// This algorithm is not of excellent performance for very long data blocks,
-// especially when population counts are longer than 2**tree_limit, but
-// we are not planning to use this with extremely long blocks.
-//
-// See http://en.wikipedia.org/wiki/Huffman_coding
-static void GenerateOptimalTree(const uint32_t* const histogram,
- int histogram_size,
- HuffmanTree* tree, int tree_depth_limit,
- uint8_t* const bit_depths) {
- uint32_t count_min;
- HuffmanTree* tree_pool;
- int tree_size_orig = 0;
- int i;
-
- for (i = 0; i < histogram_size; ++i) {
- if (histogram[i] != 0) {
- ++tree_size_orig;
- }
- }
-
- if (tree_size_orig == 0) { // pretty optimal already!
- return;
- }
-
- tree_pool = tree + tree_size_orig;
-
- // For block sizes with less than 64k symbols we never need to do a
- // second iteration of this loop.
- // If we actually start running inside this loop a lot, we would perhaps
- // be better off with the Katajainen algorithm.
- assert(tree_size_orig <= (1 << (tree_depth_limit - 1)));
- for (count_min = 1; ; count_min *= 2) {
- int tree_size = tree_size_orig;
- // We need to pack the Huffman tree in tree_depth_limit bits.
- // So, we try by faking histogram entries to be at least 'count_min'.
- int idx = 0;
- int j;
- for (j = 0; j < histogram_size; ++j) {
- if (histogram[j] != 0) {
- const uint32_t count =
- (histogram[j] < count_min) ? count_min : histogram[j];
- tree[idx].total_count_ = count;
- tree[idx].value_ = j;
- tree[idx].pool_index_left_ = -1;
- tree[idx].pool_index_right_ = -1;
- ++idx;
- }
- }
-
- // Build the Huffman tree.
- qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees);
-
- if (tree_size > 1) { // Normal case.
- int tree_pool_size = 0;
- while (tree_size > 1) { // Finish when we have only one root.
- uint32_t count;
- tree_pool[tree_pool_size++] = tree[tree_size - 1];
- tree_pool[tree_pool_size++] = tree[tree_size - 2];
- count = tree_pool[tree_pool_size - 1].total_count_ +
- tree_pool[tree_pool_size - 2].total_count_;
- tree_size -= 2;
- {
- // Search for the insertion point.
- int k;
- for (k = 0; k < tree_size; ++k) {
- if (tree[k].total_count_ <= count) {
- break;
- }
- }
- memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree));
- tree[k].total_count_ = count;
- tree[k].value_ = -1;
-
- tree[k].pool_index_left_ = tree_pool_size - 1;
- tree[k].pool_index_right_ = tree_pool_size - 2;
- tree_size = tree_size + 1;
- }
- }
- SetBitDepths(&tree[0], tree_pool, bit_depths, 0);
- } else if (tree_size == 1) { // Trivial case: only one element.
- bit_depths[tree[0].value_] = 1;
- }
-
- {
- // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria.
- int max_depth = bit_depths[0];
- for (j = 1; j < histogram_size; ++j) {
- if (max_depth < bit_depths[j]) {
- max_depth = bit_depths[j];
- }
- }
- if (max_depth <= tree_depth_limit) {
- break;
- }
- }
- }
-}
-
-// -----------------------------------------------------------------------------
-// Coding of the Huffman tree values
-
-static HuffmanTreeToken* CodeRepeatedValues(int repetitions,
- HuffmanTreeToken* tokens,
- int value, int prev_value) {
- assert(value <= MAX_ALLOWED_CODE_LENGTH);
- if (value != prev_value) {
- tokens->code = value;
- tokens->extra_bits = 0;
- ++tokens;
- --repetitions;
- }
- while (repetitions >= 1) {
- if (repetitions < 3) {
- int i;
- for (i = 0; i < repetitions; ++i) {
- tokens->code = value;
- tokens->extra_bits = 0;
- ++tokens;
- }
- break;
- } else if (repetitions < 7) {
- tokens->code = 16;
- tokens->extra_bits = repetitions - 3;
- ++tokens;
- break;
- } else {
- tokens->code = 16;
- tokens->extra_bits = 3;
- ++tokens;
- repetitions -= 6;
- }
- }
- return tokens;
-}
-
-static HuffmanTreeToken* CodeRepeatedZeros(int repetitions,
- HuffmanTreeToken* tokens) {
- while (repetitions >= 1) {
- if (repetitions < 3) {
- int i;
- for (i = 0; i < repetitions; ++i) {
- tokens->code = 0; // 0-value
- tokens->extra_bits = 0;
- ++tokens;
- }
- break;
- } else if (repetitions < 11) {
- tokens->code = 17;
- tokens->extra_bits = repetitions - 3;
- ++tokens;
- break;
- } else if (repetitions < 139) {
- tokens->code = 18;
- tokens->extra_bits = repetitions - 11;
- ++tokens;
- break;
- } else {
- tokens->code = 18;
- tokens->extra_bits = 0x7f; // 138 repeated 0s
- ++tokens;
- repetitions -= 138;
- }
- }
- return tokens;
-}
-
-int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree,
- HuffmanTreeToken* tokens, int max_tokens) {
- HuffmanTreeToken* const starting_token = tokens;
- HuffmanTreeToken* const ending_token = tokens + max_tokens;
- const int depth_size = tree->num_symbols;
- int prev_value = 8; // 8 is the initial value for rle.
- int i = 0;
- assert(tokens != NULL);
- while (i < depth_size) {
- const int value = tree->code_lengths[i];
- int k = i + 1;
- int runs;
- while (k < depth_size && tree->code_lengths[k] == value) ++k;
- runs = k - i;
- if (value == 0) {
- tokens = CodeRepeatedZeros(runs, tokens);
- } else {
- tokens = CodeRepeatedValues(runs, tokens, value, prev_value);
- prev_value = value;
- }
- i += runs;
- assert(tokens <= ending_token);
- }
- (void)ending_token; // suppress 'unused variable' warning
- return (int)(tokens - starting_token);
-}
-
-// -----------------------------------------------------------------------------
-
-// Pre-reversed 4-bit values.
-static const uint8_t kReversedBits[16] = {
- 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
- 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
-};
-
-static uint32_t ReverseBits(int num_bits, uint32_t bits) {
- uint32_t retval = 0;
- int i = 0;
- while (i < num_bits) {
- i += 4;
- retval |= kReversedBits[bits & 0xf] << (MAX_ALLOWED_CODE_LENGTH + 1 - i);
- bits >>= 4;
- }
- retval >>= (MAX_ALLOWED_CODE_LENGTH + 1 - num_bits);
- return retval;
-}
-
-// Get the actual bit values for a tree of bit depths.
-static void ConvertBitDepthsToSymbols(HuffmanTreeCode* const tree) {
- // 0 bit-depth means that the symbol does not exist.
- int i;
- int len;
- uint32_t next_code[MAX_ALLOWED_CODE_LENGTH + 1];
- int depth_count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
-
- assert(tree != NULL);
- len = tree->num_symbols;
- for (i = 0; i < len; ++i) {
- const int code_length = tree->code_lengths[i];
- assert(code_length <= MAX_ALLOWED_CODE_LENGTH);
- ++depth_count[code_length];
- }
- depth_count[0] = 0; // ignore unused symbol
- next_code[0] = 0;
- {
- uint32_t code = 0;
- for (i = 1; i <= MAX_ALLOWED_CODE_LENGTH; ++i) {
- code = (code + depth_count[i - 1]) << 1;
- next_code[i] = code;
- }
- }
- for (i = 0; i < len; ++i) {
- const int code_length = tree->code_lengths[i];
- tree->codes[i] = ReverseBits(code_length, next_code[code_length]++);
- }
-}
-
-// -----------------------------------------------------------------------------
-// Main entry point
-
-void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit,
- uint8_t* const buf_rle,
- HuffmanTree* const huff_tree,
- HuffmanTreeCode* const huff_code) {
- const int num_symbols = huff_code->num_symbols;
- memset(buf_rle, 0, num_symbols * sizeof(*buf_rle));
- OptimizeHuffmanForRle(num_symbols, buf_rle, histogram);
- GenerateOptimalTree(histogram, num_symbols, huff_tree, tree_depth_limit,
- huff_code->code_lengths);
- // Create the actual bit codes for the bit lengths.
- ConvertBitDepthsToSymbols(huff_code);
-}
diff --git a/drivers/webp/utils/huffman_encode.h b/drivers/webp/utils/huffman_encode.h
deleted file mode 100644
index 93610066f3..0000000000
--- a/drivers/webp/utils/huffman_encode.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-//
-// Entropy encoding (Huffman) for webp lossless
-
-#ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_
-#define WEBP_UTILS_HUFFMAN_ENCODE_H_
-
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Struct for holding the tree header in coded form.
-typedef struct {
- uint8_t code; // value (0..15) or escape code (16,17,18)
- uint8_t extra_bits; // extra bits for escape codes
-} HuffmanTreeToken;
-
-// Struct to represent the tree codes (depth and bits array).
-typedef struct {
- int num_symbols; // Number of symbols.
- uint8_t* code_lengths; // Code lengths of the symbols.
- uint16_t* codes; // Symbol Codes.
-} HuffmanTreeCode;
-
-// Struct to represent the Huffman tree.
-typedef struct {
- uint32_t total_count_; // Symbol frequency.
- int value_; // Symbol value.
- int pool_index_left_; // Index for the left sub-tree.
- int pool_index_right_; // Index for the right sub-tree.
-} HuffmanTree;
-
-// Turn the Huffman tree into a token sequence.
-// Returns the number of tokens used.
-int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree,
- HuffmanTreeToken* tokens, int max_tokens);
-
-// Create an optimized tree, and tokenize it.
-// 'buf_rle' and 'huff_tree' are pre-allocated and the 'tree' is the constructed
-// huffman code tree.
-void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit,
- uint8_t* const buf_rle, HuffmanTree* const huff_tree,
- HuffmanTreeCode* const tree);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // WEBP_UTILS_HUFFMAN_ENCODE_H_
diff --git a/drivers/webp/utils/quant_levels.c b/drivers/webp/utils/quant_levels.c
deleted file mode 100644
index d7c8aab922..0000000000
--- a/drivers/webp/utils/quant_levels.c
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Quantize levels for specified number of quantization-levels ([2, 256]).
-// Min and max values are preserved (usual 0 and 255 for alpha plane).
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-
-#include "./quant_levels.h"
-
-#define NUM_SYMBOLS 256
-
-#define MAX_ITER 6 // Maximum number of convergence steps.
-#define ERROR_THRESHOLD 1e-4 // MSE stopping criterion.
-
-// -----------------------------------------------------------------------------
-// Quantize levels.
-
-int QuantizeLevels(uint8_t* const data, int width, int height,
- int num_levels, uint64_t* const sse) {
- int freq[NUM_SYMBOLS] = { 0 };
- int q_level[NUM_SYMBOLS] = { 0 };
- double inv_q_level[NUM_SYMBOLS] = { 0 };
- int min_s = 255, max_s = 0;
- const size_t data_size = height * width;
- int i, num_levels_in, iter;
- double last_err = 1.e38, err = 0.;
- const double err_threshold = ERROR_THRESHOLD * data_size;
-
- if (data == NULL) {
- return 0;
- }
-
- if (width <= 0 || height <= 0) {
- return 0;
- }
-
- if (num_levels < 2 || num_levels > 256) {
- return 0;
- }
-
- {
- size_t n;
- num_levels_in = 0;
- for (n = 0; n < data_size; ++n) {
- num_levels_in += (freq[data[n]] == 0);
- if (min_s > data[n]) min_s = data[n];
- if (max_s < data[n]) max_s = data[n];
- ++freq[data[n]];
- }
- }
-
- if (num_levels_in <= num_levels) goto End; // nothing to do!
-
- // Start with uniformly spread centroids.
- for (i = 0; i < num_levels; ++i) {
- inv_q_level[i] = min_s + (double)(max_s - min_s) * i / (num_levels - 1);
- }
-
- // Fixed values. Won't be changed.
- q_level[min_s] = 0;
- q_level[max_s] = num_levels - 1;
- assert(inv_q_level[0] == min_s);
- assert(inv_q_level[num_levels - 1] == max_s);
-
- // k-Means iterations.
- for (iter = 0; iter < MAX_ITER; ++iter) {
- double q_sum[NUM_SYMBOLS] = { 0 };
- double q_count[NUM_SYMBOLS] = { 0 };
- int s, slot = 0;
-
- // Assign classes to representatives.
- for (s = min_s; s <= max_s; ++s) {
- // Keep track of the nearest neighbour 'slot'
- while (slot < num_levels - 1 &&
- 2 * s > inv_q_level[slot] + inv_q_level[slot + 1]) {
- ++slot;
- }
- if (freq[s] > 0) {
- q_sum[slot] += s * freq[s];
- q_count[slot] += freq[s];
- }
- q_level[s] = slot;
- }
-
- // Assign new representatives to classes.
- if (num_levels > 2) {
- for (slot = 1; slot < num_levels - 1; ++slot) {
- const double count = q_count[slot];
- if (count > 0.) {
- inv_q_level[slot] = q_sum[slot] / count;
- }
- }
- }
-
- // Compute convergence error.
- err = 0.;
- for (s = min_s; s <= max_s; ++s) {
- const double error = s - inv_q_level[q_level[s]];
- err += freq[s] * error * error;
- }
-
- // Check for convergence: we stop as soon as the error is no
- // longer improving.
- if (last_err - err < err_threshold) break;
- last_err = err;
- }
-
- // Remap the alpha plane to quantized values.
- {
- // double->int rounding operation can be costly, so we do it
- // once for all before remapping. We also perform the data[] -> slot
- // mapping, while at it (avoid one indirection in the final loop).
- uint8_t map[NUM_SYMBOLS];
- int s;
- size_t n;
- for (s = min_s; s <= max_s; ++s) {
- const int slot = q_level[s];
- map[s] = (uint8_t)(inv_q_level[slot] + .5);
- }
- // Final pass.
- for (n = 0; n < data_size; ++n) {
- data[n] = map[data[n]];
- }
- }
- End:
- // Store sum of squared error if needed.
- if (sse != NULL) *sse = (uint64_t)err;
-
- return 1;
-}
-
diff --git a/drivers/webp/utils/quant_levels.h b/drivers/webp/utils/quant_levels.h
deleted file mode 100644
index 3916b977ab..0000000000
--- a/drivers/webp/utils/quant_levels.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Alpha plane quantization utility
-//
-// Author: Vikas Arora (vikasa@google.com)
-
-#ifndef WEBP_UTILS_QUANT_LEVELS_H_
-#define WEBP_UTILS_QUANT_LEVELS_H_
-
-#include <stdlib.h>
-
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Replace the input 'data' of size 'width'x'height' with 'num-levels'
-// quantized values. If not NULL, 'sse' will contain the sum of squared error.
-// Valid range for 'num_levels' is [2, 256].
-// Returns false in case of error (data is NULL, or parameters are invalid).
-int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels,
- uint64_t* const sse);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_QUANT_LEVELS_H_ */
diff --git a/drivers/webp/utils/quant_levels_dec.c b/drivers/webp/utils/quant_levels_dec.c
deleted file mode 100644
index ee0a3fe127..0000000000
--- a/drivers/webp/utils/quant_levels_dec.c
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Implement gradient smoothing: we replace a current alpha value by its
-// surrounding average if it's close enough (that is: the change will be less
-// than the minimum distance between two quantized level).
-// We use sliding window for computing the 2d moving average.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./quant_levels_dec.h"
-
-#include <string.h> // for memset
-
-#include "./utils.h"
-
-// #define USE_DITHERING // uncomment to enable ordered dithering (not vital)
-
-#define FIX 16 // fix-point precision for averaging
-#define LFIX 2 // extra precision for look-up table
-#define LUT_SIZE ((1 << (8 + LFIX)) - 1) // look-up table size
-
-#if defined(USE_DITHERING)
-
-#define DFIX 4 // extra precision for ordered dithering
-#define DSIZE 4 // dithering size (must be a power of two)
-// cf. http://en.wikipedia.org/wiki/Ordered_dithering
-static const uint8_t kOrderedDither[DSIZE][DSIZE] = {
- { 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision
- { 12, 4, 14, 6 },
- { 3, 11, 1, 9 },
- { 15, 7, 13, 5 }
-};
-
-#else
-#define DFIX 0
-#endif
-
-typedef struct {
- int width_, height_; // dimension
- int stride_; // stride in bytes
- int row_; // current input row being processed
- uint8_t* src_; // input pointer
- uint8_t* dst_; // output pointer
-
- int radius_; // filter radius (=delay)
- int scale_; // normalization factor, in FIX bits precision
-
- void* mem_; // all memory
-
- // various scratch buffers
- uint16_t* start_;
- uint16_t* cur_;
- uint16_t* end_;
- uint16_t* top_;
- uint16_t* average_;
-
- // input levels distribution
- int num_levels_; // number of quantized levels
- int min_, max_; // min and max level values
- int min_level_dist_; // smallest distance between two consecutive levels
-
- int16_t* correction_; // size = 1 + 2*LUT_SIZE -> ~4k memory
-} SmoothParams;
-
-//------------------------------------------------------------------------------
-
-#define CLIP_MASK (int)(~0U << (8 + DFIX))
-static WEBP_INLINE uint8_t clip_8b(int v) {
- return (!(v & CLIP_MASK)) ? (uint8_t)(v >> DFIX) : (v < 0) ? 0u : 255u;
-}
-
-// vertical accumulation
-static void VFilter(SmoothParams* const p) {
- const uint8_t* src = p->src_;
- const int w = p->width_;
- uint16_t* const cur = p->cur_;
- const uint16_t* const top = p->top_;
- uint16_t* const out = p->end_;
- uint16_t sum = 0; // all arithmetic is modulo 16bit
- int x;
-
- for (x = 0; x < w; ++x) {
- uint16_t new_value;
- sum += src[x];
- new_value = top[x] + sum;
- out[x] = new_value - cur[x]; // vertical sum of 'r' pixels.
- cur[x] = new_value;
- }
- // move input pointers one row down
- p->top_ = p->cur_;
- p->cur_ += w;
- if (p->cur_ == p->end_) p->cur_ = p->start_; // roll-over
- // We replicate edges, as it's somewhat easier as a boundary condition.
- // That's why we don't update the 'src' pointer on top/bottom area:
- if (p->row_ >= 0 && p->row_ < p->height_ - 1) {
- p->src_ += p->stride_;
- }
-}
-
-// horizontal accumulation. We use mirror replication of missing pixels, as it's
-// a little easier to implement (surprisingly).
-static void HFilter(SmoothParams* const p) {
- const uint16_t* const in = p->end_;
- uint16_t* const out = p->average_;
- const uint32_t scale = p->scale_;
- const int w = p->width_;
- const int r = p->radius_;
-
- int x;
- for (x = 0; x <= r; ++x) { // left mirroring
- const uint16_t delta = in[x + r - 1] + in[r - x];
- out[x] = (delta * scale) >> FIX;
- }
- for (; x < w - r; ++x) { // bulk middle run
- const uint16_t delta = in[x + r] - in[x - r - 1];
- out[x] = (delta * scale) >> FIX;
- }
- for (; x < w; ++x) { // right mirroring
- const uint16_t delta =
- 2 * in[w - 1] - in[2 * w - 2 - r - x] - in[x - r - 1];
- out[x] = (delta * scale) >> FIX;
- }
-}
-
-// emit one filtered output row
-static void ApplyFilter(SmoothParams* const p) {
- const uint16_t* const average = p->average_;
- const int w = p->width_;
- const int16_t* const correction = p->correction_;
-#if defined(USE_DITHERING)
- const uint8_t* const dither = kOrderedDither[p->row_ % DSIZE];
-#endif
- uint8_t* const dst = p->dst_;
- int x;
- for (x = 0; x < w; ++x) {
- const int v = dst[x];
- if (v < p->max_ && v > p->min_) {
- const int c = (v << DFIX) + correction[average[x] - (v << LFIX)];
-#if defined(USE_DITHERING)
- dst[x] = clip_8b(c + dither[x % DSIZE]);
-#else
- dst[x] = clip_8b(c);
-#endif
- }
- }
- p->dst_ += p->stride_; // advance output pointer
-}
-
-//------------------------------------------------------------------------------
-// Initialize correction table
-
-static void InitCorrectionLUT(int16_t* const lut, int min_dist) {
- // The correction curve is:
- // f(x) = x for x <= threshold2
- // f(x) = 0 for x >= threshold1
- // and a linear interpolation for range x=[threshold2, threshold1]
- // (along with f(-x) = -f(x) symmetry).
- // Note that: threshold2 = 3/4 * threshold1
- const int threshold1 = min_dist << LFIX;
- const int threshold2 = (3 * threshold1) >> 2;
- const int max_threshold = threshold2 << DFIX;
- const int delta = threshold1 - threshold2;
- int i;
- for (i = 1; i <= LUT_SIZE; ++i) {
- int c = (i <= threshold2) ? (i << DFIX)
- : (i < threshold1) ? max_threshold * (threshold1 - i) / delta
- : 0;
- c >>= LFIX;
- lut[+i] = +c;
- lut[-i] = -c;
- }
- lut[0] = 0;
-}
-
-static void CountLevels(SmoothParams* const p) {
- int i, j, last_level;
- uint8_t used_levels[256] = { 0 };
- const uint8_t* data = p->src_;
- p->min_ = 255;
- p->max_ = 0;
- for (j = 0; j < p->height_; ++j) {
- for (i = 0; i < p->width_; ++i) {
- const int v = data[i];
- if (v < p->min_) p->min_ = v;
- if (v > p->max_) p->max_ = v;
- used_levels[v] = 1;
- }
- data += p->stride_;
- }
- // Compute the mininum distance between two non-zero levels.
- p->min_level_dist_ = p->max_ - p->min_;
- last_level = -1;
- for (i = 0; i < 256; ++i) {
- if (used_levels[i]) {
- ++p->num_levels_;
- if (last_level >= 0) {
- const int level_dist = i - last_level;
- if (level_dist < p->min_level_dist_) {
- p->min_level_dist_ = level_dist;
- }
- }
- last_level = i;
- }
- }
-}
-
-// Initialize all params.
-static int InitParams(uint8_t* const data, int width, int height, int stride,
- int radius, SmoothParams* const p) {
- const int R = 2 * radius + 1; // total size of the kernel
-
- const size_t size_scratch_m = (R + 1) * width * sizeof(*p->start_);
- const size_t size_m = width * sizeof(*p->average_);
- const size_t size_lut = (1 + 2 * LUT_SIZE) * sizeof(*p->correction_);
- const size_t total_size = size_scratch_m + size_m + size_lut;
- uint8_t* mem = (uint8_t*)WebPSafeMalloc(1U, total_size);
-
- if (mem == NULL) return 0;
- p->mem_ = (void*)mem;
-
- p->start_ = (uint16_t*)mem;
- p->cur_ = p->start_;
- p->end_ = p->start_ + R * width;
- p->top_ = p->end_ - width;
- memset(p->top_, 0, width * sizeof(*p->top_));
- mem += size_scratch_m;
-
- p->average_ = (uint16_t*)mem;
- mem += size_m;
-
- p->width_ = width;
- p->height_ = height;
- p->stride_ = stride;
- p->src_ = data;
- p->dst_ = data;
- p->radius_ = radius;
- p->scale_ = (1 << (FIX + LFIX)) / (R * R); // normalization constant
- p->row_ = -radius;
-
- // analyze the input distribution so we can best-fit the threshold
- CountLevels(p);
-
- // correction table
- p->correction_ = ((int16_t*)mem) + LUT_SIZE;
- InitCorrectionLUT(p->correction_, p->min_level_dist_);
-
- return 1;
-}
-
-static void CleanupParams(SmoothParams* const p) {
- WebPSafeFree(p->mem_);
-}
-
-int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
- int strength) {
- const int radius = 4 * strength / 100;
- if (strength < 0 || strength > 100) return 0;
- if (data == NULL || width <= 0 || height <= 0) return 0; // bad params
- if (radius > 0) {
- SmoothParams p;
- memset(&p, 0, sizeof(p));
- if (!InitParams(data, width, height, stride, radius, &p)) return 0;
- if (p.num_levels_ > 2) {
- for (; p.row_ < p.height_; ++p.row_) {
- VFilter(&p); // accumulate average of input
- // Need to wait few rows in order to prime the filter,
- // before emitting some output.
- if (p.row_ >= p.radius_) {
- HFilter(&p);
- ApplyFilter(&p);
- }
- }
- }
- CleanupParams(&p);
- }
- return 1;
-}
diff --git a/drivers/webp/utils/quant_levels_dec.h b/drivers/webp/utils/quant_levels_dec.h
deleted file mode 100644
index c99a475386..0000000000
--- a/drivers/webp/utils/quant_levels_dec.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Alpha plane de-quantization utility
-//
-// Author: Vikas Arora (vikasa@google.com)
-
-#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_
-#define WEBP_UTILS_QUANT_LEVELS_DEC_H_
-
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Apply post-processing to input 'data' of size 'width'x'height' assuming that
-// the source was quantized to a reduced number of levels. 'stride' is in bytes.
-// Strength is in [0..100] and controls the amount of dithering applied.
-// Returns false in case of error (data is NULL, invalid parameters,
-// malloc failure, ...).
-int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
- int strength);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */
diff --git a/drivers/webp/utils/random.c b/drivers/webp/utils/random.c
deleted file mode 100644
index 24e96ad648..0000000000
--- a/drivers/webp/utils/random.c
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Pseudo-random utilities
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <string.h>
-#include "./random.h"
-
-//------------------------------------------------------------------------------
-
-// 31b-range values
-static const uint32_t kRandomTable[VP8_RANDOM_TABLE_SIZE] = {
- 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828,
- 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da,
- 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f,
- 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2,
- 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c,
- 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd,
- 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3,
- 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b,
- 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494,
- 0x27e5ed3c
-};
-
-void VP8InitRandom(VP8Random* const rg, float dithering) {
- memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_));
- rg->index1_ = 0;
- rg->index2_ = 31;
- rg->amp_ = (dithering < 0.0) ? 0
- : (dithering > 1.0) ? (1 << VP8_RANDOM_DITHER_FIX)
- : (uint32_t)((1 << VP8_RANDOM_DITHER_FIX) * dithering);
-}
-
-//------------------------------------------------------------------------------
-
diff --git a/drivers/webp/utils/random.h b/drivers/webp/utils/random.h
deleted file mode 100644
index 745f3e2e87..0000000000
--- a/drivers/webp/utils/random.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Pseudo-random utilities
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_UTILS_RANDOM_H_
-#define WEBP_UTILS_RANDOM_H_
-
-#include <assert.h>
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering
-#define VP8_RANDOM_TABLE_SIZE 55
-
-typedef struct {
- int index1_, index2_;
- uint32_t tab_[VP8_RANDOM_TABLE_SIZE];
- int amp_;
-} VP8Random;
-
-// Initializes random generator with an amplitude 'dithering' in range [0..1].
-void VP8InitRandom(VP8Random* const rg, float dithering);
-
-// Returns a centered pseudo-random number with 'num_bits' amplitude.
-// (uses D.Knuth's Difference-based random generator).
-// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision.
-static WEBP_INLINE int VP8RandomBits2(VP8Random* const rg, int num_bits,
- int amp) {
- int diff;
- assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31);
- diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_];
- if (diff < 0) diff += (1u << 31);
- rg->tab_[rg->index1_] = diff;
- if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0;
- if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0;
- // sign-extend, 0-center
- diff = (int)((uint32_t)diff << 1) >> (32 - num_bits);
- diff = (diff * amp) >> VP8_RANDOM_DITHER_FIX; // restrict range
- diff += 1 << (num_bits - 1); // shift back to 0.5-center
- return diff;
-}
-
-static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) {
- return VP8RandomBits2(rg, num_bits, rg->amp_);
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_RANDOM_H_ */
diff --git a/drivers/webp/utils/rescaler.c b/drivers/webp/utils/rescaler.c
deleted file mode 100644
index 00c9300bfb..0000000000
--- a/drivers/webp/utils/rescaler.c
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Rescaling functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../dsp/dsp.h"
-#include "./rescaler.h"
-
-//------------------------------------------------------------------------------
-
-void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height,
- uint8_t* const dst,
- int dst_width, int dst_height, int dst_stride,
- int num_channels, rescaler_t* const work) {
- const int x_add = src_width, x_sub = dst_width;
- const int y_add = src_height, y_sub = dst_height;
- wrk->x_expand = (src_width < dst_width);
- wrk->y_expand = (src_height < dst_height);
- wrk->src_width = src_width;
- wrk->src_height = src_height;
- wrk->dst_width = dst_width;
- wrk->dst_height = dst_height;
- wrk->src_y = 0;
- wrk->dst_y = 0;
- wrk->dst = dst;
- wrk->dst_stride = dst_stride;
- wrk->num_channels = num_channels;
-
- // for 'x_expand', we use bilinear interpolation
- wrk->x_add = wrk->x_expand ? (x_sub - 1) : x_add;
- wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub;
- if (!wrk->x_expand) { // fx_scale is not used otherwise
- wrk->fx_scale = WEBP_RESCALER_FRAC(1, wrk->x_sub);
- }
- // vertical scaling parameters
- wrk->y_add = wrk->y_expand ? y_add - 1 : y_add;
- wrk->y_sub = wrk->y_expand ? y_sub - 1 : y_sub;
- wrk->y_accum = wrk->y_expand ? wrk->y_sub : wrk->y_add;
- if (!wrk->y_expand) {
- // this is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast.
- const uint64_t ratio =
- (uint64_t)dst_height * WEBP_RESCALER_ONE / (wrk->x_add * wrk->y_add);
- if (ratio != (uint32_t)ratio) {
- // We can't represent the ratio with the current fixed-point precision.
- // => We special-case fxy_scale = 0, in WebPRescalerExportRow().
- wrk->fxy_scale = 0;
- } else {
- wrk->fxy_scale = (uint32_t)ratio;
- }
- wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->y_sub);
- } else {
- wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->x_add);
- // wrk->fxy_scale is unused here.
- }
- wrk->irow = work;
- wrk->frow = work + num_channels * dst_width;
- memset(work, 0, 2 * dst_width * num_channels * sizeof(*work));
-
- WebPRescalerDspInit();
-}
-
-int WebPRescalerGetScaledDimensions(int src_width, int src_height,
- int* const scaled_width,
- int* const scaled_height) {
- assert(scaled_width != NULL);
- assert(scaled_height != NULL);
- {
- int width = *scaled_width;
- int height = *scaled_height;
-
- // if width is unspecified, scale original proportionally to height ratio.
- if (width == 0) {
- width = (src_width * height + src_height / 2) / src_height;
- }
- // if height is unspecified, scale original proportionally to width ratio.
- if (height == 0) {
- height = (src_height * width + src_width / 2) / src_width;
- }
- // Check if the overall dimensions still make sense.
- if (width <= 0 || height <= 0) {
- return 0;
- }
-
- *scaled_width = width;
- *scaled_height = height;
- return 1;
- }
-}
-
-//------------------------------------------------------------------------------
-// all-in-one calls
-
-int WebPRescaleNeededLines(const WebPRescaler* const wrk, int max_num_lines) {
- const int num_lines = (wrk->y_accum + wrk->y_sub - 1) / wrk->y_sub;
- return (num_lines > max_num_lines) ? max_num_lines : num_lines;
-}
-
-int WebPRescalerImport(WebPRescaler* const wrk, int num_lines,
- const uint8_t* src, int src_stride) {
- int total_imported = 0;
- while (total_imported < num_lines && !WebPRescalerHasPendingOutput(wrk)) {
- if (wrk->y_expand) {
- rescaler_t* const tmp = wrk->irow;
- wrk->irow = wrk->frow;
- wrk->frow = tmp;
- }
- WebPRescalerImportRow(wrk, src);
- if (!wrk->y_expand) { // Accumulate the contribution of the new row.
- int x;
- for (x = 0; x < wrk->num_channels * wrk->dst_width; ++x) {
- wrk->irow[x] += wrk->frow[x];
- }
- }
- ++wrk->src_y;
- src += src_stride;
- ++total_imported;
- wrk->y_accum -= wrk->y_sub;
- }
- return total_imported;
-}
-
-int WebPRescalerExport(WebPRescaler* const rescaler) {
- int total_exported = 0;
- while (WebPRescalerHasPendingOutput(rescaler)) {
- WebPRescalerExportRow(rescaler);
- ++total_exported;
- }
- return total_exported;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/utils/rescaler.h b/drivers/webp/utils/rescaler.h
deleted file mode 100644
index 868467b4d7..0000000000
--- a/drivers/webp/utils/rescaler.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Rescaling functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_UTILS_RESCALER_H_
-#define WEBP_UTILS_RESCALER_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "webp/types.h"
-
-#define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies
-#define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX)
-#define WEBP_RESCALER_FRAC(x, y) \
- ((uint32_t)(((uint64_t)(x) << WEBP_RESCALER_RFIX) / (y)))
-
-// Structure used for on-the-fly rescaling
-typedef uint32_t rescaler_t; // type for side-buffer
-typedef struct WebPRescaler WebPRescaler;
-struct WebPRescaler {
- int x_expand; // true if we're expanding in the x direction
- int y_expand; // true if we're expanding in the y direction
- int num_channels; // bytes to jump between pixels
- uint32_t fx_scale; // fixed-point scaling factors
- uint32_t fy_scale; // ''
- uint32_t fxy_scale; // ''
- int y_accum; // vertical accumulator
- int y_add, y_sub; // vertical increments
- int x_add, x_sub; // horizontal increments
- int src_width, src_height; // source dimensions
- int dst_width, dst_height; // destination dimensions
- int src_y, dst_y; // row counters for input and output
- uint8_t* dst;
- int dst_stride;
- rescaler_t* irow, *frow; // work buffer
-};
-
-// Initialize a rescaler given scratch area 'work' and dimensions of src & dst.
-void WebPRescalerInit(WebPRescaler* const rescaler,
- int src_width, int src_height,
- uint8_t* const dst,
- int dst_width, int dst_height, int dst_stride,
- int num_channels,
- rescaler_t* const work);
-
-// If either 'scaled_width' or 'scaled_height' (but not both) is 0 the value
-// will be calculated preserving the aspect ratio, otherwise the values are
-// left unmodified. Returns true on success, false if either value is 0 after
-// performing the scaling calculation.
-int WebPRescalerGetScaledDimensions(int src_width, int src_height,
- int* const scaled_width,
- int* const scaled_height);
-
-// Returns the number of input lines needed next to produce one output line,
-// considering that the maximum available input lines are 'max_num_lines'.
-int WebPRescaleNeededLines(const WebPRescaler* const rescaler,
- int max_num_lines);
-
-// Import multiple rows over all channels, until at least one row is ready to
-// be exported. Returns the actual number of lines that were imported.
-int WebPRescalerImport(WebPRescaler* const rescaler, int num_rows,
- const uint8_t* src, int src_stride);
-
-// Export as many rows as possible. Return the numbers of rows written.
-int WebPRescalerExport(WebPRescaler* const rescaler);
-
-// Return true if input is finished
-static WEBP_INLINE
-int WebPRescalerInputDone(const WebPRescaler* const rescaler) {
- return (rescaler->src_y >= rescaler->src_height);
-}
-// Return true if output is finished
-static WEBP_INLINE
-int WebPRescalerOutputDone(const WebPRescaler* const rescaler) {
- return (rescaler->dst_y >= rescaler->dst_height);
-}
-
-// Return true if there are pending output rows ready.
-static WEBP_INLINE
-int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) {
- return !WebPRescalerOutputDone(rescaler) && (rescaler->y_accum <= 0);
-}
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_RESCALER_H_ */
diff --git a/drivers/webp/utils/thread.c b/drivers/webp/utils/thread.c
deleted file mode 100644
index 93f7622797..0000000000
--- a/drivers/webp/utils/thread.c
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Multi-threaded worker
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <string.h> // for memset()
-#include "./thread.h"
-#include "./utils.h"
-
-#ifdef WEBP_USE_THREAD
-
-#if defined(_WIN32)
-
-#include <windows.h>
-typedef HANDLE pthread_t;
-typedef CRITICAL_SECTION pthread_mutex_t;
-
-#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater
-#define USE_WINDOWS_CONDITION_VARIABLE
-typedef CONDITION_VARIABLE pthread_cond_t;
-#else
-typedef struct {
- HANDLE waiting_sem_;
- HANDLE received_sem_;
- HANDLE signal_event_;
-} pthread_cond_t;
-#endif // _WIN32_WINNT >= 0x600
-
-#ifndef WINAPI_FAMILY_PARTITION
-#define WINAPI_PARTITION_DESKTOP 1
-#define WINAPI_FAMILY_PARTITION(x) x
-#endif
-
-#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-#define USE_CREATE_THREAD
-#endif
-
-#else // !_WIN32
-
-#include <pthread.h>
-
-#endif // _WIN32
-
-struct WebPWorkerImpl {
- pthread_mutex_t mutex_;
- pthread_cond_t condition_;
- pthread_t thread_;
-};
-
-#if defined(_WIN32)
-
-//------------------------------------------------------------------------------
-// simplistic pthread emulation layer
-
-#include <process.h>
-
-// _beginthreadex requires __stdcall
-#define THREADFN unsigned int __stdcall
-#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val)
-
-#if _WIN32_WINNT >= 0x0501 // Windows XP or greater
-#define WaitForSingleObject(obj, timeout) \
- WaitForSingleObjectEx(obj, timeout, FALSE /*bAlertable*/)
-#endif
-
-static int pthread_create(pthread_t* const thread, const void* attr,
- unsigned int (__stdcall *start)(void*), void* arg) {
- (void)attr;
-#ifdef USE_CREATE_THREAD
- *thread = CreateThread(NULL, /* lpThreadAttributes */
- 0, /* dwStackSize */
- start,
- arg,
- 0, /* dwStackSize */
- NULL); /* lpThreadId */
-#else
- *thread = (pthread_t)_beginthreadex(NULL, /* void *security */
- 0, /* unsigned stack_size */
- start,
- arg,
- 0, /* unsigned initflag */
- NULL); /* unsigned *thrdaddr */
-#endif
- if (*thread == NULL) return 1;
- SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL);
- return 0;
-}
-
-static int pthread_join(pthread_t thread, void** value_ptr) {
- (void)value_ptr;
- return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 ||
- CloseHandle(thread) == 0);
-}
-
-// Mutex
-static int pthread_mutex_init(pthread_mutex_t* const mutex, void* mutexattr) {
- (void)mutexattr;
-#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater
- InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/);
-#else
- InitializeCriticalSection(mutex);
-#endif
- return 0;
-}
-
-static int pthread_mutex_lock(pthread_mutex_t* const mutex) {
- EnterCriticalSection(mutex);
- return 0;
-}
-
-static int pthread_mutex_unlock(pthread_mutex_t* const mutex) {
- LeaveCriticalSection(mutex);
- return 0;
-}
-
-static int pthread_mutex_destroy(pthread_mutex_t* const mutex) {
- DeleteCriticalSection(mutex);
- return 0;
-}
-
-// Condition
-static int pthread_cond_destroy(pthread_cond_t* const condition) {
- int ok = 1;
-#ifdef USE_WINDOWS_CONDITION_VARIABLE
- (void)condition;
-#else
- ok &= (CloseHandle(condition->waiting_sem_) != 0);
- ok &= (CloseHandle(condition->received_sem_) != 0);
- ok &= (CloseHandle(condition->signal_event_) != 0);
-#endif
- return !ok;
-}
-
-static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) {
- (void)cond_attr;
-#ifdef USE_WINDOWS_CONDITION_VARIABLE
- InitializeConditionVariable(condition);
-#else
- condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
- condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL);
- condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (condition->waiting_sem_ == NULL ||
- condition->received_sem_ == NULL ||
- condition->signal_event_ == NULL) {
- pthread_cond_destroy(condition);
- return 1;
- }
-#endif
- return 0;
-}
-
-static int pthread_cond_signal(pthread_cond_t* const condition) {
- int ok = 1;
-#ifdef USE_WINDOWS_CONDITION_VARIABLE
- WakeConditionVariable(condition);
-#else
- if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) {
- // a thread is waiting in pthread_cond_wait: allow it to be notified
- ok = SetEvent(condition->signal_event_);
- // wait until the event is consumed so the signaler cannot consume
- // the event via its own pthread_cond_wait.
- ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) !=
- WAIT_OBJECT_0);
- }
-#endif
- return !ok;
-}
-
-static int pthread_cond_wait(pthread_cond_t* const condition,
- pthread_mutex_t* const mutex) {
- int ok;
-#ifdef USE_WINDOWS_CONDITION_VARIABLE
- ok = SleepConditionVariableCS(condition, mutex, INFINITE);
-#else
- // note that there is a consumer available so the signal isn't dropped in
- // pthread_cond_signal
- if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
- return 1;
- // now unlock the mutex so pthread_cond_signal may be issued
- pthread_mutex_unlock(mutex);
- ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
- WAIT_OBJECT_0);
- ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL);
- pthread_mutex_lock(mutex);
-#endif
- return !ok;
-}
-
-#else // !_WIN32
-# define THREADFN void*
-# define THREAD_RETURN(val) val
-#endif // _WIN32
-
-//------------------------------------------------------------------------------
-
-static void Execute(WebPWorker* const worker); // Forward declaration.
-
-static THREADFN ThreadLoop(void* ptr) {
- WebPWorker* const worker = (WebPWorker*)ptr;
- int done = 0;
- while (!done) {
- pthread_mutex_lock(&worker->impl_->mutex_);
- while (worker->status_ == OK) { // wait in idling mode
- pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
- }
- if (worker->status_ == WORK) {
- Execute(worker);
- worker->status_ = OK;
- } else if (worker->status_ == NOT_OK) { // finish the worker
- done = 1;
- }
- // signal to the main thread that we're done (for Sync())
- pthread_cond_signal(&worker->impl_->condition_);
- pthread_mutex_unlock(&worker->impl_->mutex_);
- }
- return THREAD_RETURN(NULL); // Thread is finished
-}
-
-// main thread state control
-static void ChangeState(WebPWorker* const worker,
- WebPWorkerStatus new_status) {
- // No-op when attempting to change state on a thread that didn't come up.
- // Checking status_ without acquiring the lock first would result in a data
- // race.
- if (worker->impl_ == NULL) return;
-
- pthread_mutex_lock(&worker->impl_->mutex_);
- if (worker->status_ >= OK) {
- // wait for the worker to finish
- while (worker->status_ != OK) {
- pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
- }
- // assign new status and release the working thread if needed
- if (new_status != OK) {
- worker->status_ = new_status;
- pthread_cond_signal(&worker->impl_->condition_);
- }
- }
- pthread_mutex_unlock(&worker->impl_->mutex_);
-}
-
-#endif // WEBP_USE_THREAD
-
-//------------------------------------------------------------------------------
-
-static void Init(WebPWorker* const worker) {
- memset(worker, 0, sizeof(*worker));
- worker->status_ = NOT_OK;
-}
-
-static int Sync(WebPWorker* const worker) {
-#ifdef WEBP_USE_THREAD
- ChangeState(worker, OK);
-#endif
- assert(worker->status_ <= OK);
- return !worker->had_error;
-}
-
-static int Reset(WebPWorker* const worker) {
- int ok = 1;
- worker->had_error = 0;
- if (worker->status_ < OK) {
-#ifdef WEBP_USE_THREAD
- worker->impl_ = (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(*worker->impl_));
- if (worker->impl_ == NULL) {
- return 0;
- }
- if (pthread_mutex_init(&worker->impl_->mutex_, NULL)) {
- goto Error;
- }
- if (pthread_cond_init(&worker->impl_->condition_, NULL)) {
- pthread_mutex_destroy(&worker->impl_->mutex_);
- goto Error;
- }
- pthread_mutex_lock(&worker->impl_->mutex_);
- ok = !pthread_create(&worker->impl_->thread_, NULL, ThreadLoop, worker);
- if (ok) worker->status_ = OK;
- pthread_mutex_unlock(&worker->impl_->mutex_);
- if (!ok) {
- pthread_mutex_destroy(&worker->impl_->mutex_);
- pthread_cond_destroy(&worker->impl_->condition_);
- Error:
- WebPSafeFree(worker->impl_);
- worker->impl_ = NULL;
- return 0;
- }
-#else
- worker->status_ = OK;
-#endif
- } else if (worker->status_ > OK) {
- ok = Sync(worker);
- }
- assert(!ok || (worker->status_ == OK));
- return ok;
-}
-
-static void Execute(WebPWorker* const worker) {
- if (worker->hook != NULL) {
- worker->had_error |= !worker->hook(worker->data1, worker->data2);
- }
-}
-
-static void Launch(WebPWorker* const worker) {
-#ifdef WEBP_USE_THREAD
- ChangeState(worker, WORK);
-#else
- Execute(worker);
-#endif
-}
-
-static void End(WebPWorker* const worker) {
-#ifdef WEBP_USE_THREAD
- if (worker->impl_ != NULL) {
- ChangeState(worker, NOT_OK);
- pthread_join(worker->impl_->thread_, NULL);
- pthread_mutex_destroy(&worker->impl_->mutex_);
- pthread_cond_destroy(&worker->impl_->condition_);
- WebPSafeFree(worker->impl_);
- worker->impl_ = NULL;
- }
-#else
- worker->status_ = NOT_OK;
- assert(worker->impl_ == NULL);
-#endif
- assert(worker->status_ == NOT_OK);
-}
-
-//------------------------------------------------------------------------------
-
-static WebPWorkerInterface g_worker_interface = {
- Init, Reset, Sync, Launch, Execute, End
-};
-
-int WebPSetWorkerInterface(const WebPWorkerInterface* const winterface) {
- if (winterface == NULL ||
- winterface->Init == NULL || winterface->Reset == NULL ||
- winterface->Sync == NULL || winterface->Launch == NULL ||
- winterface->Execute == NULL || winterface->End == NULL) {
- return 0;
- }
- g_worker_interface = *winterface;
- return 1;
-}
-
-const WebPWorkerInterface* WebPGetWorkerInterface(void) {
- return &g_worker_interface;
-}
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/utils/thread.h b/drivers/webp/utils/thread.h
deleted file mode 100644
index 6008bb7c01..0000000000
--- a/drivers/webp/utils/thread.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Multi-threaded worker
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_UTILS_THREAD_H_
-#define WEBP_UTILS_THREAD_H_
-
-#ifdef HAVE_CONFIG_H
-#include "webp/config.h"
-#endif
-
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// State of the worker thread object
-typedef enum {
- NOT_OK = 0, // object is unusable
- OK, // ready to work
- WORK // busy finishing the current task
-} WebPWorkerStatus;
-
-// Function to be called by the worker thread. Takes two opaque pointers as
-// arguments (data1 and data2), and should return false in case of error.
-typedef int (*WebPWorkerHook)(void*, void*);
-
-// Platform-dependent implementation details for the worker.
-typedef struct WebPWorkerImpl WebPWorkerImpl;
-
-// Synchronization object used to launch job in the worker thread
-typedef struct {
- WebPWorkerImpl* impl_;
- WebPWorkerStatus status_;
- WebPWorkerHook hook; // hook to call
- void* data1; // first argument passed to 'hook'
- void* data2; // second argument passed to 'hook'
- int had_error; // return value of the last call to 'hook'
-} WebPWorker;
-
-// The interface for all thread-worker related functions. All these functions
-// must be implemented.
-typedef struct {
- // Must be called first, before any other method.
- void (*Init)(WebPWorker* const worker);
- // Must be called to initialize the object and spawn the thread. Re-entrant.
- // Will potentially launch the thread. Returns false in case of error.
- int (*Reset)(WebPWorker* const worker);
- // Makes sure the previous work is finished. Returns true if worker->had_error
- // was not set and no error condition was triggered by the working thread.
- int (*Sync)(WebPWorker* const worker);
- // Triggers the thread to call hook() with data1 and data2 arguments. These
- // hook/data1/data2 values can be changed at any time before calling this
- // function, but not be changed afterward until the next call to Sync().
- void (*Launch)(WebPWorker* const worker);
- // This function is similar to Launch() except that it calls the
- // hook directly instead of using a thread. Convenient to bypass the thread
- // mechanism while still using the WebPWorker structs. Sync() must
- // still be called afterward (for error reporting).
- void (*Execute)(WebPWorker* const worker);
- // Kill the thread and terminate the object. To use the object again, one
- // must call Reset() again.
- void (*End)(WebPWorker* const worker);
-} WebPWorkerInterface;
-
-// Install a new set of threading functions, overriding the defaults. This
-// should be done before any workers are started, i.e., before any encoding or
-// decoding takes place. The contents of the interface struct are copied, it
-// is safe to free the corresponding memory after this call. This function is
-// not thread-safe. Return false in case of invalid pointer or methods.
-WEBP_EXTERN(int) WebPSetWorkerInterface(
- const WebPWorkerInterface* const winterface);
-
-// Retrieve the currently set thread worker interface.
-WEBP_EXTERN(const WebPWorkerInterface*) WebPGetWorkerInterface(void);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_THREAD_H_ */
diff --git a/drivers/webp/utils/utils.c b/drivers/webp/utils/utils.c
deleted file mode 100644
index b2193c4b47..0000000000
--- a/drivers/webp/utils/utils.c
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Misc. common utility functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-#include <string.h> // for memcpy()
-#include "webp/decode.h"
-#include "webp/encode.h"
-#include "webp/format_constants.h" // for MAX_PALETTE_SIZE
-#include "./utils.h"
-
-// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of
-// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow,
-// and not multi-thread safe!).
-// An interesting alternative is valgrind's 'massif' tool:
-// http://valgrind.org/docs/manual/ms-manual.html
-// Here is an example command line:
-/* valgrind --tool=massif --massif-out-file=massif.out \
- --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc
- ms_print massif.out
-*/
-// In addition:
-// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles
-// are printed.
-// * if MALLOC_FAIL_AT is defined, the global environment variable
-// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc
-// is called for the nth time. Example usage:
-// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png
-// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT
-// sets the maximum amount of memory (in bytes) made available to libwebp.
-// This can be used to emulate environment with very limited memory.
-// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp
-
-// #define PRINT_MEM_INFO
-// #define PRINT_MEM_TRAFFIC
-// #define MALLOC_FAIL_AT
-// #define MALLOC_LIMIT
-
-//------------------------------------------------------------------------------
-// Checked memory allocation
-
-#if defined(PRINT_MEM_INFO)
-
-#include <stdio.h>
-
-static int num_malloc_calls = 0;
-static int num_calloc_calls = 0;
-static int num_free_calls = 0;
-static int countdown_to_fail = 0; // 0 = off
-
-typedef struct MemBlock MemBlock;
-struct MemBlock {
- void* ptr_;
- size_t size_;
- MemBlock* next_;
-};
-
-static MemBlock* all_blocks = NULL;
-static size_t total_mem = 0;
-static size_t total_mem_allocated = 0;
-static size_t high_water_mark = 0;
-static size_t mem_limit = 0;
-
-static int exit_registered = 0;
-
-static void PrintMemInfo(void) {
- fprintf(stderr, "\nMEMORY INFO:\n");
- fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls);
- fprintf(stderr, " calloc = %4d\n", num_calloc_calls);
- fprintf(stderr, " free = %4d\n", num_free_calls);
- fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem);
- fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated);
- fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark);
- while (all_blocks != NULL) {
- MemBlock* b = all_blocks;
- all_blocks = b->next_;
- free(b);
- }
-}
-
-static void Increment(int* const v) {
- if (!exit_registered) {
-#if defined(MALLOC_FAIL_AT)
- {
- const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT");
- if (malloc_fail_at_str != NULL) {
- countdown_to_fail = atoi(malloc_fail_at_str);
- }
- }
-#endif
-#if defined(MALLOC_LIMIT)
- {
- const char* const malloc_limit_str = getenv("MALLOC_LIMIT");
- if (malloc_limit_str != NULL) {
- mem_limit = atoi(malloc_limit_str);
- }
- }
-#endif
- (void)countdown_to_fail;
- (void)mem_limit;
- atexit(PrintMemInfo);
- exit_registered = 1;
- }
- ++*v;
-}
-
-static void AddMem(void* ptr, size_t size) {
- if (ptr != NULL) {
- MemBlock* const b = (MemBlock*)malloc(sizeof(*b));
- if (b == NULL) abort();
- b->next_ = all_blocks;
- all_blocks = b;
- b->ptr_ = ptr;
- b->size_ = size;
- total_mem += size;
- total_mem_allocated += size;
-#if defined(PRINT_MEM_TRAFFIC)
-#if defined(MALLOC_FAIL_AT)
- fprintf(stderr, "fail-count: %5d [mem=%u]\n",
- num_malloc_calls + num_calloc_calls, (uint32_t)total_mem);
-#else
- fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size);
-#endif
-#endif
- if (total_mem > high_water_mark) high_water_mark = total_mem;
- }
-}
-
-static void SubMem(void* ptr) {
- if (ptr != NULL) {
- MemBlock** b = &all_blocks;
- // Inefficient search, but that's just for debugging.
- while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_;
- if (*b == NULL) {
- fprintf(stderr, "Invalid pointer free! (%p)\n", ptr);
- abort();
- }
- {
- MemBlock* const block = *b;
- *b = block->next_;
- total_mem -= block->size_;
-#if defined(PRINT_MEM_TRAFFIC)
- fprintf(stderr, "Mem: %u (-%u)\n",
- (uint32_t)total_mem, (uint32_t)block->size_);
-#endif
- free(block);
- }
- }
-}
-
-#else
-#define Increment(v) do {} while (0)
-#define AddMem(p, s) do {} while (0)
-#define SubMem(p) do {} while (0)
-#endif
-
-// Returns 0 in case of overflow of nmemb * size.
-static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
- const uint64_t total_size = nmemb * size;
- if (nmemb == 0) return 1;
- if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0;
- if (total_size != (size_t)total_size) return 0;
-#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT)
- if (countdown_to_fail > 0 && --countdown_to_fail == 0) {
- return 0; // fake fail!
- }
-#endif
-#if defined(MALLOC_LIMIT)
- if (mem_limit > 0 && total_mem + total_size >= mem_limit) {
- return 0; // fake fail!
- }
-#endif
-
- return 1;
-}
-
-void* WebPSafeMalloc(uint64_t nmemb, size_t size) {
- void* ptr;
- Increment(&num_malloc_calls);
- if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL;
- assert(nmemb * size > 0);
- ptr = malloc((size_t)(nmemb * size));
- AddMem(ptr, (size_t)(nmemb * size));
- return ptr;
-}
-
-void* WebPSafeCalloc(uint64_t nmemb, size_t size) {
- void* ptr;
- Increment(&num_calloc_calls);
- if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL;
- assert(nmemb * size > 0);
- ptr = calloc((size_t)nmemb, size);
- AddMem(ptr, (size_t)(nmemb * size));
- return ptr;
-}
-
-void WebPSafeFree(void* const ptr) {
- if (ptr != NULL) {
- Increment(&num_free_calls);
- SubMem(ptr);
- }
- free(ptr);
-}
-
-// Public API function.
-void WebPFree(void* ptr) {
- free(ptr);
-}
-
-//------------------------------------------------------------------------------
-
-void WebPCopyPlane(const uint8_t* src, int src_stride,
- uint8_t* dst, int dst_stride, int width, int height) {
- assert(src != NULL && dst != NULL);
- assert(src_stride >= width && dst_stride >= width);
- while (height-- > 0) {
- memcpy(dst, src, width);
- src += src_stride;
- dst += dst_stride;
- }
-}
-
-void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
- assert(src != NULL && dst != NULL);
- assert(src->width == dst->width && src->height == dst->height);
- assert(src->use_argb && dst->use_argb);
- WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb,
- 4 * dst->argb_stride, 4 * src->width, src->height);
-}
-
-//------------------------------------------------------------------------------
-
-#define MAX_COLOR_COUNT MAX_PALETTE_SIZE
-#define COLOR_HASH_SIZE (MAX_COLOR_COUNT * 4)
-#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE).
-
-int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
- int i;
- int x, y;
- int num_colors = 0;
- uint8_t in_use[COLOR_HASH_SIZE] = { 0 };
- uint32_t colors[COLOR_HASH_SIZE];
- static const uint32_t kHashMul = 0x1e35a7bdU;
- const uint32_t* argb = pic->argb;
- const int width = pic->width;
- const int height = pic->height;
- uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0]
- assert(pic != NULL);
- assert(pic->use_argb);
-
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- int key;
- if (argb[x] == last_pix) {
- continue;
- }
- last_pix = argb[x];
- key = (kHashMul * last_pix) >> COLOR_HASH_RIGHT_SHIFT;
- while (1) {
- if (!in_use[key]) {
- colors[key] = last_pix;
- in_use[key] = 1;
- ++num_colors;
- if (num_colors > MAX_COLOR_COUNT) {
- return MAX_COLOR_COUNT + 1; // Exact count not needed.
- }
- break;
- } else if (colors[key] == last_pix) {
- break; // The color is already there.
- } else {
- // Some other color sits here, so do linear conflict resolution.
- ++key;
- key &= (COLOR_HASH_SIZE - 1); // Key mask.
- }
- }
- }
- argb += pic->argb_stride;
- }
-
- if (palette != NULL) { // Fill the colors into palette.
- num_colors = 0;
- for (i = 0; i < COLOR_HASH_SIZE; ++i) {
- if (in_use[i]) {
- palette[num_colors] = colors[i];
- ++num_colors;
- }
- }
- }
- return num_colors;
-}
-
-#undef MAX_COLOR_COUNT
-#undef COLOR_HASH_SIZE
-#undef COLOR_HASH_RIGHT_SHIFT
-
-//------------------------------------------------------------------------------
diff --git a/drivers/webp/utils/utils.h b/drivers/webp/utils/utils.h
deleted file mode 100644
index cef496af78..0000000000
--- a/drivers/webp/utils/utils.h
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Misc. common utility functions
-//
-// Authors: Skal (pascal.massimino@gmail.com)
-// Urvang (urvang@google.com)
-
-#ifndef WEBP_UTILS_UTILS_H_
-#define WEBP_UTILS_UTILS_H_
-
-#ifdef HAVE_CONFIG_H
-#include "webp/config.h"
-#endif
-
-#include <assert.h>
-
-#include "../dsp/dsp.h"
-#include "webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Memory allocation
-
-// This is the maximum memory amount that libwebp will ever try to allocate.
-#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 40)
-
-// size-checking safe malloc/calloc: verify that the requested size is not too
-// large, or return NULL. You don't need to call these for constructs like
-// malloc(sizeof(foo)), but only if there's picture-dependent size involved
-// somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this
-// safe malloc() borrows the signature from calloc(), pointing at the dangerous
-// underlying multiply involved.
-WEBP_EXTERN(void*) WebPSafeMalloc(uint64_t nmemb, size_t size);
-// Note that WebPSafeCalloc() expects the second argument type to be 'size_t'
-// in order to favor the "calloc(num_foo, sizeof(foo))" pattern.
-WEBP_EXTERN(void*) WebPSafeCalloc(uint64_t nmemb, size_t size);
-
-// Companion deallocation function to the above allocations.
-WEBP_EXTERN(void) WebPSafeFree(void* const ptr);
-
-//------------------------------------------------------------------------------
-// Alignment
-
-#define WEBP_ALIGN_CST 31
-#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST)
-
-#if defined(WEBP_FORCE_ALIGNED)
-#include <string.h>
-// memcpy() is the safe way of moving potentially unaligned 32b memory.
-static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) {
- uint32_t A;
- memcpy(&A, (const int*)ptr, sizeof(A));
- return A;
-}
-static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
- memcpy(ptr, &val, sizeof(val));
-}
-#else
-static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE
-uint32_t WebPMemToUint32(const uint8_t* const ptr) {
- return *(const uint32_t*)ptr;
-}
-static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE
-void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
- *(uint32_t*)ptr = val;
-}
-#endif
-
-//------------------------------------------------------------------------------
-// Reading/writing data.
-
-// Read 16, 24 or 32 bits stored in little-endian order.
-static WEBP_INLINE int GetLE16(const uint8_t* const data) {
- return (int)(data[0] << 0) | (data[1] << 8);
-}
-
-static WEBP_INLINE int GetLE24(const uint8_t* const data) {
- return GetLE16(data) | (data[2] << 16);
-}
-
-static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) {
- return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16);
-}
-
-// Store 16, 24 or 32 bits in little-endian order.
-static WEBP_INLINE void PutLE16(uint8_t* const data, int val) {
- assert(val < (1 << 16));
- data[0] = (val >> 0);
- data[1] = (val >> 8);
-}
-
-static WEBP_INLINE void PutLE24(uint8_t* const data, int val) {
- assert(val < (1 << 24));
- PutLE16(data, val & 0xffff);
- data[2] = (val >> 16);
-}
-
-static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
- PutLE16(data, (int)(val & 0xffff));
- PutLE16(data + 2, (int)(val >> 16));
-}
-
-// Returns (int)floor(log2(n)). n must be > 0.
-// use GNU builtins where available.
-#if defined(__GNUC__) && \
- ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
-static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
- return 31 ^ __builtin_clz(n);
-}
-#elif defined(_MSC_VER) && _MSC_VER > 1310 && \
- (defined(_M_X64) || defined(_M_IX86))
-#include <intrin.h>
-#pragma intrinsic(_BitScanReverse)
-
-static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
- unsigned long first_set_bit;
- _BitScanReverse(&first_set_bit, n);
- return first_set_bit;
-}
-#else
-static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
- int log = 0;
- uint32_t value = n;
- int i;
-
- for (i = 4; i >= 0; --i) {
- const int shift = (1 << i);
- const uint32_t x = value >> shift;
- if (x != 0) {
- value = x;
- log += shift;
- }
- }
- return log;
-}
-#endif
-
-//------------------------------------------------------------------------------
-// Pixel copying.
-
-struct WebPPicture;
-
-// Copy width x height pixels from 'src' to 'dst' honoring the strides.
-WEBP_EXTERN(void) WebPCopyPlane(const uint8_t* src, int src_stride,
- uint8_t* dst, int dst_stride,
- int width, int height);
-
-// Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are
-// assumed to be already allocated and using ARGB data.
-WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src,
- struct WebPPicture* const dst);
-
-//------------------------------------------------------------------------------
-// Unique colors.
-
-// Returns count of unique colors in 'pic', assuming pic->use_argb is true.
-// If the unique color count is more than MAX_COLOR_COUNT, returns
-// MAX_COLOR_COUNT+1.
-// If 'palette' is not NULL and number of unique colors is less than or equal to
-// MAX_COLOR_COUNT, also outputs the actual unique colors into 'palette'.
-// Note: 'palette' is assumed to be an array already allocated with at least
-// MAX_COLOR_COUNT elements.
-WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic,
- uint32_t* const palette);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_UTILS_H_ */