From 2073ead37e554bdca42215129978ce46d36c45c8 Mon Sep 17 00:00:00 2001 From: DrKLO Date: Sat, 3 Jan 2015 01:15:07 +0300 Subject: [PATCH] Update to 2.3.0 --- TMessagesProj/build.gradle | 20 +- TMessagesProj/jni/Android.mk | 111 +- TMessagesProj/jni/gif.c | 2 +- TMessagesProj/jni/image.c | 150 +- TMessagesProj/jni/image.h | 8 + TMessagesProj/jni/jni.c | 9 +- TMessagesProj/jni/libwebp/dec/alpha.c | 165 ++ TMessagesProj/jni/libwebp/dec/alphai.h | 55 + TMessagesProj/jni/libwebp/dec/buffer.c | 251 +++ TMessagesProj/jni/libwebp/dec/decode_vp8.h | 185 ++ TMessagesProj/jni/libwebp/dec/frame.c | 828 +++++++++ TMessagesProj/jni/libwebp/dec/idec.c | 857 +++++++++ TMessagesProj/jni/libwebp/dec/io.c | 648 +++++++ TMessagesProj/jni/libwebp/dec/quant.c | 110 ++ TMessagesProj/jni/libwebp/dec/tree.c | 516 ++++++ TMessagesProj/jni/libwebp/dec/vp8.c | 668 +++++++ TMessagesProj/jni/libwebp/dec/vp8i.h | 354 ++++ TMessagesProj/jni/libwebp/dec/vp8l.c | 1404 ++++++++++++++ TMessagesProj/jni/libwebp/dec/vp8li.h | 132 ++ TMessagesProj/jni/libwebp/dec/webp.c | 836 +++++++++ TMessagesProj/jni/libwebp/dec/webpi.h | 120 ++ .../jni/libwebp/dsp/alpha_processing.c | 329 ++++ .../jni/libwebp/dsp/alpha_processing_sse2.c | 77 + TMessagesProj/jni/libwebp/dsp/cpu.c | 130 ++ TMessagesProj/jni/libwebp/dsp/dec.c | 731 ++++++++ .../jni/libwebp/dsp/dec_clip_tables.c | 366 ++++ TMessagesProj/jni/libwebp/dsp/dec_mips32.c | 578 ++++++ TMessagesProj/jni/libwebp/dsp/dec_neon.c | 1292 +++++++++++++ TMessagesProj/jni/libwebp/dsp/dec_sse2.c | 978 ++++++++++ TMessagesProj/jni/libwebp/dsp/dsp.h | 293 +++ TMessagesProj/jni/libwebp/dsp/enc.c | 741 ++++++++ TMessagesProj/jni/libwebp/dsp/enc_avx2.c | 24 + TMessagesProj/jni/libwebp/dsp/enc_mips32.c | 776 ++++++++ TMessagesProj/jni/libwebp/dsp/enc_neon.c | 1077 +++++++++++ TMessagesProj/jni/libwebp/dsp/enc_sse2.c | 982 ++++++++++ TMessagesProj/jni/libwebp/dsp/lossless.c | 1639 +++++++++++++++++ TMessagesProj/jni/libwebp/dsp/lossless.h | 249 +++ .../jni/libwebp/dsp/lossless_mips32.c | 416 +++++ TMessagesProj/jni/libwebp/dsp/lossless_neon.c | 332 ++++ TMessagesProj/jni/libwebp/dsp/lossless_sse2.c | 535 ++++++ TMessagesProj/jni/libwebp/dsp/neon.h | 82 + TMessagesProj/jni/libwebp/dsp/upsampling.c | 222 +++ .../jni/libwebp/dsp/upsampling_neon.c | 267 +++ .../jni/libwebp/dsp/upsampling_sse2.c | 214 +++ TMessagesProj/jni/libwebp/dsp/yuv.c | 154 ++ TMessagesProj/jni/libwebp/dsp/yuv.h | 321 ++++ TMessagesProj/jni/libwebp/dsp/yuv_mips32.c | 100 + TMessagesProj/jni/libwebp/dsp/yuv_sse2.c | 322 ++++ .../jni/libwebp/dsp/yuv_tables_sse2.h | 536 ++++++ TMessagesProj/jni/libwebp/enc/alpha.c | 433 +++++ TMessagesProj/jni/libwebp/enc/analysis.c | 498 +++++ .../jni/libwebp/enc/backward_references.c | 975 ++++++++++ .../jni/libwebp/enc/backward_references.h | 212 +++ TMessagesProj/jni/libwebp/enc/config.c | 166 ++ TMessagesProj/jni/libwebp/enc/cost.c | 735 ++++++++ TMessagesProj/jni/libwebp/enc/cost.h | 83 + TMessagesProj/jni/libwebp/enc/filter.c | 296 +++ TMessagesProj/jni/libwebp/enc/frame.c | 854 +++++++++ TMessagesProj/jni/libwebp/enc/histogram.c | 741 ++++++++ TMessagesProj/jni/libwebp/enc/histogram.h | 118 ++ TMessagesProj/jni/libwebp/enc/iterator.c | 456 +++++ TMessagesProj/jni/libwebp/enc/picture.c | 289 +++ TMessagesProj/jni/libwebp/enc/picture_csp.c | 1114 +++++++++++ TMessagesProj/jni/libwebp/enc/picture_psnr.c | 150 ++ .../jni/libwebp/enc/picture_rescale.c | 285 +++ TMessagesProj/jni/libwebp/enc/picture_tools.c | 206 +++ TMessagesProj/jni/libwebp/enc/quant.c | 1170 ++++++++++++ TMessagesProj/jni/libwebp/enc/syntax.c | 383 ++++ TMessagesProj/jni/libwebp/enc/token.c | 286 +++ TMessagesProj/jni/libwebp/enc/tree.c | 504 +++++ TMessagesProj/jni/libwebp/enc/vp8enci.h | 582 ++++++ TMessagesProj/jni/libwebp/enc/vp8l.c | 1244 +++++++++++++ TMessagesProj/jni/libwebp/enc/vp8li.h | 77 + TMessagesProj/jni/libwebp/enc/webpenc.c | 382 ++++ TMessagesProj/jni/libwebp/utils/bit_reader.c | 210 +++ TMessagesProj/jni/libwebp/utils/bit_reader.h | 169 ++ .../jni/libwebp/utils/bit_reader_inl.h | 172 ++ TMessagesProj/jni/libwebp/utils/bit_writer.c | 307 +++ TMessagesProj/jni/libwebp/utils/bit_writer.h | 120 ++ TMessagesProj/jni/libwebp/utils/color_cache.c | 39 + TMessagesProj/jni/libwebp/utils/color_cache.h | 70 + TMessagesProj/jni/libwebp/utils/endian_inl.h | 100 + TMessagesProj/jni/libwebp/utils/filters.c | 266 +++ TMessagesProj/jni/libwebp/utils/filters.h | 59 + TMessagesProj/jni/libwebp/utils/huffman.c | 319 ++++ TMessagesProj/jni/libwebp/utils/huffman.h | 102 + .../jni/libwebp/utils/huffman_encode.c | 417 +++++ .../jni/libwebp/utils/huffman_encode.h | 61 + .../jni/libwebp/utils/quant_levels.c | 140 ++ .../jni/libwebp/utils/quant_levels.h | 36 + .../jni/libwebp/utils/quant_levels_dec.c | 279 +++ .../jni/libwebp/utils/quant_levels_dec.h | 35 + TMessagesProj/jni/libwebp/utils/random.c | 43 + TMessagesProj/jni/libwebp/utils/random.h | 63 + TMessagesProj/jni/libwebp/utils/rescaler.c | 333 ++++ TMessagesProj/jni/libwebp/utils/rescaler.h | 82 + TMessagesProj/jni/libwebp/utils/thread.c | 309 ++++ TMessagesProj/jni/libwebp/utils/thread.h | 93 + TMessagesProj/jni/libwebp/utils/utils.c | 211 +++ TMessagesProj/jni/libwebp/utils/utils.h | 121 ++ TMessagesProj/jni/libwebp/webp/decode.h | 503 +++++ TMessagesProj/jni/libwebp/webp/demux.h | 224 +++ TMessagesProj/jni/libwebp/webp/encode.h | 518 ++++++ .../jni/libwebp/webp/format_constants.h | 88 + TMessagesProj/jni/libwebp/webp/mux.h | 399 ++++ TMessagesProj/jni/libwebp/webp/mux_types.h | 97 + TMessagesProj/jni/libwebp/webp/types.h | 47 + TMessagesProj/jni/sqlite/sqlite3.c | 214 ++- TMessagesProj/jni/sqlite/sqlite3.h | 4 +- TMessagesProj/jni/sqlite_statement.c | 2 +- .../libs/armeabi-v7a/libtmessages.4.so | Bin 1037088 -> 0 bytes .../libs/armeabi-v7a/libtmessages.5.so | Bin 0 -> 1565572 bytes TMessagesProj/libs/armeabi/libtmessages.4.so | Bin 951052 -> 0 bytes TMessagesProj/libs/armeabi/libtmessages.5.so | Bin 0 -> 1573732 bytes TMessagesProj/libs/x86/libtmessages.4.so | Bin 1624308 -> 0 bytes TMessagesProj/libs/x86/libtmessages.5.so | Bin 0 -> 1869740 bytes .../telegram/android/AndroidUtilities.java | 12 +- .../telegram/android/ContactsController.java | 38 +- .../main/java/org/telegram/android/Emoji.java | 4 +- .../org/telegram/android/ImageLoader.java | 440 ++++- .../org/telegram/android/ImageReceiver.java | 116 +- .../org/telegram/android/MediaController.java | 176 +- .../org/telegram/android/MessageObject.java | 67 +- .../telegram/android/MessagesController.java | 195 +- .../org/telegram/android/MessagesStorage.java | 362 ++-- .../org/telegram/android/NativeLoader.java | 2 +- .../telegram/android/NotificationCenter.java | 127 +- .../android/NotificationsController.java | 39 +- .../org/telegram/android/PhotoObject.java | 15 +- .../telegram/android/SecretChatHelper.java | 69 +- .../telegram/android/SendMessagesHelper.java | 422 ++++- .../android/volley/AuthFailureError.java | 58 + .../org/telegram/android/volley/Cache.java | 97 + .../android/volley/CacheDispatcher.java | 157 ++ .../android/volley/DefaultRetryPolicy.java | 105 ++ .../android/volley/ExecutorDelivery.java | 118 ++ .../org/telegram/android/volley/Network.java | 30 + .../android/volley/NetworkDispatcher.java | 152 ++ .../telegram/android/volley/NetworkError.java | 35 + .../android/volley/NetworkResponse.java | 73 + .../android/volley/NoConnectionError.java | 31 + .../telegram/android/volley/ParseError.java | 33 + .../org/telegram/android/volley/Request.java | 570 ++++++ .../telegram/android/volley/RequestQueue.java | 286 +++ .../org/telegram/android/volley/Response.java | 85 + .../android/volley/ResponseDelivery.java | 35 + .../telegram/android/volley/RetryPolicy.java | 41 + .../telegram/android/volley/ServerError.java | 31 + .../telegram/android/volley/TimeoutError.java | 23 + .../telegram/android/volley/VolleyError.java | 57 + .../telegram/android/volley/VolleyLog.java | 176 ++ .../volley/toolbox/AndroidAuthenticator.java | 102 + .../android/volley/toolbox/Authenticator.java | 36 + .../android/volley/toolbox/BasicNetwork.java | 264 +++ .../android/volley/toolbox/ByteArrayPool.java | 135 ++ .../volley/toolbox/ClearCacheRequest.java | 70 + .../volley/toolbox/DiskBasedCache.java | 599 ++++++ .../volley/toolbox/HttpClientStack.java | 192 ++ .../volley/toolbox/HttpHeaderParser.java | 137 ++ .../android/volley/toolbox/HttpStack.java | 44 + .../android/volley/toolbox/HurlStack.java | 243 +++ .../android/volley/toolbox/ImageLoader.java | 478 +++++ .../android/volley/toolbox/ImageRequest.java | 211 +++ .../volley/toolbox/JsonArrayRequest.java | 55 + .../volley/toolbox/JsonObjectRequest.java | 72 + .../android/volley/toolbox/JsonRequest.java | 99 + .../volley/toolbox/NetworkImageView.java | 219 +++ .../android/volley/toolbox/NoCache.java | 49 + .../toolbox/PoolingByteArrayOutputStream.java | 93 + .../android/volley/toolbox/RequestFuture.java | 150 ++ .../android/volley/toolbox/StringRequest.java | 71 + .../android/volley/toolbox/Volley.java | 81 + .../telegram/messenger/ConnectionContext.java | 8 +- .../messenger/ConnectionsManager.java | 126 +- .../org/telegram/messenger/Datacenter.java | 14 +- .../telegram/messenger/FileLoadOperation.java | 26 +- .../org/telegram/messenger/FileLoader.java | 61 +- .../org/telegram/messenger/TLClassStore.java | 16 +- .../java/org/telegram/messenger/TLRPC.java | 709 +++++-- .../org/telegram/messenger/UserConfig.java | 16 + .../org/telegram/messenger/Utilities.java | 32 +- .../telegram/ui/AccountPasswordActivity.java | 629 +++++++ .../ui/ActionBar/ActionBarLayout.java | 5 +- .../ui/ActionBar/ActionBarMenuItem.java | 102 +- .../Adapters/BaseContactsSearchAdapter.java | 2 +- .../ui/Adapters/BaseSectionsAdapter.java | 6 +- .../ui/Adapters/ContactsSearchAdapter.java | 16 +- .../telegram/ui/Adapters/CountryAdapter.java | 6 +- .../ui/Adapters/DialogsSearchAdapter.java | 28 +- .../telegram/ui/Adapters/StickersAdapter.java | 311 ++++ .../ui/Animation/PropertyValuesHolder.java | 30 +- .../org/telegram/ui/Cells/ChatAudioCell.java | 3 +- .../org/telegram/ui/Cells/ChatBaseCell.java | 7 +- .../org/telegram/ui/Cells/ChatMediaCell.java | 60 +- .../ui/Cells/PhotoPickerAlbumsCell.java | 182 ++ .../ui/Cells/PhotoPickerPhotoCell.java | 64 + .../ui/Cells/PhotoPickerSearchCell.java | 173 ++ .../org/telegram/ui/Cells/StickerCell.java | 74 + .../ui/Cells/TextDetailDocumentsCell.java | 3 +- .../org/telegram/ui/Cells/TextFieldCell.java | 104 ++ .../ui/Cells/TextInfoPrivacyCell.java | 4 + .../java/org/telegram/ui/Cells/UserCell.java | 2 +- .../telegram/ui/ChangeUsernameActivity.java | 2 +- .../java/org/telegram/ui/ChatActivity.java | 171 +- .../ui/Components/AvatarDrawable.java | 9 +- .../ui/Components/BackupImageView.java | 15 +- .../ui/Components/ChatActivityEnterView.java | 30 +- .../org/telegram/ui/Components/CheckBox.java | 58 +- .../Components/PhotoPickerBottomLayout.java | 126 ++ .../ui/Components/PopupAudioView.java | 3 +- .../ui/Components/RadialProgress.java | 4 + .../ui/Components/RecyclerListView.java | 97 + .../ui/Components/SlidingTabView.java | 149 ++ .../org/telegram/ui/ContactsActivity.java | 11 +- .../telegram/ui/CountrySelectActivity.java | 3 +- .../org/telegram/ui/GroupCreateActivity.java | 10 +- .../telegram/ui/LanguageSelectActivity.java | 3 +- .../org/telegram/ui/LastSeenActivity.java | 4 +- .../java/org/telegram/ui/LaunchActivity.java | 225 ++- .../java/org/telegram/ui/LoginActivity.java | 24 +- .../java/org/telegram/ui/MediaActivity.java | 10 +- .../org/telegram/ui/MessagesActivity.java | 6 +- .../telegram/ui/PhotoAlbumPickerActivity.java | 481 +++++ .../org/telegram/ui/PhotoCropActivity.java | 2 +- .../org/telegram/ui/PhotoPickerActivity.java | 963 +++++++--- .../java/org/telegram/ui/PhotoViewer.java | 491 +++-- .../ui/PopupNotificationActivity.java | 16 +- .../telegram/ui/PrivacySettingsActivity.java | 13 +- .../java/org/telegram/ui/ProfileActivity.java | 91 +- .../org/telegram/ui/SettingsActivity.java | 12 +- .../src/main/res/drawable-hdpi/checkbig.png | Bin 0 -> 1229 bytes .../src/main/res/drawable-hdpi/gif_search.png | Bin 0 -> 1895 bytes .../main/res/drawable-hdpi/ic_ab_attach.png | Bin 2106 -> 1674 bytes .../main/res/drawable-hdpi/ic_close_white.png | Bin 0 -> 324 bytes .../res/drawable-hdpi/ic_msg_panel_smiles.png | Bin 1092 -> 1990 bytes .../src/main/res/drawable-hdpi/pagedown.png | Bin 1472 -> 2270 bytes .../res/drawable-hdpi/selectphoto_large.png | Bin 442 -> 1371 bytes .../res/drawable-hdpi/stickers_back_all.9.png | Bin 0 -> 1520 bytes .../res/drawable-hdpi/stickers_back_arrow.png | Bin 0 -> 1087 bytes .../drawable-hdpi/stickers_back_center.9.png | Bin 0 -> 136 bytes .../drawable-hdpi/stickers_back_left.9.png | Bin 0 -> 1316 bytes .../drawable-hdpi/stickers_back_right.9.png | Bin 0 -> 1310 bytes .../src/main/res/drawable-hdpi/web_search.png | Bin 0 -> 2296 bytes .../src/main/res/drawable-mdpi/checkbig.png | Bin 0 -> 1062 bytes .../src/main/res/drawable-mdpi/gif_search.png | Bin 0 -> 1583 bytes .../main/res/drawable-mdpi/ic_ab_attach.png | Bin 1397 -> 1437 bytes .../main/res/drawable-mdpi/ic_close_white.png | Bin 0 -> 279 bytes .../src/main/res/drawable-mdpi/pagedown.png | Bin 981 -> 1960 bytes .../res/drawable-mdpi/selectphoto_large.png | Bin 319 -> 1188 bytes .../res/drawable-mdpi/stickers_back_all.9.png | Bin 0 -> 400 bytes .../res/drawable-mdpi/stickers_back_arrow.png | Bin 0 -> 1045 bytes .../drawable-mdpi/stickers_back_center.9.png | Bin 0 -> 116 bytes .../drawable-mdpi/stickers_back_left.9.png | Bin 0 -> 285 bytes .../drawable-mdpi/stickers_back_right.9.png | Bin 0 -> 290 bytes .../src/main/res/drawable-mdpi/web_search.png | Bin 0 -> 1767 bytes .../src/main/res/drawable-xhdpi/checkbig.png | Bin 0 -> 1333 bytes .../main/res/drawable-xhdpi/gif_search.png | Bin 0 -> 2295 bytes .../main/res/drawable-xhdpi/ic_ab_attach.png | Bin 2620 -> 1923 bytes .../res/drawable-xhdpi/ic_close_white.png | Bin 0 -> 402 bytes .../drawable-xhdpi/ic_msg_panel_smiles.png | Bin 1477 -> 2401 bytes .../src/main/res/drawable-xhdpi/pagedown.png | Bin 1648 -> 3058 bytes .../res/drawable-xhdpi/selectphoto_large.png | Bin 540 -> 1448 bytes .../drawable-xhdpi/stickers_back_all.9.png | Bin 0 -> 853 bytes .../drawable-xhdpi/stickers_back_arrow.png | Bin 0 -> 1272 bytes .../drawable-xhdpi/stickers_back_center.9.png | Bin 0 -> 145 bytes .../drawable-xhdpi/stickers_back_left.9.png | Bin 0 -> 541 bytes .../drawable-xhdpi/stickers_back_right.9.png | Bin 0 -> 559 bytes .../main/res/drawable-xhdpi/web_search.png | Bin 0 -> 2832 bytes .../src/main/res/drawable-xxhdpi/checkbig.png | Bin 0 -> 1595 bytes .../main/res/drawable-xxhdpi/gif_search.png | Bin 0 -> 3108 bytes .../main/res/drawable-xxhdpi/ic_ab_attach.png | Bin 3605 -> 2319 bytes .../res/drawable-xxhdpi/ic_close_white.png | Bin 0 -> 492 bytes .../drawable-xxhdpi/ic_msg_panel_smiles.png | Bin 2261 -> 3223 bytes .../src/main/res/drawable-xxhdpi/pagedown.png | Bin 2422 -> 3919 bytes .../res/drawable-xxhdpi/selectphoto_large.png | Bin 698 -> 1952 bytes .../drawable-xxhdpi/stickers_back_all.9.png | Bin 0 -> 2280 bytes .../drawable-xxhdpi/stickers_back_arrow.png | Bin 0 -> 1451 bytes .../stickers_back_center.9.png | Bin 0 -> 182 bytes .../drawable-xxhdpi/stickers_back_left.9.png | Bin 0 -> 899 bytes .../drawable-xxhdpi/stickers_back_right.9.png | Bin 0 -> 894 bytes .../main/res/drawable-xxhdpi/web_search.png | Bin 0 -> 3878 bytes .../main/res/drawable-xxxhdpi/ic_launcher.png | Bin 14660 -> 12631 bytes .../src/main/res/layout/chat_layout.xml | 23 +- .../res/layout/photo_picker_album_layout.xml | 46 - .../res/layout/photo_picker_bottom_layout.xml | 63 - .../main/res/layout/photo_picker_layout.xml | 55 - .../res/layout/photo_picker_photo_layout.xml | 34 - .../src/main/res/values-ar/strings.xml | 42 +- .../src/main/res/values-de/strings.xml | 48 +- .../src/main/res/values-es/strings.xml | 42 +- .../src/main/res/values-it/strings.xml | 74 +- .../src/main/res/values-ko/strings.xml | 40 +- .../src/main/res/values-nl/strings.xml | 40 +- .../src/main/res/values-pt-rBR/strings.xml | 38 +- .../src/main/res/values-pt-rPT/strings.xml | 38 +- TMessagesProj/src/main/res/values/strings.xml | 38 +- 296 files changed, 51945 insertions(+), 1884 deletions(-) create mode 100644 TMessagesProj/jni/image.h create mode 100644 TMessagesProj/jni/libwebp/dec/alpha.c create mode 100644 TMessagesProj/jni/libwebp/dec/alphai.h create mode 100644 TMessagesProj/jni/libwebp/dec/buffer.c create mode 100644 TMessagesProj/jni/libwebp/dec/decode_vp8.h create mode 100644 TMessagesProj/jni/libwebp/dec/frame.c create mode 100644 TMessagesProj/jni/libwebp/dec/idec.c create mode 100644 TMessagesProj/jni/libwebp/dec/io.c create mode 100644 TMessagesProj/jni/libwebp/dec/quant.c create mode 100644 TMessagesProj/jni/libwebp/dec/tree.c create mode 100644 TMessagesProj/jni/libwebp/dec/vp8.c create mode 100644 TMessagesProj/jni/libwebp/dec/vp8i.h create mode 100644 TMessagesProj/jni/libwebp/dec/vp8l.c create mode 100644 TMessagesProj/jni/libwebp/dec/vp8li.h create mode 100644 TMessagesProj/jni/libwebp/dec/webp.c create mode 100644 TMessagesProj/jni/libwebp/dec/webpi.h create mode 100644 TMessagesProj/jni/libwebp/dsp/alpha_processing.c create mode 100644 TMessagesProj/jni/libwebp/dsp/alpha_processing_sse2.c create mode 100644 TMessagesProj/jni/libwebp/dsp/cpu.c create mode 100644 TMessagesProj/jni/libwebp/dsp/dec.c create mode 100644 TMessagesProj/jni/libwebp/dsp/dec_clip_tables.c create mode 100644 TMessagesProj/jni/libwebp/dsp/dec_mips32.c create mode 100644 TMessagesProj/jni/libwebp/dsp/dec_neon.c create mode 100644 TMessagesProj/jni/libwebp/dsp/dec_sse2.c create mode 100644 TMessagesProj/jni/libwebp/dsp/dsp.h create mode 100644 TMessagesProj/jni/libwebp/dsp/enc.c create mode 100644 TMessagesProj/jni/libwebp/dsp/enc_avx2.c create mode 100644 TMessagesProj/jni/libwebp/dsp/enc_mips32.c create mode 100644 TMessagesProj/jni/libwebp/dsp/enc_neon.c create mode 100644 TMessagesProj/jni/libwebp/dsp/enc_sse2.c create mode 100644 TMessagesProj/jni/libwebp/dsp/lossless.c create mode 100644 TMessagesProj/jni/libwebp/dsp/lossless.h create mode 100644 TMessagesProj/jni/libwebp/dsp/lossless_mips32.c create mode 100644 TMessagesProj/jni/libwebp/dsp/lossless_neon.c create mode 100644 TMessagesProj/jni/libwebp/dsp/lossless_sse2.c create mode 100644 TMessagesProj/jni/libwebp/dsp/neon.h create mode 100644 TMessagesProj/jni/libwebp/dsp/upsampling.c create mode 100644 TMessagesProj/jni/libwebp/dsp/upsampling_neon.c create mode 100644 TMessagesProj/jni/libwebp/dsp/upsampling_sse2.c create mode 100644 TMessagesProj/jni/libwebp/dsp/yuv.c create mode 100644 TMessagesProj/jni/libwebp/dsp/yuv.h create mode 100644 TMessagesProj/jni/libwebp/dsp/yuv_mips32.c create mode 100644 TMessagesProj/jni/libwebp/dsp/yuv_sse2.c create mode 100644 TMessagesProj/jni/libwebp/dsp/yuv_tables_sse2.h create mode 100644 TMessagesProj/jni/libwebp/enc/alpha.c create mode 100644 TMessagesProj/jni/libwebp/enc/analysis.c create mode 100644 TMessagesProj/jni/libwebp/enc/backward_references.c create mode 100644 TMessagesProj/jni/libwebp/enc/backward_references.h create mode 100644 TMessagesProj/jni/libwebp/enc/config.c create mode 100644 TMessagesProj/jni/libwebp/enc/cost.c create mode 100644 TMessagesProj/jni/libwebp/enc/cost.h create mode 100644 TMessagesProj/jni/libwebp/enc/filter.c create mode 100644 TMessagesProj/jni/libwebp/enc/frame.c create mode 100644 TMessagesProj/jni/libwebp/enc/histogram.c create mode 100644 TMessagesProj/jni/libwebp/enc/histogram.h create mode 100644 TMessagesProj/jni/libwebp/enc/iterator.c create mode 100644 TMessagesProj/jni/libwebp/enc/picture.c create mode 100644 TMessagesProj/jni/libwebp/enc/picture_csp.c create mode 100644 TMessagesProj/jni/libwebp/enc/picture_psnr.c create mode 100644 TMessagesProj/jni/libwebp/enc/picture_rescale.c create mode 100644 TMessagesProj/jni/libwebp/enc/picture_tools.c create mode 100644 TMessagesProj/jni/libwebp/enc/quant.c create mode 100644 TMessagesProj/jni/libwebp/enc/syntax.c create mode 100644 TMessagesProj/jni/libwebp/enc/token.c create mode 100644 TMessagesProj/jni/libwebp/enc/tree.c create mode 100644 TMessagesProj/jni/libwebp/enc/vp8enci.h create mode 100644 TMessagesProj/jni/libwebp/enc/vp8l.c create mode 100644 TMessagesProj/jni/libwebp/enc/vp8li.h create mode 100644 TMessagesProj/jni/libwebp/enc/webpenc.c create mode 100644 TMessagesProj/jni/libwebp/utils/bit_reader.c create mode 100644 TMessagesProj/jni/libwebp/utils/bit_reader.h create mode 100644 TMessagesProj/jni/libwebp/utils/bit_reader_inl.h create mode 100644 TMessagesProj/jni/libwebp/utils/bit_writer.c create mode 100644 TMessagesProj/jni/libwebp/utils/bit_writer.h create mode 100644 TMessagesProj/jni/libwebp/utils/color_cache.c create mode 100644 TMessagesProj/jni/libwebp/utils/color_cache.h create mode 100644 TMessagesProj/jni/libwebp/utils/endian_inl.h create mode 100644 TMessagesProj/jni/libwebp/utils/filters.c create mode 100644 TMessagesProj/jni/libwebp/utils/filters.h create mode 100644 TMessagesProj/jni/libwebp/utils/huffman.c create mode 100644 TMessagesProj/jni/libwebp/utils/huffman.h create mode 100644 TMessagesProj/jni/libwebp/utils/huffman_encode.c create mode 100644 TMessagesProj/jni/libwebp/utils/huffman_encode.h create mode 100644 TMessagesProj/jni/libwebp/utils/quant_levels.c create mode 100644 TMessagesProj/jni/libwebp/utils/quant_levels.h create mode 100644 TMessagesProj/jni/libwebp/utils/quant_levels_dec.c create mode 100644 TMessagesProj/jni/libwebp/utils/quant_levels_dec.h create mode 100644 TMessagesProj/jni/libwebp/utils/random.c create mode 100644 TMessagesProj/jni/libwebp/utils/random.h create mode 100644 TMessagesProj/jni/libwebp/utils/rescaler.c create mode 100644 TMessagesProj/jni/libwebp/utils/rescaler.h create mode 100644 TMessagesProj/jni/libwebp/utils/thread.c create mode 100644 TMessagesProj/jni/libwebp/utils/thread.h create mode 100644 TMessagesProj/jni/libwebp/utils/utils.c create mode 100644 TMessagesProj/jni/libwebp/utils/utils.h create mode 100644 TMessagesProj/jni/libwebp/webp/decode.h create mode 100644 TMessagesProj/jni/libwebp/webp/demux.h create mode 100644 TMessagesProj/jni/libwebp/webp/encode.h create mode 100644 TMessagesProj/jni/libwebp/webp/format_constants.h create mode 100644 TMessagesProj/jni/libwebp/webp/mux.h create mode 100644 TMessagesProj/jni/libwebp/webp/mux_types.h create mode 100644 TMessagesProj/jni/libwebp/webp/types.h delete mode 100755 TMessagesProj/libs/armeabi-v7a/libtmessages.4.so create mode 100755 TMessagesProj/libs/armeabi-v7a/libtmessages.5.so delete mode 100755 TMessagesProj/libs/armeabi/libtmessages.4.so create mode 100755 TMessagesProj/libs/armeabi/libtmessages.5.so delete mode 100755 TMessagesProj/libs/x86/libtmessages.4.so create mode 100755 TMessagesProj/libs/x86/libtmessages.5.so create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/AuthFailureError.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/Cache.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/CacheDispatcher.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/DefaultRetryPolicy.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/ExecutorDelivery.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/Network.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/NetworkDispatcher.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/NetworkError.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/NetworkResponse.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/NoConnectionError.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/ParseError.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/Request.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/RequestQueue.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/Response.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/ResponseDelivery.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/RetryPolicy.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/ServerError.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/TimeoutError.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/VolleyError.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/VolleyLog.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/AndroidAuthenticator.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/Authenticator.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/BasicNetwork.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/ByteArrayPool.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/ClearCacheRequest.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/DiskBasedCache.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HttpClientStack.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HttpHeaderParser.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HttpStack.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HurlStack.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/ImageLoader.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/ImageRequest.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/JsonArrayRequest.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/JsonObjectRequest.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/JsonRequest.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/NetworkImageView.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/NoCache.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/PoolingByteArrayOutputStream.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/RequestFuture.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/StringRequest.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/Volley.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/AccountPasswordActivity.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/TextFieldCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPickerBottomLayout.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/checkbig.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/gif_search.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-hdpi/ic_ab_attach.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_close_white.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_smiles.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-hdpi/pagedown.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/stickers_back_all.9.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/stickers_back_arrow.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/stickers_back_center.9.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/stickers_back_left.9.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/stickers_back_right.9.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/web_search.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/checkbig.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/gif_search.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-mdpi/ic_ab_attach.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_close_white.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-mdpi/pagedown.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/stickers_back_all.9.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/stickers_back_arrow.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/stickers_back_center.9.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/stickers_back_left.9.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/stickers_back_right.9.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/web_search.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/checkbig.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/gif_search.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_attach.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_close_white.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_smiles.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-xhdpi/pagedown.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_all.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_arrow.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_center.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_left.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_right.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/web_search.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/checkbig.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/gif_search.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_attach.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_close_white.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_smiles.png mode change 100755 => 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pagedown.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_all.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_arrow.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_center.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_left.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_right.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/web_search.png delete mode 100644 TMessagesProj/src/main/res/layout/photo_picker_album_layout.xml delete mode 100644 TMessagesProj/src/main/res/layout/photo_picker_bottom_layout.xml delete mode 100644 TMessagesProj/src/main/res/layout/photo_picker_layout.xml delete mode 100644 TMessagesProj/src/main/res/layout/photo_picker_photo_layout.xml diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index e9eaf5a9..da1e90cf 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:0.14.0' + classpath 'com.android.tools.build:gradle:1.0.0' } } apply plugin: 'com.android.application' @@ -12,20 +12,22 @@ repositories { mavenCentral() } -tasks.withType(JavaCompile) { - options.encoding = "UTF-8" -} - dependencies { compile 'com.android.support:support-v4:21.0.+' compile 'com.google.android.gms:play-services:3.2.+' - compile 'net.hockeyapp.android:HockeySDK:3.0.2' + compile 'net.hockeyapp.android:HockeySDK:3.5.+' compile 'com.googlecode.mp4parser:isoparser:1.0.+' + compile 'com.android.support:recyclerview-v7:+' } android { compileSdkVersion 21 - buildToolsVersion '21.1.1' + buildToolsVersion '21.1.2' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } signingConfigs { debug { @@ -80,7 +82,7 @@ android { defaultConfig { minSdkVersion 8 targetSdkVersion 21 - versionCode 405 - versionName "2.1.1" + versionCode 413 + versionName "2.3.0" } } diff --git a/TMessagesProj/jni/Android.mk b/TMessagesProj/jni/Android.mk index bd2a81f0..f648a89b 100755 --- a/TMessagesProj/jni/Android.mk +++ b/TMessagesProj/jni/Android.mk @@ -1,14 +1,112 @@ LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD -finline-functions -ffast-math -ffunction-sections -fdata-sections -O2 +LOCAL_C_INCLUDES += ./libwebp/src +LOCAL_ARM_MODE := arm +LOCAL_STATIC_LIBRARIES := cpufeatures +LOCAL_MODULE := webp + +ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),) + # Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal + # instructions to be generated for armv7a code. Instead target the neon code + # specifically. + NEON := c.neon +else + NEON := c +endif + +LOCAL_SRC_FILES := \ +./libwebp/dec/alpha.c \ +./libwebp/dec/buffer.c \ +./libwebp/dec/frame.c \ +./libwebp/dec/idec.c \ +./libwebp/dec/io.c \ +./libwebp/dec/quant.c \ +./libwebp/dec/tree.c \ +./libwebp/dec/vp8.c \ +./libwebp/dec/vp8l.c \ +./libwebp/dec/webp.c \ +./libwebp/dsp/alpha_processing.c \ +./libwebp/dsp/alpha_processing_sse2.c \ +./libwebp/dsp/cpu.c \ +./libwebp/dsp/dec.c \ +./libwebp/dsp/dec_clip_tables.c \ +./libwebp/dsp/dec_mips32.c \ +./libwebp/dsp/dec_neon.$(NEON) \ +./libwebp/dsp/dec_sse2.c \ +./libwebp/dsp/enc.c \ +./libwebp/dsp/enc_avx2.c \ +./libwebp/dsp/enc_mips32.c \ +./libwebp/dsp/enc_neon.$(NEON) \ +./libwebp/dsp/enc_sse2.c \ +./libwebp/dsp/lossless.c \ +./libwebp/dsp/lossless_mips32.c \ +./libwebp/dsp/lossless_neon.$(NEON) \ +./libwebp/dsp/lossless_sse2.c \ +./libwebp/dsp/upsampling.c \ +./libwebp/dsp/upsampling_neon.$(NEON) \ +./libwebp/dsp/upsampling_sse2.c \ +./libwebp/dsp/yuv.c \ +./libwebp/dsp/yuv_mips32.c \ +./libwebp/dsp/yuv_sse2.c \ +./libwebp/enc/alpha.c \ +./libwebp/enc/analysis.c \ +./libwebp/enc/backward_references.c \ +./libwebp/enc/config.c \ +./libwebp/enc/cost.c \ +./libwebp/enc/filter.c \ +./libwebp/enc/frame.c \ +./libwebp/enc/histogram.c \ +./libwebp/enc/iterator.c \ +./libwebp/enc/picture.c \ +./libwebp/enc/picture_csp.c \ +./libwebp/enc/picture_psnr.c \ +./libwebp/enc/picture_rescale.c \ +./libwebp/enc/picture_tools.c \ +./libwebp/enc/quant.c \ +./libwebp/enc/syntax.c \ +./libwebp/enc/token.c \ +./libwebp/enc/tree.c \ +./libwebp/enc/vp8l.c \ +./libwebp/enc/webpenc.c \ +./libwebp/utils/bit_reader.c \ +./libwebp/utils/bit_writer.c \ +./libwebp/utils/color_cache.c \ +./libwebp/utils/filters.c \ +./libwebp/utils/huffman.c \ +./libwebp/utils/huffman_encode.c \ +./libwebp/utils/quant_levels.c \ +./libwebp/utils/quant_levels_dec.c \ +./libwebp/utils/random.c \ +./libwebp/utils/rescaler.c \ +./libwebp/utils/thread.c \ +./libwebp/utils/utils.c \ + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_ARM_MODE := arm +LOCAL_MODULE := sqlite +LOCAL_CFLAGS := -w -std=gnu99 -O2 -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 +LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -DHAVE_STRCHRNUL=0 + +LOCAL_SRC_FILES := \ +./sqlite/sqlite3.c + +include $(BUILD_STATIC_LIBRARY) + include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false -LOCAL_MODULE := tmessages.4 +LOCAL_STATIC_LIBRARIES := webp sqlite +LOCAL_MODULE := tmessages.5 LOCAL_CFLAGS := -w -std=gnu99 -O2 -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno -LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -DHAVE_STRCHRNUL=0 +LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -O2 -funroll-loops -#LOCAL_LDLIBS := -llog LOCAL_LDLIBS := -ljnigraphics -llog +LOCAL_ARM_MODE := arm LOCAL_SRC_FILES := \ ./opus/src/opus.c \ @@ -179,9 +277,6 @@ else endif endif -LOCAL_SRC_FILES += \ -./sqlite/sqlite3.c - LOCAL_C_INCLUDES := \ ./opus/include \ ./opus/silk \ @@ -292,4 +387,6 @@ LOCAL_SRC_FILES += \ ./image.c \ ./video.c -include $(BUILD_SHARED_LIBRARY) \ No newline at end of file +include $(BUILD_SHARED_LIBRARY) + +$(call import-module,android/cpufeatures) \ No newline at end of file diff --git a/TMessagesProj/jni/gif.c b/TMessagesProj/jni/gif.c index c47cdbd9..64dda479 100644 --- a/TMessagesProj/jni/gif.c +++ b/TMessagesProj/jni/gif.c @@ -113,7 +113,7 @@ jint gifOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env) { if (defaultCmap == NULL) { return -1; } - return JNI_VERSION_1_4; + return JNI_VERSION_1_6; } void gifOnJNIUnload(JavaVM *vm, void *reserved) { diff --git a/TMessagesProj/jni/image.c b/TMessagesProj/jni/image.c index ce371880..1532095b 100644 --- a/TMessagesProj/jni/image.c +++ b/TMessagesProj/jni/image.c @@ -3,7 +3,78 @@ #include #include #include +#include +#include #include "utils.h" +#include "image.h" + +jclass jclass_NullPointerException; +jclass jclass_RuntimeException; + +jclass jclass_Options; +jfieldID jclass_Options_inJustDecodeBounds; +jfieldID jclass_Options_outHeight; +jfieldID jclass_Options_outWidth; + +jclass jclass_Bitmap; +jmethodID jclass_Bitmap_createBitmap; +jclass jclass_Config; +jfieldID jclass_Config_ARGB_8888; + +jclass createGlobarRef(JNIEnv *env, jclass class) { + if (class) { + return (*env)->NewGlobalRef(env, class); + } + return 0; +} + +jint imageOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env) { + jclass_NullPointerException = createGlobarRef(env, (*env)->FindClass(env, "java/lang/NullPointerException")); + if (jclass_NullPointerException == 0) { + return -1; + } + jclass_RuntimeException = createGlobarRef(env, (*env)->FindClass(env, "java/lang/RuntimeException")); + if (jclass_RuntimeException == 0) { + return -1; + } + + jclass_Options = createGlobarRef(env, (*env)->FindClass(env, "android/graphics/BitmapFactory$Options")); + if (jclass_Options == 0) { + return -1; + } + jclass_Options_inJustDecodeBounds = (*env)->GetFieldID(env, jclass_Options, "inJustDecodeBounds", "Z"); + if (jclass_Options_inJustDecodeBounds == 0) { + return -1; + } + jclass_Options_outHeight = (*env)->GetFieldID(env, jclass_Options, "outHeight", "I"); + if (jclass_Options_outHeight == 0) { + return -1; + } + jclass_Options_outWidth = (*env)->GetFieldID(env, jclass_Options, "outWidth", "I"); + if (jclass_Options_outWidth == 0) { + return -1; + } + + jclass_Bitmap = createGlobarRef(env, (*env)->FindClass(env, "android/graphics/Bitmap")); + if (jclass_Bitmap == 0) { + return -1; + } + jclass_Bitmap_createBitmap = (*env)->GetStaticMethodID(env, jclass_Bitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;"); + if (jclass_Bitmap_createBitmap == 0) { + return -1; + } + + jclass_Config = createGlobarRef(env, (*env)->FindClass(env, "android/graphics/Bitmap$Config")); + if (jclass_Config == 0) { + return -1; + } + jclass_Config_ARGB_8888 = (*env)->GetStaticFieldID(env, jclass_Config, "ARGB_8888", "Landroid/graphics/Bitmap$Config;"); + if (jclass_Config_ARGB_8888 == 0) { + return -1; + } + + return JNI_VERSION_1_6; +} static inline uint64_t get_colors (const uint8_t *p) { return p[0] + (p[1] << 16) + ((uint64_t)p[2] << 32); @@ -17,7 +88,7 @@ static void fastBlurMore(int imageWidth, int imageHeight, int imageStride, void const int r1 = radius + 1; const int div = radius * 2 + 1; - if (radius > 15 || div >= w || div >= h || w * h > 90 * 90 || imageStride > imageWidth * 4) { + if (radius > 15 || div >= w || div >= h || w * h > 128 * 128 || imageStride > imageWidth * 4) { return; } @@ -105,8 +176,20 @@ static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pix const int stride = imageStride; const int r1 = radius + 1; const int div = radius * 2 + 1; + int shift; + if (radius == 1) { + shift = 2; + } else if (radius == 3) { + shift = 4; + } else if (radius == 7) { + shift = 6; + } else if (radius == 15) { + shift = 8; + } else { + return; + } - if (radius > 15 || div >= w || div >= h || w * h > 90 * 90 || imageStride > imageWidth * 4) { + if (radius > 15 || div >= w || div >= h || w * h > 128 * 128 || imageStride > imageWidth * 4) { return; } @@ -133,7 +216,7 @@ static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pix x = 0; #define update(start, middle, end) \ - rgb[y * w + x] = (rgbsum >> 4) & 0x00FF00FF00FF00FFLL; \ + rgb[y * w + x] = (rgbsum >> shift) & 0x00FF00FF00FF00FFLL; \ rgballsum += get_colors (&pix[yw + (start) * 4]) - 2 * get_colors (&pix[yw + (middle) * 4]) + get_colors (&pix[yw + (end) * 4]); \ rgbsum += rgballsum; \ x++; \ @@ -166,7 +249,7 @@ static void fastBlur(int imageWidth, int imageHeight, int imageStride, void *pix int yi = x * 4; #define update(start, middle, end) \ - int64_t res = rgbsum >> 4; \ + int64_t res = rgbsum >> shift; \ pix[yi] = res; \ pix[yi + 1] = res >> 16; \ pix[yi + 2] = res >> 32; \ @@ -313,3 +396,62 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_loadBitmap(JNIEnv *env, jcl throwException(env, "AndroidBitmap_getInfo() failed ! error=%d", i); } } + +JNIEXPORT jobject Java_org_telegram_messenger_Utilities_loadWebpImage(JNIEnv *env, jclass class, jobject buffer, int len, jobject options) { + if (!buffer) { + (*env)->ThrowNew(env, jclass_NullPointerException, "Input buffer can not be null"); + return 0; + } + + jbyte *inputBuffer = (*env)->GetDirectBufferAddress(env, buffer); + + int bitmapWidth = 0; + int bitmapHeight = 0; + if (!WebPGetInfo((uint8_t*)inputBuffer, len, &bitmapWidth, &bitmapHeight)) { + (*env)->ThrowNew(env, jclass_RuntimeException, "Invalid WebP format"); + return 0; + } + + if (options && (*env)->GetBooleanField(env, options, jclass_Options_inJustDecodeBounds) == JNI_TRUE) { + (*env)->SetIntField(env, options, jclass_Options_outWidth, bitmapWidth); + (*env)->SetIntField(env, options, jclass_Options_outHeight, bitmapHeight); + return 0; + } + + jobject value__ARGB_8888 = (*env)->GetStaticObjectField(env, jclass_Config, jclass_Config_ARGB_8888); + jobject outputBitmap = (*env)->CallStaticObjectMethod(env, jclass_Bitmap, jclass_Bitmap_createBitmap, (jint)bitmapWidth, (jint)bitmapHeight, value__ARGB_8888); + if (!outputBitmap) { + (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to allocate Bitmap"); + return 0; + } + outputBitmap = (*env)->NewLocalRef(env, outputBitmap); + + AndroidBitmapInfo bitmapInfo; + if (AndroidBitmap_getInfo(env, outputBitmap, &bitmapInfo) != ANDROID_BITMAP_RESUT_SUCCESS) { + (*env)->DeleteLocalRef(env, outputBitmap); + (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to get Bitmap information"); + return 0; + } + + void *bitmapPixels = 0; + if (AndroidBitmap_lockPixels(env, outputBitmap, &bitmapPixels) != ANDROID_BITMAP_RESUT_SUCCESS) { + (*env)->DeleteLocalRef(env, outputBitmap); + (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to lock Bitmap pixels"); + return 0; + } + + if (!WebPDecodeRGBAInto((uint8_t*)inputBuffer, len, (uint8_t*)bitmapPixels, bitmapInfo.height * bitmapInfo.stride, bitmapInfo.stride)) { + AndroidBitmap_unlockPixels(env, outputBitmap); + (*env)->DeleteLocalRef(env, outputBitmap); + (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to unlock Bitmap pixels"); + return 0; + } + + if (AndroidBitmap_unlockPixels(env, outputBitmap) != ANDROID_BITMAP_RESUT_SUCCESS) { + (*env)->DeleteLocalRef(env, outputBitmap); + (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to unlock Bitmap pixels"); + return 0; + } + + return outputBitmap; +} diff --git a/TMessagesProj/jni/image.h b/TMessagesProj/jni/image.h new file mode 100644 index 00000000..58dd5385 --- /dev/null +++ b/TMessagesProj/jni/image.h @@ -0,0 +1,8 @@ +#ifndef image_h +#define image_h + +#include + +jint imageOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env); + +#endif diff --git a/TMessagesProj/jni/jni.c b/TMessagesProj/jni/jni.c index 4a43f84d..ff600f00 100644 --- a/TMessagesProj/jni/jni.c +++ b/TMessagesProj/jni/jni.c @@ -8,12 +8,13 @@ #include "utils.h" #include "sqlite.h" #include "gif.h" +#include "image.h" jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env = 0; srand(time(NULL)); - if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_4) != JNI_OK) { + if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) { return -1; } @@ -21,9 +22,13 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { return -1; } + if (imageOnJNILoad(vm, reserved, env) == -1) { + return -1; + } + gifOnJNILoad(vm, reserved, env); - return JNI_VERSION_1_4; + return JNI_VERSION_1_6; } void JNI_OnUnload(JavaVM *vm, void *reserved) { diff --git a/TMessagesProj/jni/libwebp/dec/alpha.c b/TMessagesProj/jni/libwebp/dec/alpha.c new file mode 100644 index 00000000..f23ba7d6 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/alpha.c @@ -0,0 +1,165 @@ +// 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 +#include "./alphai.h" +#include "./vp8i.h" +#include "./vp8li.h" +#include "../utils/quant_levels_dec.h" +#include "../utils/utils.h" +#include "../webp/format_constants.h" + +//------------------------------------------------------------------------------ +// ALPHDecoder object. + +ALPHDecoder* ALPHNew(void) { + ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); + return dec; +} + +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, int width, int height, 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; + + assert(width > 0 && height > 0); + assert(data != NULL && output != NULL); + + dec->width_ = width; + dec->height_ = height; + + 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; + } + + 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, output); + } + 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->height_; + WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_]; + uint8_t* const output = dec->alpha_plane_; + if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { + const size_t offset = row * width; + const size_t num_pixels = num_rows * width; + assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels); + memcpy(dec->alpha_plane_ + offset, + dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels); + } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION + assert(alph_dec->vp8l_dec_ != NULL); + if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { + return 0; + } + } + + if (unfilter_func != NULL) { + unfilter_func(width, height, width, row, num_rows, output); + } + + if (row + num_rows == dec->pic_hdr_.height_) { + dec->is_alpha_decoded_ = 1; + } + return 1; +} + +//------------------------------------------------------------------------------ +// Main entry point. + +const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + int row, int num_rows) { + const int width = dec->pic_hdr_.width_; + const int height = dec->pic_hdr_.height_; + + if (row < 0 || num_rows <= 0 || row + num_rows > height) { + return NULL; // sanity check. + } + + if (row == 0) { + // Initialize decoding. + assert(dec->alpha_plane_ != NULL); + dec->alph_dec_ = ALPHNew(); + if (dec->alph_dec_ == NULL) return NULL; + if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, + width, height, dec->alpha_plane_)) { + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; + return NULL; + } + // 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; // decode everything in one pass + } + } + + if (!dec->is_alpha_decoded_) { + int ok = 0; + assert(dec->alph_dec_ != NULL); + ok = ALPHDecode(dec, row, num_rows); + if (ok && dec->alpha_dithering_ > 0) { + ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, + dec->alpha_dithering_); + } + if (!ok || dec->is_alpha_decoded_) { + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; + } + if (!ok) return NULL; // Error. + } + + // Return a pointer to the current decoded row. + return dec->alpha_plane_ + row * width; +} diff --git a/TMessagesProj/jni/libwebp/dec/alphai.h b/TMessagesProj/jni/libwebp/dec/alphai.h new file mode 100644 index 00000000..5fa230ca --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/alphai.h @@ -0,0 +1,55 @@ +// 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. +}; + +//------------------------------------------------------------------------------ +// internal functions. Not public. + +// Allocates a new alpha decoder instance. +ALPHDecoder* ALPHNew(void); + +// Clears and deallocates an alpha decoder instance. +void ALPHDelete(ALPHDecoder* const dec); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_DEC_ALPHAI_H_ */ diff --git a/TMessagesProj/jni/libwebp/dec/buffer.c b/TMessagesProj/jni/libwebp/dec/buffer.c new file mode 100644 index 00000000..42feac74 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/buffer.c @@ -0,0 +1,251 @@ +// 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 + +#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); +} + +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 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 = (uint64_t)y_stride * height; + const uint64_t u_size = (uint64_t)u_stride * ((height + 1) / 2); + const uint64_t v_size = (uint64_t)v_stride * ((height + 1) / 2); + const uint64_t a_size = (uint64_t)a_stride * height; + 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 >= (width + 1) / 2); + ok &= (v_stride >= (width + 1) / 2); + 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 = (uint64_t)stride * height; + ok &= (size <= buf->size); + ok &= (stride >= width * kModeBpp[mode]); + ok &= (buf->rgba != NULL); + } + return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM; +} + +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 && 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) { + if (options->scaled_width <= 0 || options->scaled_height <= 0) { + return VP8_STATUS_INVALID_PARAM; + } + w = options->scaled_width; + h = options->scaled_height; + } + } + out->width = w; + out->height = h; + + // Then, allocate buffer for real. + status = AllocateBuffer(out); + if (status != VP8_STATUS_OK) return status; + +#if WEBP_DECODER_ABI_VERSION > 0x0203 + // Use the stride trick if vertical flip is needed. + if (options != NULL && options->flip) { + status = WebPFlipBuffer(out); + } +#endif + 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) { + 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; + } + } +} + +//------------------------------------------------------------------------------ + diff --git a/TMessagesProj/jni/libwebp/dec/decode_vp8.h b/TMessagesProj/jni/libwebp/dec/decode_vp8.h new file mode 100644 index 00000000..b9337bbe --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/decode_vp8.h @@ -0,0 +1,185 @@ +// 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/TMessagesProj/jni/libwebp/dec/frame.c b/TMessagesProj/jni/libwebp/dec/frame.c new file mode 100644 index 00000000..2359acc5 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/frame.c @@ -0,0 +1,828 @@ +// 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 +#include "./vp8i.h" +#include "../utils/utils.h" + +#define ALIGN_MASK (32 - 1) + +static void ReconstructRow(const VP8Decoder* const dec, + const VP8ThreadContext* ctx); // TODO(skal): remove + +//------------------------------------------------------------------------------ +// 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_) { + // TODO(skal): only CURRENT is handled for now. + 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 + +#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; + } + } +#if WEBP_DECODER_ABI_VERSION > 0x0204 + // 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; + } +#endif + } +} + +// minimal amp that will provide a non-zero dithering effect +#define MIN_DITHER_AMP 4 +#define DITHER_DESCALE 4 +#define DITHER_DESCALE_ROUNDER (1 << (DITHER_DESCALE - 1)) +#define DITHER_AMP_BITS 8 +#define DITHER_AMP_CENTER (1 << DITHER_AMP_BITS) + +static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) { + int i, j; + for (j = 0; j < 8; ++j) { + for (i = 0; i < 8; ++i) { + // TODO: could be made faster with SSE2 + const int bits = + VP8RandomBits2(rg, DITHER_AMP_BITS + 1, amp) - DITHER_AMP_CENTER; + // Convert to range: [-2,2] for dither=50, [-4,4] for dither=100 + const int delta = (bits + DITHER_DESCALE_ROUNDER) >> DITHER_DESCALE; + const int v = (int)dst[i] + delta; + dst[i] = (v < 0) ? 0 : (v > 255) ? 255u : (uint8_t)v; + } + 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, 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 + ALIGN_MASK; + 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*)((uintptr_t)(mem + ALIGN_MASK) & ~ALIGN_MASK); + assert((yuv_size & ALIGN_MASK) == 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* 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; +} + +//------------------------------------------------------------------------------ +// 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* dst, uint8_t* 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; + 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]); + } + } else { + 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; + } + } + { + // 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); + } else if (mb_x == 0) { + // 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); + } + + // 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); + } + } + } +} + +//------------------------------------------------------------------------------ + diff --git a/TMessagesProj/jni/libwebp/dec/idec.c b/TMessagesProj/jni/libwebp/dec/idec.c new file mode 100644 index 00000000..5d8bb0c2 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/idec.c @@ -0,0 +1,857 @@ +// 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 +#include +#include + +#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) + 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 int last_part = dec->num_parts_ - 1; + if (offset != 0) { + int 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); + } + } + assert(last_part >= 0); + dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; + 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) { +#if WEBP_DECODER_ABI_VERSION > 0x0203 + const WebPDecoderOptions* const options = idec->params_.options; + WebPDecBuffer* const output = idec->params_.output; + + idec->state_ = STATE_DONE; + if (options != NULL && options->flip) { + return WebPFlipBuffer(output); + } +#endif + idec->state_ = STATE_DONE; + 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 int CopyParts0Data(WebPIDecoder* const idec) { + VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + VP8BitReader* const br = &dec->br_; + const size_t psize = br->buf_end_ - br->buf_; + MemBuffer* const mem = &idec->mem_; + assert(!idec->is_lossless_); + assert(mem->part0_buf_ == NULL); + assert(psize > 0); + assert(psize <= mem->part0_size_); // Format limit: no need for runtime check + 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, psize); + if (part0_buf == NULL) { + return 0; + } + memcpy(part0_buf, br->buf_, psize); + mem->part0_buf_ = part0_buf; + br->buf_ = part0_buf; + br->buf_end_ = part0_buf + psize; + } else { + // Else: just keep pointers to the partition #0's data in dec_->br_. + } + mem->start_ += psize; + return 1; +} + +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); + if (!CopyParts0Data(idec)) { + return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY); + } + + // 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_ - 1)]; + 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_ == 1 && 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_ == 1) { + 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)) { + return VP8_STATUS_SUSPENDED; + } + if (!VP8LDecodeHeader(dec, io)) { + 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_); + + // At present Lossless decoder can't decode image incrementally. So wait till + // all the image data is aggregated before image can be decoded. + if (curr_size < idec->chunk_size_) { + return VP8_STATUS_SUSPENDED; + } + + if (!VP8LDecodeImage(dec)) { + // The decoding is called after all the data-bytes are aggregated. Change + // the error to VP8_BITSTREAM_ERROR in case lossless decoder fails to decode + // all the pixels (VP8_STATUS_SUSPENDED). + if (dec->status_ == VP8_STATUS_SUSPENDED) { + dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + } + return ErrorStatusLossless(idec, dec->status_); + } + + return 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; +} + +//------------------------------------------------------------------------------ +// Public functions + +WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { + 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_); + idec->params_.output = (output_buffer != NULL) ? output_buffer + : &idec->output_; + WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. + + return idec; +} + +WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config) { + WebPIDecoder* idec; + + // Parse the bitstream's features, if requested: + if (data != NULL && data_size > 0 && config != NULL) { + if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) { + return NULL; + } + } + // Create an instance of the incremental decoder + idec = WebPINewDecoder(config ? &config->output : NULL); + 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); + WebPIDecoder* idec; + + if (mode >= MODE_YUV) return NULL; + if (!is_external_memory) { // 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); + WebPIDecoder* idec; + WEBP_CSP_MODE colorspace; + + if (!is_external_memory) { // 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; + } + 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; + // TODO(skal): later include handling of rotations. + if (src) { + 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/TMessagesProj/jni/libwebp/dec/io.c b/TMessagesProj/jni/libwebp/dec/io.c new file mode 100644 index 00000000..8094e44f --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/io.c @@ -0,0 +1,648 @@ +// 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 +#include +#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; +} + +//------------------------------------------------------------------------------ +// YUV444 -> RGB conversion + +#if 0 // TODO(skal): this is for future rescaling. +static int EmitRGB(const VP8Io* const io, WebPDecParams* const p) { + WebPDecBuffer* output = p->output; + const WebPRGBABuffer* const buf = &output->u.RGBA; + uint8_t* dst = buf->rgba + io->mb_y * buf->stride; + const uint8_t* y_src = io->y; + const uint8_t* u_src = io->u; + const uint8_t* v_src = io->v; + const WebPYUV444Converter convert = WebPYUV444Converters[output->colorspace]; + const int mb_w = io->mb_w; + const int last = io->mb_h; + int j; + for (j = 0; j < last; ++j) { + convert(y_src, u_src, v_src, dst, mb_w); + y_src += io->y_stride; + u_src += io->uv_stride; + v_src += io->uv_stride; + dst += buf->stride; + } + return io->mb_h; +} +#endif + +//------------------------------------------------------------------------------ +// 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 int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) { + 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; + + 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. + for (j = 0; j < mb_h; ++j) { + memset(dst, 0xff, mb_w * sizeof(*dst)); + dst += 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) { + 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* dst = base_rgba + (alpha_first ? 0 : 3); + uint32_t alpha_mask = 0xff; + int i, j; + + for (j = 0; j < num_rows; ++j) { + for (i = 0; i < mb_w; ++i) { + const uint32_t alpha_value = alpha[i]; + dst[4 * i] = alpha_value; + alpha_mask &= alpha_value; + } + alpha += io->width; + dst += buf->stride; + } + // alpha_mask is < 0xff if there's non-trivial alpha to premultiply with. + if (alpha_mask != 0xff && 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) { + 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; + } + 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) { + if (io->a != NULL) { + const WebPYUVABuffer* const buf = &p->output->u.YUVA; + 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); + 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); + } + } + 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; + int32_t* work; + + tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work); + if (has_alpha) { + tmp_size += work_size * sizeof(*work); + } + p->memory = WebPSafeCalloc(1ULL, tmp_size); + if (p->memory == NULL) { + return 0; // memory error + } + work = (int32_t*)p->memory; + WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, + buf->y, out_width, out_height, buf->y_stride, 1, + io->mb_w, out_width, io->mb_h, out_height, + work); + WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, + buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, + uv_in_width, uv_out_width, + uv_in_height, uv_out_height, + 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, + uv_in_width, uv_out_width, + uv_in_height, uv_out_height, + 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, + io->mb_w, out_width, io->mb_h, out_height, + 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 + (p->last_y + 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(p->last_y + y_pos + num_lines_out < p->output->height); + assert(p->scaler_u.y_accum == p->scaler_v.y_accum); + WebPRescalerExportRow(&p->scaler_y, 0); + WebPRescalerExportRow(&p->scaler_u, 0); + WebPRescalerExportRow(&p->scaler_v, 0); + 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); + 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); + j += y_lines_in; + uv_j += u_lines_in; + num_lines_out += ExportRGB(p, num_lines_out); + } + return num_lines_out; +} + +static int ExportAlpha(WebPDecParams* const p, int y_pos) { + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* const base_rgba = buf->rgba + (p->last_y + 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 alpha_mask = 0xff; + const int width = p->scaler_a.dst_width; + + while (WebPRescalerHasPendingOutput(&p->scaler_a)) { + int i; + assert(p->last_y + y_pos + num_lines_out < p->output->height); + WebPRescalerExportRow(&p->scaler_a, 0); + for (i = 0; i < width; ++i) { + const uint32_t alpha_value = p->scaler_a.dst[i]; + dst[4 * i] = alpha_value; + alpha_mask &= alpha_value; + } + dst += buf->stride; + ++num_lines_out; + } + if (is_premult_alpha && alpha_mask != 0xff) { + WebPApplyAlphaMultiply(base_rgba, alpha_first, + width, num_lines_out, buf->stride); + } + return num_lines_out; +} + +static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) { + const WebPRGBABuffer* const buf = &p->output->u.RGBA; + uint8_t* const base_rgba = buf->rgba + (p->last_y + 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)) { + int i; + assert(p->last_y + y_pos + num_lines_out < p->output->height); + WebPRescalerExportRow(&p->scaler_a, 0); + 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) { + if (io->a != NULL) { + WebPRescaler* const scaler = &p->scaler_a; + int j = 0; + int pos = 0; + while (j < io->mb_h) { + j += WebPRescalerImport(scaler, io->mb_h - j, + io->a + j * io->width, io->width); + pos += p->emit_alpha_row(p, pos); + } + } + 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 + int32_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 = WebPSafeCalloc(1ULL, total_size); + if (p->memory == NULL) { + return 0; // memory error + } + work = (int32_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, + io->mb_w, out_width, io->mb_h, out_height, + work + 0 * work_size); + WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, + tmp + 1 * out_width, out_width, out_height, 0, 1, + io->mb_w, 2 * out_width, io->mb_h, 2 * out_height, + work + 1 * work_size); + WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, + tmp + 2 * out_width, out_width, out_height, 0, 1, + io->mb_w, 2 * out_width, io->mb_h, 2 * out_height, + work + 2 * work_size); + p->emit = EmitRescaledRGB; + + if (has_alpha) { + WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, + tmp + 3 * out_width, out_width, out_height, 0, 1, + io->mb_w, out_width, io->mb_h, out_height, + 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) { + 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 { + WebPInitSamplers(); + } + } 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); + } + 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/TMessagesProj/jni/libwebp/dec/quant.c b/TMessagesProj/jni/libwebp/dec/quant.c new file mode 100644 index 00000000..5b648f94 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/quant.c @@ -0,0 +1,110 @@ +// 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/TMessagesProj/jni/libwebp/dec/tree.c b/TMessagesProj/jni/libwebp/dec/tree.c new file mode 100644 index 00000000..31208d9d --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/tree.c @@ -0,0 +1,516 @@ +// 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 +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; + } + } + } + } + dec->use_skip_proba_ = VP8Get(br); + if (dec->use_skip_proba_) { + dec->skip_p_ = VP8GetValue(br, 8); + } +} + diff --git a/TMessagesProj/jni/libwebp/dec/vp8.c b/TMessagesProj/jni/libwebp/dec/vp8.c new file mode 100644 index 00000000..47249d64 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/vp8.c @@ -0,0 +1,668 @@ +// 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 + +#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_ = 1; + } + 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) { + // TODO This check would be unnecessary if alpha decompression was separated + // from VP8ProcessRow/FinishRow. This avoids setting 'dec->status_' to + // something other than VP8_STATUS_BITSTREAM_ERROR on alpha decompression + // failure. + 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; + int last_part; + int p; + + dec->num_parts_ = 1 << VP8GetValue(br, 2); + last_part = dec->num_parts_ - 1; + part_start = buf + last_part * 3; + if (buf_end < part_start) { + // we can't even read the sizes with sz[]! That's a failure. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + for (p = 0; p < last_part; ++p) { + const uint32_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16); + const uint8_t* part_end = part_start + psize; + if (part_end > buf_end) part_end = buf_end; + VP8InitBitReader(dec->parts_ + p, part_start, part_end); + part_start = part_end; + sz += 3; + } + VP8InitBitReader(dec->parts_ + last_part, part_start, buf_end); + 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_; + io->use_scaling = 0; + io->use_cropping = 0; + io->crop_top = 0; + io->crop_left = 0; + io->crop_right = io->width; + io->crop_bottom = 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, 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 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 +}; + +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) { + // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'. + 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[kBands[++n]].probas_[0]; + if (n == 16) return 16; + } + { // non zero coeff + const VP8ProbaArray* const p_ctx = &prob[kBands[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) { + VP8BandProbas (* const bands)[NUM_BANDS] = dec->proba_.bands_; + const VP8BandProbas* 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; + } + + 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_ - 1)]; + 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_); + ALPHDelete(dec->alph_dec_); + dec->alph_dec_ = NULL; + WebPSafeFree(dec->mem_); + dec->mem_ = NULL; + dec->mem_size_ = 0; + memset(&dec->br_, 0, sizeof(dec->br_)); + dec->ready_ = 0; +} + +//------------------------------------------------------------------------------ + diff --git a/TMessagesProj/jni/libwebp/dec/vp8i.h b/TMessagesProj/jni/libwebp/dec/vp8i.h new file mode 100644 index 00000000..29701be7 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/vp8i.h @@ -0,0 +1,354 @@ +// 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 // for memcpy() +#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 4 +#define DEC_REV_VERSION 2 + +// intra prediction modes +enum { B_DC_PRED = 0, // 4x4 modes + B_TM_PRED, + B_VE_PRED, + B_HE_PRED, + B_RD_PRED, + B_VR_PRED, + B_LD_PRED, + B_VL_PRED, + B_HD_PRED, + B_HU_PRED, + 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 + + // 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, + NUM_BANDS = 8, + NUM_CTX = 3, + NUM_PROBAS = 11, + NUM_MV_PROBAS = 19 }; + +// YUV-cache parameters. +// 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 +// With this layout, BPS (=Bytes Per Scan-line) is one cacheline size. +#define BPS 32 // this is the common stride used by yuv[] +#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]; +} 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. + int num_parts_; + // 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_; // output. Persistent, contains the whole data. + 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* 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, + int row, int num_rows); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_DEC_VP8I_H_ */ diff --git a/TMessagesProj/jni/libwebp/dec/vp8l.c b/TMessagesProj/jni/libwebp/dec/vp8l.c new file mode 100644 index 00000000..a7e7e252 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/vp8l.c @@ -0,0 +1,1404 @@ +// 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 + +#include "./alphai.h" +#include "./vp8li.h" +#include "../dsp/dsp.h" +#include "../dsp/lossless.h" +#include "../dsp/yuv.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 +}; + + +#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 +}; + +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 1; +} + +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 HuffmanTree* tree, + VP8LBitReader* const br) { + const HuffmanTreeNode* node = tree->root_; + uint32_t bits = VP8LPrefetchBits(br); + int bitpos = br->bit_pos_; + // Check if we find the bit combination from the Huffman lookup table. + const int lut_ix = bits & (HUFF_LUT - 1); + const int lut_bits = tree->lut_bits_[lut_ix]; + if (lut_bits <= HUFF_LUT_BITS) { + VP8LSetBitPos(br, bitpos + lut_bits); + return tree->lut_symbol_[lut_ix]; + } + node += tree->lut_jump_[lut_ix]; + bitpos += HUFF_LUT_BITS; + bits >>= HUFF_LUT_BITS; + + // Decode the value from a binary tree. + assert(node != NULL); + do { + node = HuffmanTreeNextNode(node, bits & 1); + bits >>= 1; + ++bitpos; + } while (HuffmanTreeNodeIsNotLeaf(node)); + VP8LSetBitPos(br, bitpos); + return node->symbol_; +} + +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; + HuffmanTree tree; + int huff_codes[NUM_CODE_LENGTH_CODES] = { 0 }; + + if (!VP8LHuffmanTreeBuildImplicit(&tree, code_length_code_lengths, + huff_codes, NUM_CODE_LENGTH_CODES)) { + dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + return 0; + } + + 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) { + dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + goto End; + } + } else { + max_symbol = num_symbols; + } + + symbol = 0; + while (symbol < num_symbols) { + int code_len; + if (max_symbol-- == 0) break; + VP8LFillBitWindow(br); + code_len = ReadSymbol(&tree, br); + 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) { + dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + goto End; + } else { + const int length = use_prev ? prev_code_len : 0; + while (repeat-- > 0) code_lengths[symbol++] = length; + } + } + } + ok = 1; + + End: + VP8LHuffmanTreeFree(&tree); + 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, int* const huff_codes, + HuffmanTree* const tree) { + int ok = 0; + VP8LBitReader* const br = &dec->br_; + const int simple_code = VP8LReadBits(br, 1); + + if (simple_code) { // Read symbols, codes & code lengths directly. + int symbols[2]; + int codes[2]; + 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. + symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8); + codes[0] = 0; + code_lengths[0] = num_symbols - 1; + // The second code (if present), is always 8 bit long. + if (num_symbols == 2) { + symbols[1] = VP8LReadBits(br, 8); + codes[1] = 1; + code_lengths[1] = num_symbols - 1; + } + ok = VP8LHuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols, + alphabet_size, num_symbols); + } 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; + } + + memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths)); + + 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 && VP8LHuffmanTreeBuildImplicit(tree, code_lengths, huff_codes, + alphabet_size); + } + ok = ok && !br->error_; + if (!ok) { + dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + return 0; + } + return 1; +} + +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; + int num_htree_groups = 1; + int max_alphabet_size = 0; + int* code_lengths = NULL; + int* huff_codes = NULL; + + 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)) { + dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + 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->error_) 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; + } + } + + htree_groups = VP8LHtreeGroupsNew(num_htree_groups); + code_lengths = + (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths)); + huff_codes = + (int*)WebPSafeMalloc((uint64_t)max_alphabet_size, sizeof(*huff_codes)); + + if (htree_groups == NULL || code_lengths == NULL || huff_codes == NULL) { + dec->status_ = VP8_STATUS_OUT_OF_MEMORY; + goto Error; + } + + for (i = 0; i < num_htree_groups; ++i) { + HuffmanTree* const htrees = htree_groups[i].htrees_; + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + int alphabet_size = kAlphabetSize[j]; + HuffmanTree* const htree = htrees + j; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += 1 << color_cache_bits; + } + if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, huff_codes, + htree)) { + goto Error; + } + } + } + WebPSafeFree(huff_codes); + 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; + return 1; + + Error: + WebPSafeFree(huff_codes); + WebPSafeFree(code_lengths); + WebPSafeFree(huffman_image); + VP8LHtreeGroupsFree(htree_groups, num_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; + int32_t* work; // Rescaler work area. + const uint64_t scaled_data_size = num_channels * (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*)WebPSafeCalloc(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 = (int32_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, + in_width, out_width, in_height, out_height, 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, 0); + 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 + +// TODO(skal): should be in yuv.c +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 + { + int i; + uint8_t* const y = buf->y + y_pos * buf->y_stride; + for (i = 0; i < width; ++i) { + const uint32_t p = src[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } + } + + // 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; + const int uv_width = width >> 1; + int i; + for (i = 0; i < uv_width; ++i) { + const uint32_t v0 = src[2 * i + 0]; + const uint32_t v1 = src[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); + if (!(y_pos & 1)) { // even lines: store values + u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); + v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); + } else { // odd lines: average with previous values + const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); + const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); + // 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 (width & 1) { // last pixel + const uint32_t v0 = src[2 * i + 0]; + const int r = (v0 >> 14) & 0x3fc; + const int g = (v0 >> 6) & 0x3fc; + const int b = (v0 << 2) & 0x3fc; + if (!(y_pos & 1)) { // even lines + u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); + v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); + } else { // odd lines (note: we could just skip this) + const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2); + const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2); + u[i] = (u[i] + tmp_u + 1) >> 1; + v[i] = (v[i] + tmp_v + 1) >> 1; + } + } + } + // Lastly, store alpha if needed. + if (buf->a != NULL) { + int i; + uint8_t* const a = buf->a + y_pos * buf->a_stride; + for (i = 0; i < width; ++i) a[i] = (src[i] >> 24); + } +} + +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, 0); + 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; + } +} + +// Special method for paletted alpha data. +static void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows, + const uint8_t* const rows) { + const int start_row = dec->last_row_; + const int end_row = start_row + num_rows; + const uint8_t* rows_in = rows; + uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row; + VP8LTransform* const transform = &dec->transforms_[0]; + assert(dec->next_transform_ == 1); + assert(transform->type_ == COLOR_INDEXING_TRANSFORM); + VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, 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_; + + if (num_rows <= 0) return; // Nothing to be done. + ApplyInverseTransforms(dec, num_rows, rows); + + // 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 + if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { + // Nothing to output (this time). + } else { + const WebPDecBuffer* const output = dec->output_; + if (output->colorspace < MODE_YUV) { // 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) { + const HuffmanTree* const htrees = hdr->htree_groups_[i].htrees_; + if (htrees[RED].num_nodes_ > 1) return 0; + if (htrees[BLUE].num_nodes_ > 1) return 0; + if (htrees[ALPHA].num_nodes_ > 1) return 0; + } + return 1; +} + +static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { + const int num_rows = row - dec->last_row_; + const uint8_t* const in = + (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; + if (num_rows > 0) { + ApplyInverseTransformsAlpha(dec, num_rows, in); + } + dec->last_row_ = dec->last_out_row_ = row; +} + +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_; + const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); + 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_; + assert(htree_group != 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); + } + 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 % 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) { + int i; + for (i = 0; i < length; ++i) data[pos + i] = data[pos + i - dist]; + } else { + ok = 0; + goto End; + } + pos += length; + col += length; + while (col >= width) { + col -= width; + ++row; + if (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)); + ok = !br->error_; + if (!ok) goto End; + } + // Process the remaining rows corresponding to last row-block. + ExtractPalettedAlphaRows(dec, row); + + End: + if (br->error_ || !ok || (br->eos_ && pos < end)) { + ok = 0; + dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED + : VP8_STATUS_BITSTREAM_ERROR; + } else { + dec->last_pixel_ = (int)pos; + if (pos == end) dec->state_ = READ_DATA; + } + return ok; +} + +static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, + int width, int height, int last_row, + ProcessRowsFunc process_func) { + 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_; + HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); + 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_; + VP8LColorCache* const color_cache = + (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; + const int mask = hdr->huffman_mask_; + assert(htree_group != NULL); + assert(src < src_end); + assert(src_last <= src_end); + + while (!br->eos_ && src < src_last) { + int code; + // 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); + } + VP8LFillBitWindow(br); + code = ReadSymbol(&htree_group->htrees_[GREEN], br); + if (code < NUM_LITERAL_CODES) { // Literal + int red, green, blue, alpha; + red = ReadSymbol(&htree_group->htrees_[RED], br); + green = code; + VP8LFillBitWindow(br); + blue = ReadSymbol(&htree_group->htrees_[BLUE], br); + alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br); + *src = ((uint32_t)alpha << 24) | (red << 16) | (green << 8) | blue; + AdvanceByOne: + ++src; + ++col; + if (col >= width) { + col = 0; + ++row; + if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { + 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 (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { + ok = 0; + goto End; + } else { + int i; + for (i = 0; i < length; ++i) src[i] = src[i - dist]; + src += length; + } + col += length; + while (col >= width) { + col -= width; + ++row; + if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { + process_func(dec, row); + } + } + if (src < src_last) { + 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 + ok = 0; + goto End; + } + assert(br->eos_ == VP8LIsEndOfStream(br)); + ok = !br->error_; + if (!ok) goto End; + } + // Process the remaining rows corresponding to last row-block. + if (process_func != NULL) process_func(dec, row); + + End: + if (br->error_ || !ok || (br->eos_ && src < src_end)) { + ok = 0; + dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED + : VP8_STATUS_BITSTREAM_ERROR; + } else { + dec->last_pixel_ = (int)(src - data); + if (src == src_end) dec->state_ = READ_DATA; + } + return ok; +} + +// ----------------------------------------------------------------------------- +// 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); + memset(hdr, 0, sizeof(*hdr)); +} + +static void ClearMetadata(VP8LMetadata* const hdr) { + assert(hdr); + + WebPSafeFree(hdr->huffman_image_); + VP8LHtreeGroupsFree(hdr->htree_groups_, hdr->num_htree_groups_); + VP8LColorCacheClear(&hdr->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->action_ = READ_DIM; + 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->error_; + + End: + + if (!ok) { + WebPSafeFree(data); + ClearMetadata(hdr); + // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the + // status appropriately. + if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) { + dec->status_ = VP8_STATUS_SUSPENDED; + } + } 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 row) { + const int num_rows = row - dec->last_row_; + const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; + + if (num_rows <= 0) return; // Nothing to be done. + ApplyInverseTransforms(dec, num_rows, in); + + // Extract alpha (which is stored in the green plane). + { + const int width = dec->io_->width; // the final width (!= dec->width_) + const int cache_pixs = width * num_rows; + uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_; + const uint32_t* const src = dec->argb_cache_; + int i; + for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; + } + dec->last_row_ = dec->last_out_row_ = row; +} + +int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, + const uint8_t* const data, size_t data_size, + uint8_t* const output) { + int ok = 0; + VP8LDecoder* dec; + VP8Io* io; + assert(alph_dec != NULL); + alph_dec->vp8l_dec_ = VP8LNew(); + if (alph_dec->vp8l_dec_ == NULL) return 0; + dec = alph_dec->vp8l_dec_; + + dec->width_ = alph_dec->width_; + dec->height_ = alph_dec->height_; + dec->io_ = &alph_dec->io_; + io = dec->io_; + + VP8InitIo(io); + WebPInitCustomIo(NULL, io); // Just a sanity Init. io won't be used. + io->opaque = output; + io->width = alph_dec->width_; + io->height = alph_dec->height_; + + dec->status_ = VP8_STATUS_OK; + VP8LInitBitReader(&dec->br_, data, data_size); + + dec->action_ = READ_HDR; + 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; + + dec->action_ = READ_DATA; + 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(dec->action_ == READ_DATA); + assert(last_row <= dec->height_); + + if (dec->last_pixel_ == dec->width_ * dec->height_) { + 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; + + dec->action_ = READ_HDR; + 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; + + dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + 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); + dec->output_ = params->output; + assert(dec->output_ != NULL); + + // Initialization. + 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(); + } + + // Decode. + dec->action_ = READ_DATA; + if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, + dec->height_, ProcessRows)) { + goto Err; + } + + // Cleanup. + params->last_y = dec->last_out_row_; + VP8LClear(dec); + return 1; + + Err: + VP8LClear(dec); + assert(dec->status_ != VP8_STATUS_OK); + return 0; +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/dec/vp8li.h b/TMessagesProj/jni/libwebp/dec/vp8li.h new file mode 100644 index 00000000..21c593fe --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/vp8li.h @@ -0,0 +1,132 @@ +// 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 // 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_; + + int huffman_mask_; + int huffman_subsample_bits_; + int huffman_xsize_; + uint32_t *huffman_image_; + int num_htree_groups_; + HTreeGroup *htree_groups_; +} VP8LMetadata; + +typedef struct VP8LDecoder VP8LDecoder; +struct VP8LDecoder { + VP8StatusCode status_; + VP8LDecodeState action_; + 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 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, + uint8_t* const output); + +// 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/TMessagesProj/jni/libwebp/dec/webp.c b/TMessagesProj/jni/libwebp/dec/webp.c new file mode 100644 index 00000000..33872dda --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/webp.c @@ -0,0 +1,836 @@ +// 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 + +#include "./vp8i.h" +#include "./vp8li.h" +#include "./webpi.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. + +static WEBP_INLINE uint32_t get_le24(const uint8_t* const data) { + return data[0] | (data[1] << 8) | (data[2] << 16); +} + +static WEBP_INLINE uint32_t get_le32(const uint8_t* const data) { + return (uint32_t)get_le24(data) | (data[3] << 24); +} + +// 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 = get_le32(*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 = get_le32(*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 = get_le32(*data + 8); + width = 1 + get_le24(*data + 12); + height = 1 + get_le24(*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 = get_le32(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 = get_le32(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) { + 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); + } + +#if WEBP_DECODER_ABI_VERSION > 0x0203 + if (params->options != NULL && params->options->flip) { + status = WebPFlipBuffer(params->output); + } +#endif + 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(¶ms); + 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, ¶ms) != 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(¶ms); + 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, ¶ms) != 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(¶ms); + 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, ¶ms) != 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(¶ms); + params.output = &config->output; + params.options = &config->options; + status = DecodeInto(data, data_size, ¶ms); + + 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) { + if (options->scaled_width <= 0 || options->scaled_height <= 0) { + return 0; + } + io->scaled_width = options->scaled_width; + io->scaled_height = options->scaled_height; + } + + // Filter + io->bypass_filtering = options && 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/TMessagesProj/jni/libwebp/dec/webpi.h b/TMessagesProj/jni/libwebp/dec/webpi.h new file mode 100644 index 00000000..457c72ed --- /dev/null +++ b/TMessagesProj/jni/libwebp/dec/webpi.h @@ -0,0 +1,120 @@ +// 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 (*OutputRowFunc)(WebPDecParams* const p, int y_pos); + +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 + OutputFunc emit_alpha; // output alpha channel + OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values +}; + +// Should be called first, before any use of the WebPDecParams object. +void WebPResetDecParams(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'). +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); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_DEC_WEBPI_H_ */ diff --git a/TMessagesProj/jni/libwebp/dsp/alpha_processing.c b/TMessagesProj/jni/libwebp/dsp/alpha_processing.c new file mode 100644 index 00000000..d0f7a6cc --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/alpha_processing.c @@ -0,0 +1,329 @@ +// 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 +#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 + +static void MultARGBRow(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; + } + } + } +} + +static void MultRow(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 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 (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int); + +//------------------------------------------------------------------------------ +// Init function + +extern void WebPInitAlphaProcessingSSE2(void); + +void WebPInitAlphaProcessing(void) { + WebPMultARGBRow = MultARGBRow; + WebPMultRow = MultRow; + WebPApplyAlphaMultiply = ApplyAlphaMultiply; + WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b; + 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(); + } +#endif + } +} diff --git a/TMessagesProj/jni/libwebp/dsp/alpha_processing_sse2.c b/TMessagesProj/jni/libwebp/dsp/alpha_processing_sse2.c new file mode 100644 index 00000000..3d0a9b57 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/alpha_processing_sse2.c @@ -0,0 +1,77 @@ +// 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 + +//------------------------------------------------------------------------------ + +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); +} + +#endif // WEBP_USE_SSE2 + +//------------------------------------------------------------------------------ +// Init function + +extern void WebPInitAlphaProcessingSSE2(void); + +void WebPInitAlphaProcessingSSE2(void) { +#if defined(WEBP_USE_SSE2) + WebPExtractAlpha = ExtractAlpha; +#endif +} diff --git a/TMessagesProj/jni/libwebp/dsp/cpu.c b/TMessagesProj/jni/libwebp/dsp/cpu.c new file mode 100644 index 00000000..8754f874 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/cpu.c @@ -0,0 +1,130 @@ +// 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(__ANDROID__) +#include +#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)); +} +#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)); +} +#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1 +#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(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 +#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 cpu_info[4]; + GetCPUInfo(cpu_info, 1); + if (feature == kSSE2) { + return 0 != (cpu_info[3] & 0x04000000); + } + if (feature == kSSE3) { + return 0 != (cpu_info[2] & 0x00000001); + } + 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)) { + 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) { + (void)feature; + return 1; +} +VP8CPUInfo VP8GetCPUInfo = armCPUInfo; +#elif defined(WEBP_USE_MIPS32) +static int mipsCPUInfo(CPUFeature feature) { + (void)feature; + return 1; +} +VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo; +#else +VP8CPUInfo VP8GetCPUInfo = NULL; +#endif + diff --git a/TMessagesProj/jni/libwebp/dsp/dec.c b/TMessagesProj/jni/libwebp/dsp/dec.c new file mode 100644 index 00000000..65a2a885 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/dec.c @@ -0,0 +1,731 @@ +// 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. +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "./dsp.h" +#include "../dec/vp8i.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) + +static const int kC1 = 20091 + (1 << 16); +static const int kC2 = 35468; +#define MUL(a, b) (((a) * (b)) >> 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 = MUL(in[4], kC2) - MUL(in[12], kC1); // [-3783, 3783] + const int d = MUL(in[4], kC1) + MUL(in[12], kC2); // [-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. + (kC1 + kC2) / 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 = MUL(tmp[4], kC2) - MUL(tmp[12], kC1); + const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2); + 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 = 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); + 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 MUL +#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); +} + +//------------------------------------------------------------------------------ +// 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]; + *(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(A, B, C); + *(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(B, C, D); + *(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(C, D, E); + *(uint32_t*)(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(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) { // 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 + +//------------------------------------------------------------------------------ +// 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); +} + +//------------------------------------------------------------------------------ +// default C implementations + +const VP8PredFunc VP8PredLuma4[NUM_BMODES] = { + DC4, TM4, VE4, HE4, RD4, VR4, LD4, VL4, HD4, HU4 +}; + +const VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES] = { + DC16, TM16, VE16, HE16, + DC16NoTop, DC16NoLeft, DC16NoTopLeft +}; + +const VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES] = { + DC8uv, TM8uv, VE8uv, HE8uv, + DC8uvNoTop, DC8uvNoLeft, DC8uvNoTopLeft +}; + +//------------------------------------------------------------------------------ +// 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); +} + +//------------------------------------------------------------------------------ + +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; + +extern void VP8DspInitSSE2(void); +extern void VP8DspInitNEON(void); +extern void VP8DspInitMIPS32(void); + +void VP8DspInit(void) { + 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; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_USE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8DspInitSSE2(); + } +#elif defined(WEBP_USE_NEON) + if (VP8GetCPUInfo(kNEON)) { + VP8DspInitNEON(); + } +#elif defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8DspInitMIPS32(); + } +#endif + } +} + diff --git a/TMessagesProj/jni/libwebp/dsp/dec_clip_tables.c b/TMessagesProj/jni/libwebp/dsp/dec_clip_tables.c new file mode 100644 index 00000000..eec5a6d1 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/dec_clip_tables.c @@ -0,0 +1,366 @@ +// 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]; + +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/TMessagesProj/jni/libwebp/dsp/dec_mips32.c b/TMessagesProj/jni/libwebp/dsp/dec_mips32.c new file mode 100644 index 00000000..3e89ed37 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/dec_mips32.c @@ -0,0 +1,578 @@ +// 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) + +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]]; + 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 thresh) { + const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; + return ((2 * abs_mips32(p0 - q0) + (abs_mips32(p1 - q1) >> 1)) <= thresh); +} + +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 ((2 * abs_mips32(p0 - q0) + (abs_mips32(p1 - q1) >> 1)) > 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) { + while (size-- > 0) { + if (needs_filter2(p, hstride, thresh, 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) { + while (size-- > 0) { + if (needs_filter2(p, hstride, thresh, 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; + for (i = 0; i < 16; ++i) { + if (needs_filter(p + i, stride, thresh)) { + do_filter2(p + i, stride); + } + } +} + +static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { + int i; + for (i = 0; i < 16; ++i) { + if (needs_filter(p + i * stride, 1, thresh)) { + 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(%[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(%[dst]) \n\t" + "sb %[temp1], 0(%[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(%[dst]) \n\t" + "sb %[temp18], 1(%[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(%[dst]) \n\t" + "sb %[temp1], 2(%[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(%[dst]) \n\t" + "lbu %[temp5], 32(%[dst]) \n\t" + "lbu %[temp8], 33(%[dst]) \n\t" + "lbu %[temp11], 34(%[dst]) \n\t" + "lbu %[temp16], 35(%[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], 32(%[dst]) \n\t" + "sb %[temp8], 33(%[dst]) \n\t" + "sb %[temp11], 34(%[dst]) \n\t" + "sb %[temp16], 35(%[dst]) \n\t" + "lbu %[temp5], 64(%[dst]) \n\t" + "lbu %[temp8], 65(%[dst]) \n\t" + "lbu %[temp11], 66(%[dst]) \n\t" + "lbu %[temp16], 67(%[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], 64(%[dst]) \n\t" + "sb %[temp8], 65(%[dst]) \n\t" + "sb %[temp11], 66(%[dst]) \n\t" + "sb %[temp16], 67(%[dst]) \n\t" + "lbu %[temp5], 96(%[dst]) \n\t" + "lbu %[temp8], 97(%[dst]) \n\t" + "lbu %[temp11], 98(%[dst]) \n\t" + "lbu %[temp16], 99(%[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], 96(%[dst]) \n\t" + "sb %[temp8], 97(%[dst]) \n\t" + "sb %[temp11], 98(%[dst]) \n\t" + "sb %[temp16], 99(%[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); + } +} + +#endif // WEBP_USE_MIPS32 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitMIPS32(void); + +void VP8DspInitMIPS32(void) { +#if defined(WEBP_USE_MIPS32) + 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; +#endif // WEBP_USE_MIPS32 +} diff --git a/TMessagesProj/jni/libwebp/dsp/dec_neon.c b/TMessagesProj/jni/libwebp/dsp/dec_neon.c new file mode 100644 index 00000000..9c5bc1c7 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/dec_neon.c @@ -0,0 +1,1292 @@ +// 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 + +// 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, + 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(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); + } +} + +//----------------------------------------------------------------------------- +// 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 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); +} + +#if defined(USE_INTRINSICS) + +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 // 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)); + uint8x16_t tmp_p0, tmp_q0; + ApplyFilter2(p0s, q0s, simple_lf_delta, &tmp_p0, &tmp_q0); + // TODO(skal): avoid the double FlipSign() in ApplyFilter2() and here + p0s = FlipSign(tmp_p0); + q0s = FlipSign(tmp_q0); + } + + // 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)); + uint8x16_t tmp_p0, tmp_q0; + ApplyFilter2(p0s, q0s, simple_lf_delta, &tmp_p0, &tmp_q0); + // TODO(skal): avoid the double FlipSign() in ApplyFilter2() and here + p0s = FlipSign(tmp_p0); + q0s = FlipSign(tmp_q0); + } + + // 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(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 // 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 = vdup_n_s16(in[0]); + 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 + +#endif // WEBP_USE_NEON + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitNEON(void); + +void VP8DspInitNEON(void) { +#if defined(WEBP_USE_NEON) + 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; +#endif // WEBP_USE_NEON +} diff --git a/TMessagesProj/jni/libwebp/dsp/dec_sse2.c b/TMessagesProj/jni/libwebp/dsp/dec_sse2.c new file mode 100644 index 00000000..c37a637f --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/dec_sse2.c @@ -0,0 +1,978 @@ +// 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 +#include "../dec/vp8i.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((__m128i*)&in[0]); + in1 = _mm_loadl_epi64((__m128i*)&in[4]); + in2 = _mm_loadl_epi64((__m128i*)&in[8]); + in3 = _mm_loadl_epi64((__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((__m128i*)&in[16]); + const __m128i inB1 = _mm_loadl_epi64((__m128i*)&in[20]); + const __m128i inB2 = _mm_loadl_epi64((__m128i*)&in[24]); + const __m128i inB3 = _mm_loadl_epi64((__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. + // 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(tmp0, tmp1); + const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3); + const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1); + const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3); + // 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 + T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); + T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); + T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); + T3 = _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 + } + + // 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. + // 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(shifted0, shifted1); + const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3); + const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1); + const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3); + // 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 + T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); + T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); + T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); + T3 = _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 + } + + // 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(*(int*)(dst + 0 * BPS)); + dst1 = _mm_cvtsi32_si128(*(int*)(dst + 1 * BPS)); + dst2 = _mm_cvtsi32_si128(*(int*)(dst + 2 * BPS)); + dst3 = _mm_cvtsi32_si128(*(int*)(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. + *(int*)(dst + 0 * BPS) = _mm_cvtsi128_si32(dst0); + *(int*)(dst + 1 * BPS) = _mm_cvtsi128_si32(dst1); + *(int*)(dst + 2 * BPS) = _mm_cvtsi128_si32(dst2); + *(int*)(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(*(int*)(dst + 0 * BPS)); + __m128i dst1 = _mm_cvtsi32_si128(*(int*)(dst + 1 * BPS)); + __m128i dst2 = _mm_cvtsi32_si128(*(int*)(dst + 2 * BPS)); + __m128i dst3 = _mm_cvtsi32_si128(*(int*)(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. + *(int*)(dst + 0 * BPS) = _mm_cvtsi128_si32(dst0); + *(int*)(dst + 1 * BPS) = _mm_cvtsi128_si32(dst1); + *(int*)(dst + 2 * BPS) = _mm_cvtsi128_si32(dst2); + *(int*)(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 signs = _mm_cmpgt_epi8(zero, *x); + const __m128i lo_0 = _mm_unpacklo_epi8(*x, signs); // s8 -> s16 sign extend + const __m128i hi_0 = _mm_unpackhi_epi8(*x, signs); + const __m128i lo_1 = _mm_srai_epi16(lo_0, 3); + const __m128i hi_1 = _mm_srai_epi16(hi_0, 3); + *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_3 = _mm_subs_epu8(t_1, h); // abs(p1 - p0) - hev_tresh + const __m128i t_4 = _mm_subs_epu8(t_2, h); // abs(q1 - q0) - hev_tresh + + *not_hev = _mm_or_si128(t_3, t_4); + *not_hev = _mm_cmpeq_epi8(*not_hev, 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 sign_bit = _mm_set1_epi8(0x80); + const __m128i k64 = _mm_set1_epi8(0x40); + const __m128i zero = _mm_setzero_si128(); + __m128i not_hev; + __m128i t1, t2, t3; + + // compute hev mask + GetNotHEV(p1, p0, q0, q1, hev_thresh, ¬_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_set1_epi8(3); + t3 = _mm_set1_epi8(4); + t2 = _mm_adds_epi8(t1, t2); // 3 * (q0 - p0) + (p1 - q1) + 3 + t3 = _mm_adds_epi8(t1, t3); // 3 * (q0 - p0) + (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, ¬_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. +// +// TODO(somnath): Investigate _mm_shuffle* also see if it can be broken into +// two Load4x4() to avoid code duplication. +static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride, + __m128i* const p, __m128i* const q) { + __m128i t1, t2; + + // Load 0th, 1st, 4th and 5th rows + __m128i r0 = _mm_cvtsi32_si128(*((int*)&b[0 * stride])); // 03 02 01 00 + __m128i r1 = _mm_cvtsi32_si128(*((int*)&b[1 * stride])); // 13 12 11 10 + __m128i r4 = _mm_cvtsi32_si128(*((int*)&b[4 * stride])); // 43 42 41 40 + __m128i r5 = _mm_cvtsi32_si128(*((int*)&b[5 * stride])); // 53 52 51 50 + + r0 = _mm_unpacklo_epi32(r0, r4); // 43 42 41 40 03 02 01 00 + r1 = _mm_unpacklo_epi32(r1, r5); // 53 52 51 50 13 12 11 10 + + // t1 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00 + t1 = _mm_unpacklo_epi8(r0, r1); + + // Load 2nd, 3rd, 6th and 7th rows + r0 = _mm_cvtsi32_si128(*((int*)&b[2 * stride])); // 23 22 21 22 + r1 = _mm_cvtsi32_si128(*((int*)&b[3 * stride])); // 33 32 31 30 + r4 = _mm_cvtsi32_si128(*((int*)&b[6 * stride])); // 63 62 61 60 + r5 = _mm_cvtsi32_si128(*((int*)&b[7 * stride])); // 73 72 71 70 + + r0 = _mm_unpacklo_epi32(r0, r4); // 63 62 61 60 23 22 21 20 + r1 = _mm_unpacklo_epi32(r1, r5); // 73 72 71 70 33 32 31 30 + + // t2 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20 + t2 = _mm_unpacklo_epi8(r0, r1); + + // t1 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00 + // t2 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40 + r0 = t1; + t1 = _mm_unpacklo_epi16(t1, t2); + t2 = _mm_unpackhi_epi16(r0, t2); + + // *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(t1, t2); + *q = _mm_unpackhi_epi32(t1, t2); +} + +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) { + __m128i t1, t2; + // 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); + + t1 = *p1; + t2 = *q0; + // 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 + *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) { + *((int32_t*)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); +} + +#endif // WEBP_USE_SSE2 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8DspInitSSE2(void); + +void VP8DspInitSSE2(void) { +#if defined(WEBP_USE_SSE2) + 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; +#endif // WEBP_USE_SSE2 +} diff --git a/TMessagesProj/jni/libwebp/dsp/dsp.h b/TMessagesProj/jni/libwebp/dsp/dsp.h new file mode 100644 index 00000000..52c44b2d --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/dsp.h @@ -0,0 +1,293 @@ +// 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 + +//------------------------------------------------------------------------------ +// 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 + +#ifdef __clang__ +# define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__) +# define LOCAL_CLANG_PREREQ(maj, min) \ + (LOCAL_CLANG_VERSION >= (((maj) << 8) | (min))) +#else +# define LOCAL_CLANG_VERSION 0 +# define LOCAL_CLANG_PREREQ(maj, min) 0 +#endif // __clang__ + +#if defined(_MSC_VER) && _MSC_VER > 1310 && \ + (defined(_M_X64) || defined(_M_IX86)) +#define WEBP_MSC_SSE2 // Visual C++ SSE2 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(__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 + +#if defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || defined(__aarch64__) +#define WEBP_USE_NEON +#endif + +#if defined(__mips__) && !defined(__mips64) && (__mips_isa_rev < 6) +#define WEBP_USE_MIPS32 +#if (__mips_isa_rev >= 2) +#define WEBP_USE_MIPS32_R2 +#endif +#endif + +typedef enum { + kSSE2, + kSSE3, + kAVX, + kAVX2, + kNEON, + kMIPS32 +} CPUFeature; +// returns true if the CPU supports the feature. +typedef int (*VP8CPUInfo)(CPUFeature feature); +extern VP8CPUInfo VP8GetCPUInfo; + +//------------------------------------------------------------------------------ +// 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 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); +extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16; + +typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst); +extern VP8BlockCopy VP8Copy4x4; +// Quantization +struct VP8Matrix; // forward declaration +typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +extern VP8QuantizeBlock VP8EncQuantizeBlock; + +// specific to 2nd transform: +typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; + +// Collect histogram for susceptibility calculation and accumulate in histo[]. +struct VP8Histogram; +typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + struct VP8Histogram* const histo); +extern const int VP8DspScan[16 + 4 + 4]; +extern VP8CHisto VP8CollectHistogram; + +void VP8EncDspInit(void); // must be called before using any of the above + +//------------------------------------------------------------------------------ +// 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 const VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */]; +extern const VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */]; +extern const 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] +void VP8InitClipTables(void); // must be called first + +// 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; + +// 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 const 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); + +//------------------------------------------------------------------------------ +// 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); + +// 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); + +// To be called first before using the above. +void WebPInitAlphaProcessing(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_DSP_DSP_H_ */ diff --git a/TMessagesProj/jni/libwebp/dsp/enc.c b/TMessagesProj/jni/libwebp/dsp/enc.c new file mode 100644 index 00000000..e4ea8cb8 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/enc.c @@ -0,0 +1,741 @@ +// 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 +#include // 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 +}; + +static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { + int j; + 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; // TODO(skal): add rounding? + const int clipped_value = clip_max(v, MAX_COEFF_THRESH); + histo->distribution[clipped_value]++; + } + } +} + +//------------------------------------------------------------------------------ +// 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 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 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 + +#define DST(x, y) dst[(x) + (y) * BPS] + +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) { + 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) { + 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) { + if (top) { + 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) { + 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) { + for (j = 0; j < size; ++j) DC += top[j]; + if (left) { // 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) { // 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) top += 8; + if (left) 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 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]; + *(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(X, I, J); + *(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(I, J, K); + *(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(J, K, L); + *(uint32_t*)(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. +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 * Q; + out[n] = level; + if (level) last = n; + } else { + out[n] = 0; + in[j] = 0; + } + } + return (last >= 0); +} + +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 * 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 size) { + int y; + for (y = 0; y < size; ++y) { + memcpy(dst, src, size); + src += BPS; + dst += BPS; + } +} + +static void Copy4x4(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 4); } + +//------------------------------------------------------------------------------ +// Initialization + +// Speed-critical function pointers. We have to initialize them to the default +// implementations within VP8EncDspInit(). +VP8CHisto VP8CollectHistogram; +VP8Idct VP8ITransform; +VP8Fdct VP8FTransform; +VP8WHT VP8FTransformWHT; +VP8Intra4Preds VP8EncPredLuma4; +VP8IntraPreds VP8EncPredLuma16; +VP8IntraPreds VP8EncPredChroma8; +VP8Metric VP8SSE16x16; +VP8Metric VP8SSE8x8; +VP8Metric VP8SSE16x8; +VP8Metric VP8SSE4x4; +VP8WMetric VP8TDisto4x4; +VP8WMetric VP8TDisto16x16; +VP8QuantizeBlock VP8EncQuantizeBlock; +VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; +VP8BlockCopy VP8Copy4x4; + +extern void VP8EncDspInitSSE2(void); +extern void VP8EncDspInitAVX2(void); +extern void VP8EncDspInitNEON(void); +extern void VP8EncDspInitMIPS32(void); + +void VP8EncDspInit(void) { + VP8DspInit(); // common inverse transforms + InitTables(); + + // default C implementations + VP8CollectHistogram = CollectHistogram; + VP8ITransform = ITransform; + VP8FTransform = FTransform; + VP8FTransformWHT = FTransformWHT; + VP8EncPredLuma4 = Intra4Preds; + VP8EncPredLuma16 = Intra16Preds; + VP8EncPredChroma8 = IntraChromaPreds; + VP8SSE16x16 = SSE16x16; + VP8SSE8x8 = SSE8x8; + VP8SSE16x8 = SSE16x8; + VP8SSE4x4 = SSE4x4; + VP8TDisto4x4 = Disto4x4; + VP8TDisto16x16 = Disto16x16; + VP8EncQuantizeBlock = QuantizeBlock; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT; + VP8Copy4x4 = Copy4x4; + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_USE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8EncDspInitSSE2(); + } +#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 + } +} + diff --git a/TMessagesProj/jni/libwebp/dsp/enc_avx2.c b/TMessagesProj/jni/libwebp/dsp/enc_avx2.c new file mode 100644 index 00000000..372e6169 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/enc_avx2.c @@ -0,0 +1,24 @@ +// 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 + +extern void VP8EncDspInitAVX2(void); + +void VP8EncDspInitAVX2(void) { +} diff --git a/TMessagesProj/jni/libwebp/dsp/enc_mips32.c b/TMessagesProj/jni/libwebp/dsp/enc_mips32.c new file mode 100644 index 00000000..def9a169 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/enc_mips32.c @@ -0,0 +1,776 @@ +// 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 "../enc/vp8enci.h" +#include "../enc/cost.h" + +#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409 +#define WORK_AROUND_GCC +#endif + +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..D - offsets 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, B, C, D, 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], "#A"(%[temp20]) \n\t" \ + "lbu %[temp17], "#B"(%[temp20]) \n\t" \ + "lbu %[temp18], "#C"(%[temp20]) \n\t" \ + "lbu %[temp19], "#D"(%[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"], "#A"(%[temp16]) \n\t" \ + "sb %["#TEMP4"], "#B"(%[temp16]) \n\t" \ + "sb %["#TEMP8"], "#C"(%[temp16]) \n\t" \ + "sb %["#TEMP12"], "#D"(%[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, 1, 2, 3, temp0, temp4, temp8, temp12) + HORIZONTAL_PASS(16, 17, 18, 19, temp1, temp5, temp9, temp13) + HORIZONTAL_PASS(32, 33, 34, 35, temp2, temp6, temp10, temp14) + HORIZONTAL_PASS(48, 49, 50, 51, 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; +} + +#undef QUANTIZE_ONE + +// macro for one horizontal pass in Disto4x4 (TTransform) +// two calls of function TTransform are merged into single one +// A..D - offsets 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, B, C, D, E, F, G, H, E1, F1, G1, H1) \ + "lbu %[temp0], "#A"(%[a]) \n\t" \ + "lbu %[temp1], "#B"(%[a]) \n\t" \ + "lbu %[temp2], "#C"(%[a]) \n\t" \ + "lbu %[temp3], "#D"(%[a]) \n\t" \ + "lbu %[temp4], "#A"(%[b]) \n\t" \ + "lbu %[temp5], "#B"(%[b]) \n\t" \ + "lbu %[temp6], "#C"(%[b]) \n\t" \ + "lbu %[temp7], "#D"(%[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, 1, 2, 3, 0, 4, 8, 12, 64, 68, 72, 76) + HORIZONTAL_PASS(16, 17, 18, 19, 16, 20, 24, 28, 80, 84, 88, 92) + HORIZONTAL_PASS(32, 33, 34, 35, 32, 36, 40, 44, 96, 100, 104, 108) + HORIZONTAL_PASS(48, 49, 50, 51, 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..D - offsets in bytes to load from src and ref buffers +// TEMP0..TEMP3 - registers for corresponding tmp elements +#define HORIZONTAL_PASS(A, B, C, D, TEMP0, TEMP1, TEMP2, TEMP3) \ + "lw %["#TEMP1"], 0(%[args]) \n\t" \ + "lw %["#TEMP2"], 4(%[args]) \n\t" \ + "lbu %[temp16], "#A"(%["#TEMP1"]) \n\t" \ + "lbu %[temp17], "#A"(%["#TEMP2"]) \n\t" \ + "lbu %[temp18], "#B"(%["#TEMP1"]) \n\t" \ + "lbu %[temp19], "#B"(%["#TEMP2"]) \n\t" \ + "subu %[temp20], %[temp16], %[temp17] \n\t" \ + "lbu %[temp16], "#C"(%["#TEMP1"]) \n\t" \ + "lbu %[temp17], "#C"(%["#TEMP2"]) \n\t" \ + "subu %["#TEMP0"], %[temp18], %[temp19] \n\t" \ + "lbu %[temp18], "#D"(%["#TEMP1"]) \n\t" \ + "lbu %[temp19], "#D"(%["#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, 1, 2, 3, temp0, temp1, temp2, temp3) + HORIZONTAL_PASS(16, 17, 18, 19, temp4, temp5, temp6, temp7) + HORIZONTAL_PASS(32, 33, 34, 35, temp8, temp9, temp10, temp11) + HORIZONTAL_PASS(48, 49, 50, 51, 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 + +// Forward declaration. +extern int VP8GetResidualCostMIPS32(int ctx0, const VP8Residual* const res); + +int VP8GetResidualCostMIPS32(int ctx0, const VP8Residual* const res) { + 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]; + const uint16_t* t = res->cost[n][ctx0]; + int cost; + const int const_2 = 2; + const int const_255 = 255; + const int const_max_level = MAX_VARIABLE_LEVEL; + int res_cost; + int res_prob; + int res_coeffs; + int res_last; + int v_reg; + int b_reg; + int ctx_reg; + int cost_add, temp_1, temp_2, temp_3; + + if (res->last < 0) { + return VP8BitCost(0, p0); + } + + cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0; + + res_cost = (int)res->cost; + res_prob = (int)res->prob; + res_coeffs = (int)res->coeffs; + res_last = (int)res->last; + + __asm__ volatile( + ".set push \n\t" + ".set noreorder \n\t" + + "sll %[temp_1], %[n], 1 \n\t" + "addu %[res_coeffs], %[res_coeffs], %[temp_1] \n\t" + "slt %[temp_2], %[n], %[res_last] \n\t" + "bnez %[temp_2], 1f \n\t" + " li %[cost_add], 0 \n\t" + "b 2f \n\t" + " nop \n\t" + "1: \n\t" + "lh %[v_reg], 0(%[res_coeffs]) \n\t" + "addu %[b_reg], %[n], %[VP8EncBands] \n\t" + "move %[temp_1], %[const_max_level] \n\t" + "addu %[cost], %[cost], %[cost_add] \n\t" + "negu %[temp_2], %[v_reg] \n\t" + "slti %[temp_3], %[v_reg], 0 \n\t" + "movn %[v_reg], %[temp_2], %[temp_3] \n\t" + "lbu %[b_reg], 1(%[b_reg]) \n\t" + "li %[cost_add], 0 \n\t" + + "sltiu %[temp_3], %[v_reg], 2 \n\t" + "move %[ctx_reg], %[v_reg] \n\t" + "movz %[ctx_reg], %[const_2], %[temp_3] \n\t" + // cost += VP8LevelCost(t, v); + "slt %[temp_3], %[v_reg], %[const_max_level] \n\t" + "movn %[temp_1], %[v_reg], %[temp_3] \n\t" + "sll %[temp_2], %[v_reg], 1 \n\t" + "addu %[temp_2], %[temp_2], %[VP8LevelFixedCosts] \n\t" + "lhu %[temp_2], 0(%[temp_2]) \n\t" + "sll %[temp_1], %[temp_1], 1 \n\t" + "addu %[temp_1], %[temp_1], %[t] \n\t" + "lhu %[temp_3], 0(%[temp_1]) \n\t" + "addu %[cost], %[cost], %[temp_2] \n\t" + + // t = res->cost[b][ctx]; + "sll %[temp_1], %[ctx_reg], 7 \n\t" + "sll %[temp_2], %[ctx_reg], 3 \n\t" + "addu %[cost], %[cost], %[temp_3] \n\t" + "addu %[temp_1], %[temp_1], %[temp_2] \n\t" + "sll %[temp_2], %[b_reg], 3 \n\t" + "sll %[temp_3], %[b_reg], 5 \n\t" + "sub %[temp_2], %[temp_3], %[temp_2] \n\t" + "sll %[temp_3], %[temp_2], 4 \n\t" + "addu %[temp_1], %[temp_1], %[temp_3] \n\t" + "addu %[temp_2], %[temp_2], %[res_cost] \n\t" + "addiu %[n], %[n], 1 \n\t" + "addu %[t], %[temp_1], %[temp_2] \n\t" + "slt %[temp_1], %[n], %[res_last] \n\t" + "bnez %[temp_1], 1b \n\t" + " addiu %[res_coeffs], %[res_coeffs], 2 \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), [b_reg]"=&r"(b_reg), [cost_add]"=&r"(cost_add), + [temp_1]"=&r"(temp_1), [temp_2]"=&r"(temp_2), [temp_3]"=&r"(temp_3) + : [const_2]"r"(const_2), [const_255]"r"(const_255), [res_last]"r"(res_last), + [VP8EntropyCost]"r"(VP8EntropyCost), [VP8EncBands]"r"(VP8EncBands), + [const_max_level]"r"(const_max_level), [res_prob]"r"(res_prob), + [VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_coeffs]"r"(res_coeffs), + [res_cost]"r"(res_cost) + : "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; +} + +#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) + +#if !defined(WORK_AROUND_GCC) +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, 4, 8, 12) + GET_SSE( 16, 20, 24, 28) + GET_SSE( 32, 36, 40, 44) + GET_SSE( 48, 52, 56, 60) + GET_SSE( 64, 68, 72, 76) + GET_SSE( 80, 84, 88, 92) + GET_SSE( 96, 100, 104, 108) + GET_SSE(112, 116, 120, 124) + GET_SSE(128, 132, 136, 140) + GET_SSE(144, 148, 152, 156) + GET_SSE(160, 164, 168, 172) + GET_SSE(176, 180, 184, 188) + GET_SSE(192, 196, 200, 204) + GET_SSE(208, 212, 216, 220) + GET_SSE(224, 228, 232, 236) + GET_SSE(240, 244, 248, 252) + + "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, 4, 8, 12) + GET_SSE( 16, 20, 24, 28) + GET_SSE( 32, 36, 40, 44) + GET_SSE( 48, 52, 56, 60) + GET_SSE( 64, 68, 72, 76) + GET_SSE( 80, 84, 88, 92) + GET_SSE( 96, 100, 104, 108) + GET_SSE(112, 116, 120, 124) + + "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, 4, 16, 20) + GET_SSE(32, 36, 48, 52) + GET_SSE(64, 68, 80, 84) + GET_SSE(96, 100, 112, 116) + + "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, 16, 32, 48) + + "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; +} + +#endif // WORK_AROUND_GCC + +#undef GET_SSE_MIPS32 +#undef GET_SSE_MIPS32_INNER + +#endif // WEBP_USE_MIPS32 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitMIPS32(void); + +void VP8EncDspInitMIPS32(void) { +#if defined(WEBP_USE_MIPS32) + VP8ITransform = ITransform; + VP8EncQuantizeBlock = QuantizeBlock; + VP8TDisto4x4 = Disto4x4; + VP8TDisto16x16 = Disto16x16; + VP8FTransform = FTransform; +#if !defined(WORK_AROUND_GCC) + VP8SSE16x16 = SSE16x16; + VP8SSE8x8 = SSE8x8; + VP8SSE16x8 = SSE16x8; + VP8SSE4x4 = SSE4x4; +#endif +#endif // WEBP_USE_MIPS32 +} diff --git a/TMessagesProj/jni/libwebp/dsp/enc_neon.c b/TMessagesProj/jni/libwebp/dsp/enc_neon.c new file mode 100644 index 00000000..42041f73 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/enc_neon.c @@ -0,0 +1,1077 @@ +// 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 + +#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 +// USE_INTRINSICS define. +// With gcc-4.8, it's a little faster speed than inlined-assembly. +#if defined(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 // 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(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. + +// 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 +// USE_INTRINSICS define. +// With gcc-4.8, it's only slightly slower than the inlined. +#if defined(USE_INTRINSICS) + +// Zero extend an uint16x4_t 'v' to an int32x4_t. +static WEBP_INLINE int32x4_t ConvertU16ToS32(uint16x4_t v) { + return vreinterpretq_s32_u32(vmovl_u16(v)); +} + +// Does a regular 4x4 transpose followed by an adjustment of the upper columns +// in the inner rows to restore the source order of differences, +// i.e., a0 - a1 | a3 - a2. +static WEBP_INLINE int32x4x4_t DistoTranspose4x4(const int32x4x4_t rows) { + int32x4x4_t out = Transpose4x4(rows); + // restore source order in the columns containing differences. + const int32x2_t r1h = vget_high_s32(out.val[1]); + const int32x2_t r2h = vget_high_s32(out.val[2]); + out.val[1] = vcombine_s32(vget_low_s32(out.val[1]), r2h); + out.val[2] = vcombine_s32(vget_low_s32(out.val[2]), r1h); + return out; +} + +static WEBP_INLINE int32x4x4_t DistoHorizontalPass(const uint8x8_t r0r1, + const uint8x8_t r2r3) { + // a0 = in[0] + in[2] | a1 = in[1] + in[3] + const uint16x8_t a0a1 = vaddl_u8(r0r1, r2r3); + // a3 = in[0] - in[2] | a2 = in[1] - in[3] + const uint16x8_t a3a2 = vsubl_u8(r0r1, r2r3); + const int32x4_t tmp0 = vpaddlq_s16(vreinterpretq_s16_u16(a0a1)); // a0 + a1 + const int32x4_t tmp1 = vpaddlq_s16(vreinterpretq_s16_u16(a3a2)); // a3 + a2 + // no pairwise subtraction; reorder to perform tmp[2]/tmp[3] calculations. + // a0a0 a3a3 a0a0 a3a3 a0a0 a3a3 a0a0 a3a3 + // a1a1 a2a2 a1a1 a2a2 a1a1 a2a2 a1a1 a2a2 + const int16x8x2_t transpose = + vtrnq_s16(vreinterpretq_s16_u16(a0a1), vreinterpretq_s16_u16(a3a2)); + // tmp[3] = a0 - a1 | tmp[2] = a3 - a2 + const int32x4_t tmp32_1 = vsubl_s16(vget_low_s16(transpose.val[0]), + vget_low_s16(transpose.val[1])); + const int32x4_t tmp32_2 = vsubl_s16(vget_high_s16(transpose.val[0]), + vget_high_s16(transpose.val[1])); + // [0]: tmp[3] [1]: tmp[2] + const int32x4x2_t split = vtrnq_s32(tmp32_1, tmp32_2); + const int32x4x4_t res = { { tmp0, tmp1, split.val[1], split.val[0] } }; + return res; +} + +static WEBP_INLINE int32x4x4_t DistoVerticalPass(const int32x4x4_t rows) { + // a0 = tmp[0 + i] + tmp[8 + i]; + const int32x4_t a0 = vaddq_s32(rows.val[0], rows.val[1]); + // a1 = tmp[4 + i] + tmp[12+ i]; + const int32x4_t a1 = vaddq_s32(rows.val[2], rows.val[3]); + // a2 = tmp[4 + i] - tmp[12+ i]; + const int32x4_t a2 = vsubq_s32(rows.val[2], rows.val[3]); + // a3 = tmp[0 + i] - tmp[8 + i]; + const int32x4_t a3 = vsubq_s32(rows.val[0], rows.val[1]); + const int32x4_t b0 = vqabsq_s32(vaddq_s32(a0, a1)); // abs(a0 + a1) + const int32x4_t b1 = vqabsq_s32(vaddq_s32(a3, a2)); // abs(a3 + a2) + const int32x4_t b2 = vabdq_s32(a3, a2); // abs(a3 - a2) + const int32x4_t b3 = vabdq_s32(a0, a1); // abs(a0 - a1) + const int32x4x4_t res = { { b0, b1, b2, b3 } }; + return res; +} + +// Calculate the weighted sum of the rows in 'b'. +static WEBP_INLINE int64x1_t DistoSum(const int32x4x4_t b, + const int32x4_t w0, const int32x4_t w1, + const int32x4_t w2, const int32x4_t w3) { + const int32x4_t s0 = vmulq_s32(w0, b.val[0]); + const int32x4_t s1 = vmlaq_s32(s0, w1, b.val[1]); + const int32x4_t s2 = vmlaq_s32(s1, w2, b.val[2]); + const int32x4_t s3 = vmlaq_s32(s2, w3, b.val[3]); + const int64x2_t sum1 = vpaddlq_s32(s3); + const int64x1_t sum2 = vadd_s64(vget_low_s64(sum1), vget_high_s64(sum1)); + return sum2; +} + +#define LOAD_LANE_32b(src, VALUE, LANE) \ + (VALUE) = vld1q_lane_u32((const uint32_t*)(src), (VALUE), (LANE)) + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +static int Disto4x4(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + uint32x4_t d0d1 = { 0, 0, 0, 0 }; + uint32x4_t d2d3 = { 0, 0, 0, 0 }; + LOAD_LANE_32b(a + 0 * BPS, d0d1, 0); // a00 a01 a02 a03 + LOAD_LANE_32b(a + 1 * BPS, d0d1, 1); // a10 a11 a12 a13 + LOAD_LANE_32b(b + 0 * BPS, d0d1, 2); // b00 b01 b02 b03 + LOAD_LANE_32b(b + 1 * BPS, d0d1, 3); // b10 b11 b12 b13 + LOAD_LANE_32b(a + 2 * BPS, d2d3, 0); // a20 a21 a22 a23 + LOAD_LANE_32b(a + 3 * BPS, d2d3, 1); // a30 a31 a32 a33 + LOAD_LANE_32b(b + 2 * BPS, d2d3, 2); // b20 b21 b22 b23 + LOAD_LANE_32b(b + 3 * BPS, d2d3, 3); // b30 b31 b32 b33 + + { + // a00 a01 a20 a21 a10 a11 a30 a31 b00 b01 b20 b21 b10 b11 b30 b31 + // a02 a03 a22 a23 a12 a13 a32 a33 b02 b03 b22 b23 b12 b13 b32 b33 + const uint16x8x2_t tmp = + vtrnq_u16(vreinterpretq_u16_u32(d0d1), vreinterpretq_u16_u32(d2d3)); + const uint8x16_t d0d1u8 = vreinterpretq_u8_u16(tmp.val[0]); + const uint8x16_t d2d3u8 = vreinterpretq_u8_u16(tmp.val[1]); + const int32x4x4_t hpass_a = DistoHorizontalPass(vget_low_u8(d0d1u8), + vget_low_u8(d2d3u8)); + const int32x4x4_t hpass_b = DistoHorizontalPass(vget_high_u8(d0d1u8), + vget_high_u8(d2d3u8)); + const int32x4x4_t tmp_a = DistoTranspose4x4(hpass_a); + const int32x4x4_t tmp_b = DistoTranspose4x4(hpass_b); + const int32x4x4_t vpass_a = DistoVerticalPass(tmp_a); + const int32x4x4_t vpass_b = DistoVerticalPass(tmp_b); + const int32x4_t w0 = ConvertU16ToS32(vld1_u16(w + 0)); + const int32x4_t w1 = ConvertU16ToS32(vld1_u16(w + 4)); + const int32x4_t w2 = ConvertU16ToS32(vld1_u16(w + 8)); + const int32x4_t w3 = ConvertU16ToS32(vld1_u16(w + 12)); + const int64x1_t sum1 = DistoSum(vpass_a, w0, w1, w2, w3); + const int64x1_t sum2 = DistoSum(vpass_b, w0, w1, w2, w3); + const int32x2_t diff = vabd_s32(vreinterpret_s32_s64(sum1), + vreinterpret_s32_s64(sum2)); + const int32x2_t res = vshr_n_s32(diff, 5); + return vget_lane_s32(res, 0); + } +} + +#undef LOAD_LANE_32b + +#else + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +static int Disto4x4(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int kBPS = BPS; + const uint8_t* A = a; + const uint8_t* B = b; + const uint16_t* W = w; + int sum; + __asm__ volatile ( + "vld1.32 d0[0], [%[a]], %[kBPS] \n" + "vld1.32 d0[1], [%[a]], %[kBPS] \n" + "vld1.32 d2[0], [%[a]], %[kBPS] \n" + "vld1.32 d2[1], [%[a]] \n" + + "vld1.32 d1[0], [%[b]], %[kBPS] \n" + "vld1.32 d1[1], [%[b]], %[kBPS] \n" + "vld1.32 d3[0], [%[b]], %[kBPS] \n" + "vld1.32 d3[1], [%[b]] \n" + + // a d0/d2, b d1/d3 + // d0/d1: 01 01 01 01 + // d2/d3: 23 23 23 23 + // But: it goes 01 45 23 67 + // Notice the middle values are transposed + "vtrn.16 q0, q1 \n" + + // {a0, a1} = {in[0] + in[2], in[1] + in[3]} + "vaddl.u8 q2, d0, d2 \n" + "vaddl.u8 q10, d1, d3 \n" + // {a3, a2} = {in[0] - in[2], in[1] - in[3]} + "vsubl.u8 q3, d0, d2 \n" + "vsubl.u8 q11, d1, d3 \n" + + // tmp[0] = a0 + a1 + "vpaddl.s16 q0, q2 \n" + "vpaddl.s16 q8, q10 \n" + + // tmp[1] = a3 + a2 + "vpaddl.s16 q1, q3 \n" + "vpaddl.s16 q9, q11 \n" + + // No pair subtract + // q2 = {a0, a3} + // q3 = {a1, a2} + "vtrn.16 q2, q3 \n" + "vtrn.16 q10, q11 \n" + + // {tmp[3], tmp[2]} = {a0 - a1, a3 - a2} + "vsubl.s16 q12, d4, d6 \n" + "vsubl.s16 q13, d5, d7 \n" + "vsubl.s16 q14, d20, d22 \n" + "vsubl.s16 q15, d21, d23 \n" + + // separate tmp[3] and tmp[2] + // q12 = tmp[3] + // q13 = tmp[2] + "vtrn.32 q12, q13 \n" + "vtrn.32 q14, q15 \n" + + // Transpose tmp for a + "vswp d1, d26 \n" // vtrn.64 + "vswp d3, d24 \n" // vtrn.64 + "vtrn.32 q0, q1 \n" + "vtrn.32 q13, q12 \n" + + // Transpose tmp for b + "vswp d17, d30 \n" // vtrn.64 + "vswp d19, d28 \n" // vtrn.64 + "vtrn.32 q8, q9 \n" + "vtrn.32 q15, q14 \n" + + // The first Q register is a, the second b. + // q0/8 tmp[0-3] + // q13/15 tmp[4-7] + // q1/9 tmp[8-11] + // q12/14 tmp[12-15] + + // These are still in 01 45 23 67 order. We fix it easily in the addition + // case but the subtraction propagates them. + "vswp d3, d27 \n" + "vswp d19, d31 \n" + + // a0 = tmp[0] + tmp[8] + "vadd.s32 q2, q0, q1 \n" + "vadd.s32 q3, q8, q9 \n" + + // a1 = tmp[4] + tmp[12] + "vadd.s32 q10, q13, q12 \n" + "vadd.s32 q11, q15, q14 \n" + + // a2 = tmp[4] - tmp[12] + "vsub.s32 q13, q13, q12 \n" + "vsub.s32 q15, q15, q14 \n" + + // a3 = tmp[0] - tmp[8] + "vsub.s32 q0, q0, q1 \n" + "vsub.s32 q8, q8, q9 \n" + + // b0 = a0 + a1 + "vadd.s32 q1, q2, q10 \n" + "vadd.s32 q9, q3, q11 \n" + + // b1 = a3 + a2 + "vadd.s32 q12, q0, q13 \n" + "vadd.s32 q14, q8, q15 \n" + + // b2 = a3 - a2 + "vsub.s32 q0, q0, q13 \n" + "vsub.s32 q8, q8, q15 \n" + + // b3 = a0 - a1 + "vsub.s32 q2, q2, q10 \n" + "vsub.s32 q3, q3, q11 \n" + + "vld1.64 {q10, q11}, [%[w]] \n" + + // abs(b0) + "vabs.s32 q1, q1 \n" + "vabs.s32 q9, q9 \n" + // abs(b1) + "vabs.s32 q12, q12 \n" + "vabs.s32 q14, q14 \n" + // abs(b2) + "vabs.s32 q0, q0 \n" + "vabs.s32 q8, q8 \n" + // abs(b3) + "vabs.s32 q2, q2 \n" + "vabs.s32 q3, q3 \n" + + // expand w before using. + "vmovl.u16 q13, d20 \n" + "vmovl.u16 q15, d21 \n" + + // w[0] * abs(b0) + "vmul.u32 q1, q1, q13 \n" + "vmul.u32 q9, q9, q13 \n" + + // w[4] * abs(b1) + "vmla.u32 q1, q12, q15 \n" + "vmla.u32 q9, q14, q15 \n" + + // expand w before using. + "vmovl.u16 q13, d22 \n" + "vmovl.u16 q15, d23 \n" + + // w[8] * abs(b1) + "vmla.u32 q1, q0, q13 \n" + "vmla.u32 q9, q8, q13 \n" + + // w[12] * abs(b1) + "vmla.u32 q1, q2, q15 \n" + "vmla.u32 q9, q3, q15 \n" + + // Sum the arrays + "vpaddl.u32 q1, q1 \n" + "vpaddl.u32 q9, q9 \n" + "vadd.u64 d2, d3 \n" + "vadd.u64 d18, d19 \n" + + // Hadamard transform needs 4 bits of extra precision (2 bits in each + // direction) for dynamic raw. Weights w[] are 16bits at max, so the maximum + // precision for coeff is 8bit of input + 4bits of Hadamard transform + + // 16bits for w[] + 2 bits of abs() summation. + // + // This uses a maximum of 31 bits (signed). Discarding the top 32 bits is + // A-OK. + + // sum2 - sum1 + "vsub.u32 d0, d2, d18 \n" + // abs(sum2 - sum1) + "vabs.s32 d0, d0 \n" + // abs(sum2 - sum1) >> 5 + "vshr.u32 d0, #5 \n" + + // It would be better to move the value straight into r0 but I'm not + // entirely sure how this works with inline assembly. + "vmov.32 %[sum], d0[0] \n" + + : [sum] "=r"(sum), [a] "+r"(A), [b] "+r"(B), [w] "+r"(W) + : [kBPS] "r"(kBPS) + : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", + "q10", "q11", "q12", "q13", "q14", "q15" // clobbered + ) ; + + return sum; +} + +#endif // USE_INTRINSICS + +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; + 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) { + histo->distribution[out[k]]++; + } + } + } +} + +//------------------------------------------------------------------------------ + +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; + // vtbl4_u8 is marked unavailable for iOS arm64, use wider versions there. +#if defined(__APPLE__) && defined(__aarch64__) + 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; +} + +#endif // !WORK_AROUND_GCC + +#endif // WEBP_USE_NEON + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitNEON(void); + +void VP8EncDspInitNEON(void) { +#if defined(WEBP_USE_NEON) + 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; +#endif +#endif // WEBP_USE_NEON +} diff --git a/TMessagesProj/jni/libwebp/dsp/enc_sse2.c b/TMessagesProj/jni/libwebp/dsp/enc_sse2.c new file mode 100644 index 00000000..9958d9f6 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/enc_sse2.c @@ -0,0 +1,982 @@ +// 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 // for abs() +#include + +#include "../enc/cost.h" +#include "../enc/vp8enci.h" +#include "../utils/utils.h" + +//------------------------------------------------------------------------------ +// Quite useful macro for debugging. Left here for convenience. + +#if 0 +#include +static 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; + printf("%s\t: ", name); + if (size == 8) { + for (n = 0; n < 16; ++n) printf("%.2x ", tmp.i8[n]); + } else if (size == 16) { + for (n = 0; n < 8; ++n) printf("%.4x ", tmp.i16[n]); + } else if (size == 32) { + for (n = 0; n < 4; ++n) printf("%.8x ", tmp.i32[n]); + } else { + for (n = 0; n < 2; ++n) printf("%.16lx ", tmp.i64[n]); + } + printf("\n"); +} +#endif + +//------------------------------------------------------------------------------ +// 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 max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); + int j; + 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]); + // sign(out) = out >> 15 (0x0000 if positive, 0xffff if negative) + const __m128i sign0 = _mm_srai_epi16(out0, 15); + const __m128i sign1 = _mm_srai_epi16(out1, 15); + // abs(out) = (out ^ sign) - sign + const __m128i xor0 = _mm_xor_si128(out0, sign0); + const __m128i xor1 = _mm_xor_si128(out1, sign1); + const __m128i abs0 = _mm_sub_epi16(xor0, sign0); + const __m128i abs1 = _mm_sub_epi16(xor1, sign1); + // 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) { + histo->distribution[out[k]]++; + } + } +} + +//------------------------------------------------------------------------------ +// 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((__m128i*)&in[0]); + in1 = _mm_loadl_epi64((__m128i*)&in[4]); + in2 = _mm_loadl_epi64((__m128i*)&in[8]); + in3 = _mm_loadl_epi64((__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((__m128i*)&in[16]); + const __m128i inB1 = _mm_loadl_epi64((__m128i*)&in[20]); + const __m128i inB2 = _mm_loadl_epi64((__m128i*)&in[24]); + const __m128i inB3 = _mm_loadl_epi64((__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. + // 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(tmp0, tmp1); + const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3); + const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1); + const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3); + // 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 + T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); + T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); + T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); + T3 = _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 + } + + // 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. + // 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(shifted0, shifted1); + const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3); + const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1); + const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3); + // 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 + T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); + T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); + T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); + T3 = _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 + } + + // 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((__m128i*)&ref[0 * BPS]); + ref1 = _mm_loadl_epi64((__m128i*)&ref[1 * BPS]); + ref2 = _mm_loadl_epi64((__m128i*)&ref[2 * BPS]); + ref3 = _mm_loadl_epi64((__m128i*)&ref[3 * BPS]); + } else { + // Load four bytes/pixels per line. + ref0 = _mm_cvtsi32_si128(*(int*)&ref[0 * BPS]); + ref1 = _mm_cvtsi32_si128(*(int*)&ref[1 * BPS]); + ref2 = _mm_cvtsi32_si128(*(int*)&ref[2 * BPS]); + ref3 = _mm_cvtsi32_si128(*(int*)&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. + *((int32_t *)&dst[0 * BPS]) = _mm_cvtsi128_si32(ref0); + *((int32_t *)&dst[1 * BPS]) = _mm_cvtsi128_si32(ref1); + *((int32_t *)&dst[2 * BPS]) = _mm_cvtsi128_si32(ref2); + *((int32_t *)&dst[3 * BPS]) = _mm_cvtsi128_si32(ref3); + } + } +} + +static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { + const __m128i zero = _mm_setzero_si128(); + const __m128i seven = _mm_set1_epi16(7); + const __m128i k937 = _mm_set1_epi32(937); + const __m128i k1812 = _mm_set1_epi32(1812); + const __m128i k51000 = _mm_set1_epi32(51000); + const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16)); + 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 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); + __m128i v01, v32; + + + // Difference between src and ref and initial transpose. + { + // Load src and convert to 16b. + const __m128i src0 = _mm_loadl_epi64((__m128i*)&src[0 * BPS]); + const __m128i src1 = _mm_loadl_epi64((__m128i*)&src[1 * BPS]); + const __m128i src2 = _mm_loadl_epi64((__m128i*)&src[2 * BPS]); + const __m128i src3 = _mm_loadl_epi64((__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((__m128i*)&ref[0 * BPS]); + const __m128i ref1 = _mm_loadl_epi64((__m128i*)&ref[1 * BPS]); + const __m128i ref2 = _mm_loadl_epi64((__m128i*)&ref[2 * BPS]); + const __m128i ref3 = _mm_loadl_epi64((__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 00 00 00 + 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 shuf01 = _mm_unpacklo_epi32(diff0, diff1); + const __m128i shuf23 = _mm_unpacklo_epi32(diff2, diff3); + // 00 01 10 11 02 03 12 13 + // 20 21 30 31 22 23 32 33 + const __m128i shuf01_p = + _mm_shufflehi_epi16(shuf01, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i shuf23_p = + _mm_shufflehi_epi16(shuf23, _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); + v01 = _mm_unpacklo_epi32(s_lo, s_hi); + v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2.. + } + + // Second pass + { + // 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 FTransformWHT(const int16_t* in, int16_t* out) { + int32_t tmp[16]; + int i; + for (i = 0; i < 4; ++i, in += 64) { + const int a0 = (in[0 * 16] + in[2 * 16]); + 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; + tmp[1 + i * 4] = a3 + a2; + tmp[2 + i * 4] = a3 - a2; + tmp[3 + i * 4] = a0 - a1; + } + { + const __m128i src0 = _mm_loadu_si128((__m128i*)&tmp[0]); + const __m128i src1 = _mm_loadu_si128((__m128i*)&tmp[4]); + const __m128i src2 = _mm_loadu_si128((__m128i*)&tmp[8]); + const __m128i src3 = _mm_loadu_si128((__m128i*)&tmp[12]); + const __m128i a0 = _mm_add_epi32(src0, src2); + const __m128i a1 = _mm_add_epi32(src1, src3); + const __m128i a2 = _mm_sub_epi32(src1, src3); + const __m128i a3 = _mm_sub_epi32(src0, src2); + const __m128i b0 = _mm_srai_epi32(_mm_add_epi32(a0, a1), 1); + const __m128i b1 = _mm_srai_epi32(_mm_add_epi32(a3, a2), 1); + const __m128i b2 = _mm_srai_epi32(_mm_sub_epi32(a3, a2), 1); + const __m128i b3 = _mm_srai_epi32(_mm_sub_epi32(a0, a1), 1); + const __m128i out0 = _mm_packs_epi32(b0, b1); + const __m128i out1 = _mm_packs_epi32(b2, b3); + _mm_storeu_si128((__m128i*)&out[0], out0); + _mm_storeu_si128((__m128i*)&out[8], out1); + } +} + +//------------------------------------------------------------------------------ +// Metric + +static int SSE_Nx4(const uint8_t* a, const uint8_t* b, + int num_quads, int do_16) { + const __m128i zero = _mm_setzero_si128(); + __m128i sum1 = zero; + __m128i sum2 = zero; + + while (num_quads-- > 0) { + // Note: for the !do_16 case, we read 16 pixels instead of 8 but that's ok, + // thanks to buffer over-allocation to that effect. + const __m128i a0 = _mm_loadu_si128((__m128i*)&a[BPS * 0]); + const __m128i a1 = _mm_loadu_si128((__m128i*)&a[BPS * 1]); + const __m128i a2 = _mm_loadu_si128((__m128i*)&a[BPS * 2]); + const __m128i a3 = _mm_loadu_si128((__m128i*)&a[BPS * 3]); + const __m128i b0 = _mm_loadu_si128((__m128i*)&b[BPS * 0]); + const __m128i b1 = _mm_loadu_si128((__m128i*)&b[BPS * 1]); + const __m128i b2 = _mm_loadu_si128((__m128i*)&b[BPS * 2]); + const __m128i b3 = _mm_loadu_si128((__m128i*)&b[BPS * 3]); + + // compute clip0(a-b) and clip0(b-a) + const __m128i a0p = _mm_subs_epu8(a0, b0); + const __m128i a0m = _mm_subs_epu8(b0, a0); + const __m128i a1p = _mm_subs_epu8(a1, b1); + const __m128i a1m = _mm_subs_epu8(b1, a1); + const __m128i a2p = _mm_subs_epu8(a2, b2); + const __m128i a2m = _mm_subs_epu8(b2, a2); + const __m128i a3p = _mm_subs_epu8(a3, b3); + const __m128i a3m = _mm_subs_epu8(b3, a3); + + // compute |a-b| with 8b arithmetic as clip0(a-b) | clip0(b-a) + const __m128i diff0 = _mm_or_si128(a0p, a0m); + const __m128i diff1 = _mm_or_si128(a1p, a1m); + const __m128i diff2 = _mm_or_si128(a2p, a2m); + const __m128i diff3 = _mm_or_si128(a3p, a3m); + + // unpack (only four operations, instead of eight) + const __m128i low0 = _mm_unpacklo_epi8(diff0, zero); + const __m128i low1 = _mm_unpacklo_epi8(diff1, zero); + const __m128i low2 = _mm_unpacklo_epi8(diff2, zero); + const __m128i low3 = _mm_unpacklo_epi8(diff3, zero); + + // multiply with self + const __m128i low_madd0 = _mm_madd_epi16(low0, low0); + const __m128i low_madd1 = _mm_madd_epi16(low1, low1); + const __m128i low_madd2 = _mm_madd_epi16(low2, low2); + const __m128i low_madd3 = _mm_madd_epi16(low3, low3); + + // collect in a cascading way + const __m128i low_sum0 = _mm_add_epi32(low_madd0, low_madd1); + const __m128i low_sum1 = _mm_add_epi32(low_madd2, low_madd3); + sum1 = _mm_add_epi32(sum1, low_sum0); + sum2 = _mm_add_epi32(sum2, low_sum1); + + if (do_16) { // if necessary, process the higher 8 bytes similarly + const __m128i hi0 = _mm_unpackhi_epi8(diff0, zero); + const __m128i hi1 = _mm_unpackhi_epi8(diff1, zero); + const __m128i hi2 = _mm_unpackhi_epi8(diff2, zero); + const __m128i hi3 = _mm_unpackhi_epi8(diff3, zero); + + const __m128i hi_madd0 = _mm_madd_epi16(hi0, hi0); + const __m128i hi_madd1 = _mm_madd_epi16(hi1, hi1); + const __m128i hi_madd2 = _mm_madd_epi16(hi2, hi2); + const __m128i hi_madd3 = _mm_madd_epi16(hi3, hi3); + const __m128i hi_sum0 = _mm_add_epi32(hi_madd0, hi_madd1); + const __m128i hi_sum1 = _mm_add_epi32(hi_madd2, hi_madd3); + sum1 = _mm_add_epi32(sum1, hi_sum0); + sum2 = _mm_add_epi32(sum2, hi_sum1); + } + a += 4 * BPS; + b += 4 * BPS; + } + { + int32_t tmp[4]; + const __m128i sum = _mm_add_epi32(sum1, sum2); + _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_Nx4(a, b, 4, 1); +} + +static int SSE16x8(const uint8_t* a, const uint8_t* b) { + return SSE_Nx4(a, b, 2, 1); +} + +static int SSE8x8(const uint8_t* a, const uint8_t* b) { + return SSE_Nx4(a, b, 2, 0); +} + +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((__m128i*)&a[BPS * 0]); + const __m128i a1 = _mm_loadl_epi64((__m128i*)&a[BPS * 1]); + const __m128i a2 = _mm_loadl_epi64((__m128i*)&a[BPS * 2]); + const __m128i a3 = _mm_loadl_epi64((__m128i*)&a[BPS * 3]); + const __m128i b0 = _mm_loadl_epi64((__m128i*)&b[BPS * 0]); + const __m128i b1 = _mm_loadl_epi64((__m128i*)&b[BPS * 1]); + const __m128i b2 = _mm_loadl_epi64((__m128i*)&b[BPS * 2]); + const __m128i b3 = _mm_loadl_epi64((__m128i*)&b[BPS * 3]); + + // Combine pair of lines and convert to 16b. + 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); + 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); + + // Compute differences; (a-b)^2 = (abs(a-b))^2 = (sat8(a-b) + sat8(b-a))^2 + // TODO(cduvivier): Dissassemble and figure out why this is fastest. We don't + // need absolute values, there is no need to do calculation + // in 8bit as we are already in 16bit, ... Yet this is what + // benchmarks the fastest! + const __m128i d0 = _mm_subs_epu8(a01s, b01s); + const __m128i d1 = _mm_subs_epu8(b01s, a01s); + const __m128i d2 = _mm_subs_epu8(a23s, b23s); + const __m128i d3 = _mm_subs_epu8(b23s, a23s); + + // Square and add them all together. + const __m128i madd0 = _mm_madd_epi16(d0, d0); + const __m128i madd1 = _mm_madd_epi16(d1, d1); + const __m128i madd2 = _mm_madd_epi16(d2, d2); + const __m128i madd3 = _mm_madd_epi16(d3, d3); + const __m128i sum0 = _mm_add_epi32(madd0, madd1); + const __m128i sum1 = _mm_add_epi32(madd2, madd3); + const __m128i sum2 = _mm_add_epi32(sum0, sum1); + + int32_t tmp[4]; + _mm_storeu_si128((__m128i*)tmp, sum2); + 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 difference between the weighted sum of the absolute value of +// transformed coefficients. +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, combine and transpose inputs. + { + const __m128i inA_0 = _mm_loadl_epi64((__m128i*)&inA[BPS * 0]); + const __m128i inA_1 = _mm_loadl_epi64((__m128i*)&inA[BPS * 1]); + const __m128i inA_2 = _mm_loadl_epi64((__m128i*)&inA[BPS * 2]); + const __m128i inA_3 = _mm_loadl_epi64((__m128i*)&inA[BPS * 3]); + const __m128i inB_0 = _mm_loadl_epi64((__m128i*)&inB[BPS * 0]); + const __m128i inB_1 = _mm_loadl_epi64((__m128i*)&inB[BPS * 1]); + const __m128i inB_2 = _mm_loadl_epi64((__m128i*)&inB[BPS * 2]); + const __m128i inB_3 = _mm_loadl_epi64((__m128i*)&inB[BPS * 3]); + + // Combine inA and inB (we'll do two transforms in parallel). + const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0); + const __m128i inAB_1 = _mm_unpacklo_epi8(inA_1, inB_1); + const __m128i inAB_2 = _mm_unpacklo_epi8(inA_2, inB_2); + const __m128i inAB_3 = _mm_unpacklo_epi8(inA_3, inB_3); + // a00 b00 a01 b01 a02 b03 a03 b03 0 0 0 0 0 0 0 0 + // a10 b10 a11 b11 a12 b12 a13 b13 0 0 0 0 0 0 0 0 + // a20 b20 a21 b21 a22 b22 a23 b23 0 0 0 0 0 0 0 0 + // a30 b30 a31 b31 a32 b32 a33 b33 0 0 0 0 0 0 0 0 + + // Transpose the two 4x4, discarding the filling zeroes. + const __m128i transpose0_0 = _mm_unpacklo_epi8(inAB_0, inAB_2); + const __m128i transpose0_1 = _mm_unpacklo_epi8(inAB_1, inAB_3); + // a00 a20 b00 b20 a01 a21 b01 b21 a02 a22 b02 b22 a03 a23 b03 b23 + // a10 a30 b10 b30 a11 a31 b11 b31 a12 a32 b12 b32 a13 a33 b13 b33 + const __m128i transpose1_0 = _mm_unpacklo_epi8(transpose0_0, transpose0_1); + const __m128i transpose1_1 = _mm_unpackhi_epi8(transpose0_0, transpose0_1); + // 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 + + // Convert to 16b. + tmp_0 = _mm_unpacklo_epi8(transpose1_0, zero); + tmp_1 = _mm_unpackhi_epi8(transpose1_0, zero); + tmp_2 = _mm_unpacklo_epi8(transpose1_1, zero); + tmp_3 = _mm_unpackhi_epi8(transpose1_1, zero); + // 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 + } + + // Horizontal pass 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. + const __m128i transpose0_0 = _mm_unpacklo_epi16(b0, b1); + const __m128i transpose0_1 = _mm_unpacklo_epi16(b2, b3); + const __m128i transpose0_2 = _mm_unpackhi_epi16(b0, b1); + const __m128i transpose0_3 = _mm_unpackhi_epi16(b2, b3); + // 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 + tmp_0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1); + tmp_1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1); + tmp_2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3); + tmp_3 = _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 + } + + // Vertical pass and difference of weighted sums. + { + // Load all inputs. + // TODO(cduvivier): Make variable declarations and allocations aligned so + // we can use _mm_load_si128 instead of _mm_loadu_si128. + const __m128i w_0 = _mm_loadu_si128((__m128i*)&w[0]); + const __m128i w_8 = _mm_loadu_si128((__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); + + { + // sign(b) = b >> 15 (0x0000 if positive, 0xffff if negative) + const __m128i sign_A_b0 = _mm_srai_epi16(A_b0, 15); + const __m128i sign_A_b2 = _mm_srai_epi16(A_b2, 15); + const __m128i sign_B_b0 = _mm_srai_epi16(B_b0, 15); + const __m128i sign_B_b2 = _mm_srai_epi16(B_b2, 15); + + // b = abs(b) = (b ^ sign) - sign + A_b0 = _mm_xor_si128(A_b0, sign_A_b0); + A_b2 = _mm_xor_si128(A_b2, sign_A_b2); + B_b0 = _mm_xor_si128(B_b0, sign_B_b0); + B_b2 = _mm_xor_si128(B_b2, sign_B_b2); + A_b0 = _mm_sub_epi16(A_b0, sign_A_b0); + A_b2 = _mm_sub_epi16(A_b2, sign_A_b2); + B_b0 = _mm_sub_epi16(B_b0, sign_B_b0); + B_b2 = _mm_sub_epi16(B_b2, sign_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_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. + // TODO(cduvivier): Make variable declarations and allocations aligned so that + // we can use _mm_load_si128 instead of _mm_loadu_si128. + __m128i in0 = _mm_loadu_si128((__m128i*)&in[0]); + __m128i in8 = _mm_loadu_si128((__m128i*)&in[8]); + const __m128i iq0 = _mm_loadu_si128((__m128i*)&mtx->iq_[0]); + const __m128i iq8 = _mm_loadu_si128((__m128i*)&mtx->iq_[8]); + const __m128i q0 = _mm_loadu_si128((__m128i*)&mtx->q_[0]); + const __m128i q8 = _mm_loadu_si128((__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((__m128i*)&sharpen[0]); + const __m128i sharpen8 = _mm_loadu_si128((__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((__m128i*)&mtx->bias_[0]); + const __m128i bias_04 = _mm_loadu_si128((__m128i*)&mtx->bias_[4]); + const __m128i bias_08 = _mm_loadu_si128((__m128i*)&mtx->bias_[8]); + const __m128i bias_12 = _mm_loadu_si128((__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); +} + +// Forward declaration. +void VP8SetResidualCoeffsSSE2(const int16_t* const coeffs, + VP8Residual* const res); + +void VP8SetResidualCoeffsSSE2(const int16_t* const coeffs, + VP8Residual* const res) { + const __m128i c0 = _mm_loadu_si128((const __m128i*)coeffs); + const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8)); + // Use SSE to compare 8 values with a single instruction. + const __m128i zero = _mm_setzero_si128(); + const __m128i m0 = _mm_cmpeq_epi16(c0, zero); + const __m128i m1 = _mm_cmpeq_epi16(c1, zero); + // Get the comparison results as a bitmask, consisting of two times 16 bits: + // two identical bits for each result. Concatenate both bitmasks to get a + // single 32 bit value. 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 = + ~(((uint32_t)_mm_movemask_epi8(m1) << 16) | _mm_movemask_epi8(m0)); + // The position of the most significant non-zero bit indicates the position of + // the last non-zero value. Divide the result by two because __movemask_epi8 + // operates on 8 bit values instead of 16 bit values. + assert(res->first == 0 || coeffs[0] == 0); + res->last = mask ? (BitsLog2Floor(mask) >> 1) : -1; + res->coeffs = coeffs; +} + +#endif // WEBP_USE_SSE2 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8EncDspInitSSE2(void); + +void VP8EncDspInitSSE2(void) { +#if defined(WEBP_USE_SSE2) + VP8CollectHistogram = CollectHistogram; + VP8EncQuantizeBlock = QuantizeBlock; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT; + VP8ITransform = ITransform; + VP8FTransform = FTransform; + VP8FTransformWHT = FTransformWHT; + VP8SSE16x16 = SSE16x16; + VP8SSE16x8 = SSE16x8; + VP8SSE8x8 = SSE8x8; + VP8SSE4x4 = SSE4x4; + VP8TDisto4x4 = Disto4x4; + VP8TDisto16x16 = Disto16x16; +#endif // WEBP_USE_SSE2 +} + diff --git a/TMessagesProj/jni/libwebp/dsp/lossless.c b/TMessagesProj/jni/libwebp/dsp/lossless.c new file mode 100644 index 00000000..a1bf3584 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/lossless.c @@ -0,0 +1,1639 @@ +// 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 +#include +#include "../dec/vp8li.h" +#include "../utils/endian_inl.h" +#include "./lossless.h" +#include "./yuv.h" + +#define MAX_DIFF_COST (1e30f) + +// 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 +}; + +// 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 +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)); + } +} + +//------------------------------------------------------------------------------ +// Image transforms. + +// Mostly used to reduce code size + readability +static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; } + +// 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 Average2(uint32_t a0, uint32_t a1) { + return (((a0 ^ a1) & 0xfefefefeL) >> 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; +} + +static const VP8LPredictorFunc kPredictorsC[16] = { + Predictor0, Predictor1, Predictor2, Predictor3, + Predictor4, Predictor5, Predictor6, Predictor7, + Predictor8, Predictor9, Predictor10, Predictor11, + Predictor12, Predictor13, + Predictor0, Predictor0 // <- padding security sentinels +}; + +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]; + const int xy = x + Y[i]; + if (x != 0) { + sumX += x; + retval -= VP8LFastSLog2(x); + sumXY += xy; + retval -= VP8LFastSLog2(xy); + } else if (xy != 0) { + sumXY += xy; + retval -= VP8LFastSLog2(xy); + } + } + 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 += CombinedShannonEntropy(tile[i], accumulated[i]); + } + return (float)retval; +} + +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 int GetBestPredictorForTile(int width, int height, + int tile_x, int tile_y, int bits, + const int accumulated[4][256], + const uint32_t* const argb_scratch) { + const int kNumPredModes = 14; + const int col_start = tile_x << bits; + const int row_start = tile_y << bits; + const int tile_size = 1 << bits; + const int max_y = GetMin(tile_size, height - row_start); + const int max_x = GetMin(tile_size, width - col_start); + float best_diff = MAX_DIFF_COST; + int best_mode = 0; + int mode; + for (mode = 0; mode < kNumPredModes; ++mode) { + const uint32_t* current_row = argb_scratch; + const VP8LPredictorFunc pred_func = VP8LPredictors[mode]; + float cur_diff; + int y; + int histo_argb[4][256]; + memset(histo_argb, 0, sizeof(histo_argb)); + for (y = 0; y < max_y; ++y) { + int x; + const int row = row_start + y; + const uint32_t* const upper_row = current_row; + current_row = upper_row + width; + for (x = 0; x < max_x; ++x) { + const int col = col_start + x; + uint32_t predict; + if (row == 0) { + predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left. + } else if (col == 0) { + predict = upper_row[col]; // Top. + } else { + predict = pred_func(current_row[col - 1], upper_row + col); + } + UpdateHisto(histo_argb, VP8LSubPixels(current_row[col], predict)); + } + } + cur_diff = PredictionCostSpatialHistogram( + accumulated, (const int (*)[256])histo_argb); + if (cur_diff < best_diff) { + best_diff = cur_diff; + best_mode = mode; + } + } + + return best_mode; +} + +static void CopyTileWithPrediction(int width, int height, + int tile_x, int tile_y, int bits, int mode, + const uint32_t* const argb_scratch, + uint32_t* const argb) { + const int col_start = tile_x << bits; + const int row_start = tile_y << bits; + const int tile_size = 1 << bits; + const int max_y = GetMin(tile_size, height - row_start); + const int max_x = GetMin(tile_size, width - col_start); + const VP8LPredictorFunc pred_func = VP8LPredictors[mode]; + const uint32_t* current_row = argb_scratch; + + int y; + for (y = 0; y < max_y; ++y) { + int x; + const int row = row_start + y; + const uint32_t* const upper_row = current_row; + current_row = upper_row + width; + for (x = 0; x < max_x; ++x) { + const int col = col_start + x; + const int pix = row * width + col; + uint32_t predict; + if (row == 0) { + predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left. + } else if (col == 0) { + predict = upper_row[col]; // Top. + } else { + predict = pred_func(current_row[col - 1], upper_row + col); + } + argb[pix] = VP8LSubPixels(current_row[col], predict); + } + } +} + +void VP8LResidualImage(int width, int height, int bits, + uint32_t* const argb, uint32_t* const argb_scratch, + uint32_t* const image) { + const int max_tile_size = 1 << bits; + const int tiles_per_row = VP8LSubSampleSize(width, bits); + const int tiles_per_col = VP8LSubSampleSize(height, bits); + uint32_t* const upper_row = argb_scratch; + uint32_t* const current_tile_rows = argb_scratch + width; + int tile_y; + int histo[4][256]; + memset(histo, 0, sizeof(histo)); + for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { + const int tile_y_offset = tile_y * max_tile_size; + const int this_tile_height = + (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset; + int tile_x; + if (tile_y > 0) { + memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width, + width * sizeof(*upper_row)); + } + memcpy(current_tile_rows, &argb[tile_y_offset * width], + this_tile_height * width * sizeof(*current_tile_rows)); + for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { + int pred; + int y; + const int tile_x_offset = tile_x * max_tile_size; + int all_x_max = tile_x_offset + max_tile_size; + if (all_x_max > width) { + all_x_max = width; + } + pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits, + (const int (*)[256])histo, + argb_scratch); + image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8); + CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred, + argb_scratch, argb); + for (y = 0; y < max_tile_size; ++y) { + int ix; + int all_x; + int all_y = tile_y_offset + y; + if (all_y >= height) { + break; + } + ix = all_y * width + tile_x_offset; + for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) { + UpdateHisto(histo, argb[ix]); + } + } + } + } +} + +// 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; + } + } + } +} + +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; + } +} + +// 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 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); + } +} + +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); + } +} + +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 CombinedShannonEntropy(counts, accumulated) + + PredictionCostSpatial(counts, 3, kExpValue); +} + +static float GetPredictionCostCrossColorRed( + int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max, + int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red, + const int accumulated_red_histo[256], const uint32_t* const argb) { + int all_y; + int histo[256] = { 0 }; + float cur_diff; + for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) { + int ix = all_y * xsize + tile_x_offset; + int all_x; + for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) { + ++histo[TransformColorRed(green_to_red, argb[ix])]; // red. + } + } + 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( + int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max, + int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, + const int accumulated_red_histo[256], const uint32_t* const argb, + VP8LMultipliers* const best_tx) { + int min_green_to_red = -64; + int max_green_to_red = 64; + int green_to_red = 0; + int eval_min = 1; + int eval_max = 1; + float cur_diff_min = MAX_DIFF_COST; + float cur_diff_max = MAX_DIFF_COST; + // Do a binary search to find the optimal green_to_red color transform. + while (max_green_to_red - min_green_to_red > 2) { + if (eval_min) { + cur_diff_min = GetPredictionCostCrossColorRed( + tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, + prev_x, prev_y, min_green_to_red, accumulated_red_histo, argb); + eval_min = 0; + } + if (eval_max) { + cur_diff_max = GetPredictionCostCrossColorRed( + tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, + prev_x, prev_y, max_green_to_red, accumulated_red_histo, argb); + eval_max = 0; + } + if (cur_diff_min < cur_diff_max) { + green_to_red = min_green_to_red; + max_green_to_red = (max_green_to_red + min_green_to_red) / 2; + eval_max = 1; + } else { + green_to_red = max_green_to_red; + min_green_to_red = (max_green_to_red + min_green_to_red) / 2; + eval_min = 1; + } + } + best_tx->green_to_red_ = green_to_red; +} + +static float GetPredictionCostCrossColorBlue( + int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max, + int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, + int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256], + const uint32_t* const argb) { + int all_y; + int histo[256] = { 0 }; + float cur_diff; + for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) { + int all_x; + int ix = all_y * xsize + tile_x_offset; + for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) { + ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[ix])]; + } + } + 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; +} + +static void GetBestGreenRedToBlue( + int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max, + int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, + const int accumulated_blue_histo[256], const uint32_t* const argb, + VP8LMultipliers* const best_tx) { + float best_diff = MAX_DIFF_COST; + float cur_diff; + const int step = (quality < 25) ? 32 : (quality > 50) ? 8 : 16; + const int min_green_to_blue = -32; + const int max_green_to_blue = 32; + const int min_red_to_blue = -32; + const int max_red_to_blue = 32; + const int num_iters = + (1 + (max_green_to_blue - min_green_to_blue) / step) * + (1 + (max_red_to_blue - min_red_to_blue) / step); + // Number of tries to get optimal green_to_blue & red_to_blue color transforms + // after finding a local minima. + const int max_tries_after_min = 4 + (num_iters >> 2); + int num_tries_after_min = 0; + int green_to_blue; + for (green_to_blue = min_green_to_blue; + green_to_blue <= max_green_to_blue && + num_tries_after_min < max_tries_after_min; + green_to_blue += step) { + int red_to_blue; + for (red_to_blue = min_red_to_blue; + red_to_blue <= max_red_to_blue && + num_tries_after_min < max_tries_after_min; + red_to_blue += step) { + cur_diff = GetPredictionCostCrossColorBlue( + tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, prev_x, + prev_y, green_to_blue, red_to_blue, accumulated_blue_histo, argb); + if (cur_diff < best_diff) { + best_diff = cur_diff; + best_tx->green_to_blue_ = green_to_blue; + best_tx->red_to_blue_ = red_to_blue; + num_tries_after_min = 0; + } else { + ++num_tries_after_min; + } + } + } +} + +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); + VP8LMultipliers best_tx; + MultipliersClear(&best_tx); + + GetBestGreenToRed(tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, + prev_x, prev_y, accumulated_red_histo, argb, &best_tx); + GetBestGreenRedToBlue(tile_x_offset, tile_y_offset, all_x_max, all_y_max, + xsize, prev_x, prev_y, quality, accumulated_blue_histo, + argb, &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]; + } + } + } + } +} + +// 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, TYPE, GET_INDEX, GET_VALUE) \ +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 { \ + 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 WEBP_INLINE uint32_t GetARGBIndex(uint32_t idx) { + return (idx >> 8) & 0xff; +} + +static WEBP_INLINE uint8_t GetAlphaIndex(uint8_t idx) { + return idx; +} + +static WEBP_INLINE uint32_t GetARGBValue(uint32_t val) { + return val; +} + +static WEBP_INLINE uint8_t GetAlphaValue(uint32_t val) { + return (val >> 8) & 0xff; +} + +static COLOR_INDEX_INVERSE(ColorIndexInverseTransform, uint32_t, GetARGBIndex, + GetARGBValue) +COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, uint8_t, GetAlphaIndex, + GetAlphaValue) + +#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) + *(uint32_t*)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. + } +} + +//------------------------------------------------------------------------------ +// 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; +} + +// Returns the various RLE counts +static VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) { + int i; + int streak = 0; + VP8LStreaks stats; + memset(&stats, 0, sizeof(stats)); + for (i = 0; i < length - 1; ++i) { + ++streak; + if (population[i] == population[i + 1]) { + continue; + } + stats.counts[population[i] != 0] += (streak > 3); + stats.streaks[population[i] != 0][(streak > 3)] += streak; + streak = 0; + } + ++streak; + stats.counts[population[i] != 0] += (streak > 3); + stats.streaks[population[i] != 0][(streak > 3)] += streak; + return stats; +} + +static VP8LStreaks HuffmanCostCombinedCount(const uint32_t* X, + const uint32_t* Y, int length) { + int i; + int streak = 0; + VP8LStreaks stats; + memset(&stats, 0, sizeof(stats)); + for (i = 0; i < length - 1; ++i) { + const int xy = X[i] + Y[i]; + const int xy_next = X[i + 1] + Y[i + 1]; + ++streak; + if (xy == xy_next) { + continue; + } + stats.counts[xy != 0] += (streak > 3); + stats.streaks[xy != 0][(streak > 3)] += streak; + streak = 0; + } + { + const int xy = X[i] + Y[i]; + ++streak; + stats.counts[xy != 0] += (streak > 3); + stats.streaks[xy != 0][(streak > 3)] += streak; + } + return stats; +} + +//------------------------------------------------------------------------------ + +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; +VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; +VP8LPredictorFunc VP8LPredictors[16]; + +VP8LTransformColorFunc VP8LTransformColor; +VP8LTransformColorFunc VP8LTransformColorInverse; + +VP8LConvertFunc VP8LConvertBGRAToRGB; +VP8LConvertFunc VP8LConvertBGRAToRGBA; +VP8LConvertFunc VP8LConvertBGRAToRGBA4444; +VP8LConvertFunc VP8LConvertBGRAToRGB565; +VP8LConvertFunc VP8LConvertBGRAToBGR; + +VP8LFastLog2SlowFunc VP8LFastLog2Slow; +VP8LFastLog2SlowFunc VP8LFastSLog2Slow; + +VP8LCostFunc VP8LExtraCost; +VP8LCostCombinedFunc VP8LExtraCostCombined; + +VP8LCostCountFunc VP8LHuffmanCostCount; +VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount; + +VP8LHistogramAddFunc VP8LHistogramAdd; + +extern void VP8LDspInitSSE2(void); +extern void VP8LDspInitNEON(void); +extern void VP8LDspInitMIPS32(void); + +void VP8LDspInit(void) { + memcpy(VP8LPredictors, kPredictorsC, sizeof(VP8LPredictors)); + + VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C; + VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; + + VP8LTransformColor = VP8LTransformColor_C; + VP8LTransformColorInverse = VP8LTransformColorInverse_C; + + VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; + VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; + VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; + VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; + VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; + + VP8LFastLog2Slow = FastLog2Slow; + VP8LFastSLog2Slow = FastSLog2Slow; + + VP8LExtraCost = ExtraCost; + VP8LExtraCostCombined = ExtraCostCombined; + + VP8LHuffmanCostCount = HuffmanCostCount; + VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount; + + VP8LHistogramAdd = HistogramAdd; + + // 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_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8LDspInitMIPS32(); + } +#endif + } +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/dsp/lossless.h b/TMessagesProj/jni/libwebp/dsp/lossless.h new file mode 100644 index 00000000..8c7551c9 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/lossless.h @@ -0,0 +1,249 @@ +// 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 + +//------------------------------------------------------------------------------ +// Signatures and generic function-pointers + +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 VP8LSubtractGreenFromBlueAndRed; +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 VP8LTransformColor; +extern VP8LTransformColorFunc VP8LTransformColorInverse; + +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; + +// Expose some C-only fallback functions +void VP8LTransformColor_C(const VP8LMultipliers* const m, + uint32_t* data, int num_pixels); +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 VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels); +void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels); + +// Must be called before calling any of the above methods. +void VP8LDspInit(void); + +//------------------------------------------------------------------------------ +// Image transforms. + +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); + +// 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); + +void VP8LResidualImage(int width, int height, int bits, + uint32_t* const argb, uint32_t* const argb_scratch, + uint32_t* const image); + +void VP8LColorSpaceTransform(int width, int height, int bits, int quality, + uint32_t* const argb, uint32_t* image); + +//------------------------------------------------------------------------------ +// Color space conversion. + +// 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); + +//------------------------------------------------------------------------------ +// 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; +} + +// ----------------------------------------------------------------------------- +// Faster logarithm for integers. Small values use a look-up table. +#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); + +extern VP8LCostFunc VP8LExtraCost; +extern VP8LCostCombinedFunc VP8LExtraCostCombined; + +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 (*VP8LCostCountFunc)(const uint32_t* population, + int length); +typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X, + const uint32_t* Y, int length); + +extern VP8LCostCountFunc VP8LHuffmanCostCount; +extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount; + +typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out); +extern VP8LHistogramAddFunc VP8LHistogramAdd; + +// ----------------------------------------------------------------------------- +// PrefixEncode() + +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); + } +} + +// In-place difference of each component with 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); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_DSP_LOSSLESS_H_ diff --git a/TMessagesProj/jni/libwebp/dsp/lossless_mips32.c b/TMessagesProj/jni/libwebp/dsp/lossless_mips32.c new file mode 100644 index 00000000..13085807 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/lossless_mips32.c @@ -0,0 +1,416 @@ +// 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 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 +#include +#include +#include + +#define APPROX_LOG_WITH_CORRECTION_MAX 65536 +#define APPROX_LOG_MAX 4096 +#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 + +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 VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) { + int i; + int streak = 0; + VP8LStreaks stats; + int* const pstreaks = &stats.streaks[0][0]; + int* const pcnts = &stats.counts[0]; + int temp0, temp1, temp2, temp3; + memset(&stats, 0, sizeof(stats)); + for (i = 0; i < length - 1; ++i) { + ++streak; + if (population[i] == population[i + 1]) { + continue; + } + temp0 = (population[i] != 0); + HUFFMAN_COST_PASS + streak = 0; + } + ++streak; + temp0 = (population[i] != 0); + HUFFMAN_COST_PASS + + return stats; +} + +static VP8LStreaks HuffmanCostCombinedCount(const uint32_t* X, + const uint32_t* Y, int length) { + int i; + int streak = 0; + VP8LStreaks stats; + int* const pstreaks = &stats.streaks[0][0]; + int* const pcnts = &stats.counts[0]; + int temp0, temp1, temp2, temp3; + memset(&stats, 0, sizeof(stats)); + for (i = 0; i < length - 1; ++i) { + const uint32_t xy = X[i] + Y[i]; + const uint32_t xy_next = X[i + 1] + Y[i + 1]; + ++streak; + if (xy == xy_next) { + continue; + } + temp0 = (xy != 0); + HUFFMAN_COST_PASS + streak = 0; + } + { + const uint32_t xy = X[i] + Y[i]; + ++streak; + temp0 = (xy != 0); + HUFFMAN_COST_PASS + } + + return stats; +} + +#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 + +#endif // WEBP_USE_MIPS32 + +//------------------------------------------------------------------------------ +// Entry point + +extern void VP8LDspInitMIPS32(void); + +void VP8LDspInitMIPS32(void) { +#if defined(WEBP_USE_MIPS32) + VP8LFastSLog2Slow = FastSLog2Slow; + VP8LFastLog2Slow = FastLog2Slow; + VP8LExtraCost = ExtraCost; + VP8LExtraCostCombined = ExtraCostCombined; + VP8LHuffmanCostCount = HuffmanCostCount; + VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount; + VP8LHistogramAdd = HistogramAdd; +#endif // WEBP_USE_MIPS32 +} diff --git a/TMessagesProj/jni/libwebp/dsp/lossless_neon.c b/TMessagesProj/jni/libwebp/dsp/lossless_neon.c new file mode 100644 index 00000000..987767b5 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/lossless_neon.c @@ -0,0 +1,332 @@ +// 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 + +#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 + +//------------------------------------------------------------------------------ + +#ifdef USE_INTRINSICS + +static WEBP_INLINE uint32_t Average2(const uint32_t* const a, + const uint32_t* const b) { + const uint8x8_t a0 = vreinterpret_u8_u64(vcreate_u64(*a)); + const uint8x8_t b0 = vreinterpret_u8_u64(vcreate_u64(*b)); + const uint8x8_t avg = vhadd_u8(a0, b0); + return vget_lane_u32(vreinterpret_u32_u8(avg), 0); +} + +static WEBP_INLINE uint32_t Average3(const uint32_t* const a, + const uint32_t* const b, + const uint32_t* const c) { + const uint8x8_t a0 = vreinterpret_u8_u64(vcreate_u64(*a)); + const uint8x8_t b0 = vreinterpret_u8_u64(vcreate_u64(*b)); + const uint8x8_t c0 = vreinterpret_u8_u64(vcreate_u64(*c)); + const uint8x8_t avg1 = vhadd_u8(a0, c0); + const uint8x8_t avg2 = vhadd_u8(avg1, b0); + return vget_lane_u32(vreinterpret_u32_u8(avg2), 0); +} + +static WEBP_INLINE uint32_t Average4(const uint32_t* const a, + const uint32_t* const b, + const uint32_t* const c, + const uint32_t* const d) { + const uint8x8_t a0 = vreinterpret_u8_u64(vcreate_u64(*a)); + const uint8x8_t b0 = vreinterpret_u8_u64(vcreate_u64(*b)); + const uint8x8_t c0 = vreinterpret_u8_u64(vcreate_u64(*c)); + const uint8x8_t d0 = vreinterpret_u8_u64(vcreate_u64(*d)); + const uint8x8_t avg1 = vhadd_u8(a0, b0); + const uint8x8_t avg2 = vhadd_u8(c0, d0); + const uint8x8_t avg3 = vhadd_u8(avg1, avg2); + return vget_lane_u32(vreinterpret_u32_u8(avg3), 0); +} + +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 WEBP_INLINE uint32_t Select(const uint32_t* const c0, + const uint32_t* const c1, + const uint32_t* const c2) { + const uint8x8_t p0 = vreinterpret_u8_u64(vcreate_u64(*c0)); + const uint8x8_t p1 = vreinterpret_u8_u64(vcreate_u64(*c1)); + const uint8x8_t p2 = vreinterpret_u8_u64(vcreate_u64(*c2)); + const uint8x8_t bc = vabd_u8(p1, p2); // |b-c| + const uint8x8_t ac = vabd_u8(p0, p2); // |a-c| + const int16x4_t sum_bc = vreinterpret_s16_u16(vpaddl_u8(bc)); + const int16x4_t sum_ac = vreinterpret_s16_u16(vpaddl_u8(ac)); + const int32x2_t diff = vpaddl_s16(vsub_s16(sum_bc, sum_ac)); + const int32_t pa_minus_pb = vget_lane_s32(diff, 0); + return (pa_minus_pb <= 0) ? *c0 : *c1; +} + +static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { + return Select(top + 0, &left, top - 1); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractFull(const uint32_t* const c0, + const uint32_t* const c1, + const uint32_t* const c2) { + const uint8x8_t p0 = vreinterpret_u8_u64(vcreate_u64(*c0)); + const uint8x8_t p1 = vreinterpret_u8_u64(vcreate_u64(*c1)); + const uint8x8_t p2 = vreinterpret_u8_u64(vcreate_u64(*c2)); + const uint16x8_t sum0 = vaddl_u8(p0, p1); // add and widen + const uint16x8_t sum1 = vqsubq_u16(sum0, vmovl_u8(p2)); // widen and subtract + const uint8x8_t out = vqmovn_u16(sum1); // narrow and clamp + return vget_lane_u32(vreinterpret_u32_u8(out), 0); +} + +static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { + return ClampedAddSubtractFull(&left, top + 0, top - 1); +} + +static WEBP_INLINE uint32_t ClampedAddSubtractHalf(const uint32_t* const c0, + const uint32_t* const c1, + const uint32_t* const c2) { + const uint8x8_t p0 = vreinterpret_u8_u64(vcreate_u64(*c0)); + const uint8x8_t p1 = vreinterpret_u8_u64(vcreate_u64(*c1)); + const uint8x8_t p2 = vreinterpret_u8_u64(vcreate_u64(*c2)); + const uint8x8_t avg = vhadd_u8(p0, p1); // Average(c0,c1) + const uint8x8_t ab = vshr_n_u8(vqsub_u8(avg, p2), 1); // (a-b)>>1 saturated + const uint8x8_t ba = vshr_n_u8(vqsub_u8(p2, avg), 1); // (b-a)>>1 saturated + const uint8x8_t out = vqsub_u8(vqadd_u8(avg, ab), ba); + return vget_lane_u32(vreinterpret_u32_u8(out), 0); +} + +static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { + return ClampedAddSubtractHalf(&left, top + 0, top - 1); +} + +//------------------------------------------------------------------------------ +// Subtract-Green Transform + +// vtbl? are unavailable in iOS/arm64 builds. +#if !defined(__aarch64__) + +// 255 = byte will be zero'd +static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; + +static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { + const uint32_t* const end = argb_data + (num_pixels & ~3); + const uint8x8_t shuffle = vld1_u8(kGreenShuffle); + for (; argb_data < end; argb_data += 4) { + const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); + const uint8x16_t greens = + vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), + vtbl1_u8(vget_high_u8(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); +} + +static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) { + const uint32_t* const end = argb_data + (num_pixels & ~3); + const uint8x8_t shuffle = vld1_u8(kGreenShuffle); + for (; argb_data < end; argb_data += 4) { + const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); + const uint8x16_t greens = + vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), + vtbl1_u8(vget_high_u8(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); +} + +#endif // !__aarch64__ + +#endif // USE_INTRINSICS + +#endif // WEBP_USE_NEON + +//------------------------------------------------------------------------------ + +extern void VP8LDspInitNEON(void); + +void VP8LDspInitNEON(void) { +#if defined(WEBP_USE_NEON) + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB; + +#ifdef USE_INTRINSICS + 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; + +#if !defined(__aarch64__) + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; +#endif +#endif + +#endif // WEBP_USE_NEON +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/dsp/lossless_sse2.c b/TMessagesProj/jni/libwebp/dsp/lossless_sse2.c new file mode 100644 index 00000000..71309098 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/lossless_sse2.c @@ -0,0 +1,535 @@ +// 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" + +#include + +#if defined(WEBP_USE_SSE2) +#include +#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 SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { + const __m128i mask = _mm_set1_epi32(0x0000ff00); + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); + const __m128i in_00g0 = _mm_and_si128(in, mask); // 00g0|00g0|... + const __m128i in_0g00 = _mm_slli_epi32(in_00g0, 8); // 0g00|0g00|... + const __m128i in_000g = _mm_srli_epi32(in_00g0, 8); // 000g|000g|... + const __m128i in_0g0g = _mm_or_si128(in_0g00, in_000g); + 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); +} + +static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) { + const __m128i mask = _mm_set1_epi32(0x0000ff00); + int i; + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); + const __m128i in_00g0 = _mm_and_si128(in, mask); // 00g0|00g0|... + const __m128i in_0g00 = _mm_slli_epi32(in_00g0, 8); // 0g00|0g00|... + const __m128i in_000g = _mm_srli_epi32(in_00g0, 8); // 000g|000g|... + const __m128i in_0g0g = _mm_or_si128(in_0g00, in_000g); + const __m128i out = _mm_add_epi8(in, in_0g0g); + _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 WEBP_INLINE __m128i ColorTransformDelta(__m128i color_pred, + __m128i color) { + // We simulate signed 8-bit multiplication as: + // * Left shift the two (8-bit) numbers by 8 bits, + // * Perform a 16-bit signed multiplication and retain the higher 16-bits. + const __m128i color_pred_shifted = _mm_slli_epi32(color_pred, 8); + const __m128i color_shifted = _mm_slli_epi32(color, 8); + // Note: This performs multiplication on 8 packed 16-bit numbers, 4 of which + // happen to be zeroes. + const __m128i signed_mult = + _mm_mulhi_epi16(color_pred_shifted, color_shifted); + return _mm_srli_epi32(signed_mult, 5); +} + +static WEBP_INLINE void TransformColor(const VP8LMultipliers* const m, + uint32_t* argb_data, + int num_pixels) { + const __m128i g_to_r = _mm_set1_epi32(m->green_to_red_); // multipliers + const __m128i g_to_b = _mm_set1_epi32(m->green_to_blue_); + const __m128i r_to_b = _mm_set1_epi32(m->red_to_blue_); + + int i; + + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); + const __m128i alpha_green_mask = _mm_set1_epi32(0xff00ff00); // masks + const __m128i red_mask = _mm_set1_epi32(0x00ff0000); + const __m128i green_mask = _mm_set1_epi32(0x0000ff00); + const __m128i lower_8bit_mask = _mm_set1_epi32(0x000000ff); + const __m128i ag = _mm_and_si128(in, alpha_green_mask); // alpha, green + const __m128i r = _mm_srli_epi32(_mm_and_si128(in, red_mask), 16); + const __m128i g = _mm_srli_epi32(_mm_and_si128(in, green_mask), 8); + const __m128i b = in; + + const __m128i r_delta = ColorTransformDelta(g_to_r, g); // red + const __m128i r_new = + _mm_and_si128(_mm_sub_epi32(r, r_delta), lower_8bit_mask); + const __m128i r_new_shifted = _mm_slli_epi32(r_new, 16); + + const __m128i b_delta_1 = ColorTransformDelta(g_to_b, g); // blue + const __m128i b_delta_2 = ColorTransformDelta(r_to_b, r); + const __m128i b_delta = _mm_add_epi32(b_delta_1, b_delta_2); + const __m128i b_new = + _mm_and_si128(_mm_sub_epi32(b, b_delta), lower_8bit_mask); + + const __m128i out = _mm_or_si128(_mm_or_si128(ag, r_new_shifted), b_new); + _mm_storeu_si128((__m128i*)&argb_data[i], out); + } + + // Fall-back to C-version for left-overs. + VP8LTransformColor_C(m, argb_data + i, num_pixels - i); +} + +static WEBP_INLINE void TransformColorInverse(const VP8LMultipliers* const m, + uint32_t* argb_data, + int num_pixels) { + const __m128i g_to_r = _mm_set1_epi32(m->green_to_red_); // multipliers + const __m128i g_to_b = _mm_set1_epi32(m->green_to_blue_); + const __m128i r_to_b = _mm_set1_epi32(m->red_to_blue_); + + int i; + + for (i = 0; i + 4 <= num_pixels; i += 4) { + const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); + const __m128i alpha_green_mask = _mm_set1_epi32(0xff00ff00); // masks + const __m128i red_mask = _mm_set1_epi32(0x00ff0000); + const __m128i green_mask = _mm_set1_epi32(0x0000ff00); + const __m128i lower_8bit_mask = _mm_set1_epi32(0x000000ff); + const __m128i ag = _mm_and_si128(in, alpha_green_mask); // alpha, green + const __m128i r = _mm_srli_epi32(_mm_and_si128(in, red_mask), 16); + const __m128i g = _mm_srli_epi32(_mm_and_si128(in, green_mask), 8); + const __m128i b = in; + + const __m128i r_delta = ColorTransformDelta(g_to_r, g); // red + const __m128i r_new = + _mm_and_si128(_mm_add_epi32(r, r_delta), lower_8bit_mask); + const __m128i r_new_shifted = _mm_slli_epi32(r_new, 16); + + const __m128i b_delta_1 = ColorTransformDelta(g_to_b, g); // blue + const __m128i b_delta_2 = ColorTransformDelta(r_to_b, r_new); + const __m128i b_delta = _mm_add_epi32(b_delta_1, b_delta_2); + const __m128i b_new = + _mm_and_si128(_mm_add_epi32(b, b_delta), lower_8bit_mask); + + const __m128i out = _mm_or_si128(_mm_or_si128(ag, r_new_shifted), b_new); + _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); +} + +//------------------------------------------------------------------------------ + +#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((__m128i*)&a[i + 0]); + const __m128i a1 = _mm_loadu_si128((__m128i*)&a[i + 4]); +#if (LINE_SIZE == 16) + const __m128i a2 = _mm_loadu_si128((__m128i*)&a[i + 8]); + const __m128i a3 = _mm_loadu_si128((__m128i*)&a[i + 12]); +#endif + const __m128i b0 = _mm_loadu_si128((__m128i*)&b[i + 0]); + const __m128i b1 = _mm_loadu_si128((__m128i*)&b[i + 4]); +#if (LINE_SIZE == 16) + const __m128i b2 = _mm_loadu_si128((__m128i*)&b[i + 8]); + const __m128i b3 = _mm_loadu_si128((__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((__m128i*)&a[i + 0]); + const __m128i a1 = _mm_loadu_si128((__m128i*)&a[i + 4]); +#if (LINE_SIZE == 16) + const __m128i a2 = _mm_loadu_si128((__m128i*)&a[i + 8]); + const __m128i a3 = _mm_loadu_si128((__m128i*)&a[i + 12]); +#endif + const __m128i b0 = _mm_loadu_si128((__m128i*)&out[i + 0]); + const __m128i b1 = _mm_loadu_si128((__m128i*)&out[i + 4]); +#if (LINE_SIZE == 16) + const __m128i b2 = _mm_loadu_si128((__m128i*)&out[i + 8]); + const __m128i b3 = _mm_loadu_si128((__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]; + } +} + +#endif // WEBP_USE_SSE2 + +//------------------------------------------------------------------------------ + +extern void VP8LDspInitSSE2(void); + +void VP8LDspInitSSE2(void) { +#if defined(WEBP_USE_SSE2) + 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; + + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; + + VP8LTransformColor = TransformColor; + VP8LTransformColorInverse = TransformColorInverse; + + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; + VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444; + VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR; + + VP8LHistogramAdd = HistogramAdd; +#endif // WEBP_USE_SSE2 +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/dsp/neon.h b/TMessagesProj/jni/libwebp/dsp/neon.h new file mode 100644 index 00000000..7e06eaee --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/neon.h @@ -0,0 +1,82 @@ +// 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 + +#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 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/TMessagesProj/jni/libwebp/dsp/upsampling.c b/TMessagesProj/jni/libwebp/dsp/upsampling.c new file mode 100644 index 00000000..2b1656bf --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/upsampling.c @@ -0,0 +1,222 @@ +// 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 + +//------------------------------------------------------------------------------ +// 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) \ +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, VP8YuvToRgb, 3) +YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr, 3) +YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba, 4) +YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra, 4) +YUV444_FUNC(Yuv444ToArgb, VP8YuvToArgb, 4) +YUV444_FUNC(Yuv444ToRgba4444, VP8YuvToRgba4444, 2) +YUV444_FUNC(Yuv444ToRgb565, VP8YuvToRgb565, 2) + +#undef YUV444_FUNC + +const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = { + Yuv444ToRgb, // MODE_RGB + Yuv444ToRgba, // MODE_RGBA + Yuv444ToBgr, // MODE_BGR + Yuv444ToBgra, // MODE_BGRA + Yuv444ToArgb, // MODE_ARGB + Yuv444ToRgba4444, // MODE_RGBA_4444 + Yuv444ToRgb565, // MODE_RGB_565 + Yuv444ToRgba, // MODE_rgbA + Yuv444ToBgra, // MODE_bgrA + Yuv444ToArgb, // MODE_Argb + Yuv444ToRgba4444 // MODE_rgbA_4444 +}; + +//------------------------------------------------------------------------------ +// Main calls + +extern void WebPInitUpsamplersSSE2(void); +extern void WebPInitUpsamplersNEON(void); + +void WebPInitUpsamplers(void) { +#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 + } +#endif // FANCY_UPSAMPLING +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/dsp/upsampling_neon.c b/TMessagesProj/jni/libwebp/dsp/upsampling_neon.c new file mode 100644 index 00000000..d31ed4d6 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/upsampling_neon.c @@ -0,0 +1,267 @@ +// 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 +#include +#include +#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 + +static const int16_t kCoeffs[4] = { kYScale, kVToR, kUToG, kVToG }; + +#define v255 vdup_n_u8(255) + +#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 CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) { \ + int i; \ + for (i = 0; i < N; i += 8) { \ + const int off = ((cur_x) + i) * XSTEP; \ + uint8x8_t y = vld1_u8((src_y) + (cur_x) + i); \ + uint8x8_t u = vld1_u8((src_uv) + i); \ + uint8x8_t v = vld1_u8((src_uv) + i + 16); \ + const int16x8_t yy = vreinterpretq_s16_u16(vsubl_u8(y, u16)); \ + const int16x8_t uu = vreinterpretq_s16_u16(vsubl_u8(u, u128)); \ + const int16x8_t vv = vreinterpretq_s16_u16(vsubl_u8(v, u128)); \ + int32x4_t yl = vmull_lane_s16(vget_low_s16(yy), cf16, 0); \ + int32x4_t yh = vmull_lane_s16(vget_high_s16(yy), cf16, 0); \ + const int32x4_t rl = vmlal_lane_s16(yl, vget_low_s16(vv), cf16, 1);\ + const int32x4_t rh = vmlal_lane_s16(yh, vget_high_s16(vv), cf16, 1);\ + int32x4_t gl = vmlsl_lane_s16(yl, vget_low_s16(uu), cf16, 2); \ + int32x4_t gh = vmlsl_lane_s16(yh, vget_high_s16(uu), cf16, 2); \ + const int32x4_t bl = vmovl_s16(vget_low_s16(uu)); \ + const int32x4_t bh = vmovl_s16(vget_high_s16(uu)); \ + gl = vmlsl_lane_s16(gl, vget_low_s16(vv), cf16, 3); \ + gh = vmlsl_lane_s16(gh, vget_high_s16(vv), cf16, 3); \ + yl = vmlaq_lane_s32(yl, bl, cf32, 0); \ + yh = vmlaq_lane_s32(yh, bh, cf32, 0); \ + /* vrshrn_n_s32() already incorporates the rounding constant */ \ + y = vqmovun_s16(vcombine_s16(vrshrn_n_s32(rl, YUV_FIX2), \ + vrshrn_n_s32(rh, YUV_FIX2))); \ + u = vqmovun_s16(vcombine_s16(vrshrn_n_s32(gl, YUV_FIX2), \ + vrshrn_n_s32(gh, YUV_FIX2))); \ + v = vqmovun_s16(vcombine_s16(vrshrn_n_s32(yl, YUV_FIX2), \ + vrshrn_n_s32(yh, YUV_FIX2))); \ + STORE_ ## FMT(out + off, y, u, v); \ + } \ +} + +#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 cf16 = vld1_s16(kCoeffs); \ + const int32x2_t cf32 = vdup_n_s32(kUToB); \ + const uint8x8_t u16 = vdup_n_u8(16); \ + const uint8x8_t u128 = vdup_n_u8(128); \ + \ + /* 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) + +#endif // FANCY_UPSAMPLING + +#endif // WEBP_USE_NEON + +//------------------------------------------------------------------------------ + +extern void WebPInitUpsamplersNEON(void); + +#ifdef FANCY_UPSAMPLING + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +void WebPInitUpsamplersNEON(void) { +#if defined(WEBP_USE_NEON) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; +#endif // WEBP_USE_NEON +} + +#else + +// this empty function is to avoid an empty .o +void WebPInitUpsamplersNEON(void) {} + +#endif // FANCY_UPSAMPLING diff --git a/TMessagesProj/jni/libwebp/dsp/upsampling_sse2.c b/TMessagesProj/jni/libwebp/dsp/upsampling_sse2.c new file mode 100644 index 00000000..45cf0906 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/upsampling_sse2.c @@ -0,0 +1,214 @@ +// 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 +#include +#include +#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((__m128i*)&(r1)[0]); \ + const __m128i b = _mm_loadu_si128((__m128i*)&(r1)[1]); \ + const __m128i c = _mm_loadu_si128((__m128i*)&(r2)[0]); \ + const __m128i d = _mm_loadu_si128((__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) + +#undef GET_M +#undef PACK_AND_STORE +#undef UPSAMPLE_32PIXELS +#undef UPSAMPLE_LAST_BLOCK +#undef CONVERT2RGB +#undef CONVERT2RGB_32 +#undef SSE2_UPSAMPLE_FUNC + +#endif // FANCY_UPSAMPLING + +#endif // WEBP_USE_SSE2 + +//------------------------------------------------------------------------------ + +extern void WebPInitUpsamplersSSE2(void); + +#ifdef FANCY_UPSAMPLING + +extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; + +void WebPInitUpsamplersSSE2(void) { +#if defined(WEBP_USE_SSE2) + VP8YUVInitSSE2(); + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; +#endif // WEBP_USE_SSE2 +} + +#else + +// this empty function is to avoid an empty .o +void WebPInitUpsamplersSSE2(void) {} + +#endif // FANCY_UPSAMPLING diff --git a/TMessagesProj/jni/libwebp/dsp/yuv.c b/TMessagesProj/jni/libwebp/dsp/yuv.c new file mode 100644 index 00000000..d7cb4ebc --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/yuv.c @@ -0,0 +1,154 @@ +// 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]; + +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 + +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); + +void WebPInitSamplers(void) { + 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 + } +} + +//----------------------------------------------------------------------------- diff --git a/TMessagesProj/jni/libwebp/dsp/yuv.h b/TMessagesProj/jni/libwebp/dsp/yuv.h new file mode 100644 index 00000000..8a47edd8 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/yuv.h @@ -0,0 +1,321 @@ +// 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. +// In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor +// "1.164 * (Y-16)" can be handled as an offset in the VP8kClip[] table. +// So in this case the formulae should read: +// R = 1.164 * [Y + 1.371 * (V-128) ] - 18.624 +// G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624 +// B = 1.164 * [Y + 1.733 * (U-128)] - 18.624 +// once factorized. +// For YUV->RGB conversion, only 14bit fixed precision is used (YUV_FIX2). +// That's the maximum possible for a convenient ARM implementation. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_DSP_YUV_H_ +#define WEBP_DSP_YUV_H_ + +#include "./dsp.h" +#include "../dec/decode_vp8.h" + +// Define the following to use the LUT-based code: +// #define WEBP_YUV_USE_TABLE + +#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 = 14, // fixed-point precision for YUV->RGB + YUV_HALF2 = 1 << (YUV_FIX2 - 1), + YUV_MASK2 = (256 << YUV_FIX2) - 1 +}; + +// These constants are 14b fixed-point version of ITU-R BT.601 constants. +#define kYScale 19077 // 1.164 = 255 / 219 +#define kVToR 26149 // 1.596 = 255 / 112 * 0.701 +#define kUToG 6419 // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587 +#define kVToG 13320 // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587 +#define kUToB 33050 // 2.018 = 255 / 112 * 0.886 +#define kRCst (-kYScale * 16 - kVToR * 128 + YUV_HALF2) +#define kGCst (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF2) +#define kBCst (-kYScale * 16 - kUToB * 128 + YUV_HALF2) + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_YUV_USE_TABLE) + +// slower on x86 by ~7-8%, but bit-exact with the SSE2 version + +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(kYScale * y + kVToR * v + kRCst); +} + +static WEBP_INLINE int VP8YUVToG(int y, int u, int v) { + return VP8Clip8(kYScale * y - kUToG * u - kVToG * v + kGCst); +} + +static WEBP_INLINE int VP8YUVToB(int y, int u) { + return VP8Clip8(kYScale * y + kUToB * u + kBCst); +} + +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 +} + +#else + +// Table-based version, not totally equivalent to the SSE2 version. +// Rounding diff is only +/-1 though. + +extern int16_t VP8kVToR[256], VP8kUToB[256]; +extern int32_t VP8kVToG[256], VP8kUToG[256]; +extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; +extern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; + +static WEBP_INLINE void VP8YuvToRgb(int y, int u, int v, + uint8_t* const rgb) { + const int r_off = VP8kVToR[v]; + const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; + const int b_off = VP8kUToB[u]; + rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN]; + rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; + rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN]; +} + +static WEBP_INLINE void VP8YuvToBgr(int y, int u, int v, + uint8_t* const bgr) { + const int r_off = VP8kVToR[v]; + const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; + const int b_off = VP8kUToB[u]; + bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN]; + bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; + bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN]; +} + +static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v, + uint8_t* const rgb) { + const int r_off = VP8kVToR[v]; + const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; + const int b_off = VP8kUToB[u]; + const int rg = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) | + (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5)); + const int gb = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) | + (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 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_off = VP8kVToR[v]; + const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; + const int b_off = VP8kUToB[u]; + const int rg = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) | + VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]); + const int ba = (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4) | 0x0f; +#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 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) + +// When the following is defined, tables are initialized statically, adding ~12k +// to the binary size. Otherwise, they are initialized at run-time (small cost). +#define WEBP_YUV_USE_SSE2_TABLES + +#if defined(FANCY_UPSAMPLING) +// Process 32 pixels and store the result (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); +#endif // FANCY_UPSAMPLING + +// Must be called to initialize tables before using the functions. +void VP8YUVInitSSE2(void); + +#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/TMessagesProj/jni/libwebp/dsp/yuv_mips32.c b/TMessagesProj/jni/libwebp/dsp/yuv_mips32.c new file mode 100644 index 00000000..c82b4dfd --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/yuv_mips32.c @@ -0,0 +1,100 @@ +// 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 = kVToR * v[0]; \ + temp3 = kVToG * v[0]; \ + temp2 = kUToG * u[0]; \ + temp4 = kUToB * u[0]; \ + temp0 = kYScale * y[0]; \ + temp1 += kRCst; \ + temp3 -= kGCst; \ + temp2 += temp3; \ + temp4 += kBCst; \ + r = VP8Clip8(temp0 + temp1); \ + g = VP8Clip8(temp0 - temp2); \ + b = VP8Clip8(temp0 + temp4); \ + temp0 = kYScale * y[1]; \ + 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 = kVToR * v[0]; \ + temp3 = kVToG * v[0]; \ + temp2 = kUToG * u[0]; \ + temp4 = kUToB * u[0]; \ + temp0 = kYScale * y[0]; \ + temp1 += kRCst; \ + temp3 -= kGCst; \ + temp2 += temp3; \ + temp4 += kBCst; \ + 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 + +#endif // WEBP_USE_MIPS32 + +//------------------------------------------------------------------------------ + +extern void WebPInitSamplersMIPS32(void); + +void WebPInitSamplersMIPS32(void) { +#if defined(WEBP_USE_MIPS32) + WebPSamplers[MODE_RGB] = YuvToRgbRow; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow; + WebPSamplers[MODE_BGR] = YuvToBgrRow; + WebPSamplers[MODE_BGRA] = YuvToBgraRow; +#endif // WEBP_USE_MIPS32 +} diff --git a/TMessagesProj/jni/libwebp/dsp/yuv_sse2.c b/TMessagesProj/jni/libwebp/dsp/yuv_sse2.c new file mode 100644 index 00000000..6fe0f3b0 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/yuv_sse2.c @@ -0,0 +1,322 @@ +// 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 +#include // for memcpy + +typedef union { // handy struct for converting SSE2 registers + int32_t i32[4]; + uint8_t u8[16]; + __m128i m; +} VP8kCstSSE2; + +#if defined(WEBP_YUV_USE_SSE2_TABLES) + +#include "./yuv_tables_sse2.h" + +void VP8YUVInitSSE2(void) {} + +#else + +static int done_sse2 = 0; +static VP8kCstSSE2 VP8kUtoRGBA[256], VP8kVtoRGBA[256], VP8kYtoRGBA[256]; + +void VP8YUVInitSSE2(void) { + if (!done_sse2) { + int i; + for (i = 0; i < 256; ++i) { + VP8kYtoRGBA[i].i32[0] = + VP8kYtoRGBA[i].i32[1] = + VP8kYtoRGBA[i].i32[2] = (i - 16) * kYScale + YUV_HALF2; + VP8kYtoRGBA[i].i32[3] = 0xff << YUV_FIX2; + + VP8kUtoRGBA[i].i32[0] = 0; + VP8kUtoRGBA[i].i32[1] = -kUToG * (i - 128); + VP8kUtoRGBA[i].i32[2] = kUToB * (i - 128); + VP8kUtoRGBA[i].i32[3] = 0; + + VP8kVtoRGBA[i].i32[0] = kVToR * (i - 128); + VP8kVtoRGBA[i].i32[1] = -kVToG * (i - 128); + VP8kVtoRGBA[i].i32[2] = 0; + VP8kVtoRGBA[i].i32[3] = 0; + } + done_sse2 = 1; + +#if 0 // code used to generate 'yuv_tables_sse2.h' + printf("static const VP8kCstSSE2 VP8kYtoRGBA[256] = {\n"); + for (i = 0; i < 256; ++i) { + printf(" {{0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x}},\n", + VP8kYtoRGBA[i].i32[0], VP8kYtoRGBA[i].i32[1], + VP8kYtoRGBA[i].i32[2], VP8kYtoRGBA[i].i32[3]); + } + printf("};\n\n"); + printf("static const VP8kCstSSE2 VP8kUtoRGBA[256] = {\n"); + for (i = 0; i < 256; ++i) { + printf(" {{0, 0x%.8x, 0x%.8x, 0}},\n", + VP8kUtoRGBA[i].i32[1], VP8kUtoRGBA[i].i32[2]); + } + printf("};\n\n"); + printf("static VP8kCstSSE2 VP8kVtoRGBA[256] = {\n"); + for (i = 0; i < 256; ++i) { + printf(" {{0x%.8x, 0x%.8x, 0, 0}},\n", + VP8kVtoRGBA[i].i32[0], VP8kVtoRGBA[i].i32[1]); + } + printf("};\n\n"); +#endif + } +} + +#endif // WEBP_YUV_USE_SSE2_TABLES + +//----------------------------------------------------------------------------- + +static WEBP_INLINE __m128i LoadUVPart(int u, int v) { + const __m128i u_part = _mm_loadu_si128(&VP8kUtoRGBA[u].m); + const __m128i v_part = _mm_loadu_si128(&VP8kVtoRGBA[v].m); + const __m128i uv_part = _mm_add_epi32(u_part, v_part); + return uv_part; +} + +static WEBP_INLINE __m128i GetRGBA32bWithUV(int y, const __m128i uv_part) { + const __m128i y_part = _mm_loadu_si128(&VP8kYtoRGBA[y].m); + const __m128i rgba1 = _mm_add_epi32(y_part, uv_part); + const __m128i rgba2 = _mm_srai_epi32(rgba1, YUV_FIX2); + return rgba2; +} + +static WEBP_INLINE __m128i GetRGBA32b(int y, int u, int v) { + const __m128i uv_part = LoadUVPart(u, v); + return GetRGBA32bWithUV(y, uv_part); +} + +static WEBP_INLINE void YuvToRgbSSE2(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const rgb) { + const __m128i tmp0 = GetRGBA32b(y, u, v); + const __m128i tmp1 = _mm_packs_epi32(tmp0, tmp0); + const __m128i tmp2 = _mm_packus_epi16(tmp1, tmp1); + // Note: we store 8 bytes at a time, not 3 bytes! -> memory stomp + _mm_storel_epi64((__m128i*)rgb, tmp2); +} + +static WEBP_INLINE void YuvToBgrSSE2(uint8_t y, uint8_t u, uint8_t v, + uint8_t* const bgr) { + const __m128i tmp0 = GetRGBA32b(y, u, v); + const __m128i tmp1 = _mm_shuffle_epi32(tmp0, _MM_SHUFFLE(3, 0, 1, 2)); + const __m128i tmp2 = _mm_packs_epi32(tmp1, tmp1); + const __m128i tmp3 = _mm_packus_epi16(tmp2, tmp2); + // Note: we store 8 bytes at a time, not 3 bytes! -> memory stomp + _mm_storel_epi64((__m128i*)bgr, tmp3); +} + +//----------------------------------------------------------------------------- +// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. + +#ifdef FANCY_UPSAMPLING + +void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + int n; + for (n = 0; n < 32; n += 4) { + const __m128i tmp0_1 = GetRGBA32b(y[n + 0], u[n + 0], v[n + 0]); + const __m128i tmp0_2 = GetRGBA32b(y[n + 1], u[n + 1], v[n + 1]); + const __m128i tmp0_3 = GetRGBA32b(y[n + 2], u[n + 2], v[n + 2]); + const __m128i tmp0_4 = GetRGBA32b(y[n + 3], u[n + 3], v[n + 3]); + const __m128i tmp1_1 = _mm_packs_epi32(tmp0_1, tmp0_2); + const __m128i tmp1_2 = _mm_packs_epi32(tmp0_3, tmp0_4); + const __m128i tmp2 = _mm_packus_epi16(tmp1_1, tmp1_2); + _mm_storeu_si128((__m128i*)dst, tmp2); + dst += 4 * 4; + } +} + +void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + int n; + for (n = 0; n < 32; n += 2) { + const __m128i tmp0_1 = GetRGBA32b(y[n + 0], u[n + 0], v[n + 0]); + const __m128i tmp0_2 = GetRGBA32b(y[n + 1], u[n + 1], v[n + 1]); + const __m128i tmp1_1 = _mm_shuffle_epi32(tmp0_1, _MM_SHUFFLE(3, 0, 1, 2)); + const __m128i tmp1_2 = _mm_shuffle_epi32(tmp0_2, _MM_SHUFFLE(3, 0, 1, 2)); + const __m128i tmp2_1 = _mm_packs_epi32(tmp1_1, tmp1_2); + const __m128i tmp3 = _mm_packus_epi16(tmp2_1, tmp2_1); + _mm_storel_epi64((__m128i*)dst, tmp3); + dst += 4 * 2; + } +} + +void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + int n; + uint8_t tmp0[2 * 3 + 5 + 15]; + uint8_t* const tmp = (uint8_t*)((uintptr_t)(tmp0 + 15) & ~15); // align + for (n = 0; n < 30; ++n) { // we directly stomp the *dst memory + YuvToRgbSSE2(y[n], u[n], v[n], dst + n * 3); + } + // Last two pixels are special: we write in a tmp buffer before sending + // to dst. + YuvToRgbSSE2(y[n + 0], u[n + 0], v[n + 0], tmp + 0); + YuvToRgbSSE2(y[n + 1], u[n + 1], v[n + 1], tmp + 3); + memcpy(dst + n * 3, tmp, 2 * 3); +} + +void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + int n; + uint8_t tmp0[2 * 3 + 5 + 15]; + uint8_t* const tmp = (uint8_t*)((uintptr_t)(tmp0 + 15) & ~15); // align + for (n = 0; n < 30; ++n) { + YuvToBgrSSE2(y[n], u[n], v[n], dst + n * 3); + } + YuvToBgrSSE2(y[n + 0], u[n + 0], v[n + 0], tmp + 0); + YuvToBgrSSE2(y[n + 1], u[n + 1], v[n + 1], tmp + 3); + memcpy(dst + n * 3, tmp, 2 * 3); +} + +#endif // FANCY_UPSAMPLING + +//----------------------------------------------------------------------------- +// Arbitrary-length row conversion functions + +static void YuvToRgbaRowSSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 4 <= len; n += 4) { + const __m128i uv_0 = LoadUVPart(u[0], v[0]); + const __m128i uv_1 = LoadUVPart(u[1], v[1]); + const __m128i tmp0_1 = GetRGBA32bWithUV(y[0], uv_0); + const __m128i tmp0_2 = GetRGBA32bWithUV(y[1], uv_0); + const __m128i tmp0_3 = GetRGBA32bWithUV(y[2], uv_1); + const __m128i tmp0_4 = GetRGBA32bWithUV(y[3], uv_1); + const __m128i tmp1_1 = _mm_packs_epi32(tmp0_1, tmp0_2); + const __m128i tmp1_2 = _mm_packs_epi32(tmp0_3, tmp0_4); + const __m128i tmp2 = _mm_packus_epi16(tmp1_1, tmp1_2); + _mm_storeu_si128((__m128i*)dst, tmp2); + dst += 4 * 4; + y += 4; + u += 2; + v += 2; + } + // Finish off + while (n < len) { + VP8YuvToRgba(y[0], u[0], v[0], dst); + dst += 4; + ++y; + u += (n & 1); + v += (n & 1); + ++n; + } +} + +static void YuvToBgraRowSSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 2 <= len; n += 2) { + const __m128i uv_0 = LoadUVPart(u[0], v[0]); + const __m128i tmp0_1 = GetRGBA32bWithUV(y[0], uv_0); + const __m128i tmp0_2 = GetRGBA32bWithUV(y[1], uv_0); + const __m128i tmp1_1 = _mm_shuffle_epi32(tmp0_1, _MM_SHUFFLE(3, 0, 1, 2)); + const __m128i tmp1_2 = _mm_shuffle_epi32(tmp0_2, _MM_SHUFFLE(3, 0, 1, 2)); + const __m128i tmp2_1 = _mm_packs_epi32(tmp1_1, tmp1_2); + const __m128i tmp3 = _mm_packus_epi16(tmp2_1, tmp2_1); + _mm_storel_epi64((__m128i*)dst, tmp3); + dst += 4 * 2; + y += 2; + ++u; + ++v; + } + // Finish off + if (len & 1) { + VP8YuvToBgra(y[0], u[0], v[0], dst); + } +} + +static void YuvToArgbRowSSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 2 <= len; n += 2) { + const __m128i uv_0 = LoadUVPart(u[0], v[0]); + const __m128i tmp0_1 = GetRGBA32bWithUV(y[0], uv_0); + const __m128i tmp0_2 = GetRGBA32bWithUV(y[1], uv_0); + const __m128i tmp1_1 = _mm_shuffle_epi32(tmp0_1, _MM_SHUFFLE(2, 1, 0, 3)); + const __m128i tmp1_2 = _mm_shuffle_epi32(tmp0_2, _MM_SHUFFLE(2, 1, 0, 3)); + const __m128i tmp2_1 = _mm_packs_epi32(tmp1_1, tmp1_2); + const __m128i tmp3 = _mm_packus_epi16(tmp2_1, tmp2_1); + _mm_storel_epi64((__m128i*)dst, tmp3); + dst += 4 * 2; + y += 2; + ++u; + ++v; + } + // Finish off + if (len & 1) { + VP8YuvToArgb(y[0], u[0], v[0], dst); + } +} + +static void YuvToRgbRowSSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 2 < len; ++n) { // we directly stomp the *dst memory + YuvToRgbSSE2(y[0], u[0], v[0], dst); // stomps 8 bytes + dst += 3; + ++y; + u += (n & 1); + v += (n & 1); + } + VP8YuvToRgb(y[0], u[0], v[0], dst); + if (len > 1) { + VP8YuvToRgb(y[1], u[n & 1], v[n & 1], dst + 3); + } +} + +static void YuvToBgrRowSSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + int n; + for (n = 0; n + 2 < len; ++n) { // we directly stomp the *dst memory + YuvToBgrSSE2(y[0], u[0], v[0], dst); // stomps 8 bytes + dst += 3; + ++y; + u += (n & 1); + v += (n & 1); + } + VP8YuvToBgr(y[0], u[0], v[0], dst + 0); + if (len > 1) { + VP8YuvToBgr(y[1], u[n & 1], v[n & 1], dst + 3); + } +} + +#endif // WEBP_USE_SSE2 + +//------------------------------------------------------------------------------ +// Entry point + +extern void WebPInitSamplersSSE2(void); + +void WebPInitSamplersSSE2(void) { +#if defined(WEBP_USE_SSE2) + WebPSamplers[MODE_RGB] = YuvToRgbRowSSE2; + WebPSamplers[MODE_RGBA] = YuvToRgbaRowSSE2; + WebPSamplers[MODE_BGR] = YuvToBgrRowSSE2; + WebPSamplers[MODE_BGRA] = YuvToBgraRowSSE2; + WebPSamplers[MODE_ARGB] = YuvToArgbRowSSE2; +#endif // WEBP_USE_SSE2 +} diff --git a/TMessagesProj/jni/libwebp/dsp/yuv_tables_sse2.h b/TMessagesProj/jni/libwebp/dsp/yuv_tables_sse2.h new file mode 100644 index 00000000..2b0f0575 --- /dev/null +++ b/TMessagesProj/jni/libwebp/dsp/yuv_tables_sse2.h @@ -0,0 +1,536 @@ +// 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/TMessagesProj/jni/libwebp/enc/alpha.c b/TMessagesProj/jni/libwebp/enc/alpha.c new file mode 100644 index 00000000..79cb94db --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/alpha.c @@ -0,0 +1,433 @@ +// 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 +#include + +#include "./vp8enci.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. + { + int i, j; + uint32_t* dst = picture.argb; + const uint8_t* src = data; + for (j = 0; j < picture.height; ++j) { + for (i = 0; i < picture.width; ++i) { + dst[i] = src[i] << 8; // we leave A/R/B channels zero'd. + } + src += width; + dst += picture.argb_stride; + } + } + + WebPConfigInit(&config); + config.lossless = 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); + + ok = (VP8LEncodeStream(&config, &picture, bw) == VP8_ENC_OK); + WebPPictureFree(&picture); + ok = ok && !bw->error_; + if (!ok) { + VP8LBitWriterDestroy(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); + // TODO(skal): have a common function and #define's to validate alpha params. + + 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; + VP8LBitWriterDestroy(&tmp_bw); + } + } else { + VP8LBitWriterDestroy(&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) { + VP8LBitWriterDestroy(&tmp_bw); + } + ok = ok && !result->bw.error_; + result->score = VP8BitWriterSize(&result->bw); + return ok; +} + +// ----------------------------------------------------------------------------- + +// TODO(skal): move to dsp/ ? +static void CopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height) { + while (height-- > 0) { + memcpy(dst, src, width); + src += src_stride; + dst += dst_stride; + } +} + +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 : + EstimateBestFilter(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 = best.stats; + *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). + CopyPlane(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) { + 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) { + 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/TMessagesProj/jni/libwebp/enc/analysis.c b/TMessagesProj/jni/libwebp/enc/analysis.c new file mode 100644 index 00000000..e019465b --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/analysis.c @@ -0,0 +1,498 @@ +// 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 +#include +#include + +#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) { + int max_value = 0, last_non_zero = 1; + int k; + int alpha; + for (k = 0; k <= MAX_COEFF_THRESH; ++k) { + const int value = histo->distribution[k]; + if (value > 0) { + if (value > max_value) max_value = value; + last_non_zero = k; + } + } + // '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. + alpha = (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0; + return alpha; +} + +static void MergeHistograms(const VP8Histogram* const in, + VP8Histogram* const out) { + int i; + for (i = 0; i <= MAX_COEFF_THRESH; ++i) { + out->distribution[i] += in->distribution[i]; + } +} + +//------------------------------------------------------------------------------ +// 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 = { { 0 } }; + int alpha; + + VP8CollectHistogram(it->yuv_in_ + Y_OFF, + 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 = { { 0 } }; + int cur_histo = 0; + + VP8IteratorStartI4(it); + do { + int mode; + int best_mode_alpha = DEFAULT_ALPHA; + VP8Histogram histos[2]; + const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; + + VP8MakeIntra4Preds(it); + for (mode = 0; mode < max_mode; ++mode) { + int alpha; + + memset(&histos[cur_histo], 0, sizeof(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)); + + 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 = { { 0 } }; + int alpha; + VP8CollectHistogram(it->yuv_in_ + U_OFF, + 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 + ALIGN_CST]; + uint8_t* const scratch = (uint8_t*)DO_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/TMessagesProj/jni/libwebp/enc/backward_references.c b/TMessagesProj/jni/libwebp/enc/backward_references.c new file mode 100644 index 00000000..a3c30aa0 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/backward_references.c @@ -0,0 +1,975 @@ +// 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 +#include + +#include "./backward_references.h" +#include "./histogram.h" +#include "../dsp/lossless.h" +#include "../utils/color_cache.h" +#include "../utils/utils.h" + +#define VALUES_IN_BYTE 256 + +#define HASH_MULTIPLIER (0xc6a4a7935bd1e995ULL) + +#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 ((1 << 20) - 120) + +// Bounds for the match length. +#define MIN_LENGTH 2 +#define MAX_LENGTH 4096 + +// ----------------------------------------------------------------------------- + +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; +} + +static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, + const uint32_t* const array2, + const int max_limit) { + int match_len = 0; + while (match_len < max_limit && array1[match_len] == array2[match_len]) { + ++match_len; + } + return match_len; +} + +// ----------------------------------------------------------------------------- +// 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 + +// initialize as empty +static void HashChainInit(VP8LHashChain* const p) { + int i; + assert(p != NULL); + for (i = 0; i < p->size_; ++i) { + p->chain_[i] = -1; + } + for (i = 0; i < HASH_SIZE; ++i) { + p->hash_to_first_index_[i] = -1; + } +} + +int VP8LHashChainInit(VP8LHashChain* const p, int size) { + assert(p->size_ == 0); + assert(p->chain_ == NULL); + assert(size > 0); + p->chain_ = (int*)WebPSafeMalloc(size, sizeof(*p->chain_)); + if (p->chain_ == NULL) return 0; + p->size_ = size; + HashChainInit(p); + return 1; +} + +void VP8LHashChainClear(VP8LHashChain* const p) { + assert(p != NULL); + WebPSafeFree(p->chain_); + p->size_ = 0; + p->chain_ = NULL; +} + +// ----------------------------------------------------------------------------- + +static WEBP_INLINE uint64_t GetPixPairHash64(const uint32_t* const argb) { + uint64_t key = ((uint64_t)argb[1] << 32) | argb[0]; + key = (key * HASH_MULTIPLIER) >> (64 - HASH_BITS); + return key; +} + +// Insertion of two pixels at a time. +static void HashChainInsert(VP8LHashChain* const p, + const uint32_t* const argb, int pos) { + const uint64_t hash_code = GetPixPairHash64(argb); + p->chain_[pos] = p->hash_to_first_index_[hash_code]; + p->hash_to_first_index_[hash_code] = pos; +} + +static void GetParamsForHashChainFindCopy(int quality, int xsize, + int cache_bits, int* window_size, + int* iter_pos, int* iter_limit) { + const int iter_mult = (quality < 27) ? 1 : 1 + ((quality - 27) >> 4); + const int iter_neg = -iter_mult * (quality >> 1); + // Limit the backward-ref window size for lower qualities. + const int max_window_size = (quality > 50) ? WINDOW_SIZE + : (quality > 25) ? (xsize << 8) + : (xsize << 4); + assert(xsize > 0); + *window_size = (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE + : max_window_size; + *iter_pos = 8 + (quality >> 3); + // For lower entropy images, the rigorous search loop in HashChainFindCopy + // can be relaxed. + *iter_limit = (cache_bits > 0) ? iter_neg : iter_neg / 2; +} + +static int HashChainFindCopy(const VP8LHashChain* const p, + int base_position, int xsize_signed, + const uint32_t* const argb, int max_len, + int window_size, int iter_pos, int iter_limit, + int* const distance_ptr, + int* const length_ptr) { + const uint32_t* const argb_start = argb + base_position; + uint64_t best_val = 0; + uint32_t best_length = 1; + uint32_t best_distance = 0; + const uint32_t xsize = (uint32_t)xsize_signed; + const int min_pos = + (base_position > window_size) ? base_position - window_size : 0; + int pos; + assert(xsize > 0); + if (max_len > MAX_LENGTH) { + max_len = MAX_LENGTH; + } + for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)]; + pos >= min_pos; + pos = p->chain_[pos]) { + uint64_t val; + uint32_t curr_length; + uint32_t distance; + const uint32_t* const ptr1 = (argb + pos + best_length - 1); + const uint32_t* const ptr2 = (argb_start + best_length - 1); + + if (iter_pos < 0) { + if (iter_pos < iter_limit || best_val >= 0xff0000) { + break; + } + } + --iter_pos; + + // Before 'expensive' linear match, check if the two arrays match at the + // current best length index and also for the succeeding elements. + if (ptr1[0] != ptr2[0] || ptr1[1] != ptr2[1]) continue; + + curr_length = FindMatchLength(argb + pos, argb_start, max_len); + if (curr_length < best_length) continue; + + distance = (uint32_t)(base_position - pos); + val = curr_length << 16; + // Favoring 2d locality here gives savings for certain images. + if (distance < 9 * xsize) { + const uint32_t y = distance / xsize; + uint32_t x = distance % xsize; + if (x > (xsize >> 1)) { + x = xsize - x; + } + if (x <= 7) { + val += 9 * 9 + 9 * 9; + val -= y * y + x * x; + } + } + if (best_val < val) { + best_val = val; + best_length = curr_length; + best_distance = distance; + if (curr_length >= (uint32_t)max_len) { + break; + } + if ((best_distance == 1 || distance == xsize) && + best_length >= 128) { + break; + } + } + } + *distance_ptr = (int)best_distance; + *length_ptr = best_length; + return (best_length >= MIN_LENGTH); +} + +static WEBP_INLINE void PushBackCopy(VP8LBackwardRefs* const refs, int length) { + while (length >= MAX_LENGTH) { + BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, MAX_LENGTH)); + length -= MAX_LENGTH; + } + if (length > 0) { + BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, length)); + } +} + +static int BackwardReferencesRle(int xsize, int ysize, + const uint32_t* const argb, + VP8LBackwardRefs* const refs) { + const int pix_count = xsize * ysize; + int match_len = 0; + int i; + ClearBackwardRefs(refs); + PushBackCopy(refs, match_len); // i=0 case + BackwardRefsCursorAdd(refs, PixOrCopyCreateLiteral(argb[0])); + for (i = 1; i < pix_count; ++i) { + if (argb[i] == argb[i - 1]) { + ++match_len; + } else { + PushBackCopy(refs, match_len); + match_len = 0; + BackwardRefsCursorAdd(refs, PixOrCopyCreateLiteral(argb[i])); + } + } + PushBackCopy(refs, match_len); + return !refs->error_; +} + +static int BackwardReferencesHashChain(int xsize, int ysize, + const uint32_t* const argb, + int cache_bits, int quality, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs) { + int i; + int ok = 0; + int cc_init = 0; + const int use_color_cache = (cache_bits > 0); + const int pix_count = xsize * ysize; + VP8LColorCache hashers; + int window_size = WINDOW_SIZE; + int iter_pos = 1; + int iter_limit = -1; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + ClearBackwardRefs(refs); + GetParamsForHashChainFindCopy(quality, xsize, cache_bits, + &window_size, &iter_pos, &iter_limit); + HashChainInit(hash_chain); + for (i = 0; i < pix_count; ) { + // Alternative#1: Code the pixels starting at 'i' using backward reference. + int offset = 0; + int len = 0; + if (i < pix_count - 1) { // FindCopy(i,..) reads pixels at [i] and [i + 1]. + int max_len = pix_count - i; + HashChainFindCopy(hash_chain, i, xsize, argb, max_len, + window_size, iter_pos, iter_limit, + &offset, &len); + } + if (len >= MIN_LENGTH) { + // Alternative#2: Insert the pixel at 'i' as literal, and code the + // pixels starting at 'i + 1' using backward reference. + int offset2 = 0; + int len2 = 0; + int k; + HashChainInsert(hash_chain, &argb[i], i); + if (i < pix_count - 2) { // FindCopy(i+1,..) reads [i + 1] and [i + 2]. + int max_len = pix_count - (i + 1); + HashChainFindCopy(hash_chain, i + 1, xsize, argb, max_len, + window_size, iter_pos, iter_limit, + &offset2, &len2); + if (len2 > len + 1) { + const uint32_t pixel = argb[i]; + // Alternative#2 is a better match. So push pixel at 'i' as literal. + PixOrCopy v; + if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) { + const int ix = VP8LColorCacheGetIndex(&hashers, pixel); + v = PixOrCopyCreateCacheIdx(ix); + } else { + if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel); + v = PixOrCopyCreateLiteral(pixel); + } + BackwardRefsCursorAdd(refs, v); + i++; // Backward reference to be done for next pixel. + len = len2; + offset = offset2; + } + } + if (len >= MAX_LENGTH) { + len = MAX_LENGTH - 1; + } + BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); + if (use_color_cache) { + for (k = 0; k < len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + // Add to the hash_chain (but cannot add the last pixel). + { + const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i; + for (k = 1; k < last; ++k) { + HashChainInsert(hash_chain, &argb[i + k], i + k); + } + } + i += len; + } else { + const uint32_t pixel = argb[i]; + PixOrCopy v; + if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) { + // push pixel as a PixOrCopyCreateCacheIdx pixel + const int ix = VP8LColorCacheGetIndex(&hashers, pixel); + v = PixOrCopyCreateCacheIdx(ix); + } else { + if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel); + v = PixOrCopyCreateLiteral(pixel); + } + BackwardRefsCursorAdd(refs, v); + if (i + 1 < pix_count) { + HashChainInsert(hash_chain, &argb[i], i); + } + ++i; + } + } + ok = !refs->error_; +Error: + if (cc_init) VP8LColorCacheClear(&hashers); + return ok; +} + +// ----------------------------------------------------------------------------- + +typedef struct { + double alpha_[VALUES_IN_BYTE]; + double red_[VALUES_IN_BYTE]; + double literal_[PIX_OR_COPY_CODES_MAX]; + double blue_[VALUES_IN_BYTE]; + double distance_[NUM_DISTANCE_CODES]; +} CostModel; + +static int BackwardReferencesTraceBackwards( + int xsize, int ysize, int recursive_cost_model, + const uint32_t* const argb, int quality, int cache_bits, + 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 xsize, int ysize, + int recursion_level, const uint32_t* const argb, + int quality, int cache_bits, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs) { + int ok = 0; + VP8LHistogram* histo = NULL; + + ClearBackwardRefs(refs); + if (recursion_level > 0) { + if (!BackwardReferencesTraceBackwards(xsize, ysize, recursion_level - 1, + argb, quality, cache_bits, hash_chain, + refs)) { + goto Error; + } + } else { + if (!BackwardReferencesHashChain(xsize, ysize, argb, cache_bits, quality, + hash_chain, refs)) { + goto Error; + } + } + 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 int BackwardReferencesHashChainDistanceOnly( + int xsize, int ysize, int recursive_cost_model, const uint32_t* const argb, + int quality, int cache_bits, VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs, uint32_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); + float* const cost = + (float*)WebPSafeMalloc(pix_count, sizeof(*cost)); + CostModel* cost_model = (CostModel*)WebPSafeMalloc(1ULL, sizeof(*cost_model)); + VP8LColorCache hashers; + const double mul0 = (recursive_cost_model != 0) ? 1.0 : 0.68; + const double mul1 = (recursive_cost_model != 0) ? 1.0 : 0.82; + const int min_distance_code = 2; // TODO(vikasa): tune as function of quality + int window_size = WINDOW_SIZE; + int iter_pos = 1; + int iter_limit = -1; + + if (cost == NULL || cost_model == NULL) goto Error; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + if (!CostModelBuild(cost_model, xsize, ysize, recursive_cost_model, argb, + quality, cache_bits, hash_chain, refs)) { + goto Error; + } + + for (i = 0; i < pix_count; ++i) cost[i] = 1e38f; + + // We loop one pixel at a time, but store all currently best points to + // non-processed locations from this point. + dist_array[0] = 0; + GetParamsForHashChainFindCopy(quality, xsize, cache_bits, + &window_size, &iter_pos, &iter_limit); + HashChainInit(hash_chain); + for (i = 0; i < pix_count; ++i) { + double prev_cost = 0.0; + int shortmax; + if (i > 0) { + prev_cost = cost[i - 1]; + } + for (shortmax = 0; shortmax < 2; ++shortmax) { + int offset = 0; + int len = 0; + if (i < pix_count - 1) { // FindCopy reads pixels at [i] and [i + 1]. + int max_len = shortmax ? 2 : pix_count - i; + HashChainFindCopy(hash_chain, i, xsize, argb, max_len, + window_size, iter_pos, iter_limit, + &offset, &len); + } + if (len >= MIN_LENGTH) { + const int code = DistanceToPlaneCode(xsize, offset); + const double distance_cost = + prev_cost + GetDistanceCost(cost_model, code); + int k; + for (k = 1; k < len; ++k) { + const double cost_val = distance_cost + GetLengthCost(cost_model, k); + if (cost[i + k] > cost_val) { + cost[i + k] = (float)cost_val; + dist_array[i + k] = k + 1; + } + } + // This if is for speedup only. It roughly doubles the speed, and + // makes compression worse by .1 %. + if (len >= 128 && code <= 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) { + for (k = 0; k < len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + // 2) Add to the hash_chain (but cannot add the last pixel) + { + const int last = (len + i < pix_count - 1) ? len + i + : pix_count - 1; + for (k = i; k < last; ++k) { + HashChainInsert(hash_chain, &argb[k], k); + } + } + // 3) jump. + i += len - 1; // for loop does ++i, thus -1 here. + goto next_symbol; + } + } + } + if (i < pix_count - 1) { + HashChainInsert(hash_chain, &argb[i], i); + } + { + // inserting a literal pixel + double cost_val = prev_cost; + if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) { + const int ix = VP8LColorCacheGetIndex(&hashers, argb[i]); + cost_val += GetCacheCost(cost_model, ix) * mul0; + } else { + if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); + cost_val += GetLiteralCost(cost_model, argb[i]) * mul1; + } + if (cost[i] > cost_val) { + cost[i] = (float)cost_val; + dist_array[i] = 1; // only one is inserted. + } + } + next_symbol: ; + } + // Last pixel still to do, it can only be a single step if not reached + // through cheaper means already. + ok = !refs->error_; +Error: + if (cc_init) VP8LColorCacheClear(&hashers); + WebPSafeFree(cost_model); + WebPSafeFree(cost); + 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(uint32_t* const dist_array, + int dist_array_size, + uint32_t** const chosen_path, + int* const chosen_path_size) { + uint32_t* path = dist_array + dist_array_size; + uint32_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( + int xsize, int ysize, const uint32_t* const argb, + int quality, int cache_bits, + const uint32_t* const chosen_path, int chosen_path_size, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs) { + const int pix_count = xsize * ysize; + const int use_color_cache = (cache_bits > 0); + int size = 0; + int i = 0; + int k; + int ix; + int ok = 0; + int cc_init = 0; + int window_size = WINDOW_SIZE; + int iter_pos = 1; + int iter_limit = -1; + VP8LColorCache hashers; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + ClearBackwardRefs(refs); + GetParamsForHashChainFindCopy(quality, xsize, cache_bits, + &window_size, &iter_pos, &iter_limit); + HashChainInit(hash_chain); + for (ix = 0; ix < chosen_path_size; ++ix, ++size) { + int offset = 0; + int len = 0; + int max_len = chosen_path[ix]; + if (max_len != 1) { + HashChainFindCopy(hash_chain, i, xsize, argb, max_len, + window_size, iter_pos, iter_limit, + &offset, &len); + assert(len == max_len); + BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); + if (use_color_cache) { + for (k = 0; k < len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + { + const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i; + for (k = 0; k < last; ++k) { + HashChainInsert(hash_chain, &argb[i + k], 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); + if (i + 1 < pix_count) { + HashChainInsert(hash_chain, &argb[i], i); + } + ++i; + } + } + ok = !refs->error_; +Error: + if (cc_init) VP8LColorCacheClear(&hashers); + return ok; +} + +// Returns 1 on success. +static int BackwardReferencesTraceBackwards(int xsize, int ysize, + int recursive_cost_model, + const uint32_t* const argb, + int quality, int cache_bits, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs) { + int ok = 0; + const int dist_array_size = xsize * ysize; + uint32_t* chosen_path = NULL; + int chosen_path_size = 0; + uint32_t* dist_array = + (uint32_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array)); + + if (dist_array == NULL) goto Error; + + if (!BackwardReferencesHashChainDistanceOnly( + xsize, ysize, recursive_cost_model, argb, quality, cache_bits, hash_chain, + refs, dist_array)) { + goto Error; + } + TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size); + if (!BackwardReferencesHashChainFollowChosenPath( + xsize, ysize, argb, quality, 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); + } +} + +VP8LBackwardRefs* VP8LGetBackwardReferences( + int width, int height, const uint32_t* const argb, int quality, + int cache_bits, int use_2d_locality, VP8LHashChain* const hash_chain, + VP8LBackwardRefs refs_array[2]) { + int lz77_is_useful; + const int num_pix = width * height; + VP8LBackwardRefs* best = NULL; + VP8LBackwardRefs* const refs_lz77 = &refs_array[0]; + VP8LBackwardRefs* const refs_rle = &refs_array[1]; + + if (!BackwardReferencesHashChain(width, height, argb, cache_bits, quality, + hash_chain, refs_lz77)) { + return NULL; + } + if (!BackwardReferencesRle(width, height, argb, refs_rle)) { + return NULL; + } + + { + double bit_cost_lz77, bit_cost_rle; + VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits); + if (histo == NULL) return NULL; + // 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); + VP8LFreeHistogram(histo); + } + + // 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) { + // Set recursion level for large images using a color cache. + const int recursion_level = + (num_pix < 320 * 200) && (cache_bits > 0) ? 1 : 0; + VP8LBackwardRefs* const refs_trace = &refs_array[1]; + ClearBackwardRefs(refs_trace); + if (BackwardReferencesTraceBackwards(width, height, recursion_level, argb, + quality, cache_bits, hash_chain, + refs_trace)) { + best = refs_trace; + } + } + } else { + best = refs_rle; + } + + if (use_2d_locality) BackwardReferences2DLocality(width, best); + + return best; +} + +// Returns entropy for the given cache bits. +static double ComputeCacheEntropy(const uint32_t* const argb, + int xsize, int ysize, + const VP8LBackwardRefs* const refs, + int cache_bits) { + int pixel_index = 0; + uint32_t k; + 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; + } + + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + if (PixOrCopyIsLiteral(v)) { + if (use_color_cache && + VP8LColorCacheContains(&hashers, argb[pixel_index])) { + // push pixel as a cache index + const int ix = VP8LColorCacheGetIndex(&hashers, argb[pixel_index]); + const PixOrCopy token = PixOrCopyCreateCacheIdx(ix); + VP8LHistogramAddSinglePixOrCopy(histo, &token); + } else { + VP8LHistogramAddSinglePixOrCopy(histo, v); + } + } else { + VP8LHistogramAddSinglePixOrCopy(histo, v); + } + if (use_color_cache) { + for (k = 0; k < PixOrCopyLength(v); ++k) { + VP8LColorCacheInsert(&hashers, argb[pixel_index + k]); + } + } + pixel_index += PixOrCopyLength(v); + VP8LRefsCursorNext(&c); + } + assert(pixel_index == xsize * ysize); + (void)xsize; // xsize is not used in non-debug compilations otherwise. + (void)ysize; // ysize is not used in non-debug compilations otherwise. + entropy = VP8LHistogramEstimateBits(histo) + + kSmallPenaltyForLargeCache * cache_bits; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + VP8LFreeHistogram(histo); + return entropy; +} + +// *best_cache_bits will contain how many bits are to be used for a color cache. +// Returns 0 in case of memory error. +int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb, + int xsize, int ysize, int quality, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs, + int* const best_cache_bits) { + int eval_low = 1; + int eval_high = 1; + double entropy_low = MAX_ENTROPY; + double entropy_high = MAX_ENTROPY; + int cache_bits_low = 0; + int cache_bits_high = MAX_COLOR_CACHE_BITS; + + if (!BackwardReferencesHashChain(xsize, ysize, argb, 0, quality, hash_chain, + refs)) { + return 0; + } + // Do a binary search to find the optimal entropy for cache_bits. + while (cache_bits_high - cache_bits_low > 1) { + if (eval_low) { + entropy_low = + ComputeCacheEntropy(argb, xsize, ysize, refs, cache_bits_low); + eval_low = 0; + } + if (eval_high) { + entropy_high = + ComputeCacheEntropy(argb, xsize, ysize, refs, cache_bits_high); + eval_high = 0; + } + if (entropy_high < entropy_low) { + *best_cache_bits = cache_bits_high; + cache_bits_low = (cache_bits_low + cache_bits_high) / 2; + eval_low = 1; + } else { + *best_cache_bits = cache_bits_low; + cache_bits_high = (cache_bits_low + cache_bits_high) / 2; + eval_high = 1; + } + } + return 1; +} diff --git a/TMessagesProj/jni/libwebp/enc/backward_references.h b/TMessagesProj/jni/libwebp/enc/backward_references.h new file mode 100644 index 00000000..c2c81c56 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/backward_references.h @@ -0,0 +1,212 @@ +// 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 +#include +#include "../webp/types.h" +#include "../webp/format_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// The spec allows 11, we use 9 bits to reduce memory consumption in encoding. +// Having 9 instead of 11 only removes about 0.25 % of compression density. +#define MAX_COLOR_CACHE_BITS 9 + +// Max ever number of codes we'll use: +#define PIX_OR_COPY_CODES_MAX \ + (NUM_LITERAL_CODES + NUM_LENGTH_CODES + (1 << MAX_COLOR_CACHE_BITS)) + +// ----------------------------------------------------------------------------- +// 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 { + // Stores the most recently added position with the given hash value. + int32_t hash_to_first_index_[HASH_SIZE]; + // chain_[pos] stores the previous position with the same hash value + // for every pixel in the image. + int32_t* chain_; + // 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); +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. +// Further optimize for 2D locality if use_2d_locality flag is set. +// 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 cache_bits, int use_2d_locality, VP8LHashChain* const hash_chain, + VP8LBackwardRefs refs[2]); + +// Produce an estimate for a good color cache size for the image. +int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb, + int xsize, int ysize, int quality, + VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const ref, + int* const best_cache_bits); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_ENC_BACKWARD_REFERENCES_H_ diff --git a/TMessagesProj/jni/libwebp/enc/config.c b/TMessagesProj/jni/libwebp/enc/config.c new file mode 100644 index 00000000..53a3bb2e --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/config.c @@ -0,0 +1,166 @@ +// 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->image_hint = WEBP_HINT_DEFAULT; + config->emulate_jpeg_size = 0; + config->thread_level = 0; + config->low_memory = 0; + + // 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 WEBP_ENCODER_ABI_VERSION > 0x0204 + if (config->preprocessing < 0 || config->preprocessing > 7) +#else + if (config->preprocessing < 0 || config->preprocessing > 3) +#endif + 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->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; + return 1; +} + +//------------------------------------------------------------------------------ + +#if WEBP_ENCODER_ABI_VERSION > 0x0202 +#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; +} +#endif + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/enc/cost.c b/TMessagesProj/jni/libwebp/enc/cost.c new file mode 100644 index 00000000..9d2cc017 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/cost.c @@ -0,0 +1,735 @@ +// 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" + +//------------------------------------------------------------------------------ +// 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 + +// 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} +}; + +// 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 +}; + +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(VP8Proba* const proba) { + int ctype, band, ctx; + + if (!proba->dirty_) return; // nothing to do. + + for (ctype = 0; ctype < NUM_TYPES; ++ctype) { + 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. + } + } + } + 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 } } +}; + +//------------------------------------------------------------------------------ +// 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]; + const uint16_t* t = res->cost[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 b = VP8EncBands[n + 1]; + const int ctx = (v >= 2) ? 2 : v; + cost += VP8LevelCost(t, v); + t = res->cost[b][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; +} + +//------------------------------------------------------------------------------ +// init function + +#if defined(WEBP_USE_MIPS32) +extern int VP8GetResidualCostMIPS32(int ctx0, const VP8Residual* const res); +#endif // WEBP_USE_MIPS32 + +// TODO(skal): this, and GetResidualCost(), should probably go somewhere +// under src/dsp/ at some point. +VP8GetResidualCostFunc VP8GetResidualCost; + +void VP8GetResidualCostInit(void) { + VP8GetResidualCost = GetResidualCost; + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + VP8GetResidualCost = VP8GetResidualCostMIPS32; + } +#endif + } +} + +//------------------------------------------------------------------------------ +// 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->cost = enc->proba_.level_cost_[coeff_type]; + res->first = first; +} + +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 + +#if defined(WEBP_USE_SSE2) +extern void VP8SetResidualCoeffsSSE2(const int16_t* const coeffs, + VP8Residual* const res); +#endif // WEBP_USE_SSE2 + +VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; + +void VP8SetResidualCoeffsInit(void) { + VP8SetResidualCoeffs = SetResidualCoeffs; + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_USE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8SetResidualCoeffs = VP8SetResidualCoeffsSSE2; + } +#endif + } +} + +//------------------------------------------------------------------------------ +// 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/TMessagesProj/jni/libwebp/enc/cost.h b/TMessagesProj/jni/libwebp/enc/cost.h new file mode 100644 index 00000000..4e558952 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/cost.h @@ -0,0 +1,83 @@ +// 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 +#include +#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 { + int first; + int last; + const int16_t* coeffs; + + int coeff_type; + ProbaArray* prob; + StatsArray* stats; + CostArray* cost; +} VP8Residual; + +void VP8InitResidual(int first, int coeff_type, + VP8Encoder* const enc, VP8Residual* const res); + +typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs, + VP8Residual* const res); +extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs; + +void VP8SetResidualCoeffsInit(void); // must be called first + +int VP8RecordCoeffs(int ctx, const VP8Residual* const res); + +// approximate cost per level: +extern const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1]; +extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p) + +// 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]; +} + +// Cost calculation function. +typedef int (*VP8GetResidualCostFunc)(int ctx0, const VP8Residual* const res); +extern VP8GetResidualCostFunc VP8GetResidualCost; + +void VP8GetResidualCostInit(void); // must be called first + +// Level cost calculations +extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2]; +void VP8CalculateLevelCosts(VP8Proba* 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/TMessagesProj/jni/libwebp/enc/filter.c b/TMessagesProj/jni/libwebp/enc/filter.c new file mode 100644 index 00000000..11db4bd8 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/filter.c @@ -0,0 +1,296 @@ +// 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 +#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; + uint8_t* const u_dst = it->yuv_out2_ + U_OFF; + uint8_t* const v_dst = it->yuv_out2_ + V_OFF; + + // copy current block to yuv_out2_ + memcpy(y_dst, it->yuv_out_, YUV_SIZE * 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 + +enum { KERNEL = 3 }; +static const double kMinValue = 1.e-10; // minimal threshold + +void VP8SSIMAddStats(const DistoStats* const src, DistoStats* 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; +} + +static void VP8SSIMAccumulate(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int xo, int yo, int W, int H, + DistoStats* const stats) { + const int ymin = (yo - KERNEL < 0) ? 0 : yo - KERNEL; + const int ymax = (yo + KERNEL > H - 1) ? H - 1 : yo + KERNEL; + const int xmin = (xo - KERNEL < 0) ? 0 : xo - KERNEL; + const int xmax = (xo + KERNEL > W - 1) ? W - 1 : xo + 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; + } + } +} + +double VP8SSIMGet(const DistoStats* 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 DistoStats* 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; +} + +void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int W, int H, DistoStats* const stats) { + int x, y; + for (y = 0; y < H; ++y) { + for (x = 0; x < W; ++x) { + VP8SSIMAccumulate(src1, stride1, src2, stride2, x, y, W, H, stats); + } + } +} + +static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) { + int x, y; + DistoStats s = { .0, .0, .0, .0, .0, .0 }; + + // compute SSIM in a 10 x 10 window + for (x = 3; x < 13; x++) { + for (y = 3; y < 13; y++) { + VP8SSIMAccumulate(yuv1 + Y_OFF, BPS, yuv2 + Y_OFF, BPS, x, y, 16, 16, &s); + } + } + for (x = 1; x < 7; x++) { + for (y = 1; y < 7; y++) { + VP8SSIMAccumulate(yuv1 + U_OFF, BPS, yuv2 + U_OFF, BPS, x, y, 8, 8, &s); + VP8SSIMAccumulate(yuv1 + V_OFF, BPS, yuv2 + V_OFF, 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; + } + } + } +} + +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_; // TODO: ref_lf_delta[] + + // 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/TMessagesProj/jni/libwebp/enc/frame.c b/TMessagesProj/jni/libwebp/enc/frame.c new file mode 100644 index 00000000..cdf1dabf --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/frame.c @@ -0,0 +1,854 @@ +// 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 +#include + +#include "./vp8enci.h" +#include "./cost.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 VP8EncBands[16 + 1] = { + 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 0 // sentinel +}; + +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) { + VP8Proba* 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) { + VP8Proba* 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) { + VP8Proba* const proba = &enc->proba_; + memset(proba->stats_, 0, sizeof(proba->stats_)); +} + +static int FinalizeTokenProbas(VP8Proba* 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, out + Y_OFF); + enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF); + enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF); + 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, mb->segment_ * 64, 16); + SetBlock(it->yuv_out_ + U_OFF, it->preds_[0] * 64, 8); + SetBlock(it->yuv_out_ + V_OFF, 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; + VP8Proba* 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/TMessagesProj/jni/libwebp/enc/histogram.c b/TMessagesProj/jni/libwebp/enc/histogram.c new file mode 100644 index 00000000..7c6abb4d --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/histogram.c @@ -0,0 +1,741 @@ +// 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 + +#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) + +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; +} + +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 size_t total_size = sizeof(*set) + + sizeof(*set->histograms) * size + + (size_t)VP8LGetHistogramSize(cache_bits) * size; + 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) { + 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); + // There's no padding/alignment between successive histograms. + memory += VP8LGetHistogramSize(cache_bits); + } + 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]; + } +} + +static WEBP_INLINE double BitsEntropyRefine(int nonzeros, int sum, int max_val, + double retval) { + double mix; + if (nonzeros < 5) { + if (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 (nonzeros == 2) { + return 0.99 * sum + 0.01 * retval; + } + // 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 (nonzeros == 3) { + mix = 0.95; + } else { + mix = 0.7; // nonzeros == 4. + } + } else { + mix = 0.627; + } + + { + double min_limit = 2 * sum - max_val; + min_limit = mix * min_limit + (1.0 - mix) * retval; + return (retval < min_limit) ? min_limit : retval; + } +} + +static double BitsEntropy(const uint32_t* const array, int n) { + double retval = 0.; + uint32_t sum = 0; + int nonzeros = 0; + uint32_t max_val = 0; + int i; + for (i = 0; i < n; ++i) { + if (array[i] != 0) { + sum += array[i]; + ++nonzeros; + retval -= VP8LFastSLog2(array[i]); + if (max_val < array[i]) { + max_val = array[i]; + } + } + } + retval += VP8LFastSLog2(sum); + return BitsEntropyRefine(nonzeros, sum, max_val, retval); +} + +static double BitsEntropyCombined(const uint32_t* const X, + const uint32_t* const Y, int n) { + double retval = 0.; + int sum = 0; + int nonzeros = 0; + int max_val = 0; + int i; + for (i = 0; i < n; ++i) { + const int xy = X[i] + Y[i]; + if (xy != 0) { + sum += xy; + ++nonzeros; + retval -= VP8LFastSLog2(xy); + if (max_val < xy) { + max_val = xy; + } + } + } + retval += VP8LFastSLog2(sum); + return BitsEntropyRefine(nonzeros, sum, max_val, retval); +} + +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; +} + +// Trampolines +static double HuffmanCost(const uint32_t* const population, int length) { + const VP8LStreaks stats = VP8LHuffmanCostCount(population, length); + return FinalHuffmanCost(&stats); +} + +static double HuffmanCostCombined(const uint32_t* const X, + const uint32_t* const Y, int length) { + const VP8LStreaks stats = VP8LHuffmanCostCombinedCount(X, Y, length); + return FinalHuffmanCost(&stats); +} + +// Aggregated costs +static double PopulationCost(const uint32_t* const population, int length) { + return BitsEntropy(population, length) + HuffmanCost(population, length); +} + +static double GetCombinedEntropy(const uint32_t* const X, + const uint32_t* const Y, int length) { + return BitsEntropyCombined(X, Y, length) + HuffmanCostCombined(X, Y, length); +} + +// Estimates the Entropy + Huffman + other block overhead size cost. +double VP8LHistogramEstimateBits(const VP8LHistogram* const p) { + return + PopulationCost(p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_)) + + PopulationCost(p->red_, NUM_LITERAL_CODES) + + PopulationCost(p->blue_, NUM_LITERAL_CODES) + + PopulationCost(p->alpha_, NUM_LITERAL_CODES) + + PopulationCost(p->distance_, NUM_DISTANCE_CODES) + + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES) + + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); +} + +double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) { + return + BitsEntropy(p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_)) + + BitsEntropy(p->red_, NUM_LITERAL_CODES) + + BitsEntropy(p->blue_, NUM_LITERAL_CODES) + + BitsEntropy(p->alpha_, NUM_LITERAL_CODES) + + BitsEntropy(p->distance_, NUM_DISTANCE_CODES) + + 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_; + } + + 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) { + const double alpha_cost = PopulationCost(h->alpha_, NUM_LITERAL_CODES); + const double distance_cost = + PopulationCost(h->distance_, NUM_DISTANCE_CODES) + + VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); + const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_); + h->literal_cost_ = PopulationCost(h->literal_, num_codes) + + VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES); + h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES); + h->blue_cost_ = PopulationCost(h->blue_, NUM_LITERAL_CODES); + h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ + + alpha_cost + distance_cost; +} + +static int GetBinIdForEntropy(double min, double max, double val) { + const double range = max - min + 1e-6; + const double delta = val - min; + return (int)(NUM_PARTITIONS * delta / range); +} + +// TODO(vikasa): Evaluate, if there's any correlation between red & blue. +static int GetHistoBinIndex( + const VP8LHistogram* const h, const DominantCostRange* const c) { + const int bin_id = + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_) + + NUM_PARTITIONS * GetBinIdForEntropy(c->red_min_, c->red_max_, + h->red_cost_) + + NUM_PARTITIONS * NUM_PARTITIONS * GetBinIdForEntropy(c->literal_min_, + c->literal_max_, + h->literal_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); + // Construct the Histo from a given backward references. + 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 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) { + int num_histos; + VP8LHistogram* const histo = histograms[i]; + const int16_t bin_id = (int16_t)GetHistoBinIndex(histo, &cost_range); + 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. + 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 moving the valid one left in the set to the +// head and moving the ones that have been merged to other histograms towards +// the end. +// TODO(vikasa): Evaluate if this method can be avoided by altering the code +// logic of HistogramCombineEntropyBin main loop. +static void HistogramCompactBins(VP8LHistogramSet* const image_histo) { + int start = 0; + int end = image_histo->size - 1; + VP8LHistogram** const histograms = image_histo->histograms; + while (start < end) { + while (start <= end && histograms[start] != NULL && + histograms[start]->bit_cost_ != 0.) { + ++start; + } + while (start <= end && histograms[end]->bit_cost_ == 0.) { + histograms[end] = NULL; + --end; + } + if (start < end) { + assert(histograms[start] != NULL); + assert(histograms[end] != NULL); + HistogramCopy(histograms[end], histograms[start]); + histograms[end] = NULL; + --end; + } + } + image_histo->size = end + 1; +} + +static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo, + VP8LHistogram* const histos, + int16_t* const bin_map, int bin_depth, + double combine_cost_factor) { + int bin_id; + VP8LHistogram* cur_combo = histos; + VP8LHistogram** const histograms = image_histo->histograms; + + for (bin_id = 0; bin_id < BIN_SIZE; ++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 n; + for (n = 2; n <= num_histos; ++n) { + const int idx2 = bin_map[bin_offset + n]; + 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) { + HistogramCopy(cur_combo, histograms[idx1]); + histograms[idx2]->bit_cost_ = 0.; + } + } + } + } + HistogramCompactBins(image_histo); +} + +static uint32_t MyRand(uint32_t *seed) { + *seed *= 16807U; + if (*seed == 0) { + *seed = 1; + } + return *seed; +} + +static void HistogramCombine(VP8LHistogramSet* const image_histo, + VP8LHistogramSet* const histos, int quality) { + 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; + const int min_cluster_size = 2; + VP8LHistogram** const histograms = image_histo->histograms; + VP8LHistogram* cur_combo = histos->histograms[0]; // trial histogram + VP8LHistogram* best_combo = histos->histograms[1]; // best histogram so far + + // Collapse similar histograms in 'image_histo'. + 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], + cur_combo, best_cost_diff); + if (curr_cost_diff < best_cost_diff) { // found a better pair? + { // swap cur/best combo histograms + VP8LHistogram* const tmp_histo = cur_combo; + cur_combo = best_combo; + best_combo = tmp_histo; + } + best_cost_diff = curr_cost_diff; + best_idx1 = idx1; + best_idx2 = idx2; + } + } + + if (best_idx1 >= 0) { + HistogramCopy(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) { + HistogramCopy(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 orig_histo, + const VP8LHistogramSet* const image_histo, + uint16_t* const symbols) { + int i; + VP8LHistogram** const orig_histograms = orig_histo->histograms; + VP8LHistogram** const histograms = image_histo->histograms; + for (i = 0; i < orig_histo->size; ++i) { + int best_out = 0; + double best_bits = + HistogramAddThresh(histograms[0], orig_histograms[i], MAX_COST); + int k; + for (k = 1; k < image_histo->size; ++k) { + const double cur_bits = + HistogramAddThresh(histograms[k], orig_histograms[i], best_bits); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = k; + } + } + symbols[i] = best_out; + } + + // Recompute each out based on raw and symbols. + for (i = 0; i < image_histo->size; ++i) { + HistogramClear(histograms[i]); + } + + for (i = 0; i < orig_histo->size; ++i) { + const int idx = symbols[i]; + VP8LHistogramAdd(orig_histograms[i], histograms[idx], histograms[idx]); + } +} + +static double GetCombineCostFactor(int histo_size, int quality) { + double combine_cost_factor = 0.16; + 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 histo_bits, int cache_bits, + VP8LHistogramSet* const image_histo, + 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; + + // 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] = un-used indices. + const int bin_depth = image_histo_raw_size + 1; + int16_t* bin_map = NULL; + VP8LHistogramSet* const histos = VP8LAllocateHistogramSet(2, cache_bits); + VP8LHistogramSet* const orig_histo = + VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits); + + if (orig_histo == NULL || histos == NULL) { + goto Error; + } + + // Don't attempt linear bin-partition heuristic for: + // histograms of small sizes, as bin_map will be very sparse and; + // Higher qualities (> 90), to preserve the compression gains at those + // quality settings. + if (orig_histo->size > 2 * BIN_SIZE && quality < 90) { + const int bin_map_size = bin_depth * BIN_SIZE; + 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); + + if (bin_map != NULL) { + const double combine_cost_factor = + GetCombineCostFactor(image_histo_raw_size, quality); + HistogramAnalyzeEntropyBin(orig_histo, bin_map); + // Collapse histograms with similar entropy. + HistogramCombineEntropyBin(image_histo, histos->histograms[0], + bin_map, bin_depth, combine_cost_factor); + } + + // Collapse similar histograms by random histogram-pair compares. + HistogramCombine(image_histo, histos, quality); + + // 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); + VP8LFreeHistogramSet(histos); + return ok; +} diff --git a/TMessagesProj/jni/libwebp/enc/histogram.h b/TMessagesProj/jni/libwebp/enc/histogram.h new file mode 100644 index 00000000..1cf4c547 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/histogram.h @@ -0,0 +1,118 @@ +// 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 +#include +#include +#include +#include + +#include "./backward_references.h" +#include "../webp/format_constants.h" +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// 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_; + double bit_cost_; // cached value of VP8LHistogramEstimateBits(this) + 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); + +// Estimate how many bits the combined entropy of literals and distance +// approximately maps to. +double VP8LHistogramEstimateBits(const VP8LHistogram* const p); + +// This function estimates the cost in bits excluding the bits needed to +// represent the entropy code itself. +double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p); + +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 histogram_bits, int cache_bits, + VP8LHistogramSet* const image_in, + uint16_t* const histogram_symbols); + +#ifdef __cplusplus +} +#endif + +#endif // WEBP_ENC_HISTOGRAM_H_ diff --git a/TMessagesProj/jni/libwebp/enc/iterator.c b/TMessagesProj/jni/libwebp/enc/iterator.c new file mode 100644 index 00000000..e42ad001 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/iterator.c @@ -0,0 +1,456 @@ +// 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 + +#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*)DO_ALIGN(it->yuv_mem_); + it->yuv_out_ = it->yuv_in_ + YUV_SIZE; + it->yuv_out2_ = it->yuv_out_ + YUV_SIZE; + it->yuv_p_ = it->yuv_out2_ + YUV_SIZE; + it->lf_stats_ = enc->lf_stats_; + it->percent0_ = enc->percent_; + it->y_left_ = (uint8_t*)DO_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, w, h, 16); + ImportBlock(usrc, pic->uv_stride, it->yuv_in_ + U_OFF, uv_w, uv_h, 8); + ImportBlock(vsrc, pic->uv_stride, it->yuv_in_ + V_OFF, 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; + const uint8_t* const usrc = it->yuv_out_ + U_OFF; + const uint8_t* const vsrc = it->yuv_out_ + V_OFF; + 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; + const uint8_t* const uvsrc = it->yuv_out_ + U_OFF; + 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/TMessagesProj/jni/libwebp/enc/picture.c b/TMessagesProj/jni/libwebp/enc/picture.c new file mode 100644 index 00000000..9a66fbe7 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/picture.c @@ -0,0 +1,289 @@ +// 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 +#include + +#include "./vp8enci.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 (!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/TMessagesProj/jni/libwebp/enc/picture_csp.c b/TMessagesProj/jni/libwebp/enc/picture_csp.c new file mode 100644 index 00000000..7875f625 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/picture_csp.c @@ -0,0 +1,1114 @@ +// 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 +#include +#include + +#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) + +static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { + return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); +} + +//------------------------------------------------------------------------------ +// 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 int kGammaTablesOk = 0; + +static 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 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 use a-priori a different precision for storing RGB and Y/W components +// We could use YFIX=0 and only uint8_t for fixed_y_t, but it produces some +// banding sometimes. Better use extra precision. +// TODO(skal): cleanup once TFIX/YFIX values are fixed. + +typedef int16_t fixed_t; // signed type with extra TFIX precision for UV +typedef uint16_t fixed_y_t; // unsigned type with extra YFIX precision for W +#define TFIX 6 // fixed-point precision of RGB +#define YFIX 2 // fixed point precision for Y/W + +#define THALF ((1 << TFIX) >> 1) +#define MAX_Y_T ((256 << YFIX) - 1) +#define TROUNDER (1 << (YUV_FIX + TFIX - 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 int kGammaTablesFOk = 0; + +static 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 float 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 y; +} + +#else + +static void InitGammaTablesF(void) {} +static WEBP_INLINE float GammaToLinearF(int v) { + const float norm = 1.f / MAX_Y_T; + return norm * v; +} +static WEBP_INLINE float LinearToGammaF(float value) { + return MAX_Y_T * value; +} + +#endif // USE_GAMMA_COMPRESSION + +//------------------------------------------------------------------------------ + +// precision: YFIX -> TFIX +static WEBP_INLINE int FixedYToW(int v) { +#if TFIX == YFIX + return v; +#elif TFIX >= YFIX + return v << (TFIX - YFIX); +#else + return v >> (YFIX - TFIX); +#endif +} + +static WEBP_INLINE int FixedWToY(int v) { +#if TFIX == YFIX + return v; +#elif YFIX >= TFIX + return v << (YFIX - TFIX); +#else + return v >> (TFIX - YFIX); +#endif +} + +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; +} + +// precision: TFIX -> YFIX +static fixed_y_t clip_fixed_t(fixed_t v) { + const int y = FixedWToY(v); + const fixed_y_t w = clip_y(y); + return w; +} + +//------------------------------------------------------------------------------ + +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 float 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) + .5); + src += 3; + } +} + +static WEBP_INLINE void UpdateChroma(const fixed_y_t* src1, + const fixed_y_t* src2, + fixed_t* dst, fixed_y_t* tmp, int len) { + while (len--> 0) { + const float r = ScaleDown(src1[0], src1[3], src2[0], src2[3]); + const float g = ScaleDown(src1[1], src1[4], src2[1], src2[4]); + const float b = ScaleDown(src1[2], src1[5], src2[2], src2[5]); + const float W = RGBToGrayF(r, g, b); + dst[0] = (fixed_t)FixedYToW((int)(r - W)); + dst[1] = (fixed_t)FixedYToW((int)(g - W)); + dst[2] = (fixed_t)FixedYToW((int)(b - W)); + dst += 3; + src1 += 6; + src2 += 6; + if (tmp != NULL) { + tmp[0] = tmp[1] = clip_y((int)(W + .5)); + tmp += 2; + } + } +} + +//------------------------------------------------------------------------------ + +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; } + +//------------------------------------------------------------------------------ + +// 8bit -> YFIX +static WEBP_INLINE fixed_y_t UpLift(uint8_t a) { + return ((fixed_y_t)a << YFIX) | (1 << (YFIX - 1)); +} + +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 = FixedYToW(best_y[0]); + const int W1 = FixedYToW(best_y[w]); + for (k = 0; k <= 2; ++k) { + out1[k] = clip_fixed_t(Filter2(cur_uv[k], prev_uv[k]) + W0); + out2[k] = clip_fixed_t(Filter2(cur_uv[k], next_uv[k]) + W1); + } + } + for (i = 1; i < w - 1; ++i) { + const int W0 = FixedYToW(best_y[i + 0]); + const int W1 = FixedYToW(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_fixed_t(tmp0 + W0); + out2[3 * i + k] = clip_fixed_t(tmp1 + W1); + } + } + { // special boundary case for i == w - 1 + const int W0 = FixedYToW(best_y[i + 0]); + const int W1 = FixedYToW(best_y[i + w]); + const int off = 3 * (i >> 1); + for (k = 0; k <= 2; ++k) { + out1[3 * i + k] = + clip_fixed_t(Filter2(cur_uv[off + k], prev_uv[off + k]) + W0); + out2[3 * i + k] = + clip_fixed_t(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 + TROUNDER; + return clip_8b(16 + (luma >> (YUV_FIX + TFIX))); +} + +static WEBP_INLINE uint8_t ConvertRGBToU(int r, int g, int b) { + const int u = -9719 * r - 19081 * g + 28800 * b + TROUNDER; + return clip_8b(128 + (u >> (YUV_FIX + TFIX))); +} + +static WEBP_INLINE uint8_t ConvertRGBToV(int r, int g, int b) { + const int v = +28800 * r - 24116 * g - 4684 * b + TROUNDER; + return clip_8b(128 + (v >> (YUV_FIX + TFIX))); +} + +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 = FixedYToW(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; + + 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); + 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; + 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); + 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; + } + } + } + // TODO(skal): add early-termination criterion + } + + // 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<> (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, j += step) { + dst_y[i] = RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], rg); + } +} + +static WEBP_INLINE void ConvertRowsToUVWithAlpha(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, + uint8_t* const dst_u, + uint8_t* const dst_v, + int width, + VP8Random* const rg) { + int i, j; + // we loop over 2x2 blocks and produce one U/V value for each. + for (i = 0, j = 0; i < (width >> 1); ++i, j += 2 * sizeof(uint32_t)) { + 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_u[i] = RGBToU(r, g, b, rg); + dst_v[i] = RGBToV(r, g, b, rg); + } + 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_u[i] = RGBToU(r, g, b, rg); + dst_v[i] = RGBToV(r, g, b, rg); + } +} + +static WEBP_INLINE void ConvertRowsToUV(const uint8_t* const r_ptr, + const uint8_t* const g_ptr, + const uint8_t* const b_ptr, + int step, int rgb_stride, + uint8_t* const dst_u, + uint8_t* const dst_v, + int width, + VP8Random* const rg) { + int i, j; + for (i = 0, j = 0; i < (width >> 1); ++i, j += 2 * step) { + const int r = SUM4(r_ptr + j, step); + const int g = SUM4(g_ptr + j, step); + const int b = SUM4(b_ptr + j, step); + dst_u[i] = RGBToU(r, g, b, rg); + dst_v[i] = RGBToV(r, g, b, rg); + } + if (width & 1) { + const int r = SUM2(r_ptr + j); + const int g = SUM2(g_ptr + j); + const int b = SUM2(b_ptr + j); + 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); + + 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_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 { + 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; + } + + InitGammaTables(); + + // 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; + 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; + } + if (!rows_have_alpha) { + ConvertRowsToUV(r_ptr + off1, g_ptr + off1, b_ptr + off1, + step, rgb_stride, dst_u, dst_v, width, rg); + } else { + ConvertRowsToUVWithAlpha(r_ptr + off1, g_ptr + off1, b_ptr + off1, + a_ptr + off1, rgb_stride, + dst_u, dst_v, 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; + 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); + } + if (!row_has_alpha) { + ConvertRowsToUV(r_ptr + off, g_ptr + off, b_ptr + off, + step, 0, dst_u, dst_v, width, rg); + } else { + ConvertRowsToUVWithAlpha(r_ptr + off, g_ptr + off, b_ptr + off, + a_ptr + off, 0, + dst_u, dst_v, width, rg); + } + } + } + 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); +} + +#if WEBP_ENCODER_ABI_VERSION > 0x0204 +int WebPPictureSmartARGBToYUVA(WebPPicture* picture) { + return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1); +} +#endif + +//------------------------------------------------------------------------------ +// 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; + + assert(step >= (import_alpha ? 4 : 3)); + for (y = 0; y < height; ++y) { + uint32_t* const dst = &picture->argb[y * picture->argb_stride]; + int x; + for (x = 0; x < width; ++x) { + const int offset = step * x + y * rgb_stride; + dst[x] = MakeARGB32(import_alpha ? a_ptr[offset] : 0xff, + r_ptr[offset], g_ptr[offset], b_ptr[offset]); + } + } + return 1; +} + +// Public API + +int WebPPictureImportRGB(WebPPicture* picture, + const uint8_t* rgb, int rgb_stride) { + return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 0, 0) : 0; +} + +int WebPPictureImportBGR(WebPPicture* picture, + const uint8_t* rgb, int rgb_stride) { + return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 1, 0) : 0; +} + +int WebPPictureImportRGBA(WebPPicture* picture, + const uint8_t* rgba, int rgba_stride) { + return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 1) : 0; +} + +int WebPPictureImportBGRA(WebPPicture* picture, + const uint8_t* rgba, int rgba_stride) { + return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 1) : 0; +} + +int WebPPictureImportRGBX(WebPPicture* picture, + const uint8_t* rgba, int rgba_stride) { + return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 0) : 0; +} + +int WebPPictureImportBGRX(WebPPicture* picture, + const uint8_t* rgba, int rgba_stride) { + return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 0) : 0; +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/enc/picture_psnr.c b/TMessagesProj/jni/libwebp/enc/picture_psnr.c new file mode 100644 index 00000000..2254b7e5 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/picture_psnr.c @@ -0,0 +1,150 @@ +// 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 + +#include "./vp8enci.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 float AccumulateLSIM(const uint8_t* src, int src_stride, + const uint8_t* ref, int ref_stride, + int w, int h) { + 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* s = src + j * src_stride; + for (i = x_0; i < x_1; ++i) { + const double sse = (double)(s[i] - value) * (s[i] - value); + if (sse < best_sse) best_sse = sse; + } + } + total_sse += best_sse; + } + } + return (float)total_sse; +} +#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]) { + DistoStats stats[5]; + int has_alpha; + int uv_w, uv_h; + + if (src == NULL || ref == NULL || + src->width != ref->width || src->height != ref->height || + src->y == NULL || ref->y == NULL || + src->u == NULL || ref->u == NULL || + src->v == NULL || ref->v == NULL || + result == NULL) { + return 0; + } + // TODO(skal): provide distortion for ARGB too. + if (src->use_argb == 1 || src->use_argb != ref->use_argb) { + 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; + } + + memset(stats, 0, sizeof(stats)); + + uv_w = (src->width + 1) >> 1; + uv_h = (src->height + 1) >> 1; + if (type >= 2) { + float sse[4]; + sse[0] = AccumulateLSIM(src->y, src->y_stride, + ref->y, ref->y_stride, src->width, src->height); + sse[1] = AccumulateLSIM(src->u, src->uv_stride, + ref->u, ref->uv_stride, uv_w, uv_h); + sse[2] = AccumulateLSIM(src->v, src->uv_stride, + ref->v, ref->uv_stride, uv_w, uv_h); + sse[3] = has_alpha ? AccumulateLSIM(src->a, src->a_stride, + ref->a, ref->a_stride, + src->width, src->height) + : 0.f; + result[0] = GetPSNR(sse[0] / (src->width * src->height)); + result[1] = GetPSNR(sse[1] / (uv_w * uv_h)); + result[2] = GetPSNR(sse[2] / (uv_w * uv_h)); + result[3] = GetPSNR(sse[3] / (src->width * src->height)); + { + double total_sse = sse[0] + sse[1] + sse[2]; + int total_pixels = src->width * src->height + 2 * uv_w * uv_h; + if (has_alpha) { + total_pixels += src->width * src->height; + total_sse += sse[3]; + } + result[4] = GetPSNR(total_sse / total_pixels); + } + } else { + int c; + VP8SSIMAccumulatePlane(src->y, src->y_stride, + ref->y, ref->y_stride, + src->width, src->height, &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, + src->width, src->height, &stats[3]); + } + 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/TMessagesProj/jni/libwebp/enc/picture_rescale.c b/TMessagesProj/jni/libwebp/enc/picture_rescale.c new file mode 100644 index 00000000..de52848c --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/picture_rescale.c @@ -0,0 +1,285 @@ +// 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 +#include + +#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); +} + +//------------------------------------------------------------------------------ +// Picture copying + +static void CopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height) { + while (height-- > 0) { + memcpy(dst, src, width); + src += src_stride; + dst += dst_stride; + } +} + +// 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) { + CopyPlane(src->y, src->y_stride, + dst->y, dst->y_stride, dst->width, dst->height); + CopyPlane(src->u, src->uv_stride, + dst->u, dst->uv_stride, HALVE(dst->width), HALVE(dst->height)); + CopyPlane(src->v, src->uv_stride, + dst->v, dst->uv_stride, HALVE(dst->width), HALVE(dst->height)); + if (dst->a != NULL) { + CopyPlane(src->a, src->a_stride, + dst->a, dst->a_stride, dst->width, dst->height); + } + } else { + CopyPlane((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; + CopyPlane(pic->y + y_offset, pic->y_stride, + tmp.y, tmp.y_stride, width, height); + CopyPlane(pic->u + uv_offset, pic->uv_stride, + tmp.u, tmp.uv_stride, HALVE(width), HALVE(height)); + CopyPlane(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; + CopyPlane(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); + CopyPlane(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, + int32_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, + src_width, dst_width, + src_height, dst_height, + work); + memset(work, 0, 2 * dst_width * num_channels * sizeof(*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; + int32_t* work; + + if (pic == NULL) return 0; + prev_width = pic->width; + prev_height = pic->height; + // if width is unspecified, scale original proportionally to height ratio. + if (width == 0) { + width = (prev_width * height + prev_height / 2) / prev_height; + } + // if height is unspecified, scale original proportionally to width ratio. + if (height == 0) { + height = (prev_height * width + prev_width / 2) / prev_width; + } + // Check if the overall dimensions still make sense. + if (width <= 0 || height <= 0) return 0; + + PictureGrabSpecs(pic, &tmp); + tmp.width = width; + tmp.height = height; + if (!WebPPictureAlloc(&tmp)) return 0; + + if (!pic->use_argb) { + work = (int32_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 = (int32_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/TMessagesProj/jni/libwebp/enc/picture_tools.c b/TMessagesProj/jni/libwebp/enc/picture_tools.c new file mode 100644 index 00000000..7c736463 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/picture_tools.c @@ -0,0 +1,206 @@ +// 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 "./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 + +//------------------------------------------------------------------------------ +// 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/TMessagesProj/jni/libwebp/enc/quant.c b/TMessagesProj/jni/libwebp/enc/quant.c new file mode 100644 index 00000000..9130a416 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/quant.c @@ -0,0 +1,1170 @@ +// 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 +#include +#include // 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. + +#define I4_PENALTY 4000 // Rate-penalty for quick i4/i16 decision + +// 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 DEBUG_BLOCK + +//------------------------------------------------------------------------------ + +#if defined(DEBUG_BLOCK) + +#include +#include + +static void PrintBlockInfo(const VP8EncIterator* const it, + const VP8ModeScore* const rd) { + int i, j; + const int is_i16 = (it->mb_->type_ == 1); + printf("SOURCE / OUTPUT / ABS DELTA\n"); + for (j = 0; j < 24; ++j) { + if (j == 16) printf("\n"); // newline before the U/V block + for (i = 0; i < 16; ++i) printf("%3d ", it->yuv_in_[i + j * BPS]); + printf(" "); + for (i = 0; i < 16; ++i) printf("%3d ", it->yuv_out_[i + j * BPS]); + printf(" "); + for (i = 0; i < 16; ++i) { + printf("%1d ", abs(it->yuv_out_[i + j * BPS] - it->yuv_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 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 q4, q16, quv; + 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)]; + + q4 = ExpandMatrix(&m->y1_, 0); + q16 = ExpandMatrix(&m->y2_, 1); + quv = ExpandMatrix(&m->uv_, 2); + + m->lambda_i4_ = (3 * q4 * q4) >> 7; + m->lambda_i16_ = (3 * q16 * q16); + m->lambda_uv_ = (3 * quv * quv) >> 6; + m->lambda_mode_ = (1 * q4 * q4) >> 7; + m->lambda_trellis_i4_ = (7 * q4 * q4) >> 3; + m->lambda_trellis_i16_ = (q16 * q16) >> 2; + m->lambda_trellis_uv_ = (quv *quv) << 1; + m->tlambda_ = (tlambda_scale * q4) >> 5; + + m->min_disto_ = 10 * m->y1_.q_[0]; // quantization-aware min disto + m->max_edge_ = 0; + } +} + +//------------------------------------------------------------------------------ +// 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 }; + const int num_segments = enc->segment_hdr_.num_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| 0 +// |YYYY| 4 +// |YYYY| 8 +// |YYYY| 12 +// +----+ +// |UUVV| 16 +// |UUVV| 20 +// +----+ + +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) { + // TODO: incorporate the "* 256" in the tables? + rd->score = (rd->R + rd->H) * lambda + 256 * (rd->D + rd->SD); +} + +static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate, + score_t distortion) { + return rate * lambda + 256 * 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]; + const CostArray* const costs = enc->proba_.level_cost_[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[VP8EncBands[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[band][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; + 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) { + VP8FTransform(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) { + // 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] = 0; + nz |= VP8EncQuantizeBlock(tmp[n], rd->y_ac_levels[n], &dqm->y1_) << n; + assert(rd->y_ac_levels[n][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; + 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) { + VP8FTransform(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) { + nz |= VP8EncQuantizeBlock(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 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* const 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; + VP8ModeScore rd16; + int mode; + + rd->mode_i16 = -1; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer + int nz; + + // Reconstruct + nz = ReconstructIntra16(it, &rd16, tmp_dst, mode); + + // Measure RD-score + rd16.D = VP8SSE16x16(src, tmp_dst); + rd16.SD = tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) + : 0; + rd16.H = VP8FixedCostsI16[mode]; + rd16.R = VP8GetCostLuma16(it, &rd16); + if (mode > 0 && + IsFlat(rd16.y_ac_levels[0], kNumBlocks, FLATNESS_LIMIT_I16)) { + // penalty to avoid flat area to be mispredicted by complex mode + rd16.R += FLATNESS_PENALTY * kNumBlocks; + } + + // Since we always examine Intra16 first, we can overwrite *rd directly. + SetRDScore(lambda, &rd16); + if (mode == 0 || rd16.score < rd->score) { + CopyScore(rd, &rd16); + rd->mode_i16 = mode; + rd->nz = nz; + memcpy(rd->y_ac_levels, rd16.y_ac_levels, sizeof(rd16.y_ac_levels)); + memcpy(rd->y_dc_levels, rd16.y_dc_levels, sizeof(rd16.y_dc_levels)); + SwapOut(it); + } + } + 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; + uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF; + 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]; + rd_tmp.R = VP8GetCostLuma4(it, tmp_levels); + if (mode > 0 && IsFlat(tmp_levels, kNumBlocks, FLATNESS_LIMIT_I4)) { + rd_tmp.R += FLATNESS_PENALTY * kNumBlocks; + } + + 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(tmp_levels)); + } + } + 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; + uint8_t* const tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer + uint8_t* const dst0 = it->yuv_out_ + U_OFF; + 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; // TODO: should we call TDisto? 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)); + memcpy(dst0, tmp_dst, UV_SIZE); // TODO: SwapUVOut() ? + } + } + VP8SetIntraUVMode(it, rd->mode_uv); + AddScore(rd, &rd_best); +} + +//------------------------------------------------------------------------------ +// 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, 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 + VP8Scan[it->i4_]; + uint8_t* const dst = it->yuv_out_ + Y_OFF + 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)); + } + + nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF, it->mb_->uv_mode_); + rd->nz = nz; +} + +// Refine intra16/intra4 sub-modes based on distortion only (not rate). +static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) { + const int is_i16 = (it->mb_->type_ == 1); + score_t best_score = MAX_COST; + + if (try_both_i4_i16 || is_i16) { + int mode; + int best_mode = -1; + for (mode = 0; mode < NUM_PRED_MODES; ++mode) { + const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; + const uint8_t* const src = it->yuv_in_ + Y_OFF; + const score_t score = VP8SSE16x16(src, ref); + if (score < best_score) { + best_mode = mode; + best_score = score; + } + } + VP8SetIntra16Mode(it, best_mode); + } + if (try_both_i4_i16 || !is_i16) { + uint8_t modes_i4[16]; + // 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). + score_t score_i4 = (score_t)I4_PENALTY; + + VP8IteratorStartI4(it); + do { + int mode; + int best_sub_mode = -1; + score_t best_sub_score = MAX_COST; + const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; + + // TODO(skal): we don't really need the prediction pixels here, + // but just the distortion against 'src'. + 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); + if (score < best_sub_score) { + best_sub_mode = mode; + best_sub_score = score; + } + } + modes_i4[it->i4_] = best_sub_mode; + score_i4 += best_sub_score; + if (score_i4 >= best_score) break; + } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF)); + if (score_i4 < best_score) { + VP8SetIntra4Mode(it, modes_i4); + } + } +} + +//------------------------------------------------------------------------------ +// 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 { + // For method == 2, pick the best intra4/intra16 based on SSE (~tad slower). + // For method <= 1, we refine intra4 or intra16 (but don't re-examine mode). + DistoRefine(it, (method >= 2)); + SimpleQuantize(it, rd); + } + is_skipped = (rd->nz == 0); + VP8SetSkip(it, is_skipped); + return is_skipped; +} + diff --git a/TMessagesProj/jni/libwebp/enc/syntax.c b/TMessagesProj/jni/libwebp/enc/syntax.c new file mode 100644 index 00000000..d1ff0a53 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/syntax.c @@ -0,0 +1,383 @@ +// 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 + +#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 VP8SegmentHeader* const hdr = &enc->segment_hdr_; + const VP8Proba* 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) { + VP8PutSignedValue(bw, enc->dqm_[s].quant_, 7); + } + for (s = 0; s < NUM_MB_SEGMENTS; ++s) { + VP8PutSignedValue(bw, enc->dqm_[s].fstrength_, 6); + } + } + if (hdr->update_map_) { + for (s = 0; s < 3; ++s) { + if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) { + VP8PutValue(bw, proba->segments_[s], 8); + } + } + } + } +} + +// Filtering parameters header +static void PutFilterHeader(VP8BitWriter* const bw, + const VP8FilterHeader* const hdr) { + const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0); + VP8PutBitUniform(bw, hdr->simple_); + VP8PutValue(bw, hdr->level_, 6); + VP8PutValue(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 + VP8PutValue(bw, 0, 4); + // we use mode_lf_delta for i4x4 + VP8PutSignedValue(bw, hdr->i4x4_lf_delta_, 6); + VP8PutValue(bw, 0, 3); // all others unused + } + } +} + +// Nominal quantization parameters +static void PutQuant(VP8BitWriter* const bw, + const VP8Encoder* const enc) { + VP8PutValue(bw, enc->base_quant_, 7); + VP8PutSignedValue(bw, enc->dq_y1_dc_, 4); + VP8PutSignedValue(bw, enc->dq_y2_dc_, 4); + VP8PutSignedValue(bw, enc->dq_y2_ac_, 4); + VP8PutSignedValue(bw, enc->dq_uv_dc_, 4); + VP8PutSignedValue(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_); + VP8PutValue(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/TMessagesProj/jni/libwebp/enc/token.c b/TMessagesProj/jni/libwebp/enc/token.c new file mode 100644 index 00000000..8af13a08 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/token.c @@ -0,0 +1,286 @@ +// 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 +#include +#include + +#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 + // bit #14: 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) ((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) { + const VP8Tokens* p = b->pages_; + while (p != NULL) { + const VP8Tokens* const next = p->next_; + WebPSafeFree((void*)p); + p = next; + } + VP8TBufferInit(b, b->page_size_); + } +} + +static int TBufferNewPage(VP8TBuffer* const b) { + VP8Tokens* page = NULL; + const size_t size = sizeof(*page) + b->page_size_ * sizeof(token_t); + if (!b->error_) { + 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_DATA(page); + return 1; +} + +//------------------------------------------------------------------------------ + +#define TOKEN_ID(t, b, ctx, p) \ + ((p) + NUM_PROBAS * ((ctx) + NUM_CTX * ((b) + NUM_BANDS * (t)))) + +static WEBP_INLINE int AddToken(VP8TBuffer* const b, + int bit, uint32_t proba_idx) { + assert(proba_idx < FIXED_PROBA_BIT); + assert(bit == 0 || 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, + int bit, int proba) { + assert(proba < 256); + assert(bit == 0 || bit == 1); + if (b->left_ > 0 || TBufferNewPage(b)) { + const int slot = --b->left_; + b->tokens_[slot] = (bit << 15) | FIXED_PROBA_BIT | proba; + } +} + +int VP8RecordCoeffTokens(int ctx, 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, 0); + if (!AddToken(tokens, last >= 0, base_id + 0)) { + return 0; + } + + while (n < 16) { + const int c = coeffs[n++]; + const int sign = c < 0; + int v = sign ? -c : c; + if (!AddToken(tokens, v != 0, base_id + 1)) { + ctx = 0; + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], ctx, 0); + continue; + } + if (!AddToken(tokens, v > 1, base_id + 2)) { + 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; + if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) + AddToken(tokens, 0, base_id + 8); + AddToken(tokens, 0, base_id + 9); + v -= 3 + (8 << 0); + mask = 1 << 2; + tab = VP8Cat3; + } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) + AddToken(tokens, 0, base_id + 8); + AddToken(tokens, 1, base_id + 9); + v -= 3 + (8 << 1); + mask = 1 << 3; + tab = VP8Cat4; + } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) + AddToken(tokens, 1, base_id + 8); + AddToken(tokens, 0, base_id + 10); + v -= 3 + (8 << 2); + mask = 1 << 4; + tab = VP8Cat5; + } else { // VP8Cat6 (11b) + AddToken(tokens, 1, base_id + 8); + AddToken(tokens, 1, base_id + 10); + v -= 3 + (8 << 3); + mask = 1 << 10; + tab = VP8Cat6; + } + while (mask) { + AddConstantToken(tokens, !!(v & mask), *tab++); + mask >>= 1; + } + } + ctx = 2; + } + AddConstantToken(tokens, sign, 128); + base_id = TOKEN_ID(coeff_type, VP8EncBands[n], ctx, 0); + 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_; + (void)final_pass; + 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/TMessagesProj/jni/libwebp/enc/tree.c b/TMessagesProj/jni/libwebp/enc/tree.c new file mode 100644 index 00000000..e5d05e52 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/tree.c @@ -0,0 +1,504 @@ +// 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) { + VP8Proba* 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 VP8Proba* 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])) { + VP8PutValue(bw, p0, 8); + } + } + } + } + } + if (VP8PutBitUniform(bw, probas->use_skip_proba_)) { + VP8PutValue(bw, probas->skip_proba_, 8); + } +} + diff --git a/TMessagesProj/jni/libwebp/enc/vp8enci.h b/TMessagesProj/jni/libwebp/enc/vp8enci.h new file mode 100644 index 00000000..10c8fb0a --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/vp8enci.h @@ -0,0 +1,582 @@ +// 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 // for memcpy() +#include "../webp/encode.h" +#include "../dsp/dsp.h" +#include "../utils/bit_writer.h" +#include "../utils/thread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------ +// Various defines and enums + +// version numbers +#define ENC_MAJ_VERSION 0 +#define ENC_MIN_VERSION 4 +#define ENC_REV_VERSION 2 + +// 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, + NUM_PRED_MODES = 4 + }; + +enum { NUM_MB_SEGMENTS = 4, + MAX_NUM_PARTITIONS = 8, + NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC + NUM_BANDS = 8, + NUM_CTX = 3, + NUM_PROBAS = 11, + 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 16-pixels wide. +// 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. See VP8Scan[] for accessing the blocks. +// Y_OFF |YYYY| <- original samples ('yuv_in_') +// |YYYY| +// |YYYY| +// |YYYY| +// U_OFF |UUVV| V_OFF (=U_OFF + 8) +// |UUVV| +// +----+ +// Y_OFF |YYYY| <- compressed/decoded samples ('yuv_out_') +// |YYYY| There are two buffers like this ('yuv_out_'/'yuv_out2_') +// |YYYY| +// |YYYY| +// U_OFF |UUVV| V_OFF +// |UUVV| +// x2 (for yuv_out2_) +// +----+ Prediction area ('yuv_p_', size = PRED_SIZE) +// I16DC16 |YYYY| Intra16 predictions (16x16 block each) +// |YYYY| +// |YYYY| +// |YYYY| +// I16TM16 |YYYY| +// |YYYY| +// |YYYY| +// |YYYY| +// I16VE16 |YYYY| +// |YYYY| +// |YYYY| +// |YYYY| +// I16HE16 |YYYY| +// |YYYY| +// |YYYY| +// |YYYY| +// +----+ Chroma U/V predictions (16x8 block each) +// C8DC8 |UUVV| +// |UUVV| +// C8TM8 |UUVV| +// |UUVV| +// C8VE8 |UUVV| +// |UUVV| +// C8HE8 |UUVV| +// |UUVV| +// +----+ Intra 4x4 predictions (4x4 block each) +// |YYYY| I4DC4 I4TM4 I4VE4 I4HE4 +// |YYYY| I4RD4 I4VR4 I4LD4 I4VL4 +// |YY..| I4HD4 I4HU4 I4TMP +// +----+ +#define BPS 16 // this is the common stride +#define Y_SIZE (BPS * 16) +#define UV_SIZE (BPS * 8) +#define YUV_SIZE (Y_SIZE + UV_SIZE) +#define PRED_SIZE (6 * 16 * BPS + 12 * BPS) +#define Y_OFF (0) +#define U_OFF (Y_SIZE) +#define V_OFF (U_OFF + 8) +#define ALIGN_CST 15 +#define DO_ALIGN(PTR) ((uintptr_t)((PTR) + ALIGN_CST) & ~ALIGN_CST) + +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 (1 * 16 * BPS) +#define I16VE16 (2 * 16 * BPS) +#define I16HE16 (3 * 16 * BPS) +// chroma 8x8, two U/V blocks side by side (hence: 16x8 each) +#define C8DC8 (4 * 16 * BPS) +#define C8TM8 (4 * 16 * BPS + 8 * BPS) +#define C8VE8 (5 * 16 * BPS) +#define C8HE8 (5 * 16 * BPS + 8 * BPS) +// intra 4x4 +#define I4DC4 (6 * 16 * BPS + 0) +#define I4TM4 (6 * 16 * BPS + 4) +#define I4VE4 (6 * 16 * BPS + 8) +#define I4HE4 (6 * 16 * BPS + 12) +#define I4RD4 (6 * 16 * BPS + 4 * BPS + 0) +#define I4VR4 (6 * 16 * BPS + 4 * BPS + 4) +#define I4LD4 (6 * 16 * BPS + 4 * BPS + 8) +#define I4VL4 (6 * 16 * BPS + 4 * BPS + 12) +#define I4HD4 (6 * 16 * BPS + 8 * BPS + 0) +#define I4HU4 (6 * 16 * BPS + 8 * BPS + 4) +#define I4TMP (6 * 16 * BPS + 8 * BPS + 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); +} + +// size of histogram used by CollectHistogram. +#define MAX_COEFF_THRESH 31 +typedef struct VP8Histogram VP8Histogram; +struct VP8Histogram { + // TODO(skal): we only need to store the max_value and last_non_zero actually. + int distribution[MAX_COEFF_THRESH + 1]; +}; + +// 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 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 +} VP8SegmentHeader; + +// 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 + 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 +} VP8Proba; + +// 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 +} VP8FilterHeader; + +//------------------------------------------------------------------------------ +// 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_; +} 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_ and yuv_in_/out_* + uint8_t yuv_left_mem_[17 + 16 + 16 + 8 + ALIGN_CST]; // memory for *_left_ + uint8_t yuv_mem_[3 * YUV_SIZE + PRED_SIZE + ALIGN_CST]; // memory for yuv_* +} 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(int ctx, 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 + VP8FilterHeader filter_hdr_; // filtering information + VP8SegmentHeader 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 + VP8Proba 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 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 VP8Proba* 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 VP8EncBands[16 + 1]; +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 + +// SSIM utils +typedef struct { + double w, xm, ym, xxm, xym, yym; +} DistoStats; +void VP8SSIMAddStats(const DistoStats* const src, DistoStats* const dst); +void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int W, int H, DistoStats* const stats); +double VP8SSIMGet(const DistoStats* const stats); +double VP8SSIMGetSquaredError(const DistoStats* 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); + +//------------------------------------------------------------------------------ + +#if WEBP_ENCODER_ABI_VERSION <= 0x0203 +void WebPMemoryWriterClear(WebPMemoryWriter* writer); +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_ENC_VP8ENCI_H_ */ diff --git a/TMessagesProj/jni/libwebp/enc/vp8l.c b/TMessagesProj/jni/libwebp/enc/vp8l.c new file mode 100644 index 00000000..891dd01b --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/vp8l.c @@ -0,0 +1,1244 @@ +// 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 +#include +#include + +#include "./backward_references.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" + +#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer. +#define MAX_HUFF_IMAGE_SIZE (16 * 1024 * 1024) +#define MAX_COLORS_FOR_GRAPH 64 + +// ----------------------------------------------------------------------------- +// Palette + +static int CompareColors(const void* p1, const void* p2) { + const uint32_t a = *(const uint32_t*)p1; + const uint32_t b = *(const uint32_t*)p2; + assert(a != b); + return (a < b) ? -1 : 1; +} + +// 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, + uint32_t palette[MAX_PALETTE_SIZE], + int* const palette_size) { + int i, x, y, key; + int num_colors = 0; + uint8_t in_use[MAX_PALETTE_SIZE * 4] = { 0 }; + uint32_t colors[MAX_PALETTE_SIZE * 4]; + static const uint32_t kHashMul = 0x1e35a7bd; + 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] + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (argb[x] == last_pix) { + continue; + } + last_pix = argb[x]; + key = (kHashMul * last_pix) >> PALETTE_KEY_RIGHT_SHIFT; + while (1) { + if (!in_use[key]) { + colors[key] = last_pix; + in_use[key] = 1; + ++num_colors; + if (num_colors > MAX_PALETTE_SIZE) { + return 0; + } + break; + } else if (colors[key] == last_pix) { + // The color is already there. + break; + } else { + // Some other color sits there. + // Do linear conflict resolution. + ++key; + key &= (MAX_PALETTE_SIZE * 4 - 1); // key mask for 1K buffer. + } + } + } + argb += pic->argb_stride; + } + + // TODO(skal): could we reuse in_use[] to speed up EncodePalette()? + num_colors = 0; + for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) { + if (in_use[i]) { + palette[num_colors] = colors[i]; + ++num_colors; + } + } + + qsort(palette, num_colors, sizeof(*palette), CompareColors); + *palette_size = num_colors; + return 1; +} + +static int AnalyzeEntropy(const uint32_t* argb, + int width, int height, int argb_stride, + double* const nonpredicted_bits, + double* const predicted_bits) { + int x, y; + const uint32_t* last_line = NULL; + uint32_t last_pix = argb[0]; // so we're sure that pix_diff == 0 + + VP8LHistogramSet* const histo_set = VP8LAllocateHistogramSet(2, 0); + if (histo_set == NULL) return 0; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const uint32_t pix = argb[x]; + const uint32_t pix_diff = VP8LSubPixels(pix, last_pix); + if (pix_diff == 0) continue; + if (last_line != NULL && pix == last_line[x]) { + continue; + } + last_pix = pix; + { + const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix); + const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff); + VP8LHistogramAddSinglePixOrCopy(histo_set->histograms[0], &pix_token); + VP8LHistogramAddSinglePixOrCopy(histo_set->histograms[1], + &pix_diff_token); + } + } + last_line = argb; + argb += argb_stride; + } + *nonpredicted_bits = VP8LHistogramEstimateBitsBulk(histo_set->histograms[0]); + *predicted_bits = VP8LHistogramEstimateBitsBulk(histo_set->histograms[1]); + VP8LFreeHistogramSet(histo_set); + return 1; +} + +static int AnalyzeAndInit(VP8LEncoder* const enc, WebPImageHint image_hint) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const int pix_cnt = width * height; + // 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_palette_ = + AnalyzeAndCreatePalette(pic, enc->palette_, &enc->palette_size_); + + if (image_hint == WEBP_HINT_GRAPH) { + if (enc->use_palette_ && enc->palette_size_ < MAX_COLORS_FOR_GRAPH) { + enc->use_palette_ = 0; + } + } + + if (!enc->use_palette_) { + if (image_hint == WEBP_HINT_PHOTO) { + enc->use_predict_ = 1; + enc->use_cross_color_ = 1; + } else { + double non_pred_entropy, pred_entropy; + if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, + &non_pred_entropy, &pred_entropy)) { + return 0; + } + if (pred_entropy < 0.95 * non_pred_entropy) { + enc->use_predict_ = 1; + enc->use_cross_color_ = 1; + } + } + } + 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; + } + } + VP8LWriteBits(bw, 4, codes_to_store - 4); + for (i = 0; i < codes_to_store; ++i) { + VP8LWriteBits(bw, 3, code_length_bitdepth[kStorageOrder[i]]); + } +} + +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; + VP8LWriteBits(bw, huffman_code->code_lengths[ix], huffman_code->codes[ix]); + switch (ix) { + case 16: + VP8LWriteBits(bw, 2, extra_bits); + break; + case 17: + VP8LWriteBits(bw, 3, extra_bits); + break; + case 18: + VP8LWriteBits(bw, 7, extra_bits); + 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; + + VP8LWriteBits(bw, 1, 0); + 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; + VP8LWriteBits(bw, 1, write_trimmed_length); + if (write_trimmed_length) { + const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); + const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; + VP8LWriteBits(bw, 3, nbitpairs - 1); + assert(trimmed_length >= 2); + VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 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 + VP8LWriteBits(bw, 4, 0x01); + } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { + VP8LWriteBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. + VP8LWriteBits(bw, 1, count - 1); + if (symbols[0] <= 1) { + VP8LWriteBits(bw, 1, 0); // Code bit for small (1 bit) symbol value. + VP8LWriteBits(bw, 1, symbols[0]); + } else { + VP8LWriteBits(bw, 1, 1); + VP8LWriteBits(bw, 8, symbols[0]); + } + if (count == 2) { + VP8LWriteBits(bw, 8, symbols[1]); + } + } else { + StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code); + } +} + +static 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]; + VP8LWriteBits(bw, depth, symbol); +} + +static WebPEncodingError StoreImageToBitMask( + VP8LBitWriter* const bw, int width, int histo_bits, + VP8LBackwardRefs* const refs, + const uint16_t* histogram_symbols, + const HuffmanTreeCode* const huffman_codes) { + // x and y trace the position in the image. + int x = 0; + int y = 0; + const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + const int histogram_ix = histogram_symbols[histo_bits ? + (y >> histo_bits) * histo_xsize + + (x >> histo_bits) : 0]; + const HuffmanTreeCode* const codes = huffman_codes + 5 * histogram_ix; + if (PixOrCopyIsCacheIdx(v)) { + const int code = PixOrCopyCacheIdx(v); + const int literal_ix = 256 + NUM_LENGTH_CODES + code; + WriteHuffmanCode(bw, codes, literal_ix); + } else 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 { + int bits, n_bits; + int code, distance; + + VP8LPrefixEncode(v->len, &code, &n_bits, &bits); + WriteHuffmanCode(bw, codes, 256 + code); + VP8LWriteBits(bw, n_bits, bits); + + distance = PixOrCopyDistance(v); + VP8LPrefixEncode(distance, &code, &n_bits, &bits); + WriteHuffmanCode(bw, codes + 4, code); + VP8LWriteBits(bw, n_bits, 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 + VP8LHistogramSet* const histogram_image = VP8LAllocateHistogramSet(1, 0); + HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( + 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); + if (histogram_image == NULL || huff_tree == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // Calculate backward references from ARGB image. + refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, 1, + hash_chain, refs_array); + if (refs == 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. + VP8LWriteBits(bw, 1, 0); + + // 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 cache_bits, + int histogram_bits) { + WebPEncodingError err = VP8_ENC_OK; + const int use_2d_locality = 1; + const int use_color_cache = (cache_bits > 0); + const uint32_t histogram_image_xysize = + VP8LSubSampleSize(width, histogram_bits) * + VP8LSubSampleSize(height, histogram_bits); + VP8LHistogramSet* histogram_image = + VP8LAllocateHistogramSet(histogram_image_xysize, cache_bits); + 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); + + VP8LBackwardRefsInit(&refs, refs_array[0].block_size_); + if (histogram_image == NULL || histogram_symbols == NULL) { + VP8LFreeHistogramSet(histogram_image); + WebPSafeFree(histogram_symbols); + return 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. + best_refs = VP8LGetBackwardReferences(width, height, argb, quality, + cache_bits, use_2d_locality, + hash_chain, refs_array); + if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) { + goto Error; + } + // Build histogram image and symbols from backward references. + if (!VP8LGetHistoImageSymbols(width, height, &refs, + quality, histogram_bits, cache_bits, + histogram_image, + histogram_symbols)) { + 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)); + if (huffman_codes == NULL || + !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { + goto Error; + } + // Free combined histograms. + VP8LFreeHistogramSet(histogram_image); + histogram_image = NULL; + + // Color Cache parameters. + VP8LWriteBits(bw, 1, use_color_cache); + if (use_color_cache) { + VP8LWriteBits(bw, 4, cache_bits); + } + + // Huffman image + meta huffman. + { + const int write_histogram_image = (histogram_image_size > 1); + VP8LWriteBits(bw, 1, write_histogram_image); + 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) goto Error; + for (i = 0; i < histogram_image_xysize; ++i) { + const int symbol_index = histogram_symbols[i] & 0xffff; + histogram_argb[i] = 0xff000000 | (symbol_index << 8); + if (symbol_index >= max_index) { + max_index = symbol_index + 1; + } + } + histogram_image_size = max_index; + + VP8LWriteBits(bw, 3, histogram_bits - 2); + 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) 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) 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); + } + } + + // Store actual literals. + err = StoreImageToBitMask(bw, width, histogram_bits, &refs, + histogram_symbols, huffman_codes); + + Error: + WebPSafeFree(tokens); + WebPSafeFree(huff_tree); + VP8LFreeHistogramSet(histogram_image); + VP8LBackwardRefsClear(&refs); + if (huffman_codes != NULL) { + WebPSafeFree(huffman_codes->codes); + WebPSafeFree(huffman_codes); + } + WebPSafeFree(histogram_symbols); + return err; +} + +// ----------------------------------------------------------------------------- +// Transforms + +// Check if it would be a good idea to subtract green from red and blue. We +// only impact entropy in red/blue components, don't bother to look at others. +static WebPEncodingError EvalAndApplySubtractGreen(VP8LEncoder* const enc, + int width, int height, + VP8LBitWriter* const bw) { + if (!enc->use_palette_) { + int i; + const uint32_t* const argb = enc->argb_; + double bit_cost_before, bit_cost_after; + // Allocate histogram with cache_bits = 1. + VP8LHistogram* const histo = VP8LAllocateHistogram(1); + if (histo == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; + for (i = 0; i < width * height; ++i) { + const uint32_t c = argb[i]; + ++histo->red_[(c >> 16) & 0xff]; + ++histo->blue_[(c >> 0) & 0xff]; + } + bit_cost_before = VP8LHistogramEstimateBits(histo); + + VP8LHistogramInit(histo, 1); + for (i = 0; i < width * height; ++i) { + const uint32_t c = argb[i]; + const int green = (c >> 8) & 0xff; + ++histo->red_[((c >> 16) - green) & 0xff]; + ++histo->blue_[((c >> 0) - green) & 0xff]; + } + bit_cost_after = VP8LHistogramEstimateBits(histo); + VP8LFreeHistogram(histo); + + // Check if subtracting green yields low entropy. + enc->use_subtract_green_ = (bit_cost_after < bit_cost_before); + if (enc->use_subtract_green_) { + VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); + VP8LWriteBits(bw, 2, SUBTRACT_GREEN); + VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); + } + } + return VP8_ENC_OK; +} + +static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc, + int width, int height, int quality, + 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); + + VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_, + enc->transform_data_); + VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); + VP8LWriteBits(bw, 2, PREDICTOR_TRANSFORM); + assert(pred_bits >= 2); + VP8LWriteBits(bw, 3, pred_bits - 2); + 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_); + VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); + VP8LWriteBits(bw, 2, CROSS_COLOR_TRANSFORM); + assert(ccolor_transform_bits >= 2); + VP8LWriteBits(bw, 3, ccolor_transform_bits - 2); + 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); + + VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, width); + VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, height); + return !bw->error_; +} + +static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { + VP8LWriteBits(bw, 1, has_alpha); + VP8LWriteBits(bw, VP8L_VERSION_BITS, VP8L_VERSION); + 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; +} + +// ----------------------------------------------------------------------------- + +// Allocates the memory for argb (W x H) buffer, 2 rows of context for +// prediction and transform data. +static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, + int width, int height) { + WebPEncodingError err = VP8_ENC_OK; + const int tile_size = 1 << enc->transform_bits_; + const uint64_t image_size = width * height; + const uint64_t argb_scratch_size = tile_size * width + width; + const int transform_data_size = + VP8LSubSampleSize(width, enc->transform_bits_) * + VP8LSubSampleSize(height, enc->transform_bits_); + const uint64_t total_size = + image_size + argb_scratch_size + (uint64_t)transform_data_size; + uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem)); + if (mem == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + enc->argb_ = mem; + mem += image_size; + enc->argb_scratch_ = mem; + mem += argb_scratch_size; + enc->transform_data_ = mem; + enc->current_width_ = width; + + Error: + return err; +} + +static void ApplyPalette(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 xbits, uint8_t* row) { + int i, x, y; + int use_LUT = 1; + 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; + row[x] = inv_palette[color]; + } + VP8LBundleColorMap(row, width, xbits, dst); + src += src_stride; + dst += dst_stride; + } + } else { + // Use 1 pixel cache for ARGB pixels. + uint32_t last_pix = palette[0]; + int last_idx = 0; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const uint32_t pix = src[x]; + if (pix != last_pix) { + for (i = 0; i < palette_size; ++i) { + if (pix == palette[i]) { + last_idx = i; + last_pix = pix; + break; + } + } + } + row[x] = last_idx; + } + VP8LBundleColorMap(row, width, xbits, dst); + src += src_stride; + dst += dst_stride; + } + } +} + +// Note: Expects "enc->palette_" to be set properly. +// Also, "enc->palette_" will be modified after this call and should not be used +// later. +static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, + VP8LEncoder* const enc, int quality) { + WebPEncodingError err = VP8_ENC_OK; + int i; + const WebPPicture* const pic = enc->pic_; + uint32_t* src = pic->argb; + uint32_t* dst; + const int width = pic->width; + const int height = pic->height; + uint32_t* const palette = enc->palette_; + const int palette_size = enc->palette_size_; + uint8_t* row = NULL; + 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) goto Error; + dst = enc->argb_; + + row = (uint8_t*)WebPSafeMalloc(width, sizeof(*row)); + if (row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; + + ApplyPalette(src, dst, pic->argb_stride, enc->current_width_, + palette, palette_size, width, height, xbits, row); + + // Save palette to bitstream. + VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); + VP8LWriteBits(bw, 2, COLOR_INDEXING_TRANSFORM); + assert(palette_size >= 1); + VP8LWriteBits(bw, 8, palette_size - 1); + for (i = palette_size - 1; i >= 1; --i) { + palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); + } + err = EncodeImageNoHuffman(bw, palette, &enc->hash_chain_, enc->refs_, + palette_size, 1, quality); + + Error: + WebPSafeFree(row); + return err; +} + +// ----------------------------------------------------------------------------- + +static int GetHistoBits(int method, int use_palette, int width, int height) { + const int hist_size = VP8LGetHistogramSize(MAX_COLOR_CACHE_BITS); + // 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 ((uint64_t)huff_image_size * hist_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 GetCacheBits(float quality) { + return (quality <= 25.f) ? 0 : 7; +} + +static void FinishEncParams(VP8LEncoder* const enc) { + const WebPConfig* const config = enc->config_; + const WebPPicture* const pic = enc->pic_; + const int method = config->method; + const float quality = config->quality; + const int use_palette = enc->use_palette_; + enc->histo_bits_ = GetHistoBits(method, use_palette, pic->width, pic->height); + enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); + enc->cache_bits_ = GetCacheBits(quality); +} + +// ----------------------------------------------------------------------------- +// 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; + + VP8LDspInit(); + + return enc; +} + +static void VP8LEncoderDelete(VP8LEncoder* enc) { + if (enc != NULL) { + VP8LHashChainClear(&enc->hash_chain_); + VP8LBackwardRefsClear(&enc->refs_[0]); + VP8LBackwardRefsClear(&enc->refs_[1]); + WebPSafeFree(enc->argb_); + WebPSafeFree(enc); + } +} + +// ----------------------------------------------------------------------------- +// Main call + +WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, + VP8LBitWriter* const bw) { + WebPEncodingError err = VP8_ENC_OK; + const int quality = (int)config->quality; + const int width = picture->width; + const int height = picture->height; + VP8LEncoder* const enc = VP8LEncoderNew(config, picture); + const size_t byte_position = VP8LBitWriterNumBytes(bw); + + if (enc == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + // --------------------------------------------------------------------------- + // Analyze image (entropy, num_palettes etc) + + if (!AnalyzeAndInit(enc, config->image_hint)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + + FinishEncParams(enc); + + if (enc->use_palette_) { + err = EncodePalette(bw, enc, quality); + if (err != VP8_ENC_OK) goto Error; + // Color cache is disabled for palette. + enc->cache_bits_ = 0; + } + + // In case image is not packed. + if (enc->argb_ == NULL) { + int y; + err = AllocateTransformBuffer(enc, width, height); + if (err != VP8_ENC_OK) goto Error; + for (y = 0; y < height; ++y) { + memcpy(enc->argb_ + y * width, + picture->argb + y * picture->argb_stride, + width * sizeof(*enc->argb_)); + } + enc->current_width_ = width; + } + + // --------------------------------------------------------------------------- + // Apply transforms and write transform data. + + err = EvalAndApplySubtractGreen(enc, enc->current_width_, height, bw); + if (err != VP8_ENC_OK) goto Error; + + if (enc->use_predict_) { + err = ApplyPredictFilter(enc, enc->current_width_, height, quality, 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; + } + + VP8LWriteBits(bw, 1, !TRANSFORM_PRESENT); // No more transforms. + + // --------------------------------------------------------------------------- + // Estimate the color cache size. + + if (enc->cache_bits_ > 0) { + if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_, + height, quality, &enc->hash_chain_, + &enc->refs_[0], &enc->cache_bits_)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + } + + // --------------------------------------------------------------------------- + // Encode and write the transformed image. + + err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, + enc->current_width_, height, quality, + enc->cache_bits_, enc->histo_bits_); + 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); + } + + 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); + 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; + VP8LBitWriterDestroy(&bw); + if (err != VP8_ENC_OK) { + WebPEncodingSetError(picture, err); + return 0; + } + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/enc/vp8li.h b/TMessagesProj/jni/libwebp/enc/vp8li.h new file mode 100644 index 00000000..6b6db127 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/vp8li.h @@ -0,0 +1,77 @@ +// 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. + 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. +WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, + VP8LBitWriter* const bw); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_ENC_VP8LI_H_ */ diff --git a/TMessagesProj/jni/libwebp/enc/webpenc.c b/TMessagesProj/jni/libwebp/enc/webpenc.c new file mode 100644 index 00000000..0cb83f12 --- /dev/null +++ b/TMessagesProj/jni/libwebp/enc/webpenc.c @@ -0,0 +1,382 @@ +// 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 +#include +#include +#include + +#include "./vp8enci.h" +#include "./vp8li.h" +#include "./cost.h" +#include "../utils/utils.h" + +// #define PRINT_MEMORY_INFO + +#ifdef PRINT_MEMORY_INFO +#include +#endif + +//------------------------------------------------------------------------------ + +int WebPGetEncoderVersion(void) { + return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION; +} + +//------------------------------------------------------------------------------ +// VP8Encoder +//------------------------------------------------------------------------------ + +static void ResetSegmentHeader(VP8Encoder* const enc) { + VP8SegmentHeader* 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) { + VP8FilterHeader* 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-score i4/16 | | | 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. + + 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 +// VP8Proba: 18352 +// LFStats: 2048 +// Picture size (yuv): 419328 + +static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, + WebPPicture* const picture) { + 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(uint8_t); + const int top_stride = mb_w * 16; + const size_t nz_size = (mb_w + 1) * sizeof(uint32_t) + ALIGN_CST; + const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo); + const size_t samples_size = 2 * top_stride * sizeof(uint8_t) // top-luma/u/v + + ALIGN_CST; // align all + const size_t lf_stats_size = + config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0; + VP8Encoder* enc; + uint8_t* mem; + const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct + + 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(VP8Encoder) + 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" + " VP8Proba: %ld\n" + " LFStats: %ld\n", + sizeof(VP8EncIterator), sizeof(VP8ModeScore), + sizeof(VP8SegmentInfo), sizeof(VP8Proba), + 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*)DO_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_w * preds_h * sizeof(uint8_t); + enc->nz_ = 1 + (uint32_t*)DO_ALIGN(mem); + mem += nz_size; + enc->lf_stats_ = lf_stats_size ? (LFStats*)DO_ALIGN(mem) : NULL; + mem += lf_stats_size; + + // top samples (all 16-aligned) + mem = (uint8_t*)DO_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); + VP8GetResidualCostInit(); + VP8SetResidualCoeffsInit(); + 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 (pic->y == NULL || pic->u == NULL || pic->v == NULL) { + // Make sure we have YUVA samples. + if (config->preprocessing & 4) { +#if WEBP_ENCODER_ABI_VERSION > 0x0204 + if (!WebPPictureSmartARGBToYUVA(pic)) { + return 0; + } +#endif + } 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; + } + + ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. + } + + return ok; +} diff --git a/TMessagesProj/jni/libwebp/utils/bit_reader.c b/TMessagesProj/jni/libwebp/utils/bit_reader.c new file mode 100644 index 00000000..64503e6b --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/bit_reader.c @@ -0,0 +1,210 @@ +// 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" + +//------------------------------------------------------------------------------ +// VP8BitReader + +void VP8InitBitReader(VP8BitReader* const br, + const uint8_t* const start, const uint8_t* const end) { + assert(br != NULL); + assert(start != NULL); + assert(start <= end); + br->range_ = 255 - 1; + br->buf_ = start; + br->buf_end_ = end; + br->value_ = 0; + br->bits_ = -8; // to load the very first 8bits + br->eof_ = 0; + VP8LoadNewBytes(br); +} + +void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { + if (br->buf_ != NULL) { + br->buf_ += offset; + br->buf_end_ += 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 range_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; + } +} + +//------------------------------------------------------------------------------ +// 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(WEBP_FORCE_ALIGNED) && \ + (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \ + defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64)) +#define VP8L_USE_UNALIGNED_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; + br->error_ = 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->error_ = (br->pos_ > br->len_); + br->eos_ = br->error_ || VP8LIsEndOfStream(br); +} + +// 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; + } + br->eos_ = VP8LIsEndOfStream(br); +} + +void VP8LDoFillBitWindow(VP8LBitReader* const br) { + assert(br->bit_pos_ >= VP8L_WBITS); + // TODO(jzern): given the fixed read size it may be possible to force + // alignment in this block. +#if defined(VP8L_USE_UNALIGNED_LOAD) + if (br->pos_ + sizeof(br->val_) < br->len_) { + br->val_ >>= VP8L_WBITS; + br->bit_pos_ -= VP8L_WBITS; + // The expression below needs a little-endian arch to work correctly. + // This gives a large speedup for decoding speed. + br->val_ |= (vp8l_val_t)*(const uint32_t*)(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 = + (uint32_t)(br->val_ >> br->bit_pos_) & kBitMask[n_bits]; + const int new_bits = br->bit_pos_ + n_bits; + br->bit_pos_ = new_bits; + ShiftBytes(br); + return val; + } else { + br->error_ = 1; + return 0; + } +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/utils/bit_reader.h b/TMessagesProj/jni/libwebp/utils/bit_reader.h new file mode 100644 index 00000000..f569734f --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/bit_reader.h @@ -0,0 +1,169 @@ +// 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 +#ifdef _MSC_VER +#include // _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. + +#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(__mips__) // MIPS +#define BITS 24 +#else // reasonable default +#define BITS 24 // TODO(skal): test aarch64 and find the proper BITS value. +#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 + 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, const uint8_t* const end); + +// 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. +#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_; // bitstream is finished + int error_; // an error occurred (buffer overflow attempt...) +} 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_); +} + +// 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->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/TMessagesProj/jni/libwebp/utils/bit_reader_inl.h b/TMessagesProj/jni/libwebp/utils/bit_reader_inl.h new file mode 100644 index 00000000..81427c62 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/bit_reader_inl.h @@ -0,0 +1,172 @@ +// 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 // 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 range_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_INLINE void VP8LoadNewBytes(VP8BitReader* const br) { + assert(br != NULL && br->buf_ != NULL); + // Read 'BITS' bits at a time if possible. + if (br->buf_ + sizeof(lbit_t) <= br->buf_end_) { + // 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/TMessagesProj/jni/libwebp/utils/bit_writer.c b/TMessagesProj/jni/libwebp/utils/bit_writer.c new file mode 100644 index 00000000..9875ca66 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/bit_writer.c @@ -0,0 +1,307 @@ +// 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 +#include // for memcpy() +#include + +#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 VP8PutValue(VP8BitWriter* const bw, int value, int nb_bits) { + int mask; + for (mask = 1 << (nb_bits - 1); mask; mask >>= 1) + VP8PutBitUniform(bw, value & mask); +} + +void VP8PutSignedValue(VP8BitWriter* const bw, int value, int nb_bits) { + if (!VP8PutBitUniform(bw, value != 0)) + return; + if (value < 0) { + VP8PutValue(bw, ((-value) << 1) | 1, nb_bits + 1); + } else { + VP8PutValue(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) { + VP8PutValue(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) + +#define VP8L_WRITER_BYTES ((int)sizeof(vp8l_wtype_t)) +#define VP8L_WRITER_BITS (VP8L_WRITER_BYTES * 8) +#define VP8L_WRITER_MAX_BITS (8 * (int)sizeof(vp8l_atype_t)) + +// 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 VP8LBitWriterDestroy(VP8LBitWriter* const bw) { + if (bw != NULL) { + WebPSafeFree(bw->buf_); + memset(bw, 0, sizeof(*bw)); + } +} + +void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits) { + assert(n_bits <= 32); + // That's the max we can handle: + assert(bw->used_ + n_bits <= 2 * VP8L_WRITER_MAX_BITS); + if (n_bits > 0) { + // Local field copy. + 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); + } + } + // 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; + } + // Eventually, insert new 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/TMessagesProj/jni/libwebp/utils/bit_writer.h b/TMessagesProj/jni/libwebp/utils/bit_writer.h new file mode 100644 index 00000000..c80d22ae --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/bit_writer.h @@ -0,0 +1,120 @@ +// 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 VP8PutValue(VP8BitWriter* const bw, int value, int nb_bits); +void VP8PutSignedValue(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 +#else +typedef uint32_t vp8l_atype_t; +typedef uint16_t vp8l_wtype_t; +#define WSWAP HToLE16 +#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); +} + +uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); + +// Returns 0 in case of memory allocation error. +int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); + +void VP8LBitWriterDestroy(VP8LBitWriter* const bw); + +// 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. +void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_BIT_WRITER_H_ */ diff --git a/TMessagesProj/jni/libwebp/utils/color_cache.c b/TMessagesProj/jni/libwebp/utils/color_cache.c new file mode 100644 index 00000000..8a88f08b --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/color_cache.c @@ -0,0 +1,39 @@ +// 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 +#include +#include "./color_cache.h" +#include "../utils/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; + return 1; +} + +void VP8LColorCacheClear(VP8LColorCache* const cc) { + if (cc != NULL) { + WebPSafeFree(cc->colors_); + cc->colors_ = NULL; + } +} + diff --git a/TMessagesProj/jni/libwebp/utils/color_cache.h b/TMessagesProj/jni/libwebp/utils/color_cache.h new file mode 100644 index 00000000..0f824ed4 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/color_cache.h @@ -0,0 +1,70 @@ +// 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. +} VP8LColorCache; + +static const uint32_t kHashMul = 0x1e35a7bd; + +static WEBP_INLINE uint32_t VP8LColorCacheLookup( + const VP8LColorCache* const cc, uint32_t key) { + assert(key <= (~0U >> cc->hash_shift_)); + return cc->colors_[key]; +} + +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); + +// 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/TMessagesProj/jni/libwebp/utils/endian_inl.h b/TMessagesProj/jni/libwebp/utils/endian_inl.h new file mode 100644 index 00000000..cd56c37f --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/endian_inl.h @@ -0,0 +1,100 @@ +// 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) +// clang-3.3 and gcc-4.3 have builtin functions for swap32/swap64 +#if LOCAL_GCC_PREREQ(4,3) || LOCAL_CLANG_PREREQ(3,3) +#define HAVE_BUILTIN_BSWAP32 +#define HAVE_BUILTIN_BSWAP64 +#endif +// clang-3.3 and gcc-4.8 have a builtin function for swap16 +#if LOCAL_GCC_PREREQ(4,8) || LOCAL_CLANG_PREREQ(3,3) +#define HAVE_BUILTIN_BSWAP16 +#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/TMessagesProj/jni/libwebp/utils/filters.c b/TMessagesProj/jni/libwebp/utils/filters.c new file mode 100644 index 00000000..2d15bd0e --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/filters.c @@ -0,0 +1,266 @@ +// 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 "./filters.h" +#include +#include +#include + +//------------------------------------------------------------------------------ +// 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; + } +} + +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 HorizontalUnfilter(int width, int height, int stride, int row, + int num_rows, uint8_t* data) { + DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); +} + +//------------------------------------------------------------------------------ +// 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; + } +} + +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 VerticalUnfilter(int width, int height, int stride, int row, + int num_rows, uint8_t* data) { + DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); +} + +//------------------------------------------------------------------------------ +// 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; + } +} + +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 GradientUnfilter(int width, int height, int stride, int row, + int num_rows, uint8_t* data) { + DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); +} + +#undef SANITY_CHECK + +// ----------------------------------------------------------------------------- +// 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) + +WEBP_FILTER_TYPE EstimateBestFilter(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 + +//------------------------------------------------------------------------------ + +const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST] = { + NULL, // WEBP_FILTER_NONE + HorizontalFilter, // WEBP_FILTER_HORIZONTAL + VerticalFilter, // WEBP_FILTER_VERTICAL + GradientFilter // WEBP_FILTER_GRADIENT +}; + +const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST] = { + NULL, // WEBP_FILTER_NONE + HorizontalUnfilter, // WEBP_FILTER_HORIZONTAL + VerticalUnfilter, // WEBP_FILTER_VERTICAL + GradientUnfilter // WEBP_FILTER_GRADIENT +}; + +//------------------------------------------------------------------------------ + diff --git a/TMessagesProj/jni/libwebp/utils/filters.h b/TMessagesProj/jni/libwebp/utils/filters.h new file mode 100644 index 00000000..dde39cb5 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/filters.h @@ -0,0 +1,59 @@ +// 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" + +#ifdef __cplusplus +extern "C" { +#endif + +// Filters. +typedef enum { + 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, + WEBP_FILTER_FAST +} WEBP_FILTER_TYPE; + +typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height, + int stride, uint8_t* out); +typedef void (*WebPUnfilterFunc)(int width, int height, int stride, + int row, int num_rows, uint8_t* data); + +// 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 const 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 const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST]; + +// Fast estimate of a potentially good filter. +WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data, + int width, int height, int stride); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_FILTERS_H_ */ diff --git a/TMessagesProj/jni/libwebp/utils/huffman.c b/TMessagesProj/jni/libwebp/utils/huffman.c new file mode 100644 index 00000000..c4c16d9e --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/huffman.c @@ -0,0 +1,319 @@ +// 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 +#include +#include +#include "./huffman.h" +#include "../utils/utils.h" +#include "../webp/format_constants.h" + +// Uncomment the following to use look-up table for ReverseBits() +// (might be faster on some platform) +// #define USE_LUT_REVERSE_BITS + +// Huffman data read via DecodeImageStream is represented in two (red and green) +// bytes. +#define MAX_HTREE_GROUPS 0x10000 +#define NON_EXISTENT_SYMBOL (-1) + +static void TreeNodeInit(HuffmanTreeNode* const node) { + node->children_ = -1; // means: 'unassigned so far' +} + +static int NodeIsEmpty(const HuffmanTreeNode* const node) { + return (node->children_ < 0); +} + +static int IsFull(const HuffmanTree* const tree) { + return (tree->num_nodes_ == tree->max_nodes_); +} + +static void AssignChildren(HuffmanTree* const tree, + HuffmanTreeNode* const node) { + HuffmanTreeNode* const children = tree->root_ + tree->num_nodes_; + node->children_ = (int)(children - node); + assert(children - node == (int)(children - node)); + tree->num_nodes_ += 2; + TreeNodeInit(children + 0); + TreeNodeInit(children + 1); +} + +// A Huffman tree is a full binary tree; and in a full binary tree with L +// leaves, the total number of nodes N = 2 * L - 1. +static int HuffmanTreeMaxNodes(int num_leaves) { + return (2 * num_leaves - 1); +} + +static int HuffmanTreeAllocate(HuffmanTree* const tree, int num_nodes) { + assert(tree != NULL); + tree->root_ = + (HuffmanTreeNode*)WebPSafeMalloc(num_nodes, sizeof(*tree->root_)); + return (tree->root_ != NULL); +} + +static int TreeInit(HuffmanTree* const tree, int num_leaves) { + assert(tree != NULL); + if (num_leaves == 0) return 0; + tree->max_nodes_ = HuffmanTreeMaxNodes(num_leaves); + assert(tree->max_nodes_ < (1 << 16)); // limit for the lut_jump_ table + if (!HuffmanTreeAllocate(tree, tree->max_nodes_)) return 0; + TreeNodeInit(tree->root_); // Initialize root. + tree->num_nodes_ = 1; + memset(tree->lut_bits_, 255, sizeof(tree->lut_bits_)); + memset(tree->lut_jump_, 0, sizeof(tree->lut_jump_)); + return 1; +} + +void VP8LHuffmanTreeFree(HuffmanTree* const tree) { + if (tree != NULL) { + WebPSafeFree(tree->root_); + tree->root_ = NULL; + tree->max_nodes_ = 0; + tree->num_nodes_ = 0; + } +} + +HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) { + HTreeGroup* const htree_groups = + (HTreeGroup*)WebPSafeCalloc(num_htree_groups, sizeof(*htree_groups)); + assert(num_htree_groups <= MAX_HTREE_GROUPS); + if (htree_groups == NULL) { + return NULL; + } + return htree_groups; +} + +void VP8LHtreeGroupsFree(HTreeGroup* htree_groups, int num_htree_groups) { + if (htree_groups != NULL) { + int i, j; + for (i = 0; i < num_htree_groups; ++i) { + HuffmanTree* const htrees = htree_groups[i].htrees_; + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + VP8LHuffmanTreeFree(&htrees[j]); + } + } + WebPSafeFree(htree_groups); + } +} + +int VP8LHuffmanCodeLengthsToCodes( + const int* const code_lengths, int code_lengths_size, + int* const huff_codes) { + int symbol; + int code_len; + int code_length_hist[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; + int curr_code; + int next_codes[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 }; + int max_code_length = 0; + + assert(code_lengths != NULL); + assert(code_lengths_size > 0); + assert(huff_codes != NULL); + + // Calculate max code length. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + if (code_lengths[symbol] > max_code_length) { + max_code_length = code_lengths[symbol]; + } + } + if (max_code_length > MAX_ALLOWED_CODE_LENGTH) return 0; + + // Calculate code length histogram. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + ++code_length_hist[code_lengths[symbol]]; + } + code_length_hist[0] = 0; + + // Calculate the initial values of 'next_codes' for each code length. + // next_codes[code_len] denotes the code to be assigned to the next symbol + // of code length 'code_len'. + curr_code = 0; + next_codes[0] = -1; // Unused, as code length = 0 implies code doesn't exist. + for (code_len = 1; code_len <= max_code_length; ++code_len) { + curr_code = (curr_code + code_length_hist[code_len - 1]) << 1; + next_codes[code_len] = curr_code; + } + + // Get symbols. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + if (code_lengths[symbol] > 0) { + huff_codes[symbol] = next_codes[code_lengths[symbol]]++; + } else { + huff_codes[symbol] = NON_EXISTENT_SYMBOL; + } + } + return 1; +} + +#ifndef USE_LUT_REVERSE_BITS + +static int ReverseBitsShort(int bits, int num_bits) { + int retval = 0; + int i; + assert(num_bits <= 8); // Not a hard requirement, just for coherency. + for (i = 0; i < num_bits; ++i) { + retval <<= 1; + retval |= bits & 1; + bits >>= 1; + } + return retval; +} + +#else + +static const uint8_t kReversedBits[16] = { // Pre-reversed 4-bit values. + 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf +}; + +static int ReverseBitsShort(int bits, int num_bits) { + const uint8_t v = (kReversedBits[bits & 0xf] << 4) | kReversedBits[bits >> 4]; + assert(num_bits <= 8); + return v >> (8 - num_bits); +} + +#endif + +static int TreeAddSymbol(HuffmanTree* const tree, + int symbol, int code, int code_length) { + int step = HUFF_LUT_BITS; + int base_code; + HuffmanTreeNode* node = tree->root_; + const HuffmanTreeNode* const max_node = tree->root_ + tree->max_nodes_; + assert(symbol == (int16_t)symbol); + if (code_length <= HUFF_LUT_BITS) { + int i; + base_code = ReverseBitsShort(code, code_length); + for (i = 0; i < (1 << (HUFF_LUT_BITS - code_length)); ++i) { + const int idx = base_code | (i << code_length); + tree->lut_symbol_[idx] = (int16_t)symbol; + tree->lut_bits_[idx] = code_length; + } + } else { + base_code = ReverseBitsShort((code >> (code_length - HUFF_LUT_BITS)), + HUFF_LUT_BITS); + } + while (code_length-- > 0) { + if (node >= max_node) { + return 0; + } + if (NodeIsEmpty(node)) { + if (IsFull(tree)) return 0; // error: too many symbols. + AssignChildren(tree, node); + } else if (!HuffmanTreeNodeIsNotLeaf(node)) { + return 0; // leaf is already occupied. + } + node += node->children_ + ((code >> code_length) & 1); + if (--step == 0) { + tree->lut_jump_[base_code] = (int16_t)(node - tree->root_); + } + } + if (NodeIsEmpty(node)) { + node->children_ = 0; // turn newly created node into a leaf. + } else if (HuffmanTreeNodeIsNotLeaf(node)) { + return 0; // trying to assign a symbol to already used code. + } + node->symbol_ = symbol; // Add symbol in this node. + return 1; +} + +int VP8LHuffmanTreeBuildImplicit(HuffmanTree* const tree, + const int* const code_lengths, + int* const codes, + int code_lengths_size) { + int symbol; + int num_symbols = 0; + int root_symbol = 0; + + assert(tree != NULL); + assert(code_lengths != NULL); + + // Find out number of symbols and the root symbol. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + if (code_lengths[symbol] > 0) { + // Note: code length = 0 indicates non-existent symbol. + ++num_symbols; + root_symbol = symbol; + } + } + + // Initialize the tree. Will fail for num_symbols = 0 + if (!TreeInit(tree, num_symbols)) return 0; + + // Build tree. + if (num_symbols == 1) { // Trivial case. + const int max_symbol = code_lengths_size; + if (root_symbol < 0 || root_symbol >= max_symbol) { + VP8LHuffmanTreeFree(tree); + return 0; + } + return TreeAddSymbol(tree, root_symbol, 0, 0); + } else { // Normal case. + int ok = 0; + memset(codes, 0, code_lengths_size * sizeof(*codes)); + + if (!VP8LHuffmanCodeLengthsToCodes(code_lengths, code_lengths_size, + codes)) { + goto End; + } + + // Add symbols one-by-one. + for (symbol = 0; symbol < code_lengths_size; ++symbol) { + if (code_lengths[symbol] > 0) { + if (!TreeAddSymbol(tree, symbol, codes[symbol], + code_lengths[symbol])) { + goto End; + } + } + } + ok = 1; + End: + ok = ok && IsFull(tree); + if (!ok) VP8LHuffmanTreeFree(tree); + return ok; + } +} + +int VP8LHuffmanTreeBuildExplicit(HuffmanTree* const tree, + const int* const code_lengths, + const int* const codes, + const int* const symbols, int max_symbol, + int num_symbols) { + int ok = 0; + int i; + assert(tree != NULL); + assert(code_lengths != NULL); + assert(codes != NULL); + assert(symbols != NULL); + + // Initialize the tree. Will fail if num_symbols = 0. + if (!TreeInit(tree, num_symbols)) return 0; + + // Add symbols one-by-one. + for (i = 0; i < num_symbols; ++i) { + if (codes[i] != NON_EXISTENT_SYMBOL) { + if (symbols[i] < 0 || symbols[i] >= max_symbol) { + goto End; + } + if (!TreeAddSymbol(tree, symbols[i], codes[i], code_lengths[i])) { + goto End; + } + } + } + ok = 1; + End: + ok = ok && IsFull(tree); + if (!ok) VP8LHuffmanTreeFree(tree); + return ok; +} diff --git a/TMessagesProj/jni/libwebp/utils/huffman.h b/TMessagesProj/jni/libwebp/utils/huffman.h new file mode 100644 index 00000000..624bc175 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/huffman.h @@ -0,0 +1,102 @@ +// 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 +#include "../webp/format_constants.h" +#include "../webp/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// A node of a Huffman tree. +typedef struct { + int symbol_; + int children_; // delta offset to both children (contiguous) or 0 if leaf. +} HuffmanTreeNode; + +// Huffman Tree. +#define HUFF_LUT_BITS 7 +#define HUFF_LUT (1U << HUFF_LUT_BITS) +typedef struct HuffmanTree HuffmanTree; +struct HuffmanTree { + // Fast lookup for short bit lengths. + uint8_t lut_bits_[HUFF_LUT]; + int16_t lut_symbol_[HUFF_LUT]; + int16_t lut_jump_[HUFF_LUT]; + // Complete tree for lookups. + HuffmanTreeNode* root_; // all the nodes, starting at root. + int max_nodes_; // max number of nodes + int num_nodes_; // number of currently occupied nodes +}; + +// Huffman Tree group. +typedef struct HTreeGroup HTreeGroup; +struct HTreeGroup { + HuffmanTree htrees_[HUFFMAN_CODES_PER_META_CODE]; +}; + +// Returns true if the given node is not a leaf of the Huffman tree. +static WEBP_INLINE int HuffmanTreeNodeIsNotLeaf( + const HuffmanTreeNode* const node) { + return node->children_; +} + +// Go down one level. Most critical function. 'right_child' must be 0 or 1. +static WEBP_INLINE const HuffmanTreeNode* HuffmanTreeNextNode( + const HuffmanTreeNode* node, int right_child) { + return node + node->children_ + right_child; +} + +// Releases the nodes of the Huffman tree. +// Note: It does NOT free 'tree' itself. +void VP8LHuffmanTreeFree(HuffmanTree* const tree); + +// 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* htree_groups, int num_htree_groups); + +// Builds Huffman tree assuming code lengths are implicitly in symbol order. +// The 'huff_codes' and 'code_lengths' are pre-allocated temporary memory +// buffers, used for creating the huffman tree. +// Returns false in case of error (invalid tree or memory error). +int VP8LHuffmanTreeBuildImplicit(HuffmanTree* const tree, + const int* const code_lengths, + int* const huff_codes, + int code_lengths_size); + +// Build a Huffman tree with explicitly given lists of code lengths, codes +// and symbols. Verifies that all symbols added are smaller than max_symbol. +// Returns false in case of an invalid symbol, invalid tree or memory error. +int VP8LHuffmanTreeBuildExplicit(HuffmanTree* const tree, + const int* const code_lengths, + const int* const codes, + const int* const symbols, int max_symbol, + int num_symbols); + +// Utility: converts Huffman code lengths to corresponding Huffman codes. +// 'huff_codes' should be pre-allocated. +// Returns false in case of error (memory allocation, invalid codes). +int VP8LHuffmanCodeLengthsToCodes(const int* const code_lengths, + int code_lengths_size, int* const huff_codes); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_UTILS_HUFFMAN_H_ diff --git a/TMessagesProj/jni/libwebp/utils/huffman_encode.c b/TMessagesProj/jni/libwebp/utils/huffman_encode.c new file mode 100644 index 00000000..6421c2be --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/huffman_encode.c @@ -0,0 +1,417 @@ +// 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 +#include +#include +#include "./huffman_encode.h" +#include "../utils/utils.h" +#include "../webp/format_constants.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/TMessagesProj/jni/libwebp/utils/huffman_encode.h b/TMessagesProj/jni/libwebp/utils/huffman_encode.h new file mode 100644 index 00000000..91aa18f4 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/huffman_encode.h @@ -0,0 +1,61 @@ +// 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. +// TODO(vikasa): Add comment for the fields of the Struct. +typedef struct { + uint32_t total_count_; + int 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/TMessagesProj/jni/libwebp/utils/quant_levels.c b/TMessagesProj/jni/libwebp/utils/quant_levels.c new file mode 100644 index 00000000..d7c8aab9 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/quant_levels.c @@ -0,0 +1,140 @@ +// 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 + +#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/TMessagesProj/jni/libwebp/utils/quant_levels.h b/TMessagesProj/jni/libwebp/utils/quant_levels.h new file mode 100644 index 00000000..1cb5a32c --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/quant_levels.h @@ -0,0 +1,36 @@ +// 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 + +#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/TMessagesProj/jni/libwebp/utils/quant_levels_dec.c b/TMessagesProj/jni/libwebp/utils/quant_levels_dec.c new file mode 100644 index 00000000..5b8b8b49 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/quant_levels_dec.c @@ -0,0 +1,279 @@ +// 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 // 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 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->width_; + } +} + +// 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_ += w; // 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(const uint8_t* const data, int size, + SmoothParams* const p) { + int i, last_level; + uint8_t used_levels[256] = { 0 }; + p->min_ = 255; + p->max_ = 0; + for (i = 0; i < size; ++i) { + const int v = data[i]; + if (v < p->min_) p->min_ = v; + if (v > p->max_) p->max_ = v; + used_levels[v] = 1; + } + // 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 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->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(data, width * height, 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 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, 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/TMessagesProj/jni/libwebp/utils/quant_levels_dec.h b/TMessagesProj/jni/libwebp/utils/quant_levels_dec.h new file mode 100644 index 00000000..9aab0680 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/quant_levels_dec.h @@ -0,0 +1,35 @@ +// 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. +// 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 strength); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */ diff --git a/TMessagesProj/jni/libwebp/utils/random.c b/TMessagesProj/jni/libwebp/utils/random.c new file mode 100644 index 00000000..24e96ad6 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/random.c @@ -0,0 +1,43 @@ +// 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 +#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/TMessagesProj/jni/libwebp/utils/random.h b/TMessagesProj/jni/libwebp/utils/random.h new file mode 100644 index 00000000..c392a615 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/random.h @@ -0,0 +1,63 @@ +// 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 +#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/TMessagesProj/jni/libwebp/utils/rescaler.c b/TMessagesProj/jni/libwebp/utils/rescaler.c new file mode 100644 index 00000000..fad9c6b0 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/rescaler.c @@ -0,0 +1,333 @@ +// 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 +#include +#include "./rescaler.h" +#include "../dsp/dsp.h" + +//------------------------------------------------------------------------------ +// Implementations of critical functions ImportRow / ExportRow + +void (*WebPRescalerImportRow)(WebPRescaler* const wrk, + const uint8_t* const src, int channel) = NULL; +void (*WebPRescalerExportRow)(WebPRescaler* const wrk, int x_out) = NULL; + +#define RFIX 30 +#define MULT_FIX(x, y) (((int64_t)(x) * (y) + (1 << (RFIX - 1))) >> RFIX) + +static void ImportRowC(WebPRescaler* const wrk, + const uint8_t* const src, int channel) { + const int x_stride = wrk->num_channels; + const int x_out_max = wrk->dst_width * wrk->num_channels; + int x_in = channel; + int x_out; + int accum = 0; + if (!wrk->x_expand) { + int sum = 0; + for (x_out = channel; x_out < x_out_max; x_out += x_stride) { + accum += wrk->x_add; + for (; accum > 0; accum -= wrk->x_sub) { + sum += src[x_in]; + x_in += x_stride; + } + { // Emit next horizontal pixel. + const int32_t base = src[x_in]; + const int32_t frac = base * (-accum); + x_in += x_stride; + wrk->frow[x_out] = (sum + base) * wrk->x_sub - frac; + // fresh fractional start for next pixel + sum = (int)MULT_FIX(frac, wrk->fx_scale); + } + } + } else { // simple bilinear interpolation + int left = src[channel], right = src[channel]; + for (x_out = channel; x_out < x_out_max; x_out += x_stride) { + if (accum < 0) { + left = right; + x_in += x_stride; + right = src[x_in]; + accum += wrk->x_add; + } + wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum; + accum -= wrk->x_sub; + } + } + // Accumulate the contribution of the new row. + for (x_out = channel; x_out < x_out_max; x_out += x_stride) { + wrk->irow[x_out] += wrk->frow[x_out]; + } +} + +static void ExportRowC(WebPRescaler* const wrk, int x_out) { + if (wrk->y_accum <= 0) { + uint8_t* const dst = wrk->dst; + int32_t* const irow = wrk->irow; + const int32_t* const frow = wrk->frow; + const int yscale = wrk->fy_scale * (-wrk->y_accum); + const int x_out_max = wrk->dst_width * wrk->num_channels; + for (; x_out < x_out_max; ++x_out) { + const int frac = (int)MULT_FIX(frow[x_out], yscale); + const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + dst[x_out] = (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; + irow[x_out] = frac; // new fractional start + } + wrk->y_accum += wrk->y_add; + wrk->dst += wrk->dst_stride; + } +} + +//------------------------------------------------------------------------------ +// MIPS version + +#if defined(WEBP_USE_MIPS32) + +static void ImportRowMIPS(WebPRescaler* const wrk, + const uint8_t* const src, int channel) { + 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; + int* frow = wrk->frow + channel; + int* irow = wrk->irow + channel; + const uint8_t* src1 = src + channel; + int temp1, temp2, temp3; + int base, frac, sum; + int accum, accum1; + const int x_stride1 = x_stride << 2; + int loop_c = x_out_max - channel; + + if (!wrk->x_expand) { + __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" + "blez %[accum], 3f \n\t" + "2: \n\t" + "lbu %[temp3], 0(%[src1]) \n\t" + "subu %[accum], %[accum], %[x_sub] \n\t" + "addu %[src1], %[src1], %[x_stride] \n\t" + "addu %[sum], %[sum], %[temp3] \n\t" + "bgtz %[accum], 2b \n\t" + "3: \n\t" + "lbu %[base], 0(%[src1]) \n\t" + "addu %[src1], %[src1], %[x_stride] \n\t" + "negu %[accum1], %[accum] \n\t" + "mul %[frac], %[base], %[accum1] \n\t" + "addu %[temp3], %[sum], %[base] \n\t" + "mul %[temp3], %[temp3], %[x_sub] \n\t" + "lw %[base], 0(%[irow]) \n\t" + "subu %[loop_c], %[loop_c], %[x_stride] \n\t" + "sll %[accum1], %[frac], 2 \n\t" + "mult %[temp1], %[temp2] \n\t" + "madd %[accum1], %[fx_scale] \n\t" + "mfhi %[sum] \n\t" + "subu %[temp3], %[temp3], %[frac] \n\t" + "sw %[temp3], 0(%[frow]) \n\t" + "add %[base], %[base], %[temp3] \n\t" + "sw %[base], 0(%[irow]) \n\t" + "addu %[irow], %[irow], %[x_stride1] \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), [irow] "+r" (irow), [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" + ); + } else { + __asm__ volatile ( + "lbu %[temp1], 0(%[src1]) \n\t" + "move %[temp2], %[temp1] \n\t" + "li %[accum], 0 \n\t" + "1: \n\t" + "bgez %[accum], 2f \n\t" + "move %[temp2], %[temp1] \n\t" + "addu %[src1], %[x_stride] \n\t" + "lbu %[temp1], 0(%[src1]) \n\t" + "addu %[accum], %[x_add] \n\t" + "2: \n\t" + "subu %[temp3], %[temp2], %[temp1] \n\t" + "mul %[temp3], %[temp3], %[accum] \n\t" + "mul %[base], %[temp1], %[x_add] \n\t" + "subu %[accum], %[accum], %[x_sub] \n\t" + "lw %[frac], 0(%[irow]) \n\t" + "subu %[loop_c], %[loop_c], %[x_stride] \n\t" + "addu %[temp3], %[base], %[temp3] \n\t" + "sw %[temp3], 0(%[frow]) \n\t" + "addu %[frow], %[x_stride1] \n\t" + "addu %[frac], %[temp3] \n\t" + "sw %[frac], 0(%[irow]) \n\t" + "addu %[irow], %[x_stride1] \n\t" + "bgtz %[loop_c], 1b \n\t" + + : [src1] "+r" (src1), [accum] "=&r" (accum), [temp1] "=&r" (temp1), + [temp2] "=&r" (temp2), [temp3] "=&r" (temp3), [base] "=&r" (base), + [frac] "=&r" (frac), [frow] "+r" (frow), [irow] "+r" (irow) + : [x_stride] "r" (x_stride), [x_add] "r" (x_add), [x_sub] "r" (x_sub), + [x_stride1] "r" (x_stride1), [loop_c] "r" (loop_c) + : "memory", "hi", "lo" + ); + } +} + +static void ExportRowMIPS(WebPRescaler* const wrk, int x_out) { + if (wrk->y_accum <= 0) { + uint8_t* const dst = wrk->dst; + int32_t* const irow = wrk->irow; + const int32_t* const frow = wrk->frow; + const int yscale = wrk->fy_scale * (-wrk->y_accum); + const int x_out_max = wrk->dst_width * wrk->num_channels; + // if wrk->fxy_scale can fit into 32 bits use optimized code, + // otherwise use C code + if ((wrk->fxy_scale >> 32) == 0) { + int temp0, temp1, temp3, temp4, temp5, temp6, temp7, loop_end; + const int temp2 = (int)(wrk->fxy_scale); + const int temp8 = x_out_max << 2; + uint8_t* dst_t = (uint8_t*)dst; + int32_t* irow_t = (int32_t*)irow; + const int32_t* frow_t = (const int32_t*)frow; + + __asm__ volatile( + "addiu %[temp6], $zero, -256 \n\t" + "addiu %[temp7], $zero, 255 \n\t" + "li %[temp3], 0x10000 \n\t" + "li %[temp4], 0x8000 \n\t" + "addu %[loop_end], %[frow_t], %[temp8] \n\t" + "1: \n\t" + "lw %[temp0], 0(%[frow_t]) \n\t" + "mult %[temp3], %[temp4] \n\t" + "addiu %[frow_t], %[frow_t], 4 \n\t" + "sll %[temp0], %[temp0], 2 \n\t" + "madd %[temp0], %[yscale] \n\t" + "mfhi %[temp1] \n\t" + "lw %[temp0], 0(%[irow_t]) \n\t" + "addiu %[dst_t], %[dst_t], 1 \n\t" + "addiu %[irow_t], %[irow_t], 4 \n\t" + "subu %[temp0], %[temp0], %[temp1] \n\t" + "mult %[temp3], %[temp4] \n\t" + "sll %[temp0], %[temp0], 2 \n\t" + "madd %[temp0], %[temp2] \n\t" + "mfhi %[temp5] \n\t" + "sw %[temp1], -4(%[irow_t]) \n\t" + "and %[temp0], %[temp5], %[temp6] \n\t" + "slti %[temp1], %[temp5], 0 \n\t" + "beqz %[temp0], 2f \n\t" + "xor %[temp5], %[temp5], %[temp5] \n\t" + "movz %[temp5], %[temp7], %[temp1] \n\t" + "2: \n\t" + "sb %[temp5], -1(%[dst_t]) \n\t" + "bne %[frow_t], %[loop_end], 1b \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6), + [temp7]"=&r"(temp7), [frow_t]"+r"(frow_t), [irow_t]"+r"(irow_t), + [dst_t]"+r"(dst_t), [loop_end]"=&r"(loop_end) + : [temp2]"r"(temp2), [yscale]"r"(yscale), [temp8]"r"(temp8) + : "memory", "hi", "lo" + ); + wrk->y_accum += wrk->y_add; + wrk->dst += wrk->dst_stride; + } else { + ExportRowC(wrk, x_out); + } + } +} +#endif // WEBP_USE_MIPS32 + +//------------------------------------------------------------------------------ + +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, int x_add, int x_sub, + int y_add, int y_sub, int32_t* const work) { + wrk->x_expand = (src_width < dst_width); + wrk->src_width = src_width; + wrk->src_height = src_height; + wrk->dst_width = dst_width; + wrk->dst_height = dst_height; + 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 - x_sub; + wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub; + wrk->y_accum = y_add; + wrk->y_add = y_add; + wrk->y_sub = y_sub; + wrk->fx_scale = (1 << RFIX) / x_sub; + wrk->fy_scale = (1 << RFIX) / y_sub; + wrk->fxy_scale = wrk->x_expand ? + ((int64_t)dst_height << RFIX) / (x_sub * src_height) : + ((int64_t)dst_height << RFIX) / (x_add * src_height); + wrk->irow = work; + wrk->frow = work + num_channels * dst_width; + + if (WebPRescalerImportRow == NULL) { + WebPRescalerImportRow = ImportRowC; + WebPRescalerExportRow = ExportRowC; + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_USE_MIPS32) + if (VP8GetCPUInfo(kMIPS32)) { + WebPRescalerImportRow = ImportRowMIPS; + WebPRescalerExportRow = ExportRowMIPS; + } +#endif + } + } +} + +#undef MULT_FIX +#undef RFIX + +//------------------------------------------------------------------------------ +// 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 && wrk->y_accum > 0) { + int channel; + for (channel = 0; channel < wrk->num_channels; ++channel) { + WebPRescalerImportRow(wrk, src, channel); + } + 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, 0); + ++total_exported; + } + return total_exported; +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/utils/rescaler.h b/TMessagesProj/jni/libwebp/utils/rescaler.h new file mode 100644 index 00000000..a6f37871 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/rescaler.h @@ -0,0 +1,82 @@ +// 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" + +// Structure used for on-the-fly rescaling +typedef struct { + int x_expand; // true if we're expanding in the x direction + int num_channels; // bytes to jump between pixels + int fy_scale, fx_scale; // fixed-point scaling factor + int64_t fxy_scale; // '' + // we need hpel-precise add/sub increments, for the downsampled U/V planes. + int y_accum; // vertical accumulator + int y_add, y_sub; // vertical increments (add ~= src, sub ~= dst) + int x_add, x_sub; // horizontal increments (add ~= src, sub ~= dst) + int src_width, src_height; // source dimensions + int dst_width, dst_height; // destination dimensions + uint8_t* dst; + int dst_stride; + int32_t* irow, *frow; // work buffer +} WebPRescaler; + +// 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, + int x_add, int x_sub, + int y_add, int y_sub, + int32_t* const work); + +// 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); + +// Import a row of data and save its contribution in the rescaler. +// 'channel' denotes the channel number to be imported. +extern void (*WebPRescalerImportRow)(WebPRescaler* const wrk, + const uint8_t* const src, int channel); +// Export one row (starting at x_out position) from rescaler. +extern void (*WebPRescalerExportRow)(WebPRescaler* const wrk, int x_out); + +// Return true if there is pending output rows ready. +static WEBP_INLINE +int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { + return (rescaler->y_accum <= 0); +} + +// Export as many rows as possible. Return the numbers of rows written. +int WebPRescalerExport(WebPRescaler* const rescaler); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_RESCALER_H_ */ diff --git a/TMessagesProj/jni/libwebp/utils/thread.c b/TMessagesProj/jni/libwebp/utils/thread.c new file mode 100644 index 00000000..264210ba --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/thread.c @@ -0,0 +1,309 @@ +// 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 +#include // for memset() +#include "./thread.h" +#include "./utils.h" + +#ifdef WEBP_USE_THREAD + +#if defined(_WIN32) + +#include +typedef HANDLE pthread_t; +typedef CRITICAL_SECTION pthread_mutex_t; +typedef struct { + HANDLE waiting_sem_; + HANDLE received_sem_; + HANDLE signal_event_; +} pthread_cond_t; + +#else // !_WIN32 + +#include + +#endif // _WIN32 + +struct WebPWorkerImpl { + pthread_mutex_t mutex_; + pthread_cond_t condition_; + pthread_t thread_; +}; + +#if defined(_WIN32) + +//------------------------------------------------------------------------------ +// simplistic pthread emulation layer + +#include + +// _beginthreadex requires __stdcall +#define THREADFN unsigned int __stdcall +#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val) + +static int pthread_create(pthread_t* const thread, const void* attr, + unsigned int (__stdcall *start)(void*), void* arg) { + (void)attr; + *thread = (pthread_t)_beginthreadex(NULL, /* void *security */ + 0, /* unsigned stack_size */ + start, + arg, + 0, /* unsigned initflag */ + NULL); /* unsigned *thrdaddr */ + 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; + InitializeCriticalSection(mutex); + 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; + ok &= (CloseHandle(condition->waiting_sem_) != 0); + ok &= (CloseHandle(condition->received_sem_) != 0); + ok &= (CloseHandle(condition->signal_event_) != 0); + return !ok; +} + +static int pthread_cond_init(pthread_cond_t* const condition, void* cond_attr) { + (void)cond_attr; + 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; + } + return 0; +} + +static int pthread_cond_signal(pthread_cond_t* const condition) { + int ok = 1; + 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); + } + return !ok; +} + +static int pthread_cond_wait(pthread_cond_t* const condition, + pthread_mutex_t* const mutex) { + int ok; + // 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); + 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/TMessagesProj/jni/libwebp/utils/thread.h b/TMessagesProj/jni/libwebp/utils/thread.h new file mode 100644 index 00000000..7bd451b1 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/thread.h @@ -0,0 +1,93 @@ +// 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 interface); + +// 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/TMessagesProj/jni/libwebp/utils/utils.c b/TMessagesProj/jni/libwebp/utils/utils.c new file mode 100644 index 00000000..8ff7f12f --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/utils.c @@ -0,0 +1,211 @@ +// 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 +#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 +#include // for abort() + +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); +} + +//------------------------------------------------------------------------------ diff --git a/TMessagesProj/jni/libwebp/utils/utils.h b/TMessagesProj/jni/libwebp/utils/utils.h new file mode 100644 index 00000000..f2c498a9 --- /dev/null +++ b/TMessagesProj/jni/libwebp/utils/utils.h @@ -0,0 +1,121 @@ +// 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_ + +#include + +#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); + +//------------------------------------------------------------------------------ +// 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 (uint32_t)GetLE16(data) | (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 +#pragma intrinsic(_BitScanReverse) + +static WEBP_INLINE int BitsLog2Floor(uint32_t n) { + uint32_t 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 + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_UTILS_UTILS_H_ */ diff --git a/TMessagesProj/jni/libwebp/webp/decode.h b/TMessagesProj/jni/libwebp/webp/decode.h new file mode 100644 index 00000000..8d3f7be9 --- /dev/null +++ b/TMessagesProj/jni/libwebp/webp/decode.h @@ -0,0 +1,503 @@ +// 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 0x0203 // 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 and return 0 in +// case of formatting error. +// 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 free(). +// 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 free()'d, +// 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); + +// 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 true, 'internal_memory' pointer is not used. + 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 false). 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 +// set to 1. 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 + + // Unused for now: + int no_incremental_decoding; // if true, using incremental decoding is not + // recommended. + int rotate; // TODO(later) + int uv_sampling; // should be 0 for now. TODO(later) + uint32_t pad[2]; // 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) +#if WEBP_DECODER_ABI_VERSION > 0x0203 + int flip; // flip output vertically +#endif +#if WEBP_DECODER_ABI_VERSION > 0x0204 + int alpha_dithering_strength; // alpha dithering strength in [0..100] +#endif + + // Unused for now: + int force_rotation; // forced rotation (to be applied _last_) + int no_enhancement; // if true, discard enhancement layer +#if WEBP_DECODER_ABI_VERSION < 0x0203 + uint32_t pad[5]; // padding for later use +#elif WEBP_DECODER_ABI_VERSION < 0x0204 + uint32_t pad[4]; // padding for later use +#else + uint32_t pad[3]; // padding for later use +#endif +}; + +// 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. +// 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). +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). +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/TMessagesProj/jni/libwebp/webp/demux.h b/TMessagesProj/jni/libwebp/webp/demux.h new file mode 100644 index 00000000..2da3239d --- /dev/null +++ b/TMessagesProj/jni/libwebp/webp/demux.h @@ -0,0 +1,224 @@ +// 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 "./mux_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_DEMUX_ABI_VERSION 0x0101 // 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; + +//------------------------------------------------------------------------------ + +// 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'. +// 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 fragment_num; + int num_fragments; + int x_offset, y_offset; // offset relative to the canvas. + int width, height; // dimensions of this frame or fragment. + 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 or fragment given by 'frame_num' and + // 'fragment_num'. + int has_alpha; // True if the frame or fragment 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 first fragment on return from this function. +// Individual fragments may be extracted using WebPDemuxSelectFragment(). +// 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); + +// Sets 'iter->fragment' to reflect fragment number 'fragment_num'. +// Returns true if fragment 'fragment_num' is present, false otherwise. +WEBP_EXTERN(int) WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num); + +// 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); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_WEBP_DEMUX_H_ */ diff --git a/TMessagesProj/jni/libwebp/webp/encode.h b/TMessagesProj/jni/libwebp/webp/encode.h new file mode 100644 index 00000000..3c263748 --- /dev/null +++ b/TMessagesProj/jni/libwebp/webp/encode.h @@ -0,0 +1,518 @@ +// 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 0x0202 // 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 'free(*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); + +//------------------------------------------------------------------------------ +// 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). + + uint32_t pad[5]; // padding for later use +}; + +// 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); +} + +#if WEBP_ENCODER_ABI_VERSION > 0x0202 +// 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); +#endif + +// 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 + + uint32_t pad[4]; // 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); + +#if WEBP_ENCODER_ABI_VERSION > 0x0203 +// The following must be called to deallocate writer->mem memory. The 'writer' +// object itself is not deallocated. +WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer); +#endif +// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon +// completion, writer.mem and writer.size will hold the coded data. +#if WEBP_ENCODER_ABI_VERSION > 0x0203 +// writer.mem must be freed by calling WebPMemoryWriterClear. +#else +// writer.mem must be freed by calling 'free(writer.mem)'. +#endif +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. +// Result is in dB, stores in result[] in the Y/U/V/Alpha/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. +// Now 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); + +#if WEBP_ENCODER_ABI_VERSION > 0x0204 +// 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); +#endif + +// 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/TMessagesProj/jni/libwebp/webp/format_constants.h b/TMessagesProj/jni/libwebp/webp/format_constants.h new file mode 100644 index 00000000..4c04b50c --- /dev/null +++ b/TMessagesProj/jni/libwebp/webp/format_constants.h @@ -0,0 +1,88 @@ +// 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) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (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/TMessagesProj/jni/libwebp/webp/mux.h b/TMessagesProj/jni/libwebp/webp/mux.h new file mode 100644 index 00000000..1ae03b34 --- /dev/null +++ b/TMessagesProj/jni/libwebp/webp/mux.h @@ -0,0 +1,399 @@ +// 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 for WebP images. +// +// Authors: Urvang (urvang@google.com) +// Vikas (vikasa@google.com) + +// 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); +*/ + +#ifndef WEBP_WEBP_MUX_H_ +#define WEBP_WEBP_MUX_H_ + +#include "./mux_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_MUX_ABI_VERSION 0x0101 // 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 WebPMuxError WebPMuxError; +// typedef enum WebPChunkId WebPChunkId; +typedef struct WebPMux WebPMux; // main opaque object. +typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; +typedef struct WebPMuxAnimParams WebPMuxAnimParams; + +// 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. + +#if WEBP_MUX_ABI_VERSION > 0x0101 +// 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); +#endif + +// 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); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_WEBP_MUX_H_ */ diff --git a/TMessagesProj/jni/libwebp/webp/mux_types.h b/TMessagesProj/jni/libwebp/webp/mux_types.h new file mode 100644 index 00000000..c94043a3 --- /dev/null +++ b/TMessagesProj/jni/libwebp/webp/mux_types.h @@ -0,0 +1,97 @@ +// 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 // free() +#include // 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/TMessagesProj/jni/libwebp/webp/types.h b/TMessagesProj/jni/libwebp/webp/types.h new file mode 100644 index 00000000..568d1f26 --- /dev/null +++ b/TMessagesProj/jni/libwebp/webp/types.h @@ -0,0 +1,47 @@ +// 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 // for size_t + +#ifndef _MSC_VER +#include +#ifdef __STRICT_ANSI__ +#define WEBP_INLINE +#else /* __STRICT_ANSI__ */ +#define WEBP_INLINE 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. +#define WEBP_EXTERN(type) extern type +#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/TMessagesProj/jni/sqlite/sqlite3.c b/TMessagesProj/jni/sqlite/sqlite3.c index 62f39e99..81e9c733 100644 --- a/TMessagesProj/jni/sqlite/sqlite3.c +++ b/TMessagesProj/jni/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.8.7.1. By combining all the individual C code files into this +** version 3.8.7.4. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -231,9 +231,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.8.7.1" +#define SQLITE_VERSION "3.8.7.4" #define SQLITE_VERSION_NUMBER 3008007 -#define SQLITE_SOURCE_ID "2014-10-29 13:59:56 3b7b72c4685aa5cf5e675c2c47ebec10d9704221" +#define SQLITE_SOURCE_ID "2014-12-09 01:34:36 f66f7a17b78ba617acde90fc810107f34f1a1f2e" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -9013,7 +9013,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int); SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); @@ -9046,7 +9046,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*); -SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); +SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); @@ -11537,7 +11537,7 @@ struct Expr { /* ** The following are the meanings of bits in the Expr.flags field. */ -#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */ +#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x000008 /* Expression contains one or more errors */ @@ -11557,6 +11557,7 @@ struct Expr { #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ #define EP_Constant 0x080000 /* Node is a constant */ +#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ /* ** These macros can be used to test, set, or clear bits in the @@ -13062,7 +13063,7 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int); SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); -SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum*,int); +SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char); SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); @@ -20947,7 +20948,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( const et_info *infop; /* Pointer to the appropriate info structure */ char *zOut; /* Rendering buffer */ int nOut; /* Size of the rendering buffer */ - char *zExtra; /* Malloced memory used by some conversion */ + char *zExtra = 0; /* Malloced memory used by some conversion */ #ifndef SQLITE_OMIT_FLOATING_POINT int exp, e2; /* exponent of real numbers */ int nsd; /* Number of significant digits returned */ @@ -21064,7 +21065,6 @@ SQLITE_PRIVATE void sqlite3VXPrintf( break; } } - zExtra = 0; /* ** At this point, variables are initialized as follows: @@ -21355,13 +21355,16 @@ SQLITE_PRIVATE void sqlite3VXPrintf( }else{ c = va_arg(ap,int); } - buf[0] = (char)c; - if( precision>=0 ){ - for(idx=1; idx1 ){ + width -= precision-1; + if( width>1 && !flag_leftjustify ){ + sqlite3AppendChar(pAccum, width-1, ' '); + width = 0; + } + sqlite3AppendChar(pAccum, precision-1, c); } + length = 1; + buf[0] = c; bufpt = buf; break; case etSTRING: @@ -21462,11 +21465,14 @@ SQLITE_PRIVATE void sqlite3VXPrintf( ** the output. */ width -= length; - if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width); + if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); sqlite3StrAccumAppend(pAccum, bufpt, length); - if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width); + if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); - if( zExtra ) sqlite3_free(zExtra); + if( zExtra ){ + sqlite3_free(zExtra); + zExtra = 0; + } }/* End for loop over the format string */ } /* End of function */ @@ -21519,11 +21525,11 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ } /* -** Append N space characters to the given string buffer. +** Append N copies of character c to the given string buffer. */ -SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *p, int N){ +SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return; - while( (N--)>0 ) p->zText[p->nChar++] = ' '; + while( (N--)>0 ) p->zText[p->nChar++] = c; } /* @@ -50636,7 +50642,6 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } - assert( rc==SQLITE_OK ); return rc; } @@ -51715,6 +51720,11 @@ struct CellInfo { ** ** Fields in this structure are accessed under the BtShared.mutex ** found at self->pBt->mutex. +** +** skipNext meaning: +** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op. +** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op. +** eState==FAULT: Cursor fault with skipNext as error code. */ struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ @@ -51727,7 +51737,8 @@ struct BtCursor { void *pKey; /* Saved key that was cursor last known position */ Pgno pgnoRoot; /* The root page of this tree */ int nOvflAlloc; /* Allocated size of aOverflow[] array */ - int skipNext; /* Prev() is noop if negative. Next() is noop if positive */ + int skipNext; /* Prev() is noop if negative. Next() is noop if positive. + ** Error code if eState==CURSOR_FAULT */ u8 curFlags; /* zero or more BTCF_* flags defined below */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ u8 hints; /* As configured by CursorSetHints() */ @@ -51773,7 +51784,7 @@ struct BtCursor { ** on a different connection that shares the BtShared cache with this ** cursor. The error has left the cache in an inconsistent state. ** Do nothing else with this cursor. Any attempt to use the cursor -** should return the error code stored in BtCursor.skip +** should return the error code stored in BtCursor.skipNext */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 @@ -54355,7 +54366,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ ** The call to sqlite3BtreeRollback() drops any table-locks held by ** this handle. */ - sqlite3BtreeRollback(p, SQLITE_OK); + sqlite3BtreeRollback(p, SQLITE_OK, 0); sqlite3BtreeLeave(p); /* If there are still other outstanding references to the shared-btree @@ -55648,60 +55659,91 @@ SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){ /* ** This routine sets the state to CURSOR_FAULT and the error -** code to errCode for every cursor on BtShared that pBtree -** references. +** code to errCode for every cursor on any BtShared that pBtree +** references. Or if the writeOnly flag is set to 1, then only +** trip write cursors and leave read cursors unchanged. ** -** Every cursor is tripped, including cursors that belong -** to other database connections that happen to be sharing -** the cache with pBtree. +** Every cursor is a candidate to be tripped, including cursors +** that belong to other database connections that happen to be +** sharing the cache with pBtree. ** -** This routine gets called when a rollback occurs. -** All cursors using the same cache must be tripped -** to prevent them from trying to use the btree after -** the rollback. The rollback may have deleted tables -** or moved root pages, so it is not sufficient to -** save the state of the cursor. The cursor must be -** invalidated. +** This routine gets called when a rollback occurs. If the writeOnly +** flag is true, then only write-cursors need be tripped - read-only +** cursors save their current positions so that they may continue +** following the rollback. Or, if writeOnly is false, all cursors are +** tripped. In general, writeOnly is false if the transaction being +** rolled back modified the database schema. In this case b-tree root +** pages may be moved or deleted from the database altogether, making +** it unsafe for read cursors to continue. +** +** If the writeOnly flag is true and an error is encountered while +** saving the current position of a read-only cursor, all cursors, +** including all read-cursors are tripped. +** +** SQLITE_OK is returned if successful, or if an error occurs while +** saving a cursor position, an SQLite error code. */ -SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ +SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ BtCursor *p; - if( pBtree==0 ) return; - sqlite3BtreeEnter(pBtree); - for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - int i; - sqlite3BtreeClearCursor(p); - p->eState = CURSOR_FAULT; - p->skipNext = errCode; - for(i=0; i<=p->iPage; i++){ - releasePage(p->apPage[i]); - p->apPage[i] = 0; + int rc = SQLITE_OK; + + assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 ); + if( pBtree ){ + sqlite3BtreeEnter(pBtree); + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ + int i; + if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ + if( p->eState==CURSOR_VALID ){ + rc = saveCursorPosition(p); + if( rc!=SQLITE_OK ){ + (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); + break; + } + } + }else{ + sqlite3BtreeClearCursor(p); + p->eState = CURSOR_FAULT; + p->skipNext = errCode; + } + for(i=0; i<=p->iPage; i++){ + releasePage(p->apPage[i]); + p->apPage[i] = 0; + } } + sqlite3BtreeLeave(pBtree); } - sqlite3BtreeLeave(pBtree); + return rc; } /* -** Rollback the transaction in progress. All cursors will be -** invalided by this operation. Any attempt to use a cursor -** that was open at the beginning of this operation will result -** in an error. +** Rollback the transaction in progress. +** +** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped). +** Only write cursors are tripped if writeOnly is true but all cursors are +** tripped if writeOnly is false. Any attempt to use +** a tripped cursor will result in an error. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){ +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ int rc; BtShared *pBt = p->pBt; MemPage *pPage1; + assert( writeOnly==1 || writeOnly==0 ); + assert( tripCode==SQLITE_ABORT_ROLLBACK || tripCode==SQLITE_OK ); sqlite3BtreeEnter(p); if( tripCode==SQLITE_OK ){ rc = tripCode = saveAllCursors(pBt, 0, 0); + if( rc ) writeOnly = 0; }else{ rc = SQLITE_OK; } if( tripCode ){ - sqlite3BtreeTripAllCursors(p, tripCode); + int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly); + assert( rc==SQLITE_OK || (writeOnly==0 && rc2==SQLITE_OK) ); + if( rc2!=SQLITE_OK ) rc = rc2; } btreeIntegrity(p); @@ -56036,13 +56078,9 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ */ SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); - if( pCur->eState!=CURSOR_VALID ){ - *pSize = 0; - }else{ - getCellInfo(pCur); - *pSize = pCur->info.nKey; - } + assert( pCur->eState==CURSOR_VALID ); + getCellInfo(pCur); + *pSize = pCur->info.nKey; return SQLITE_OK; } @@ -61466,7 +61504,7 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ } /* If a transaction is still open on the Btree, roll it back. */ - sqlite3BtreeRollback(p->pDest, SQLITE_OK); + sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0); /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; @@ -71304,7 +71342,7 @@ case OP_Column: { pC->payloadSize = pC->szRow = avail = pReg->n; pC->aRow = (u8*)pReg->z; }else{ - MemSetTypeFlag(pDest, MEM_Null); + sqlite3VdbeMemSetNull(pDest); goto op_column_out; } }else{ @@ -71828,11 +71866,18 @@ case OP_Savepoint: { db->isTransactionSavepoint = 0; rc = p->rc; }else{ + int isSchemaChange; iSavepoint = db->nSavepoint - iSavepoint - 1; if( p1==SAVEPOINT_ROLLBACK ){ + isSchemaChange = (db->flags & SQLITE_InternChanges)!=0; for(ii=0; iinDb; ii++){ - sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT); + rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, + SQLITE_ABORT_ROLLBACK, + isSchemaChange==0); + if( rc!=SQLITE_OK ) goto abort_due_to_error; } + }else{ + isSchemaChange = 0; } for(ii=0; iinDb; ii++){ rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); @@ -71840,7 +71885,7 @@ case OP_Savepoint: { goto abort_due_to_error; } } - if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ + if( isSchemaChange ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); db->flags = (db->flags | SQLITE_InternChanges); @@ -72237,7 +72282,7 @@ case OP_OpenWrite: { || p->readOnly==0 ); if( p->expired ){ - rc = SQLITE_ABORT; + rc = SQLITE_ABORT_ROLLBACK; break; } @@ -73404,6 +73449,10 @@ case OP_Rowid: { /* out2-prerelease */ assert( pC->pCursor!=0 ); rc = sqlite3VdbeCursorRestore(pC); if( rc ) goto abort_due_to_error; + if( pC->nullRow ){ + pOut->flags = MEM_Null; + break; + } rc = sqlite3BtreeKeySize(pC->pCursor, &v); assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */ } @@ -79456,6 +79505,10 @@ static int lookupName( if( pMatch ){ pExpr->iTable = pMatch->iCursor; pExpr->pTab = pMatch->pTab; + assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */ + if( (pMatch->jointype & JT_LEFT)!=0 ){ + ExprSetProperty(pExpr, EP_CanBeNull); + } pSchema = pExpr->pTab->pSchema; } } /* if( pSrcList ) */ @@ -81992,7 +82045,8 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ return 0; case TK_COLUMN: assert( p->pTab!=0 ); - return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0; + return ExprHasProperty(p, EP_CanBeNull) || + (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); default: return 1; } @@ -82435,7 +82489,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); pSelect->iLimit = 0; testcase( pSelect->selFlags & SF_Distinct ); - pSelect->selFlags &= ~SF_Distinct; testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ if( sqlite3Select(pParse, pSelect, &dest) ){ sqlite3KeyInfoUnref(pKeyInfo); @@ -87368,7 +87421,7 @@ static void initAvgEq(Index *pIdx){ i64 nSum100 = 0; /* Number of terms contributing to sumEq */ i64 nDist100; /* Number of distinct values in index */ - if( pIdx->aiRowEst==0 || pIdx->aiRowEst[iCol+1]==0 ){ + if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){ nRow = pFinal->anLt[iCol]; nDist100 = (i64)100 * pFinal->anDLt[iCol]; nSample--; @@ -125841,6 +125894,16 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ for(j=0; jnDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ + if( pDb->pSchema ){ + /* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */ + sqlite3BtreeEnter(pDb->pBt); + for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){ + Index *pIdx = sqliteHashData(i); + sqlite3KeyInfoUnref(pIdx->pKeyInfo); + pIdx->pKeyInfo = 0; + } + sqlite3BtreeLeave(pDb->pBt); + } sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; if( j!=1 ){ @@ -125927,13 +125990,15 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ /* ** Rollback all database files. If tripCode is not SQLITE_OK, then -** any open cursors are invalidated ("tripped" - as in "tripping a circuit +** any write cursors are invalidated ("tripped" - as in "tripping a circuit ** breaker") and made to return tripCode if there are any further -** attempts to use that cursor. +** attempts to use that cursor. Read cursors remain open and valid +** but are "saved" in case the table pages are moved around. */ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ int i; int inTrans = 0; + int schemaChange; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); @@ -125944,6 +126009,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ ** the database rollback and schema reset, which can cause false ** corruption reports in some cases. */ sqlite3BtreeEnterAll(db); + schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0; for(i=0; inDb; i++){ Btree *p = db->aDb[i].pBt; @@ -125951,7 +126017,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ if( sqlite3BtreeIsInTrans(p) ){ inTrans = 1; } - sqlite3BtreeRollback(p, tripCode); + sqlite3BtreeRollback(p, tripCode, !schemaChange); } } sqlite3VtabRollback(db); @@ -127485,7 +127551,9 @@ static int openDatabase( sqlite3Error(db, rc); goto opendb_out; } + sqlite3BtreeEnter(db->aDb[0].pBt); db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); + sqlite3BtreeLeave(db->aDb[0].pBt); db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); /* The default safety_level for the main database is 'full'; for the temp diff --git a/TMessagesProj/jni/sqlite/sqlite3.h b/TMessagesProj/jni/sqlite/sqlite3.h index 184003ea..c31f126d 100644 --- a/TMessagesProj/jni/sqlite/sqlite3.h +++ b/TMessagesProj/jni/sqlite/sqlite3.h @@ -107,9 +107,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.8.7.1" +#define SQLITE_VERSION "3.8.7.4" #define SQLITE_VERSION_NUMBER 3008007 -#define SQLITE_SOURCE_ID "2014-10-29 13:59:56 3b7b72c4685aa5cf5e675c2c47ebec10d9704221" +#define SQLITE_SOURCE_ID "2014-12-09 01:34:36 f66f7a17b78ba617acde90fc810107f34f1a1f2e" /* ** CAPI3REF: Run-Time Library Version Numbers diff --git a/TMessagesProj/jni/sqlite_statement.c b/TMessagesProj/jni/sqlite_statement.c index 1090de3d..2fc4ef33 100755 --- a/TMessagesProj/jni/sqlite_statement.c +++ b/TMessagesProj/jni/sqlite_statement.c @@ -5,7 +5,7 @@ jfieldID queryArgsCountField; jint sqliteOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env) { jclass class = (*env)->FindClass(env, "org/telegram/SQLite/SQLitePreparedStatement"); queryArgsCountField = (*env)->GetFieldID(env, class, "queryArgsCount", "I"); - return JNI_VERSION_1_4; + return JNI_VERSION_1_6; } int Java_org_telegram_SQLite_SQLitePreparedStatement_step(JNIEnv* env, jobject object, int statementHandle) { diff --git a/TMessagesProj/libs/armeabi-v7a/libtmessages.4.so b/TMessagesProj/libs/armeabi-v7a/libtmessages.4.so deleted file mode 100755 index c38583ba533627a9e80384b78599d77a91af4ccd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1037088 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

xTy)JW0r6!ThYjUjkW-_TT1T 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%0DMh3tC|I(7A_Y?j{ytyac7jORW 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 z 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

uE^Y)$#lo5$>gFXkE2^ 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

2$ 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 vtV~#7~Z|v?uEf+u@L1;PL#nHAitH$$=5PE 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 diff --git a/TMessagesProj/libs/armeabi-v7a/libtmessages.5.so b/TMessagesProj/libs/armeabi-v7a/libtmessages.5.so new file mode 100755 index 0000000000000000000000000000000000000000..46e200f5b551e78095bd997878986b9340ffc5cb GIT binary patch literal 1565572 zcmbT951f=$x%gjTfrVXgRRmP3wJ^Cx#h+ENsDNEz(M4BS5Q`dyo!Q-y*`0A_78WBz z1L6HQ>1a>2V?&+7Q)8)yT$2#4<_g6+HUXc$5yS_ax z>iUuWS51KOPtqlE-2C6A6ui(gT z6pYBf#P8~N430L}TK)!H|DK`IOqD;u@1}c)Mw=*X(f>8PFEcb+|02tOhj-pPI9jIq zb!2$*14E-N$`gVDko>+p;Pc_v3BPZU_rDn4N_bLE65mRA9r4XlrYNFi=uhOg$RFUh z`;qY94iDI}KM;zS2G< z{1NEY!fnbgfuj!&ipD6v4$hvvD5_V!2_A#Ip3WiuSHKP121T<}-UFB5lgjJh$8C;wIz%~E*-+_0DSia*hx3-3g~iEQCGEUGUO3 z4~e#_{9W*tuMUciD}NYX`!&*|`d@&Leq&H{TIG+yhxQMO_9*`t-tf&q(J9sc9b9!_ zXmn8J&x-!zLw)^Mq1X2~<#VM??>P9x8wdOHo(Q`iDW5Chm4{+x*0iH2vun#{AZ-G;)eayrpNpOcq#1a^R@8IpnPtHTj2>BegV$H zPJbipex!aj!^>t4_U&yKydG{qCi(jo-1?fqzJ8Cud*I_LKMikvZEQa-pxqtAXztMb zOoTVgVSKsNhIci*<)NWb8$+Ok|2kOa2hxAe=l@37{Yd)e!-wBAI6A29XK{u6)(U}>Wes8*s@Kyf-cs%`Wnerp>&i9XvFgK*H zCi)D#Y-ODPeZq{lu0I`wXJrTb@%JfsOwADAo_+(bMZSRnQsVy~xU_aiG*jFAxRKQF zLw5ck@m&R1y@mFv@_Fzw!aJem+X^?09un0lr{R{n21jBCCHysT{$FW7D&Ghny_5E- z{1JHkql5i;`$hQ3KI&8DkHM!`4~a@z9#6tuedI^e^Gi575ZB*xa4YGj8=3MN%eZx7 z>X2xg`o99sBA50k`I`-&diPl7qn2CYDM9|*;r+<}Mdf|)B;-`5@qZuO9EA5Uypj5< zSNZ4QL-&t0b6JV+ad>=?-v5HT@K1J4cz=hN!*p-MFQH+U2v25g;{RGWkDTUcxCNdu zW=M2I+h+n^{=u=7y_NUE;~yRy?N;6dmxA~nhPSy0VLa0Ot%Og~|E6g8Yv2iAjmMjJz$v(-<@;gL z-!j(N7YXkx@P2rbhJP5&KE&!z!#@Qd-#jGRp!uu9?o9Z`;AjRNPVzSjuBY;{G+5ym z!Uw)Y=G6aGxM{4 z-y`tpU_AIeTpRS)S|Zv^f2KH0e3Ri>L4SQ6+!FN9h4A{IzugXRfG<}6?}WF*^~yWo z{V>s*@V^Wn4&+b3rvp9-k0Jlg|4_=YZu}76UM_^U!fUmCUk*3jJ|wEu@_ZHC@Hynf zC*|J^kH3umruChMXTF5?uY3o5`tl*s6s^y9zm%A z<@Hl|JmdKxEx)ty4BGD|<;l{~36JEN^vr{+U^m{p5k3UF{<}u_Lveq454Srto5T>1T#S zOxX;V;MPZIFIv9$!S(2u)c?oe65&%ECj9?^m$3-jukt71jk|_;d-ErF4EoDepQUkh za`%v^MdP~)-m(vSspY*8ZupOQ{Jsr73}XUK`tF4DE32ZE>OTk{|K^ZrvbL{J!qG3| z_WBLD<&TV)Y@A4bpMj_RW=J$a_5TX58_#+{+u!+YTTQr-@O8dD5nlUa+N;KYHN5Gn zs;G*3m+wil7*ZePm55R6b=z@1msES%telL9F#l(kQ7ynz~v&fx&e-xf_Ta_OV zWgG3}^eR98{TZG~{B0VZtRvU6NOb8t58m8d741;D>_6pMWS-==#5a}S%etz(eZ3w& zR$mpJ(eiAEtEZA4t)F|~=ANo(rsjVWJac}PpTB+(o_K!j|Lbs9{jlh$+Mh%4;cQh@ z((r!+pZNLEXqT417{(c!;`Q<!;=t+RMkQqV*d7`Ecp8q@Qs@>iaVI^uDTSuZH(>c-J?pqCVBX2A=e-D!=}^ z4qgV=sr-%b?vKRdO*h>44E3YwzZ2f_o1sxw=RfzsRnJnN${&EMpNh->^YG-eRldI; zgj-)eEZV2x9fNCMJuI4t-H`PE5w4p)EUMD>Gn8>)OvA9KPx(@~>&Vb(oBDq_yzatb z(FwKJSHsO!!=lYvUNVksyo&X{@)G#?HOMu;x50f3R&ITCH@suxQ1&crdN#qw-Z|9! ze;7XSR}!oKcf#9gpR<&|3~!-5FI7GOpZpB%8M`C-`vE-Zn?obn2NgaJ&-hlnANFVX z5c^ZhR9=N)uTKy2`?F)=r7+cN{QnEQ43_ag!kY=N59F=z2Dnw_?eG!U*^|}q3x6}b6rQa9KMt>l-Te9su=`tX>43CFhdR_xJ1@fEVX80g!k@8q3{*w{!`VFLqv8Eg z{KL*34SFHt1?>9gXt?(FI6W_b>jHimJO;)boBY2Po)E|v!cz*QN9FDCOxT6L3T_Gb z9(Y;6o8T;bQvGj-mlosl{35(A;BUb@;908wBzyv%sC)vhEyeBeS$H|@`sWDF5vo>U zZ&iN+JP|&oJPkf`2j!>z`#L!P7W%WwZ-sZlF2A?Idjehu?}t;W{{TGc&S8Fk=Tq<| zm}Y9q^ULr~*tMSn@L|}shbQ6cx5nu`0Z)Qm{C|NP-~$@o@OtVOcIh1p&sax$)%G(9 zc0ba;URm!*(i25j!_{{WitUDv2jD#c z?|@IjQz9GQSK$d8;`;j@T)h$2@_!nh{H{2^zlCSOZISi=Kk!D_mG|h&*q?z9sr&`7 z`;q)jg!jFBn4fP>gV%40`)4zJ8g}(@E4=rEasImC3HQh8?Sp5*8wgv zM{#;zA^NbJkIjOQ9UbQ9lM6-u(|9~cz%$Rp_16U-MDFTyHGCBLGL3&D96c5Le+Zrd zJN+GS7H(GkFTlHD*Zv=c55d(c|2BLi;3wf@aFfb^22Xr?ShP*~6ucjH<@+4G^H?0; z(3eo3u(L;F;i_k1`}jh5Ej&iUdj-4+?oz%MJ_ENXx4=#RHO!wkErn+QVLWJe&NE_ro(`XU~5Cx51Ot|1q5?;XXYds*rySUW$D4ARGT@ z;geOvqf>+>>Hj)>bm;JiC6(bHz-LCp@?XFwMh-XoqoRKX-dZ!<+oPJxu|Mz@4eurJ zhT7rLQRS&{-?&)b1UFnn{#3pMPK_Gw+j9rp!lBMCl^5W%@NVU|!n@8J9?ep|4?YDS zR(?OcpYkP{CO;pA-H(*tPIx=z?dG?S!ZXIi;e8+OgZH8<`TaS(gY>49pM`734v(^0 zo;5F({iNZ3|L#(F-<09ea@D^A-gbG+)8Q>#CfGT|hCdf>svqwA>q58NnNV9!>wx;O2%nzGva+ zJ;VL{aM%^pMxCy>Gu+#w zx5G2x^(ub|Zo6xEv`zWb@IK@_mA?+>3vv5-63)&T9*x)dPr~c3B|pkyICi~iIKHVj z>bC~YbKj#LminFmZyG`d=tEF>2Pl^^CJIu z&i%FjuY+fO6{dnEzD@9{uT)2^D&GdroIB3!XGr~h9zN4CJUXf2e+NFArGF~_7u-sH zP1N+CfyYoDZoI1DV5ao0;Zd{dzZl+I8XoOa{a3+#Uyk)}gpWT#eQ0`?!`ZJifSMJo8gnNtN(YxWB#Q&TCe^;3fH}od6cIA%W!E*wcp?P4m{~v_B}QI zPr>`)l=2yolfQM!7rp{}1J@}}gU`UOz1BHcq{#5x7N>daO))_ z{Qi3NRI2CF5&k~R`Ebh%M?||+{|fl*i$-{RGY3BO_lx{|?(+3hsLG2tVH_ zz?o_{BATzw02p<>jPD9r&LdgglgG>c=G-X-vcK%Rv6z-~Q~g-->% z8lLp3SbjIW9Cr5ZUGU^bMtb}C2t58ZvHTP8mTj?o4}6GAL2mr~CS3L5k$yaW5?(ha zmj4{ia*4%_zkh|NTo=nnOeekDsUI!x7r@8nQ9oLKli;P-)cE_5GvMP~I&$(xc<;3} z(FWCD1fRG8`=a5!3Eps19A5@LG^-|>r21>%84F|idiczo8oyt?89vcA!q4v>fp`9G zWVBE1*)F)@%Oj&%8sDSvWG?r)@$>+kjcTF>)&CK^{SC4FIJ~W@#$4u>_WUP!LSh7K zHrxJXU@1L1GO8P9c{Ds_Sxr>0>AzIuD`NeZ!UxkMqD|_5s_+9fQM2mLhL>exc?&$| z!5V+QxC}nYr7Ty!o$%IN+#UyVUON2B08h-jfYFW z9qH%aSHP!!MSIlpxe9Jt7l$`X{LiS3wv4gmeFHpk{RqDvSpx5X*Qz~Aiu_+=c~<1` zQkD0@(c9>M8s9p2#=Rr_`Qv@?tc|h!LAdYTvHU~uy7!ET4r+dO!Y%I|;pfX=f=lpn zmH!8P_d7jC^SwqHMm8{QwwPr%3K#qu-o=B=@O$kmMh*T?b;;nNSt@)yCUF0b+T z)uzC0AByF#f|pN<<@4d)ABp8l;iWIH@$=0rJmzDu{LS#8E93tCZn(4~mT!fRyfO~| zGw|V0j)<5toAKkT@b1o9e}4A=;Qg15^yfKGiT=eg{}w)YNzDHP&-#A6o)~@&>x1#J zd>p*zb0eYy3`x>|FNa(4&$QFw zHoQCG)bY4|-wV(DPs&5%+YC4TAa0M3z-xp2d=}pG1mm~re;Ka&>j=NT{5Cx6w=q8< z`ag-s`={WuM`HdZJpRwI{u#J|@YiejLl~G!PsQmS4Ig`dY!5DmXMS*GbV|p+E8zpA zKdb()g4=!-hd&!G1@(6`yzCco_{-q+L49W7tx`VP|5n4Rh z{|HY=)i-!L9n}53n^QLY z^!EQ0JUQrJaxrLP&_CgD%P*<% z`>kE@i5HLb_se@lPJ3c_G39YLoVuL$uY4ce_R^8j3FXc3%qyrb}tL2ef|Q37@Kt*F#(3@oyOE@3-xQ_l}@ERR8Pn#5axf>-j_Q{=`VXet#OSs)_ag z2%kyD@9~1edHNHH54NvZi3>3t)-{h^v@xypOt18<4j!#!}-2Uw4&{)2Gey4c=+9G>yPcs=kaJoz5_ zyN35T-1Vopy*~r*T_3OSeh1HbTf8264sLn}>m{|%wXY-oO(UavEw4-9i2?r$+yuM% z@(g(G1JtLs|0a0Mme~JIa0AS+Y1+pd;4JL+BRb(pZSi`q7oNcUW54R(1)q9)q`wdM zZn*DfBmH{(VL0{Qv~Ml{Pr_BaRN>a^UxL@3ireG2;JQD={3N{nkJu+IzZ39@(0f+4W}-w_3N{{;l0(h(MB!r_re>`5Wf2VD12r}Z8SsU`wD#U zxf=g|*mvQ+!L|PU=NLR?7~!e@8F=SknD0ckzAl)J{;3-O{>w|@9e=>yX?e|pH=U-x zss1hSkuMUTavEO$CDsSZIkG?5{C%2wIQt#aui;${H~l~Cp{92pyb;DM+V%?{ zfR8H|;GN&YzAJBp*Bz?y`=uX&mwli7YkfTmAOFvIKJsli|0Lz5?d1qO;U{tV{sON0 zX^r2Xc^2OAR9qi5jo8y;*rUNVeJ_IheiqMv8{jSfP5M-R1Drh(=WiLj8+Q52!>8bu zK{mX%!!v&s&zC*~ANqBT-_P3vZ##+oRsA2pJAcD|kn%Hd-S6W0#UJ73QMG=&9MMGn zXy22y{KmjjU}vxE;mH$gP5+Yl={3TWkXPCC-3%|ETpJzN_TK?FO{;P1kv z+iU&&^r!Ip57+wrnUnDD_tpCK*t75%!mlDM$?vf1u=iVP{e0~r_$+c)-YszT$~Zl( z@R8s?P7>aQyk6`7J+S+c^u8ZH)J=FiOMKsft6xy(=lf5?N0Ha7{DQf}4?BB44_-eZ z)_*@r|{B1{zrHxau@!~=3y^>e!fr7>)_+aH)?wBfa{OP z@^`^!d*bwb1kUH;{5=h?h5OY1rF8VuuuIc4(I>+74(^XvPU!$+RD(3jV1;M!9c`TDpXuKR;qk6jog z#XpzkrG1>w*Ccv{X3-VU!V)kd>az7?)5obT)B)9~Iv{tI|BFDbeD{VRMnkYC+G{K#81yzAka)UUID z>)|nkKS|{e!cq2oe}48cc=DJF{QGoYfDip?oavuZAA8`XtJu%d{`UXi(|xsmzWEe9 zgZk{k{)qlF@Y>(T_4zBfFW^7GrGWnm?+EI@Y60a<{M95=!n*)I6YvB$Lf^@+gii$W zYvJQTc=O=H0WXG61^Q`t-|2B?e3bZB!rT5hE~?l36yROx*K2xuMgNXk|9-^Xu=^4F z^B~+3?l-_kg7`lN9}RdfoWH9!Iyuy~@5kU}Z?Euq(e0!pj5xEW9+(|95yi_IIs@|4n$=kg?vL{XlpF=~wwr z;pTg5y*)SqSG@y!LwQR2{|KkV~^lkmCu6@!%MY%?t~}5pYcigi*U;aXm85Dh0kt{!+X&}#-|U~`u@EH zUIy1``0s|Zuq(gE;C=8$l@D7)_`GynuRIIR!VSuAfw#f#{iV;r?&ks?_P{$ngni&y z^7~kY{7?lSftNF1aP9d7yf-WBl2 z;oSj$0p1hvcj1{It&KKJxB2@Y*!@WU$1HXva=wRC!OiggBeni~Y)yrH9o%-5@nDDz zf4A_-+GzYR%lqK$FXQ@t0^a;|JYN3{-VdME_HpSF%Ig{GSMAAUcv&?I_)$-e-)DOq&J+F=jsGazMfgjVe+G}AKPsA~&# z^`rcH?lSmv{V3nw8sKdcM)~`m*TH>+=hlBW!3{xqC*kb@m*ArTzYQMqtGIq1f?Hs> zANVPF8~K~1`FRxXJ00tP2i_I%kKq#m{}QhMQ>_0Ncxk}HD5y=aTThOG5AqQJX{J)2 z)8P6uwb4Os57)ydpJRP7+{zcjhlY;w_cK?*8-~a2;SPBGp3(mPr6I3M({!*Dj><8Ue9Kfx36KZ*QEc!O`HeFXCJ;J$!g2+!ap z{$`!8Tm@Ir{wHX8%!aE2{Tt!BfL{-<3%C>B5O5J*AMjo9#(>`iFAexZ@bZ9n!>ND| zz_kJY5FQio&){VN{{^1-nbCg!IrR0k{}<5TwEtfSS5rUE{$B}ic;P6&UV1gWgZ|K> z<#7W%{xaIX+MlKHu|=c&c+v%r`3C)6%d-e?4$|{3czrNm*bZ+B<

g4PI&9*NBjPBKfLW7qx^d0VR-k4Mn_$$zYAWT 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%0DeXWhNit$mrt%3{1XV0_!0YjcsU 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%0DJBI?6vnpw;Fpb0dDGd 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 z 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%0D`DSkD)8HG2c`&ZIO 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

s0_=(cYx(`U?CTH zq^;aGXC;iZmVb*ErP7i$pD68)vtN{ZY}v0+`U1Xvlfxt!v}Twa$!*0T?)RQEd^5{D zEsp8VmIzNbP)D$RiSK>yABU&+m+^G$f5lT9uwfUCC~xIz+VX~?xc(m6NDTs4p8O8Z z>hxI;H80}Vx418u|0nW0k$(<4UC(@Umge$a^Q-+3R-QYa_?AyqxwJn12;Y&vn|KCv zr+ow(k8tauC!{U(wHz{iNb4ZYnphj&8n^ZjHSNJSIA8vRYRix0ZRHtC9lE!2ijh^= z+TtgQGxW0FwDy}=b871&6Et`1$A)Ib_folRXn(MWKC<-B9j@Bzi*1-_>UC_ZcPf3e zn=5Dg&M%YNBR+KJ!&CT8z8Nx8_iK!UUv}Zs?7`3(RcXd3-lDv>nmO=2`s%KYVCdrg ziAnbHP$tr=%^4s2yZFDx??w1t9`3qwbUlHFg?#2H_J6?K4 zG!|gjI48o><@?ke7@t}?7w=3DBt5G?)LvEPTv_0@1HMsBKl1rbq)ii7%|$T_JC7b2 zaE47@F^$#8zaDglK6Ad%KmRVuaZ?v>bvI%^Vqg5?mUNw5m^~_<4{y)R_MC4~I zKYBS!{2jx}5mS3VrLBqOcKmT= zQYwR9t1??DqkdZ87j5IpOjH@})>N7AQATk(?ZZ&n+2hL9s2qBN%4ys=%6gPlIr)}b z-&R)T)>B6D68VW$&U=S4t0^PjduzE&%R7`=PMJlNsevXH%b89Ya~7-r@bKNxk^JIU zW|^-U%Y&9II0W|{Y2t}PtRJ780xyzbf(a{y?~f&r0g_y9415IOk=0 zKpvty0L^i?2zW{nhuHhjx^PJz-e*O*lO0KGw8f45)bdf+m)F}S>bv>d%^fi6Lp}rb zZDJlxt37y)C*N`^-!oGSHp9~7)5`AJK;t&Bp*yA2j1krJH#Qq+h+(--B@;mdvf^|$ODroYPn zm4092`9j)mpby2+kaZ@0CRyZKx10D`S3uvi!~bSYP0k1CihgmC)f4JGW?ML6EeT%H z#z~abJWBQr0#6cqd~*e-yjM(2=Utqv@$&z5!a>fad9urkK$g^%SHe1 zqwXWXE*gA0?6Nf~u+t7OM|;sMavXJ+`Z^SV+Q%a zIZ)U^U^ zO6nMWD2UeQEsRBag4UmSq|1HU*t>_~ej58^FIQU1*#}=xdnZKtYahQ4a`uIE*&cpN zA2V|`#J&e`rg_o)X#F{Q>Yg>6}o9EKSY6g*8{2o94-+(XapUO!% z@o(Dyu-@p{w2y6tj_OE$4uscEjoQ@NxK)F>_%W1~+^pkVNBI@xA8O0;E-Qbi@P`~p zN9PWR_XtMW_^rfAe*R>1u7J@Et>rJJybZ~OmrPcn_sOS{%E)d)W@q^fL3=~gqiyY{ zm7J11sqz_rmu$RfU;IQDn*~3UU{OwJ&7Ii2^oNbP%?-4NyO$VFXF>O(R2RrK&#sZV%R(SgZy7qKBBfx+ofHcl*N0z$(5yJs{5l+Q2tX?%|3ueOM!t z_<#10^yy2?eZ2PvdkP!rU*l=9nB!n|>Hgs1g5;O*D%k)Xlr{}LX=I^f!)E%un@<~k zY=o}V-`cokY+UZUYMgGd9_dGMcfn;7bC3+td5eOV%L%!oZ++N0xWdSuHolEM;~~p= zKAXOMp0)D7%(W> zPiz-kN&1!6v2>$0>iEd6qtGcD@N)&vqkjRTe!s}?iq0WfEj?cS8yFeG^>vIDoS6I) z;L(_L&!F_YA2PODa(uN`uVCz2ljaUW_Ufn{x^;Q4&ZE&@oqSI${?NLkI`Vx>HR4mn&!FoMd@8l z9(w1U;%3unS8`bP^xH8!o`NG>chZHhlC-ggP@=(pahUG=BupWyjR z#HknknsjMC9Y~)#zV+GltGM+NpWhH&{yyLOczine4Dsy1F3J(dTevs+2p_`trz?0& z(--S+06GS~!cu+<&Pa~DRmPuAor-)vq;pVTvZ#f330HiB^(Wjg4n04S=W0v3f^>$; zb9Y=@lDB$p4MlAo%{zk!>Zy&2u29Q!=_s=2ZiGgYIdUoK|3Bg9l5eunYIwGb|7C~2 zS9C2tPx*G)JD+D-9}Cq6ziaqyIbRRw^1sLbIuk&=A3wtW zQ`}#MPd5d_@;StaM=O4@+O|fzn{EnD;XI5K`Mj&pp={Z#=uJIMJ%Rk)q9e(ScKik& z-{P0;`99|RIdg}m_?_gyk?=sldR;yZKa6Ui?J5{m#+Daj_$xitIGWzoZ)=oA9GJ5%1FeTK07nrT1vfsqOcIcfs|2 z+B9nn*ce!&bZ+%0T#Bw_tNWDmz@66RZ0wwm#w@cxQ@Vog^8B3SDE7GrpW1Uu*-l8)u`eLVE8Hnonm|MHSr>kyCH{>E7K1JJ3~vZeTmhfH(Cw-;5WJywft@g4XfjKt3#PD`ETbvGFv^FJw zv`)32t`vSLH(vIr-fUozp7lEOf4@uI$?Y!P?;>xgCpjZ|ve6kRiq{L~R^~yt%eiJf zl#~Oi_9c%F$su?!8$Aral%I9d>zvgO4GC9mLF6Bh43)f*tf8M;U?D9ol3zY$ByZGb zrG3en*}VTX?P_i$U#fxUpO_oSY8N>q83f%oR_ueyeV7NaD^yQ%=ycVk zj&N)EvI{)a6P~4~*YLmQ`UmJgl2aR@4auVq>^m%*&fs@NHfjC7T{e;YJ8D7aMmB*b z&5Lj=*(AJ8U|s~ba3kGCI8OQCmUjt0fpbe2~0S-xc|w z_9Y_(3xSPDJ}|b!@pu}cz$XqpVHbo6StpnHgQme?2IfAW0^4l5h!Gn>&(=62PYS&{Uqf%r<)uv z_H`dcJ;@f;`xI>}rmgm-@Lcl!)aN37Ky6BQfH&;dcvNPR%btecMZQ79d;GF4I27SB zTI1l-Wo4WppbA?N_r+p&CX%Fq~SDT`JjrsSS=QYXX(dtgF@p-h7AHc=OAQ};G z6+R=L&|`Q|tG^=bvm%)&dad{})V|T{f%AFV7hih2y*}R8Fy3B2S#txPB!4S7lB{}+ zc8oph^$;I>%*duGD$Dpj&iKUZ)Ne({h_P2fejn)=hIaB1KWxX}Ejvm&MviAG_^osb zi*M;1n|UUE<9qZMvR)(y|0lWp;19<}UzGfQTmRa_AsRC}4)4^T`V}ndS2T2YfGjNc znJmLGK)-rtbP*SxYvwbe72!ej(@U9O0Gnj(u5+L(_|2>2iVlO1{|(+-fOnC~SHO*_BrUMv(%g?heLjE ziw?f0wXPTzevK2$?I zR6nEO@!;S9`8zr8t363_zpx9L=(^FK`w4%0bJRkQzuV!gZD{j1_{HIG!LAv7oEi4Z zg3mY=SH9ob$DYbf?3dL&E9=8~Q-WdcQ!=)KWI>HJr68K)+>b!9PUSm^H*2qAk~$iL zVo$OUbSJv-^=0rSyy&;eNPpjc7x&|Qzq+Wsr`o&KCp$xOZ78z)v?oTg>}Y63v94+4 z|H$`p?<-@YCqOUS|7@cNTRCFi?(*;@`kaoemETA{fB3(liM!ElzYqMP2l=c1mH&r4 z_7d_rG5<)|PRx9t{dnQ!KfTHM(Zb~=rS0~^?2ps^Z^#z(5S__k?l`&UCT~(xbp8#` zXX?H7Of>LbXW&TQY0tj&C+SQYgU)a11Ln83MZPNVRNuMEtERn#)jhM8yB}vWPT{7q zhkbwCYCH(9(46j?w=TTSYYNxA@uuN3ikT6!HKRVPP0+(T~I zCePuqg3Ei2)!5TkG}gI{Q@+}{yi;u6H9D19FV$`3HF7<4>Vq$>mw%Bx;yhRI*~4rb z`d?65Dt>^@rT5$eQGLG!omh^}K!LW*-A55^xuUK4r6t6>jGW;26_l}qDaE+~>x}lK zKd2q@IT{U5;J2Q8f%?C+bP>&Eof5aIdw~%J1=O zM|+c{%jnMCBzS7!|B9WdeiPgwxRf?dns~Xi)Oq$55B>>OAE(P zR(+8}!T0=<<=j&LCUJP_v2RS^jsfeIurA1zz7coH6YnVw*}LI|W-nx84RhNugr1t- zWbz!6?qQvqeImsy>+3Ur9vc;XWsz6n%bsl9A?)6A-PXaVzGC0^`_Gv@U`aPoZ03K> zsqH09J1y{)={%dxcMIR*GX?lWe;HT5m5-v#`(@{z^SJgkt_%A;aLKxpPt(qK7uUGb zPgy5<@FSk2xE$*<&fSQT%~qB(ZJCRWoF|oHJjU`5WS)w$pNWe+{~)?bu8u zd=q;k>%3@m8q30#lE260&Mn4cACs#^uVk4-I;8enRs&lqKM?-yJ=mYf(iH1Oxr-B- zt5n>2LiUMh4V=d50CzTHWxR^BWn~ZZPBb)~z0>*)jP?EWCz?p|d@nhelAp?Nk)H{k z6^ExJwGUVDQg@rdHFXz4Kgz}8eNp;fmhS}LX8!T%SM+(K&jNER&!qpZL%$clxtQ3@ zGGL0+)~_|knnQj+1RR6q-=p}w8jgu_tQGT6yk`-48`4u#KC&afkvZX9Fxowzc~SgW z|NkAot^6~{esG!Pt|#8BZN&~c_}xyq=a?J$eO_np(;B|z3-EaNb)M^7RMB9X=b}mJ zoYM0)3x}M$Fz8AS)D~^`)4?KlAp8~ZtFI1du{{f1w59yoxxBNzmBkKxHqvJg(DowQ z)cECJ6YbgPztSU>;~_lGrJX;$4E$cM^iQHyo~gX_N!bj)<6VvDkNJ?#UolqZWxvYE zXZ02ND=DY{Wy39|4b|mxSJS5YlAgmp@%@4&nL$4ZWK(NDEq59PJ;B_Z#(a6u(lroH z&P6$kHEC=&kNpv97nrc2%z0pD48&`GM*G$5@6^3Bb94AUDBsd0+{@-)g&tOwh9%b(o-{)PW z4l=3q8ZzPQJQqD^t}FG}lU*W5qgp=F1p37+>fcN`@n_{_Xidpy;SS-WVNGc*>Fl#< z=zxOL<#RH1G?Hz>^;33j^xI3+M0=nZ6eF!d>wk_({(67P&f1@)>R=q`Ubfh;f3u|3; zKgMwbb5Nnl6J&F^tZQOHx^qA@&3x~-y#>WBQ+5>U7`yzrrhK_Sm4WUaey4I3S+E#c zu-MJ@fb$;Y)H2B}t#!%N$ML0$=Y6R)8pqu}aY!puwD4VZS>mM|!#_M7`4Ke_nzy^V zz#Vlo7lP&cxdEeJ?{hg51irAHPoB?CKKNQp9*)XszGu_tUY-Zk-@qPUJrf-3`K@)Q zb*iu`NQvG{j>kYiv=pnKBFgmpS}IEKiG@%0`1Nuhd_FqbVFomwc;hpDN49} zpb0zZFN&_(gT8PV@HaooxpvUWE@0Rz_%Dk>|syLoc_TKiw3j|K}LYBpCGoZ$vF(2DlK=)78J=bO;=H(6IEe|0vv7tC$Yg3gJF zdrNZIY@E-q?mqICbJ7jk_@BAk68BaPF-Q0D?7sADa7MqXt8r@G{OJg5RImt+W3ln! z&86#doB^E%e>rUUwDxUVBRYer0iQrEWnQAL^86AW=L@6TC)s<1|74rwwc1WNw+v6t z!?z`)0_F`rE_+U2(OyLH#mBMF#21fa-lDiSd7i8T&5LpvwAQSABuk%viMug@kMrb= z4*zHV*E}>^1L5bHhi&+2`>7}Xp>_N@?Q_Vci$}3;Z0^XN2t4=uj}@d3=>2*A*l2$? z^2biMR)B+`lw*!hg6FmStUH%EU|ne(w$oc|cc4@BnqGe(yx@^Yz8E^B&Ul^uN5G{% z-mbI1Kz^~-%S!4e;5*`tt~vKKS4;U?^Z^HbpgzuAp!bFiz|k>;jxoqt9QXwVhjdoo z-4yj-VKg*2?va<py5Dt!0fO|teiajS;!>E9tH&u8B?B}c%opmmn7SEL~D4)mqjO8)P zt)#B%P35;}%lHd`U1g;Qi7r1xS<$8Z(9&u3&iIjeH;Z>0DJLB%HZJE)_^;?-<8`DX z)DJLxc3fM+@d>n3(UZOGCe8`X?WyR?XZ>yLkiN{ja0nl$bd*`NCEG${(;6{!N86fj z=_U?sUSFn_Yq1>{1=t4;GRT!4zq-hL2h!^Wk92UxZ{(83Y?sF@{s$dZA3kr6^9P;W z={L6=_m1a8zCnNTIbCDUF?}?=nlnpvj;ZK7*0gT8)g^9&9jG#PnNFf}O&<--xu!GL z4U1-eK|9ywptutINV;dks{Ey@Sk;rAJxPy8yyx)i?_4)$=)R|OxRE00a`a2Mrv z=^gS@d_;D$*3iGbJ6fN@i~fJ_EaD3A(IvDc9y&WK9=YkhwtU}x&l6J-ERwYbZ;VNO zGM1^fi+p-p9*<(*w%-%eT8PgfpU3Y@8vdHqn#X6&^Y4s?)!RASL1#;{-xEK{BI#d^OY+c?IU5LH6?(o||1LQWj8A#U=y%Aa zc?D8m3~x}|ZhoV&Nqk>-s!|NfQ?@-Tx=-DT*c)Rks^`>cbs^bO`D zK=-9i741D9JPG}A54CgaaQ!6Yquw)Tb?|vIY;?cGwyLgNp^Ldy?%rJLoy@p}OVJy$ zvmUuN)pGmm^-g#Z|6J^{_Q09W73=Ueg-?K+=0NXrrT0-k4m>V8#bjX6e29mMmOn;0 z=^h$u2Y66B^0T~-yb;}K&C5r(kTwOw*_soc-^lX}&t)g*c^l6Sf8d?up>zlFMZKFT zSojv7aEUJ@@DVDnwz5_<4<3C-=S$;z^af`N9<2lUX3x7xdxaw!mQG_cXVP!pL%X{3 z2wq#Q_etKR%YBMYjxw+w&VR0qL1i7)b#o>+NMoq9UoBXHM><%guLySLn|ksk*s2SS zidR5soh9k9By}fdx|+5o@&m2F7wGb>xLi1e+i}Y zQNOpJIW`K<9jW+=Kdkso*>+RR<5imJ}u3Q zd|C2iad(yB1D;EM$69y+bg%bXtHy?sKFWNluHhN@?pxTuBD+&%S~$no#dkc04-Fn; z69}tL`SN3%`>60&{LlAONw-dwa~-vJeU`fi9b&54Ln)a5I`!$of#Y>Aj&vMre{&fR zXM!``c_AMBd*cgVSh|AxI>)dgzr^3BF*je^7U?MB8`Buy8LT7uLnP}h$|#Rjw9rvr zPnxF$ZAp*ObM12%k39ogIY52zZO&0rUA3VyDPU25e=S6PRh}#F#^~$3`vdPPy4h!F zUwl$)Rrpq{Uu#u-LAv&roG7-|oO?UySfgSd1Obg}M^m%1 zI%;+4X1Bx4zyLCO1QbNjU0K(jk7Q-$!x1FAC-bD+@_W74K1a~{ z{_gMl`(w}Sv-jF-eb#4vp4Ml5)@Nz%D%z1RL4F1K669NuFX08nlW?y#UCJDaf8lNj zycoP@2E)nVtByP2^!vP%td*RtKNn8DLvZ=ynlHsY^@vchfwFDQ98)xFNBXGe{SiKX zc1NVY)MwS(1bnwr-_~);V@n%+{|0rh28ZIqdfrj&2a{tnQ9D~rc|`Pnt=hzgXxdY| zd`~`zp%U#ifgjn=m+WKxmid=r=uX$TGsaDsNIpwGrjgmADUGqlTDa1Dx{3dSQFf7N z>&5rgV)mG;-39%ttdXz0`*&>n9g|uA1t#%C3SLn?qG9FvmVGWybLl6Q1`5&@+kweZ;gWUN|v3kdll&F_3#x_{)^%<6U6>?amh zhr1Zph79&JFlwxl*i1UVZaQuLsyP}z!Q902pC9r&&F`Ppe%t8MWMLWgo<~kF;vKo# zxTJILnT#H$J!~msPZ8gp^%&729@$lL>fUk`O_Jf8#qDaxiC z`D!BAW&@MPQ7{R%i|LQrR$m^ayw=-B@UFSYnv-D5F7&&3X65An*hF85aU*6U!8%i$ z&w6!3($`+0^U1%Z`8m1ke0*ZyYlg{()5N`SvNT1z1uuB^*|*RO+Dk-!g+jlni#VDg z(TJJ%Yp#^>6SurZ9D>$yfsNlLem+@?XIuUnF<9hJQJ-CVY1nCNd{~RiMlt!4M`{zf z9sB{^ufEpnmj3P}POs5Hrev2G*e2T4MXb!vCBOJq-%YHI+eGSCUH4OuaLIc!#$Q#v zlvO#spFp`UoGSZjN%%`=ckoM>9EDE2l5l&u|IeU{`bC#r?vi$RzO~C=+J0h@J$;^@ zUr@aiIjMT4!{cs_cogVy*SG`wehqH)+^WGWI5z^P*0g2sKzq$m`%$0t{x`hWvx$d% zb1lyVt6PHu*jtr{DYB2TN3pHRHDh8BEQ@g+HO`k!P>MaI^+fD|NH*55!G1`alm|3mBAJA@B>A!l>{G46ZH(v9SU&fgrSEb2uj^pr)jPlQ$x zx}*(qxEMQ8d+zbgCzyM-Cd!O2?@n^IXni5oOfKULzfUZ033GpjZY<8RwO56o18)|4 zBDH3wIBV(JB<+0Rhy@kdKmE}6=aBnN$ZE-T{7jWD zd2h;3j$?gD_EI@otCSAr%%4iP)6ajc`7JWOx+&HcgR7%WKj&0CIp;z9?MlETyep^1 z3hsqd?F-C-=P9+gh-uhaQ;6Bi&6H2488LfLotJpWyb)z-LS>wA>Ji6xB z(AxIpCI{$+Rcz2PBNunpX2z;7Ee zK;MIZGtc|bWb}9)ZjUvC8r&OeaLXQaYPekkUeuoOyqNn#aW221+UW#7&7b6>6MaDk zRh9oNe5;&h2}ioh3y#FEatVAWSVl1ytMijp@PgxL)8Gl3KM5SQjgR)?*7;2OCrO@O z+5S5oS{c5{IoyV};Dz~OWM z7@co1)q(Heo0IG?XZ!!23y_t0!=Fs0ggzoO4 z9gVN}S2W+3kPL$Ec;3T#M^)8keDi=WRXA*w)V58n<$f10KeK z>w{-*Jsd{9>6LrLFH`t-u^Wwp&S{%V8_H=y{jt}vU4M$bnxH+6@e#<0t0^NJ``8hY z%y@zKl9hr-a#8D)g0+)+K1kX6w>IDA_$|I|<-dG*NAf?pGHJc|S)|ljviorrZcSLf zTf;s^Wcx(P_A;_P>jm8fVi0n)f$mEKcf1Jw8=puad{(sNGIk}-7(vd!lg$}VXK+f^ zTqt=0Ek^NIC(1tpemDc8IcB}DDjBLc)H|=b$>doQ&D}YPv)%Z1c=C4In^}Dn`qlGz z2EVMsJg|oUi{3i0Pk6cWs)gain(Q>P?$lPDZ#yQPiF`L{{5GPWn+|7P1Yf^o#Dlb( zqCR~;wm_b%+V^Q+ym^siMRN}_1ey-iu5@yb;x3%)%{rm>mZk8!Fs~caRqK=Hb)B{Q zN4R%%j~ymI7&$xfgGKgPnfneC=Wt%tX3XxRt%=M7ZS0l<#MVIX@PxjNd}wCQr{5Va zWbhhr!ugkDY#UgieTf^O?Z@Gae&t^N$$*8N||*~tIpufUfry#+0LHUAgzu@0tv z9L-v5jr?C18vmEh#1T!^=hZ(cDh~wlv-#+`#zW_pJLF1J8RaXvdb8y3oN5#NbtPk# zbRr$1dNeox=`X1R{0=w+eiEN~FS+StFTj6(yS<&Y>1aOx@nfU5R8Lbz`+8?puK`Eu zo8n|Uy+Jd7YV)FX!<7pG{4!)vy*E&FQjhG|J0XG+Essk!8}wj%0FYy9ihL9jX@rg zONAIs<)y08Y6E>&zQ;5;)HhaUJMD6Y5%Ub~eX$+I7-;Scy?~E4bB5Q<>LlLD7aPT8 z&j~ok%WWK2KbKU#|FwvB^4HdU|7QX71o1U;Iet8GTIlu!^WaIq{~?}dfJr)S6!(Td zp)1*7rxHUumS^hUx9C?heX(8o=A#E|<7;Iixz|?f_d&SGFFmc_O#)X8UOBifvG#2{ zr<1zV)F-@%uT2vp<8eYbqAQmB=K)5zA@+ z(FH*~3(oW8$c6SNa@`5OMTrY5`zUR5H$A`|Q{GD9ux$fdBah(Y+@vRU2gzLv#KjOl-KJ)`FmHiK{ z?{j^R>kh8(a(##E+gu*k?OeBUE#q3tMeOO&8m?QoG)AkqZsxj)YbDnTuH{_n+ehfb z5&S>E|7W>W$8}swxt4G(<{IE)pT*EZu70jQu3oMMT;HQl-{SwjbA6NRTCU@%hk4l$ z4!ogL_&tWp;`b%|m&`~x#5EpZo(YdiABuMoNSu={`7uNKHx}df%DNtc&ZnSn#7~Dl zJAr5T-_3r5`g5IIC_VRP+`9MZ+If!?ZS>#xCj!SF+}jSn)!X&?R(tU*&#RvOpRzxQ z_v3dD_u^UU|CD=B4#`hA?rHdnchYszosGPoKf>CFEmf7gQW>q?>AS;KwxDw=YkTdG zN6pAm_Sm&IY2R#)wvh?)o9R2weyJSAw{vs721n8ZDe7p<>)eZX?boA@#+F{ry|^V* zf9h*oKcY`Cf@3J}240I&)7R z`!F|9>B*6sIS*{u_dWT3<3k&1`j6g_9I=tl(v`>@;iM@y7|!JR-PlYT&#{uvjA>hG zZTKMd3a@HcW&c2%(gO}SP(7-52H&c#v@hFMbw>4i#+Hll+XIdoC@b9G|3~S`*;V)m zoinEj&x{d1w0}jkCOrItc5G;1BKOiKYP-a$%8xbABc5jc;Rek3lQs1}#L49j^ralNJpxkWPr9qZUZ?BQLPdANmSwcdQFnFXw-gcm_PEzrua%Xsep!e+#rH zdaCp6m$4C3*f`R$#%7@%&1cl^cwi9CU!d{eUTYa$M|1CJ&4#`?(6T8X;pJS)$rq(I z#XCPcA;Qxe*x>bX`@}!M^JzTOcxjx}SDpRm0Q+*_oB-X6_aC57FM`_%(#PaLZL(H` z`>0oWXa#o@-)f95VE(DG`7hqt;8y1qr}-u}VpR1UY^WDl4{a+;p3JL`1s`Jz>rz%> zZF`faXBSqROSN3frQQ7gl-3Q2pCOlIi9Tr_M6M0l=gQ$fvh;aBao3~F0a;6<&%%-6 zBYvwNvil}0Z!L4JGl5_G*wvShbHCnwI*6xRtL@Ns?9@c%8drPYW>zmUG(T5)hjt5> zojLd>3r=$pP7@w_y~LH_cbU1mJIK7?!YXon_j-G0AUjp(Kq6}qzcZ^Bh!)5**oGbT zGBA&|SkK^FeP`AYu^Cg;)0tx}n|3}=dG-4Q{`Yt*iFsb^t4{ea1alexlyG8fF>ovU zUHR0NFP(Lo){nUx6GyubrR3L&t`k?uV za;0)_VAVQtlSBVq&U&M~?Ec0^;gnc&;E}&f@i`7-E;O7rqg#zi#k z;Pa7hL+xw5HbK2@(5%`w9vDt$pO5mIU&yb83j(S@b_u#odrW`x z@D_EcUBM9@)hjnZx}n#J8t&l9#iq4W1VpYYm1d>gI+5>&N~eIl=GQoAdPlr+alD z{a?-h>-RR;tVz^x@^FK4yZk9stO9zvnqv%e_`+hxZGc~uuYh$g%4$q!<0re4-eStT3He$GO$xnZpYf_^&!2`(_%jNdCmh8zB0YZ+*Udxao`H=QjbrVk6AFJRj*R zjlm@JkjCm#`*5Szrr`@S{zY55j?0c{Tx;Je85@;-4|#+CH(PEb{62xTsJcD(Bx}0{ zerIgubCO;3#k32|Dc~SKq;KLSYOpJYI5vqnuiYAs1tyh!eiZX%zN_bCxaw~Q4mm$9 z%KLC7V_3(7&RDPGLSs7LJ3Q?BKj7hcXw|?|!@~jcLl`_*$Zp{R{0kqVpYv*Xcoca4 z|KI`Nj-gfA<#l=#Ep}0_=>0j?Z03O%>9PXjJRC>vS$)2qOJ+!irwgo6BkN+s`bamw zNKCro-c?^3KK`&^&XVi2R_Bv^`w#t*7q8rN7vu4FzR0Uq?qLrIa7N=_pF^}#-#XwI zt}N)Fi!xdd(eF3Ghu|kS)R1Ui&tBu%S(Ir)E?9oVpQg_~aRUxzpsx;KZQ}QrYOs>e zZ)i1n7tCA)9KaW`c48A`^C@qn)-hFw-V1M6)xNup?=;TMjIrn>rTS%mAj|6Z@)E{X zdY62MyJID<>J-S|RbY-(LYI2@s&kQyJO`NceSI#ZeKb3EMf5KlMQxurk(}3zllrN$ zby`cZZqYz&Y8&+bMcUK*40sUD>kJXjiyiYDjYp399l!b+#<75}eI#`>(;t=B`qST* zM)WZ@_O!_2EEAEn0r@bW3)NOMhVu?j_^({urZs|CeLN($i9((tBJlV7Hvy1vU48R zIHUirteq)zZw(hmsZDQP_%q(ms=fO;?^I7G?=;_As4~EpL@&e`$D~y>aLKnW*gA;$ z7hLj*%MKDgN8Ni}%NMA#Z6SI5`Vv-CKjsYcJy+)xWZ@}%O!18Ikuqo47TykB$_7gU zcZ#+zd_%O6Wjxg<*`La#K(2W1#j{Dqbv&?0*PjL*rSS>4oKqovWq6vtj^llk#TpdWpT5q^Q9h@%gDlf{0=H~L>EV&UF;;Ma7s-<=D4W7xyX)f3!G=#8e>eS{ z18vTZ?Vq-JL8i8L{Ry?7qrGe-%VL>Dm7dI!Fr8T%#-aZnqst@S=y8{X8Q{JXpNYYn z`VKuEZTgM;c=Dakm(-rW%JUR>6%JKi@QR-W|MR?a$ibQ=4P=eJp8&= zw0>jO=}YuE$5~nh@>}Iu=PkoCT+%zTg*v$=aB1JcXvSZ8VcrkTux0u7NUx?~CHKq&t?@?sM?$0QV=>@O3dV)^avMk8@0Hh2=bH+JP=j zJNov&YVF{Q$4zGqMc+IU=4x~-UbI+85q#&?zEe9}Yu{m)FchDP>L+F@32d^FE{^mL zGVj(DJl!fj`4e(RebV|)Q(5|XUNu9VlDqn@tAs7Xx7x#>bgtWwbWh)a{N0JX-4rYJ zJ&p|CMBL2d$laY9!!-B{@kQuc^(E$9R|#sr1!J7wf8uxA$f$W*-)SBumPI+^fr)(? z_?q0$_*RLvX~upc<88{?oWqIU(|g$v#CpFyZyQ0on!9NpmDJn`7-o=9THkfpI^$kA zzl#6V>8xj;oflkB-R;zU1N0N&^;6Z0RnFZI-X&eebM@f_(OcOI?yb?8^6AK~A8l<7 z$LGDoxV+aYIVK!h$mYLsu4*!SBfKVli{$V}v3KIdM5PmbD0$mO+?90U*Ne|TlePy# ztI+FPo~QGBh9pDegA+Zy{#T97EF*tO9@jihYfct;Kz}o$>1*0r{CF6K+VsX4ERygT;!4pqJ`JLN;>_(-IvNoCa1AJ(z0%@9ZtlYt8m( z;^~MjD=qSyGU$WSb+m_Hv|I?|`GGj+owSSRt^DU~*2Pne`O9tD7h0D~yVqIC0{g=0 zZ;!h))#yNDw#oTZMZPcwv#YznxoMa7eh;p+wm#Cm!o<@krlQeVOpM)NSOBlmQ>;(y zR$Pp}?Ln`cK-|u$Hs_K@dw_lE>_%saO?%?A7Uit~pX_72DTREFL96CW6l8fyvgz~G zoAhrA8yUOfXiw{C@{F&BJNr}BmAunhyXek_$7WIYh+@tkkz3?9=*8T`qf&q14vQ!L*%it!Ibga6I9h8B5u6lKjG zoC1BKU(fJPJ{y(Qx6+e(?(@73zuJ)9{5iq6;LzBtT0c0aK;O?T_hPF;JAxq})&G0y z(X)E}s$01de|Jdz3G9-0uG78~KlNCH?h^BW68lR3a9u^Q8PL72v57m2{46>_`>!qo z@5l1az~R>MLe3Z3Y;>3SKcrp7d8BWM|D5*{~7+r%1^ap3$%-FBvX#TC#4u}jY%i>O}RDL z26~5oBFl4P@LbBj!FcxIpKfp#`r5mma2GNM8Q8@8ja=KYEjID(CjRe~Tu5i(_ZV>= z#10~GcUvXpSb;CWhxC)?xT0tAknG

9@|l#cm!Gt=G(}eu_3@CCQw)t&zsJrqP8SDt?85u#mK6Ri!d_((_ zdVR&^jzuS%*km(TWn3JsVfTTrGb*Ap*-!M@m#^;lT7RZ{ejG%+)}@hzQ$Wt>`DGK;tlEVPttFlYh?D^6&MeE)jZ#JuI+8_a@pIONv}*+WmMczH=hbefp7YBY9cT)D+r zA51}8DgL)ZPt1*18968U_UV|l*|C)0=SqJnV{frHL3zjpx6X+&^Yj8|E0-2mZWe8q zBKuo?m;Q?S&AtZe{lgCFunTlX>TV|s4vNf!O5hneESp{5Xx=x%>Gc&u-p1IJ#yxIi zF#DFFztbuYP)8GU2-bkdXdczXcjD!#PEBWIi7TOuXj<*dpRc*A>K6WgDi|nJFONJm zd$jK4x%!l%&+rdEf|aI^@0RmXY{om~QJsIzgU&^RT5C{T%xlM>d#F?R6fUQh2jJIr zo5(4>sZIlzK?AdDHoTD$%NyW2WcWDs#cZ zQsPKgfk&P9MNVYofn*CYa6eSPXuq1o&Qi`Q!8pR1Sutzx?$zWD`MIxgn)f$y``}-x z_Xm12djqwvLAGFAwg=y8Z{~|nF%IvNUFv@fxI1!+X$4OH3wCU;A<4Lyz1!H@$~E`u z5fN_02as5JH*JZ2V+F6Oacgpx`l4gCha4HzlU-Fimm#8M=p)|4o{q$fRii}%TCY(b znhMBj#`pV-r}`=1nq=Ne#zJ;wecUAzHTI&rV?`6lP5RfYZ&G~Ib{KveV6Nwxz6sn} zW#7P~vlXOc=hHVccIV!|w_}HVKg6>0z4V>x6`o?~pZZuQs6%zu@p*tX9+goaZv&sg zy^*WXo?>vwHSnT7Q0)I{p!Egx8ARL0{(qyZWZ}?k(>*u#X&vLl!c8D!7oHr8YI^kMV3L z-+Y|+qEo>n`q%qdVOgcCC|;NwL^OQGR>2FcY(lo|9N{kB8Y|*+<394a4QvvOBeKhU z_5DHW6)iVFGq*8Tb)7nmd-=yyr+jZJn`C?qyo^yaj>|X;Z&~HQn-N`%puFhfFz6!U z&$;9m7}&%WEJcj|}cVpmh2>K1LOJ?W%QEBfXH-bHgPp7UPy$iCLTMahGs59#Mj)=_2S$OdLD z*Jmx)#~%=$Q-j6wB%>pLMl83iqP+9?EGkJal0|~`T~b+S|xQX-fR5-ztF1aWAiJrUGX1hpclad?MYW@{LOe0udKSQ?4mG5y}DQZqRrdVcvJ5ZnO?sq!yXmK3vMTlQuUa#k?|>aF()u*rxYpY8CqkU7!w!$<_?aM?HJ1- zPqM|Z@G^bOM>PJ)4@NmkE_JjP8rfvVhAzDGjG;@xEjB1}c~L5{;O5b3d!_O5f0#Wf z4HkJ&Sfj`<`fj?>K&s!0xn+-Q^L#a?r+CzeV>~KaMQ~4PVJS!_Pc} zuD~1fWoYX2ydUXAYbnNd({svR%5%l|%jX~M!{J=IhnBhNxBa&7+=mkbz74<=D?uyy z2#yc4HrqsdYD@arrCu|K&ku$VP```r5Nvv{cw_0JBdJ4tBY#AaZ@;B-$fIU{Pv^N= z|IS44pUS&N2mQc1Jy$(~{iGV~5!?r3Ya`q3op4LHN$(@i0^#~_=tKW+hX=Z9cA4rI zEZx-oDe6}Ip~gt%+VU&Iy+4$XK|Yh4!jm7={wCsS`28K~RgN0LW%^yC0rJFvc?Bk#y^NmNWyy~W6Sr5 z{w{fj+=<-+saOX3Smm9Azcfk5+&9evtmu>0UIiXCLR?0ME4_UgN2D z%swW4n<1uw_ut~Z?vucyZ&a`7{p&ne%(rAxy)Bhj`>N+E-YcK7-a}jAmD~@1;zQ3O zw}^o%h8^;GWFr~YfbYf5vA$7&w)vkZdI9U3;AKYePyDya+t_D_&F)RC+{|zIb!iX3 z7jb_I_pRLLx&H+JXEP2R7U$1CfX^I$vE5_MJXJzz54bI`tvL9RgZrEnR?#chuu7j`l)z8@Cxj)#Ne~4 z>u13FAGNwJW;`|Cdam)-xNFSo<4ulr^qd!DXnzggh@V&|Gc@Gik6fZZ`VP7^w6D3) z;o$Foqmep&ETm42)d;@nRsBw+`y*P2e4XD156FR`;nP`5_QiYHL|JrxfxKn#$$PB_ z_O31yvz0}5%%6B95^V`{>5%1I`w6ZiVn9{M-%Ah%T@ZSqCJ(;t<-_^9#ZCW1{W8`}h78ypSXE zplm3-TQ-SZ)-;chFr^)ZP&+^t( z)aMV0r#*ODaMt?&5_yvzpic3W4-R!N9{v{Nd=K|^o*tr}ck^_}vpP@97BjFmM6liq ztjzU@A6gy0eqXJed)(VHO|t!R+7Pd6Of|OemhG2;$B1tg6L6?(UtN>!t3$zE=iO6* z|GHY6f1*vZFVZ&S-2xv5Dhr&kM%rot=Y|fT3Be*-ke>V*_=sZA{=Us)z zz@v%#h-fO354TZ=_8BPFWUTaN5f}^1cj4i98J>Vg6;mdEzUBj&4E`RT^?2k?guXh> zJH=@&N@=}cHlyMy@1#$*i*05_XKgfE}V%@tcliA67FZWHaG*sH{F7tWy#K1PH|03@UaY(i8I+G zT*?Mk-pK~+spGlVnv<)4(lzBwdmXzdG!9kt^kXU-*_Dl`Zy?yWH&K5Pv)aZRp)G z;QJbUD~+td;>R-fnB=+Em`Cuwfp0ZdKOK+10azP&CRnHDmu%|FE!i|yGUG}&*{Ob=<=hC#}My3GxB@Ss&1t%!EP4^+tWp_h5bIwN#a=qchV=mhjm=m zu|vW5QhBYR&6oV!Oh0sfyX?=T`d{Mwm_z!Ksr3cjKE^JR@32M#v8=|v$o|)J%-$QL zFWg1sIx7$(fNfBeOxIqF8Pzwbx6LBH4t;HxSM0PrZ#y)w+xA(rW{Ou{$kF5DChRd zP&urXFQ%JV71{FZr|bl_EayS%j34O6DYiqqqOo`Mu`XJ3_&!XQD6TD=w_8&95Gg&hRyJ z>;6<%N%%DC=Oes*L73hprPxb5MNa?y8f7<5-cn-&*X`0_7Rtn-sp1Q>a^VLGoPn zDt1tER5*N|`V+j@-XM*M-mCA9v+C{G6~V38m65_5efd1)zsz?hiuP#*uK;K-(R5gr}I#e3o|S`U^tkV$&R`s|KH*>$kqwyOVjY-+HcR z>X)9oJg@VB@&BX7g3Iez~T*`R0lG;yvq_wahC{kX&I$Ni^ArdLKhI=#|TE7N3q!CxB>?E5*t z4=V$Q$J~#5(bd0ON zE`Nw|`0%;P;b`>x^ZehBt*`m7Rg7{pw4smeg5pAFR`>Vazst&_|B#nT*UgZsa@VJK1{)=d-Ng zkw?=}d{Cb`zwg=-ePUdVj`DoutY6*#-7Ue^?`#R;-qL`0y(^0p54N;x%}S>9(DmovsDO2+6w~VrH=DDyu;%+1>#fTSNdG`TavMmU;Ww= zv2nDE;vA|!!zbMw`Q&eG$L>xUpS&%fe3WBMxUj_w;5MoY`lBvvq-N>^m#QmzcCfBu zd)g{Sby=z_Ykc~uYb)>{xWTG!1-iu49Ti;N3vqdgd zJ$q93;7M}=$seoanK4n!tmr}Xp}Zt*^!r@OF0RpyY~+~58c2Q`Yf~3j>{F1p%<@(kIGUl;k%qR>wRzU!YP8$HGjQZL+A-quiosI8(HvO%O5b!)?%%NCjQ;@s zngZQIgZOFJg%2!1pNb|aC%OIE_aZl#r)6B?LnD}TLthBnviR<^3;kV;K^telwA-7Qn=b=*o5KC$%fY4K;R7}NIoywh zekA)uzr&NaVSg^v8fGgtsG(u(p4I~XpVm{n7WRN1-o&`BpR_3$P=Vb69e{EB+*zgu@1&W0^ z44w5~3`V|_X%{t{29+zaeu6|coy z$t&4!il=y-chP=F(Qw>h&*Qia#3>k>scL_dbc}3Ba8{kxfUKoF{NKF3ycHT6Yu4+? zxiCg>61U7)Ne9lX-e%&YSl6TP!nfq^4%RzmD`xV*LV|h1)iiNWB#KxBvFt@pJPtJ>MhFQRVsm-3f{9yRU;YdF#_i);} zEAId47@eS;uc7k0d;e ztaFOWPsx0_c#Cv@g0W)CJd3qQ@8{$s{ElMDT;@QrOm~G`9L=TQvi3E+`;`O5v6WAN z`-}1yhH-v3*^QM0c1vZ5aqqTn3O`>MW5!dte0mrM#UG%zTNtk~pC&&=q_^ekg=Q#<%RV&qq8$a^iw zl~%R&6JoTw3LVhS1;LMiUu`uOYHbx3`$=pC*$q~Kwu;E$giT#~h{vqyu2CopS9A5t6s2`tv9(uqYycReva>3g~ zuX=gD8Cm63OGlp-IOMFn$UO`C7(jO13Qe#!S{y(o4{&Y}_7L~BJrG_E9==+m3)zJi zKo?oYFj*Q1GX>G}+$w*@q>HPJB zM`KrPL)T2JoK2p3<$q$oP+teWzwQj@>v_C~E)L@P!r%w=Lp}u66_+hi9t)jc7>uip zsa3v=SjZVcLwOnh3lW}cW4eoWa-n|BznmP6Jai>}8smC_V_jVNC}TPXefeL!GrAIZG)9sOe>e)6 z!g!ude>4Z6{vgM@R%~1gdAk|8bt!F2<|ZxH0{{%!E1e|&zCGrmX;d*tK6?`%yZk>52G`_ z+BmDt!k#`C*)$$Hv0e5$u*cHit&IIP(W=BAOINOT4m_hdMWW1^?vzumKighpzDt)E zg<1FX-ne^YZ`SSWwcOt>l-`z)%KW%-K;WpOo=%_X>GU_TWQyk@H~A% z7s1QD!SJZ3$s4jc*eY3RFU5}7j7=Bi`@~jAq-b|KeLI&pxi~Vjz_U?PB731RPcDo? zqrZN^=3pUXG$Myy_u!K}=hT7Y5f1kSaL71Fp3LCc$PDM9dxo~NX`8~h5 zE_}&b7C@h|-@wzm?${E{qKw|JpY)i{IcRo}>D`5em1{leB<9_GgIQLc3x8h$Z>Mv& z;2XjQBwplK_R%Y5b9X+j>8&)4v{^6R+eWyp}PRjcsw6*e>qOmj2DcH6A0iUw_HkbDL$ z%%!>=;0Jcc`Anr{iU&-bXE=VTd9MC$?PQMN#NiG2AKRM!so2xA$?3N?{CF*Ao6g>t zT3S|l%v**GA>XreVVH3?RPS-lGW~Xmzm^^w5x35Ao%chB=b1R{vV%@Re<{vJK1j_S z6<5K&*v;Yv$?(T0V_VCOPx))@tldZtF@|aO2;t8Uui}~f652z7zJ%Y-YkiJ>M=HUpn+-x&ToXA@{WO+FUkNO7mv zXkYTA!{LAC7qqb#T)5ysdNB!{7VBwoYryZJKM7<^+#c97oqNkJgq$~5ohEwmC|81C zpa*E4zMiLb=H^(sjGpQdZFT_1 zeMde?-j`9;1a`yvNjqb)Z+MADw=agxAKOZK+4h<$d zHfUb=Y4#6GCqCD9VBcxTPIAPLnTYJ0NLkMQsLtWH@#E#>f06n5Y0hznuE@Mdk(6$2WVS-a}+W(!{uiG&z94>uT^&r!URt2 z@BD<-|7yZ|c~8Q+^9=SuPgTOanZ}0Hw<-Eb8@!5JM{}dC20#Bw8|rV2IRZL3 znj6`|-3*fp#>|b}oS#rW7<|~GgM_nnkNWPk91&)~x90lvD-m}V_-0QCayj9Y_jEm^ zvonyJCLPv3>Z>A*}`W9w;tZ}vyg=b7N_ z(Qkq?J6kdHPjf~O9YQ# z`NARXA9G0ijfb><9_|0=|FZq*_4e~o`;GMLRpR~X_Ly|wNanp)lCwhdWZ7l|`2in2 zUu_`ImFCte+gQ7o&2uq4g&YkE#1V*}UV)AjFLLO!VV?a&&uCA+1kIzBGpH$lD>B`z zqdbmY+|Jx><9*Jmoh?&(w+WW}+<}n!G(NP0`GyobDxbP+HMQ4Tqc5$+w0Y~=wFjjq zyEfJ8ZjRPtvWnebM(qBY(J9)Wz3;$2)-H(0RP5Sm73se=&XEPSDaF)S-AA6a zr-^U9nw+ent8w(>807y13wzU!v)>&50k*_F&bA;{8dc#u1H>2SCfV#G{BPpcZ0M2P zUGlLIr_#LYB>F)+Bmel;z6AU<5_<*RHAc^RPBt_Z2+s~W9sL#I*Y-CmclUkPik&T^ z3)}AFOs*Z0ZzW_FGJ-m^*JbDm=MX*Ou%C-EdGam9vgrN{KBOG{nVD6|7w+##@{Q!a zaHYBOCD2pM`bt&4a^4&Nb36mzFjr0EhX#+vAEQ_>`P@#-5+?}nUQVB;^Z#@FpITr) z3_ft>8$XNRs$aef+A{im!?W;_WJt*iX7XPAGqxz*M%}>c0)HdlD2`S(C+m2L&oM9F z{K$cQova1KPwlIAx{E0%|M_`U;x(G(=Xc4|ZWU<5x;d2ZTl{{a&Av0{3oB2+pU0ZO ziB>;nD)py``D%9Ig&2EJX(RSo+UR2r!+pz#H3y#ru8>oST!Fb;VGnh+u#S^TDQ>{> zSY8;^I%UiEfJw2b>Vx9wM33r6W5G)_6xd5!_$@ZuBGVuBEk%D;^G%Ze$=A5if6J_a zr)xg@vEWU8x(mJ;>nslw?&EtzZ}4BU@Dg*bu87uM>WbnjR)u%m4GiGIrf;&-1y9U{ zo?XhJ%f8PuwJTr#q9JH28_gpHv+yjq>Un6c0ygxTiCH-P&*a9qmbhH@En2KwTZNgG z`>vhCe1bg#7XB>ik?k`t!x}_xFnpP|_H(_-Wldr($mQO}9>+XoHO`FP$LNby@HS?O z(0OKE_-28e%$$d)wGicB>ng8n@20-kqmQ+wf9JJKG1ZBZv@o1{)Tfpf@<(8;;{cRvyDW?jFJz36?@7%yPnd~Scd$LWtB`P^IkWNTz{ z@;TrS%#(Wv-s=V?`Jc3RAekBPGx)ZSEtbRcZZEL5fM2UfYzFV`(5l0WRG;N zbnVgjle#m~eY2`R0_P2kQA37(H95sGkc(F39sI4Vxw-6{(|qDczEO^tIP{ycR_yuy z0pyk7hDXJ_$du;&w)%u$23t9W-|*|NL~XZGSIS|X30!tdRvt>)U**y;0^Y}xd#P{YM38r!IUo7A%s23z>ji4F3Ex55T^c@}pB)a9 z@656WSnsl{FI$5Z%?UaR>)OY%j-|PQ>}suhf0g=QUxa)Cuez5mlZ=}V{0q>*+B>Cj zoC<8>;X5bwhX=Gi13urT58jDZlUZ~(`H@72qC3%{_IWB7(r)%m?02yJ$!~K@IS1f5<4~|Ib#`FKePHi&hHl8t)Kj4tf@4Rig)!T)=z#U)p zvUf8p*=Q zf890`TCi-&T@d`OIntR4>oQ+{tQhmxL;cs%VXrr{hdAQ}n#aDcHqTmuT~Hry(ZUPg z<(%hf_@SK5K|IqRB(e*G{rpy+{++T8xX-{VH9j8Wil^ACtMi*uz`JTwEE8KSlIE7Jq^0v1@W)K+NxuXz7ZQ?4pRa_Qj(8U>5W{d?&nJPd8R*PCRgx{opfyc~|+_hm_Zv%G9Fjiq?qm$&N8Pqh_z3&F^EgPa64< zw5&DCVIduN-;}3=80(+kY?8j?Y%<1jc>I&Woh|rXt;4ID+uS*hc|T=4rmSLYk;ToU zh#h1PKd@^|k9HnmU+-%4!sGOFRFyI*d_sv%r!OTPb;9olj2$We_z5Ge-CY^ZR=r_B z@r6~}OIBj{CM*Bu9eAe0WAC!JF8oI6z%vs{+GjgA?8!oJ!@FKVFZz8Cai%-ICp&j* z*v))d`h)X@%{;u#5}jwOr#33ig8Pi(8ni|>1G}siXL0a%v-FALEYLe9&SIkTMA$|< zao|5O+Y$biZ*V-c27dKef0y4R`b!d zwWG1XW@GeKoseqQjX`C{$a>x_@$qB0IT)@cgoSvoHfKOrnzhMm{X*4suXY7i$*yiPfLq;g9+8 zr*988e|eyC=M9|glJTpl><#{%IrzPBgTEE}-BCaWWc}*0FW(*xpRpxaOu2^K4Sql0 z_214~H|6w=!+4D--r(=zo2U6+`pD2!C88^%4& z*qm2wM!pG7jjsc&eb}*6iFZ^CAO3B4i`)-cXu3eWC%*4)d;t@3@}J^&!N1m2T1}1{ z6Nj#O3bG{17y5hZb#juUUbWj=RB7;8C)aPMrelnMb#}0Tv5-!S+h0Pi5Ic5=e^oM3 z_SM$QSi1r4M*N~$188vK{&45!KyuEpuB>zvS8?|6bk28M6=pc2qv#B#KC;#eT8m3q zo4+-ja^sQ!`P~vLj;J{9k)yUx_D2`l2UWQXeKu3VIlOuG6~aG7u~BSv=h zrU~VBn?!e0-NhzWw!vMvl|8rRE`Im8i#KVF_EKjtw6rLm&aUBn!ok#B>iD?ul*M;R zY>vzCSeE%ic`(eEv>s~>S*H!|y`8vfySyfx%k$~rOZqPjeV@#?6PedEK6FN<33^rR zW6V9Hl78sMJz8(oSf+ff@8a)5PprQSnPk1cN-R429@mD-4{6)vdVlV~KKV2yJJAtA zOnx!$HO9)hn_+xA;MsUnE91jBm@s-eGNocJz(b`==Xx6Za)~ zjx2NR(<`Hp;cIPjm(vHw{!C?Z%d%k9kAY>pwFn;c_|bY@LYN_mZ#gHE!l3GkF~EuWkz!51a}t{qi*p8pPb z5&rI(u_G8JXYG2{aK`3{4au`k$J#V`iBsAW4m`2`Jbo_f-a#3~07J{W*S9`Fe`f@{ zQr1%0k&Zp8LLQn_4E?_n{7ke~w)1T(@-CK&6-N_8)^5XBbKxu1rSnvDK74G_ianYS z&83d<4dP?wc{%ddAQyU|`FkFEf-?_pHgnkm@T9T5?!EYl;10^;GxMSMP`t1h94`aM zIm%e@&6RsuKc?@p;ihpmVve?!(dRtnq+^tWmpMQRdP!uQjVZw}3Amb|ed)MsDR&=u zR6Oss4)PItsK=ge+6a&Ey#AZ{yV=+AAkU}idCm*emhh`@&3u>oWG9OjUZh+bGNB%0 zs@%x+d`o;wtWEDp9oV0|e>?A>>Qg=V2~3?0IKqH$MbD#6M za_d;{pBMZpVeLNbA>hhz7BSdP;oG@8Iiydu!kN zNq-C$IIWdid8c;NrtEmtqqfv8$4c!kaNi6*)V97Cd=u@pVXC~yKdeOD&Zxn?vPBiM z(~loBvPI_wlIbC|eTPNej1TMDnEvR0zL)=0eIL*7%jqZYhJM#^dzgXOr>ZTm*mm;RoRC+|sa@usQy z#hdiaBX4ppZ;l*ISKS=WyHPd-aWC$goo7M&vM*iiNsn)1jMrHAf^f(1Q?E3@pTzWy z*=3!{Ivi`DPTa@0>nDgsJtp^X`+In2+0Zuir|54q-z6`p{XU}~l4X3s=mg>afftZ1 z)Qf#g{bz<+e^Q%TBUJm!V>WBX%5dH^%?;15G9TFxUukXR+s)&QOgX=zIf{HvW1U&y zSB7^0-zei_dtltGU<9&CzWxbL8@g9(ShJ&?HOQRjdG6-hjK8##_wpA^$P>SZ4%J?f z;T-XfdFYg9Q)SEG&z62`!>6fz^|xa`2|lgkNrs`<#%%5191IgH@)ck=b6jBSpp0;w z!hZV-bm_7${%7d?J3ag~`K6URsh|CPLl$FZmx#G@BDwobVtGw2TIhr`e3;YEs$!=% zH`qJ&NDdDW?=g*c(2tSf4fey0yc>OEEe3cR^OFYW;n7-Km7W$2^#GUbmnQa<^ndrQ#D7~MPmkLb`v71>kr;aS+fQy9OA#ItPe+Y&Te`Ntz43kLdD~b|e*7cnE!_6L)4gr+8QwGp;x+&o>4vdB7pAP%i zZ5R3lu7{~>uE$&jd}P3N2Kz|#ayc;+veDiPFFWO1jb5(jZqfLTEn{zG2gA>7kbl(+ ze#BaV?9N%STNoe34`zecm_uy6baNmcfHo!D%>9X+r#sf2W$c>d3*rg0K09WY(;dhr zlzpgvz6cMfZtl`Ir}m}hoG%gU)SiFay8@@gV_!N=B_`jBumuX+M=!fa0Wv#ZB*pQb+SKlAQn z{KqHZH?D%GVR-Wx@f-N+$Vw*6tGYfq7Cf;4x;ts#%GnPKD)ZeI=3?7kVQhz3yEOAa z>El@AC}JB{v~$)-%ESRHKL=wW8DWu^T<2qaLFI@|YLh<)9BZ$Uba+!y^6`S|rZ?~x zL*thgu;KF9Kza7e)aEPlm#>%4l{z2NQe@V|&JXFC>>tVC$vW#8+kc@4p0L}6|3>KM z_1p^VA)lBo_{qU;16K{;L4J*nwGoXghQRV!8{&KUN>bxi?D+uwHaO3q$8y*~e4|`! z$(DXUhV7)eC-lJdMQd>A(Pmq+*W@Zu?2Ud$xUv7wxUqyA)>4EUXzeg$0eb9S^-FzP zL|@yAg6V?lZ-7y2=q~vAH_k9m;=diA|4+J2^w5MZ9pNYP%LAQ7g#9r}b`5;Gd3f2DAO~LO z0_zpX0mUc@_F?U%GJ0TJ6ID}4V1+vw-`L$=kx`{BeGBFwlJlA2YjElZ!AB zrC1@p}%ftjX6It=Jr;)Wp_dMUjc`m_^Z1ZGsP%R<$NN|nT#H` zrE>?vYmkZ3&3h@&oHw+}@&!fuJjPsK`arh7MV*qbewjR)(683J_k-&^xa;%D`^{J+ zSc_|591=O`2wG%4c(-UzGAc$H$A;!kfab>aau3b%|D=D`d@G_+^oO5N+~V!B4#|{EfeWZ`dDt)q*{uEzzdvl6miD@%kd_-#-yu4h-T8gQN1c%4Zde#dlO) z-I0a2Gn)4h>u)UxrUILTk3{lM^T~L2*`99Zys}t(37gfHj z@30-@YZi{>^J4y5O<aUHdS z>eGBjb;xEz54f>$^|LnLndhCH5knIw`|9K!@XpNY3eL}51P(Qh9~11zZjJXY#*Vo| zc$Ztimc!S@^Emo3o-OP#F@EtU8S|NvQ}>D%^nF3{8GkM7_03)QI;0b&caZHv9mxOM z?`G{e$&_Uq&NKc^$;t`v_K31y72n9eco=w>4`c;+(!T2=IFzsRVdQ$O=KJ~>JY-}0 zKlnQSWbBYxR>Uv=N; zxB2!}VlsrE+uk^^d7}LUet?*XZC}H?T}M6|Bz*Sa(a-O?rQj0kN?6Em@FQR8JYb0N z>^5JQ_dnke2{nn#wVZE9F}=~W*u`{@|xz> zh4UE;*-9z*iP88q+SgBcl6?Ye81M4~*{mt@GK|GOPC1Y7sjq9t@wJX-9ZNd;e;5bF z+s$Da_UP&e{t7W(vT3JIA?_xnAzit1jmItNG3X7vdesFgvI7-xm6^ofF_ndjIS_ z+DqgGr|!_2soKj{uS>EYrv@AIOy=)T?@^g<;&=4CJ|EJvl>JyE??<1*_xcvRwNI0; z#{KQ+#gvWZ7FG&AYkBx_uP^uc4bEqM1CI@kX-~Rx0)DJ}PCmluqdfSM-qcy+>;v$V z^h5cs()m8W-@ymLH~sH_GQ68{lg%Kyo27obwSMLd9aJ0g^fSl#X!LRGsK~Zge;eud zVYNQLwLOBli~g!F!#bCoKB|ABv--2cYkfP1c4S}5Cp8`TudvpIU&0?$_XEry9rfW_ z!GIq@IA4PQcx6`cLJNGsF8!iBe(KAz_iqb(>Bn5^63^s!y=DCRn%{kq`(j@Gn^Qd# zI+{;iio2bN{j4>WGocynd+MjH2Iw&ZyiHm0`}uG4e|gFSp_++cec#ypwa5-}V8=^1U0P{qD6qdO44Lpy(s$IceV%-ko?l(3!&; z|DTs{WS(phxB7T+ZTUfB%+V3hgJjaF>ui=53n~Gc;(yj%{h_Ld`EQAO*#2OJ$GIBVQ|@rFHkX^m*MMW4%Du8#f!wh zwBmP5XkOG0-X>(1hQCA}D_-tsp6R>yBG0gO634ikQ_GQa;`2`66#v4PRq?WD&V?q$ z%Z85`&onYv{%p~8Plj9r4t*fbKsJ0&W^pJzC;#3bU)B6#R=|A4$g$eG4f;RQckB1V zgBf(C%NiQ}lAKIYmvACod@p#=|Bu)DT=yN{&2zP#q8?;HwGDd5A4y!w_8?B5K94OA zKFpkO9{qB%qsWI_^Qq#KwX!#|4nC^--5Rb&DV*Mtpea|HSth(^(%qB7BZG zJMm^=4emKcv7Xx6mL99gzvPkwPIzE)nB(a)&w zJ9LIbC5tY(ojko7|Ct#tF(X5425r~tU1{pPpenzecz8t7OEeX|)}xA>nTMTU?I>!^ zZD}~6xHLSB`KZRWJ{SKiW1#UJLAx4bja8C<&Y(|+;{NNvtNzQD5nl^VjprxKSfUGo z@wL~Ld-GNk(|Ks_xfjq`@?A)0UG!RHL-gjfPitkk2s@^J?sw+R17p65y($~=R{qN- z`~8060CU3S?CO8*KhS)I+Yw&sHia+o9Q{#s%kqDF!I88PXZ`kz;QQ%^{5_JV*B~Fd zCLUqNO)^IC#vSBwvDX*hh$f5so(fmK|EcgOe{(3A)=GagPk?vOj|E@8hli+JeDgVQ zWpI!~$3he8Pb1|Us7JQC-pL29=P{oDGxvNKWcXe&1scD^Rm=A%W+L?Xi4O~ z7JPMMRDXS3>b8Yw?|<$;ue)sK$CjRhO&aF9QoF4lt@!hof1K^lSpR7FiqQ3ve zcInQsz5&1M9EfhM)gf0kpV9hZ5&Y($%}0MoP6%*03V7_|O<^vhzAX=@7nvs)(JkfW z#-}a$cr3B%i|Jzw+Uci1*II+&6U-T-HBT>)-fPHR>Bll3uk?@W_j|EJv#gtZC5ZIt zT*|M4roZMs|BQGoNvv59xNC9?e>o%fhGbw>e&=KnnTa1-`(EaPpXLnpuvQtPZ&zyH zy6{b(#pC!2{5b2qeJy?df|e!z6zWm_KJuH6ksodSy}}*O(;fZIAqs_|%$B+&A)De#SQJgHf!F$?v{? z()M7cyAPh8S;fEBjIYa#-AkjRI6vsw{QeQYrIQ2;`6Y+CGXoX*Sd;YaC+MVDi8Hut z=*5Hfk5 z_ZqQy1^o88b)o$CH66&hb>u%hhProI8{x5LKjx0~wcatF@k%3m+sfoNf)0|WX~`tZNOkI#BccaHr($Ya%~y1?xkY#76zb(tYu@VQst+DHB|#_+g4Xlr78NT;glZsttQA7AJ58K-~iV_Vs8W9uB7X06l3#xI99jJ?>b zv-X55&W1@L-($2oK6Ch=IpXrk0OTB^0Jlp!(SW5?F#S6X?}Sg@i9-3 z^OQL^->%2T5??;d7|QO_yef^oFfsE4a*Ft5=1Wc{S;4>8LeBZbflOOPGW1zs)Lf$} zC%clp7ImJ@X^v}t!?RDkgJ-n{xBm1eI2$UOlPBCuw<@kdaSkcBf2(2|V%fe83AdkI zV2W*+W%51?*FOgDjo?&cB0khU?IeDZewY9LfUh#bgLM8&&T{he*3Mc0R?V4Dk-q_Z z5ue%S6yG*d2X<8O?Y2^I`S7Siz z81K|}$`(w-9k3RozRK?~HM4kASC+o`HCY2JEqtGI*uTT~AL3iJE&7&?lf=$Abd5Oj zcgWX$>)Y$Y9aGkX$Jo2W`5D1IqiT2)+bKSARAqh!dUFO-iuaO#S+woCgDK5F6dR|w zMQF4YnrtWDki9}B;scv_j4|3&@b44sw%)N8m z3_FipxzN)gd2(-USDxJehp{t{ld8D-{_SOEnqkxiW^^1!X#^FO#0F7G9Hr6GOblwX zh^WLgt{6#djZq#&ZT59^Slv)sMPt;&QE>@zX%-a;Bq%O~_?X+>T)`QWkch?zVczer z?!C}VG|&4-efoB-r%s(Zb?VfqQ(8wPhxvZ-j>T3^@53;6?i0PM{eL)n+FiViEYA9} zqi!bg>SN%&J?+zwtwi6l2b2A!;Ez-1Db(YyEpg(~i9k_j=P!Em+|WR7|8aW_c$X-h zxvg~VA$+Ts=??I@pM@iE;hWHD% zrbZ4GzDniL9|;cHj3WzAh&MZn^*_b`RI?*rCz78vMv|3kX~V3Ez$@6VXHO=&7OhYA z;5U1E%k9@H!3O;2QIF&c!6|)|>JZLXo`60#*X+D8cy>W=!CI`H+u@huCE_DLrd$*2 zg7g{co9+Pw(sRw8K(b&3?T)97L&S%HS?8_gY2KdGe|X~cf0DX z%3%i#o^<{fr7qpG{(!qAMxG-65@_p8Xh<@q^4F>jaQeZ{J?(c&u4jy7=Q9(0N~cne zPNgj6>Qx?RUl*W%6Y1XszBPx;SjXJE5!iLv(#0IB@y=z7OUR@Cm^|P~`Y_Rhc|CN0*TAM~2e^}3+_&)N}2%VSDR{C}1 z)p|0MdV}^pJ8P{aX3p5Om4d#(o93zXVwwk^E%fbLlEpF9AzP)TiY}?vUmLPPR7vFPj99_du72W`eFJ!#KXgcOvlH^(2siV zro1#6d-O@JJ^C2RZ*0V-SlofE(q zlWxw~)V^!zp~A`ruK%o~^6#Iy^d*~G+0TZkb2W2Ze$j@?FItj&Nom?@amP%19^t;s zV*JRP&T{8t#{cGzhUZv`WZ?wHN$WYb9sKgvBz@___l;5Js&wBiQ=OZsqfhHpr(cw} z-ihy@=L#Fxji z`5U8d-+xq&et>+81$&OWo!nY?omfde)a8LS~aqk&NxMLY1PBa>B zd3YPLmSbh6JFc(83yP6Mb|ri3E%M)62~6Q`^S24V%Zj=u=;F5va4Kynar(93KTG&l zofdP*uTOVAt?tYZWKiyMMz#*o_ek@tc@sXe#VMowD&X7=eGQCqXDv3BKDhLnPQ0>x z6@C7axfV##P7CETj4ADhvdHI@4QpP-7t?p0p4tpcNBXZvpi zN5hIE`r9v(_8d5V{(f^tw>pGfV-Mnb$X}%PjPm7D8(eD6iZl<$LQ7^`7{5C^*Ee8a zeKV*p8ebjae%9XlCVTZotOd@`52Kz0ei@_Lz(nAcy@>dW(q{Kl+H?c=&ndH{|57vd z8sp7BK+gys0=f6lCuW~v{d{I)<61N3R_yJH>zaJy&|QUO;5c|nzl7{c zMi!4@o^I^DHoqghmN_+?G2K)+lKf5JQ*hIB%$Cq_(w1e_r62w=m z7(4_S?%)$T+VKn3rgr^$v42{jwnTrN?=$B%*~m;!^rf$&W7^uHIyN%K<&+1n`R@p) z7Ie?|$$Z08iUavo9*uc00L<}C1@729p}5~vP!71Uf2=HrFHDFsCt~Pa2bUL(ZxeKh zmE~5kIycjq2me&PG3qOa{wv~~O?c&@|G+ua@%hEO+6Q@c-0(GZWV|{KqK-su*gE?6 zL2FPUXl1*Etxs#<&TT=fiePw4E91%fy+r&a!TOyNFGv2(wm7$f=h4`PiuY+RDOyfo z>pnXEmXnS*7n*W&oIYB2-F0L|fIV6?$y>yfll+lp9Sm~!MSYK1%?`Gnl{xsG{$t-& zC*H4o|N3xGyY4pY{4H_=ea=m@rOy@q)ovg3U_HQbWcZ>(V(?q}re>d0(}y`L{=MnP zz>rE7v@YqbD%E)@XD0fs=l>;qFY$QTyFFR!Vs5*_{peee2WcChK5c4i={4?HN$0Gp6=k8?CMQ%vImi-$weU{9DMMK;KZ6oI^cR3W@j}=V{8< zvKG}+r_qsMW7!J)w-Fy=tkh-*816ZJsexT{{iP#azYsHjztlMy{0vI7-_CJgF^yk< z40Z&q{LiSL=!c*+(O5i-?lslyBw85rKhEnf7x_Cl%IThW>|k zU(2~PR7Sr7iL;&!v`%|C%)8U*7PiE*+#v@(;YPXz*<1|FU^hzpl{xu0;NCs$=)P@Z zt9yqa(SqKIaz8^(9B8BajDN&B*P~dhwCdKJw$v%h&9&9HD$as84%p=MW*qgd@?RoW z+n>T#+dYISWmelK{O`_hBjF8fFu2s(ww1VN_?<==L)a6t+72e9NykpS?H3hRTSYnf z_^qbgX7W!WyvX;-{AS5>7vFOTpAfe2zlJaazI7wvV#4W!qX=5FC3}btMQfFrEZeRz z#hKh0w+>&5zW`)g#{4=De*xsgTe`Y$XE2_{$FcJdK|@W9eJQ>D=m2b9z-JhI8k$T% zXQDaA@VXa7o5)3^iyo9NdQ?5*NIL?UTzK5O3HPw}E5Gcr#Ajh`-)tPx!a^%v6VW z?e?~Dx8DZ-N8+5J>6}-0o!{+h&9>kngE>pp+bXY9mtcH@bwGU{oLW@(% zlT=H*`Z$-o@!Uwq;!ac$AJ84S`U1MS?%MZ>=gYRZJT{KAOy0wzO}%lt_IcMg*;vwo zUcB;3zw|x3+Q{)?n{yWE^wfB@qkN2cQLw2F*)70B04M@RjJv@V zcQ+;T^*DetYxJx;Vw>`kZ)wMz)0Kgve^{RpmxRy33$YDAj**?$7K0DkP`iS48gOa6 z{QsJxs^<>k{c(}3>C^Yoz;HVBELOlx8N5+n;8xf@aLQKkXhwc`L=ZLJ#t(GCdCM#oY6K)hqgVF0&-B zF;~Ba(iio6LguxPHQs(-Bb1qmFXTqj6(_$P{#Xkh)irbFl5J+3p^vA?r+B}-kE?;i z3pUXs>-f5D*o64_+KQhH@mKMlM>^d3^=INTahDf=Sn1lY3x|RS-kTpz-vw`mxoP^4 zaL0;=9*s|V@!Mw7#b*U$HSvn`;ZeMmbb0atq#Z?Gjj3c?zf1-3&{}?$pXSvSAU+n8 z-$!hpIZx#d)QR&>Iw~HCO*^TUIMO)VJA=EwQ=DIw^i%o~&EJ90hvDT(^t|-DHrdO$ zl75SitGzJrO3rSI&UQ9n$6WzmqK}~jHh=e0pZXI7CfR{%tU9kbw?YTYhj6Zl{NK#o zGAkz<0(a?!?wJK;ggezE*(sEoYp=(zlD^H@at5S%rn;3ULVP&a?3_fueOb%Lqw>6> zvI*W_%~2n1ZiTO02b__ldj@kVbGeLq!nFAj{*)Mp{pffdb3*oczKph!u@|m%78_0L z{Psfm$~5#GN!;zim~wf6#$I(xM-d@TaCQ}(8cY5wO=mWOa{+LE6?~U<7<|UEn*!`d z3dpnM&HH(U7t!xb^6n1opZ5bVukxr5ewo|Uf3GbcFG|0e_y~9rPWp;Jk;lLVtb)t% zG~xuC;Qn9o?+9V<3G4<&;9KFfY33Ap)war}R5$X9^6s!UxqTx4ufGAtk>3F0dBpoR zM(=AqNXwVYg~erj@8LYppQH7RVU)9K?#nr^4%~#EDg?jez8roKtwz?NYOUFK+4V`@ z;5lzfTMW~AJbK|RwE=X}7 zVmr93hs#6jHQ%ZG%Bwos-v>TJpHbc}eZ!LzklAX1)t8mb{6bc0MyAOm#7~SL67(DB z;SyJL4-T$>;*-Pu$Ia(t|ZbnZua_8qd!2_95uL8ryxzo%p5Lvivgent(Q#yYgcawYl%Y zo=)%yjtcuuTl64U!uErdyR_I_bjEz$3_SYPT>zh7i_TOoyb6Bp&FKVviXtzvzPWX# zvE7X6Ehxr=aFFL;RCPQapI>I^m$IgO++EjC5N#2sx_b*AXj1)q5g61T?a^clg??b& zH69)U*B-Mo9?;F#fhQvqYmd~5enNFiroB#jTIvoZ1h3VG@5k+t1a~iiLG9AV zywAS{%VJ;C>vKzam(bnw$@VqJ zf9?MU@%@tb-N1LN_nqMTaqqj4@2vMdkZ=Fpjr-sUgHp2!RvMnKyQ%m#E61iOnmL%g zfx8#GiTzU+Ts}m=Cq&!*gh5uws{bfx?cRgF;~ydG#=nQGjsFf>jSv32V|+)@>PvWu z4cWpiL94I^9mrQfYwos?726rKhH^>0{FR`U=KG}`L2Er>IU!4!=!L%ge)^Z7l_M-C z>}U^KOXf04b3#_)lb{uu9kRx^1ugrte|O9!Z4GgK{}i&q+en*9yW4}-_UYUs{Hb-=kYqB*xu2lNk>QU{Kw{K_u$R9iov&;0ja! zD#k6EaCO81@PSQEL3h~)Wue<-wwTJGb7EfT&T5}5XK*R;cdM(V-Y+dc#GjMrw#F7#9Dn97w=M})kGgA;QvJSUnQ zW6mhU$tBJi(8t8;o_qB=|N5=V-#?6S7bB4^o{?B*=pUIif2GcFXmbVk3FW_+Hx7y~ ze$_Gir9M3kezm99-GkqLdvc+QePk8)1NQ9?lKDUsKbkrG2;ft8e!O=)oSAZx_6Y1B zPSSb5iSJK5`N}vm+CP1ao8Hhn9*KT^IpH>(C{0VcWoXOH0oq%#W>5QU?kc$SfZmb+ z(#KlpU`Bwy!|7Qy~Pd(CMD?Be(KUox5cD0+|{>uC9&*}I<_mDfJV;N)cCq_kfb{P|y`b;T@?aO*)Vi(xqhz%td$m%T z?Wf$0Kb<<1C*YlVgriH$e8)egp(QIZ&)I=~>_B8L?OmlmTmP>;?M7!7wV8(s=p5`# z_KwJgXINLB*~q+r#-G`7+#2Y3SaC?y zl&*Z*@08|SPd<2LQEAHG^MYMkyNX-sx8l_AI^t~Xnf$SPT|OTB_LQ!#D4mLEP4puk zJ@2TaY#$Hrp0UUYes4`^gr~dwEi@{BJIsrGEjGKNHPI@4$xCLxlll(AkD9NiS^Y2h z{O3%V_H(qa@84lZ_(};Zq6LoQL*W!}q%h`!!*Bm2+7%DP=A!`rkp7<57?qVgCE4=Em@9Yw7`$oE zr2W#6GHc7$ww~A-+xhH4>{007f%aW?%EI4)%{omVchjfcz_FWrraxWb%fO?2L$iW| zbATv!A!w&dmNT3fatnPMN%=9BeAl4EZDqc*w#)Z|&aWi<=>ASm+D|30afBaV0eo7k zfIAdOgfU+kY3}mGEjRrl=x`SOkW47rP`@;XPNqM##EVA!c&!OaJAt&AXrKM3?y>5w zxO8b%le2lU-RY_VqA2@75i&Aa|t%gZ8av4~?weRk+t2rf)_!j?Iqh=5VM^Hu90!i~=%r zK48HMQ>^)nVH0bD1e0=^i@)7+sci|cTSoFS{YHVmG z#{TwkOaI={q2yE9Zm~1*MFC7HbV8KdMmgbOJoq<#jxE?mA2}D#=Kp;II_a33S31kF z)FJ;sp*XnqVEMlAOT35sqWY?K-lpD5-FUN4_s8mY#P=p%?W>H|Amx9Z_sCqdx{a+SPW{ zyMy<-{0VvOh$hsI_Ds{L*T0uHTKD+V!u5(U++=m7cae%_%Dvs`_I@yq_e9-E!ou-*f2I(X5Owll(SLs z{aV_QulXAMmG6{~ZR$tIR;lw3?#=JLw~4)XrQi`h%c9=AWSs8E*u^c#^1lA%15$zymXuAlJ3hf zPjaWQRG;)IHkh(+c$D~v+0%|JUV+Ra-G7LFSC{?gd5?9O@TPZgwT_M`a^Q#_$~|vf zKs}<%iWK{wm@C&A8a6nk&h!j>)2}J7@hLgO34&X->FdrLz}3mI_Y6-oW5OAo(p3)L z-eZ+lhvGCo;`hq;GV#7I2i{MtyAB(5t#1MHtSv zIfE;sykw9v>i*SBu1ujdLFZxR@Os_VmF@aL@&+%nC^;L5$$~$Pf)2Z^vf4m*Vo`he&PWAmeD`^*es*L1X!6X{L796T>Y-5iT zUag!fBQQn=*OHMgBTp^36lp1L+Zk-tqT`y-4Os+;i~3JEc4JH#L9w zV&B}Gj%=_4TL^dGbeFy7MYrsD{N4Kac$Dt|G$h#z|3g||RwLwWk#0P6q;%rEgW&1J zt328>_7T_@ik^gv<9Q>M^9`4r1ePrd_k11=yRQ36;^Dc!D;Xz?0#>v7y*YN;Vvx z=dNEo*liN>#-x)-Gdx>&bH~`otn4LJek^s#50=&e)dk$euq_=edLjDcui<9_ci&d% zFbVI<$Q}_&dz}0zuQNG)Wm%oSsv@Jduj7_suMrk*b z7KzU)oKG5O!v%l;d_D16WB0C`(3{pnmAS6PF7CI^wz%u;6>6V)wRcfJ1&i8K8J~A= zAdloat(oe(&ft}PfmgO7=B|gm$)j;TpLoeCzTS>^jm-NCR!(ObV~WzF&f`tOq2RbW z_n`9y=OaE2(aly`;4XuGw`@*y=Ab=YAAV&Qs_}E>de+ZLGvg7)@9WlD(TU~{lesRO z;hbLZz_TTT-$Wa=)_u-d_}$ao(H(Kg7Rct6(lKZ3W+PXHqwoux_UTger?Sjh zQ}!dumeNF+a(;WV<9VO-TIx2qVf?KY7hdLFK8TD_3XfmsTa<~A*QXQpQ+2K;eim>W z-atEk{40V1c%V5mhmBmGaoc%;w0*R2NxthdbK+gUffi0?&!)BGI&a+H#K+&WJ>E6z zwZ>gGuU0NwY=o}M((XE?JMi#cBme3>X=rat*jnUF1s2zjNlShT>sP7Y66D`HjrUOc zBE5zBRu!9SYwTwO@3TGL%d_WeE2Hj;WH!&cSB5sg8TnoOiZ0au+r7T4tp4j>GB6sN z5dLrS`mZr?=fjwM)ylc?Dh~&Hc^P*dZ=kH|5j>-Fyh%eD(WFm@&w6zDAax!^UUwYq zz2k5R@gpe{fHp;c+7D`6L`UKk{&;B|yLj-bEdw+8en5QJ)*bM1@!XQT=j>OzcH{0j zYoTw~BHKaDEgtu4kLsIt#WQ3#tTO?vOK)zJZfmileV^`pSH{2*uynz8SLqMYp3*Ga zU5moDdw*Pcw9l3g^UKL&S=r*%lsD%Zz$u?>D&JFSijTVejN}%Zc%65s|4H(x?=#3J z{vlkr`#N`B3$VUu?Kwd807E!VUBIBaMf;7kUrt&@S~$@g9i=$Ax2D42gttAY+sDg5 zOY70xg7}*Dw+FqCUeMDcoDYv1BRFUa`)6}zBbiq1iMHCG)Lg-*GkL=3!;KFW{Dp(>s|I*?r{zx?qz

`6DSKS{45p+B$s|^3iH&d0i8<9qvDW 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