Author: phoudoin Date: 2010-11-19 13:43:27 +0100 (Fri, 19 Nov 2010) New Revision: 39503 Changeset: http://dev.haiku-os.org/changeset/39503 Added: haiku/trunk/src/add-ons/translators/webp/ haiku/trunk/src/add-ons/translators/webp/ConfigView.cpp haiku/trunk/src/add-ons/translators/webp/ConfigView.h haiku/trunk/src/add-ons/translators/webp/Jamfile haiku/trunk/src/add-ons/translators/webp/WEBPTranslator.cpp haiku/trunk/src/add-ons/translators/webp/WEBPTranslator.h haiku/trunk/src/add-ons/translators/webp/bits.c haiku/trunk/src/add-ons/translators/webp/bits.h haiku/trunk/src/add-ons/translators/webp/dsp.c haiku/trunk/src/add-ons/translators/webp/frame.c haiku/trunk/src/add-ons/translators/webp/main.cpp haiku/trunk/src/add-ons/translators/webp/quant.c haiku/trunk/src/add-ons/translators/webp/tree.c haiku/trunk/src/add-ons/translators/webp/vp8.c haiku/trunk/src/add-ons/translators/webp/vp8i.h haiku/trunk/src/add-ons/translators/webp/webp.c haiku/trunk/src/add-ons/translators/webp/webp/ haiku/trunk/src/add-ons/translators/webp/webp/decode.h haiku/trunk/src/add-ons/translators/webp/webp/decode_vp8.h haiku/trunk/src/add-ons/translators/webp/yuv.c haiku/trunk/src/add-ons/translators/webp/yuv.h Modified: haiku/trunk/src/add-ons/translators/Jamfile Log: Add a (read-only ATM) WEBP image translator, based on Google's libwebp decoding code. Modified: haiku/trunk/src/add-ons/translators/Jamfile =================================================================== --- haiku/trunk/src/add-ons/translators/Jamfile 2010-11-19 12:30:21 UTC (rev 39502) +++ haiku/trunk/src/add-ons/translators/Jamfile 2010-11-19 12:43:27 UTC (rev 39503) @@ -18,4 +18,5 @@ SubInclude HAIKU_TOP src add-ons translators stxt ; SubInclude HAIKU_TOP src add-ons translators tga ; SubInclude HAIKU_TOP src add-ons translators tiff ; +SubInclude HAIKU_TOP src add-ons translators webp ; SubInclude HAIKU_TOP src add-ons translators wonderbrush ; Added: haiku/trunk/src/add-ons/translators/webp/ConfigView.cpp =================================================================== --- haiku/trunk/src/add-ons/translators/webp/ConfigView.cpp (rev 0) +++ haiku/trunk/src/add-ons/translators/webp/ConfigView.cpp 2010-11-19 12:43:27 UTC (rev 39503) @@ -0,0 +1,71 @@ +/* + * Copyright 2010, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Philippe Houdoin + */ + + +#include "ConfigView.h" +#include "WEBPTranslator.h" + +#include <StringView.h> +#include <CheckBox.h> +#include <GroupLayout.h> +#include <GroupLayoutBuilder.h> + +#include <stdio.h> +#include <string.h> + + +ConfigView::ConfigView(uint32 flags) + : BView("WebPTranslator Settings", flags) +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + BStringView *fTitle = new BStringView("title", "WebP Images"); + fTitle->SetFont(be_bold_font); + + char version[256]; + sprintf(version, "Version %d.%d.%d, %s", + int(B_TRANSLATION_MAJOR_VERSION(WEBP_TRANSLATOR_VERSION)), + int(B_TRANSLATION_MINOR_VERSION(WEBP_TRANSLATOR_VERSION)), + int(B_TRANSLATION_REVISION_VERSION(WEBP_TRANSLATOR_VERSION)), + __DATE__); + BStringView *fVersion = new BStringView("version", version); + + BStringView *fCopyright = new BStringView("copyright", + B_UTF8_COPYRIGHT "2010 Haiku Inc."); + + BStringView *fCopyright2 = new BStringView("copyright2", + "Based on libwebp v0.1"); + + BStringView *fCopyright3 = new BStringView("copyright3", + B_UTF8_COPYRIGHT "2010 Google Inc."); + + // Build the layout + SetLayout(new BGroupLayout(B_HORIZONTAL)); + + AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) + .Add(fTitle) + .AddGlue() + .Add(fVersion) + .Add(fCopyright) + .AddGlue() + .Add(fCopyright2) + .Add(fCopyright3) + .AddGlue() + .SetInsets(5, 5, 5, 5) + ); + + BFont font; + GetFont(&font); + SetExplicitPreferredSize(BSize((font.Size() * 233)/12, (font.Size() * 200)/12)); +} + + +ConfigView::~ConfigView() +{ +} + Added: haiku/trunk/src/add-ons/translators/webp/ConfigView.h =================================================================== --- haiku/trunk/src/add-ons/translators/webp/ConfigView.h (rev 0) +++ haiku/trunk/src/add-ons/translators/webp/ConfigView.h 2010-11-19 12:43:27 UTC (rev 39503) @@ -0,0 +1,21 @@ +/* + * Copyright 2010, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Philippe Houdoin + */ +#ifndef CONFIG_VIEW_H +#define CONFIG_VIEW_H + + +#include <View.h> + + +class ConfigView : public BView { + public: + ConfigView(uint32 flags = B_WILL_DRAW); + virtual ~ConfigView(); +}; + +#endif /* CONFIG_VIEW_H */ Added: haiku/trunk/src/add-ons/translators/webp/Jamfile =================================================================== --- haiku/trunk/src/add-ons/translators/webp/Jamfile (rev 0) +++ haiku/trunk/src/add-ons/translators/webp/Jamfile 2010-11-19 12:43:27 UTC (rev 39503) @@ -0,0 +1,29 @@ +SubDir HAIKU_TOP src add-ons translators webp ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) shared ] ; +SubDirHdrs [ FDirName $(SUBDIR) webp ] ; + + +Translator WEBPTranslator : + + main.cpp + + WEBPTranslator.cpp + ConfigView.cpp + + bits.c + dsp.c + frame.c + quant.c + tree.c + vp8.c + webp.c + yuv.c + + : be translation libtranslatorsutils.a $(TARGET_LIBSUPC++) + $(HAIKU_LOCALE_LIBS) + : true +; + Added: haiku/trunk/src/add-ons/translators/webp/WEBPTranslator.cpp =================================================================== --- haiku/trunk/src/add-ons/translators/webp/WEBPTranslator.cpp (rev 0) +++ haiku/trunk/src/add-ons/translators/webp/WEBPTranslator.cpp 2010-11-19 12:43:27 UTC (rev 39503) @@ -0,0 +1,245 @@ +/* + * Copyright 2010, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Philippe Houdoin + */ + + +#include "WEBPTranslator.h" +#include "ConfigView.h" + +#include "decode.h" + +#include <BufferIO.h> +#include <Messenger.h> +#include <TranslatorRoster.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +class FreeAllocation { + public: + FreeAllocation(void* buffer) + : + fBuffer(buffer) + { + } + + ~FreeAllocation() + { + free(fBuffer); + } + + private: + void* fBuffer; +}; + + + +// The input formats that this translator supports. +translation_format sInputFormats[] = { + { + WEBP_IMAGE_FORMAT, + B_TRANSLATOR_BITMAP, + WEBP_IN_QUALITY, + WEBP_IN_CAPABILITY, + "image/webp", + "WEBP image" + }, +}; + +// The output formats that this translator supports. +translation_format sOutputFormats[] = { + { + B_TRANSLATOR_BITMAP, + B_TRANSLATOR_BITMAP, + BITS_OUT_QUALITY, + BITS_OUT_CAPABILITY, + "image/x-be-bitmap", + "Be Bitmap Format (WEBPTranslator)" + }, +}; + +// Default settings for the Translator +static TranSetting sDefaultSettings[] = { + {B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false}, + {B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false} +}; + +const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format); +const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format); +const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting); + + +// #pragma mark - + + +WEBPTranslator::WEBPTranslator() + : BaseTranslator("WEBP images", "WEBP image translator", + WEBP_TRANSLATOR_VERSION, + sInputFormats, kNumInputFormats, + sOutputFormats, kNumOutputFormats, + "WEBPTranslator_Settings", + sDefaultSettings, kNumDefaultSettings, + B_TRANSLATOR_BITMAP, WEBP_IMAGE_FORMAT) +{ +} + + +WEBPTranslator::~WEBPTranslator() +{ +} + + +status_t +WEBPTranslator::DerivedIdentify(BPositionIO *stream, + const translation_format *format, BMessage *settings, + translator_info *info, uint32 outType) +{ + if (!outType) + outType = B_TRANSLATOR_BITMAP; + if (outType != B_TRANSLATOR_BITMAP) + return B_NO_TRANSLATOR; + + // Check RIFF and 'WEBPVP8 ' signatures... + uint32 buf[4]; + ssize_t size = 16; + if (stream->Read(buf, size) != size) + return B_IO_ERROR; + + const uint32 kRIFFMagic = B_HOST_TO_BENDIAN_INT32('RIFF'); + const uint32 kWEBPMagic = B_HOST_TO_BENDIAN_INT32('WEBP'); + const uint32 kVP8Magic = B_HOST_TO_BENDIAN_INT32('VP8 '); + if (buf[0] != kRIFFMagic || buf[2] != kWEBPMagic || buf[3] != kVP8Magic) + return B_ILLEGAL_DATA; + + info->type = WEBP_IMAGE_FORMAT; + info->group = B_TRANSLATOR_BITMAP; + info->quality = WEBP_IN_QUALITY; + info->capability = WEBP_IN_CAPABILITY; + snprintf(info->name, sizeof(info->name), "WEBP image"); + strcpy(info->MIME, "image/webp"); + + return B_OK; +} + + +status_t +WEBPTranslator::DerivedTranslate(BPositionIO *stream, + const translator_info *info, BMessage *settings, + uint32 outType, BPositionIO *target, int32 baseType) +{ + if (!outType) + outType = B_TRANSLATOR_BITMAP; + if (outType != B_TRANSLATOR_BITMAP || baseType != 0) + return B_NO_TRANSLATOR; + + off_t streamLength = 0; + stream->GetSize(&streamLength); + printf("stream GetSize(): %lld\n", streamLength); + + off_t streamSize = stream->Seek(0, SEEK_END); + stream->Seek(0, SEEK_SET); + + void* streamData = malloc(streamSize); + if (streamData == NULL) + return B_NO_MEMORY; + + if (stream->Read(streamData, streamSize) != streamSize) { + free(streamData); + return B_IO_ERROR; + } + + int width, height; + uint8* out = WebPDecodeRGB((const uint8*)streamData, streamSize, &width, &height); + free(streamData); + + if (out == NULL) { + printf("WebPDecodeRGB(%p, %lld) failed.\n", streamData, streamSize); + return B_ILLEGAL_DATA; + } + printf("WebPDecodeRGB(%p, %lld) succeed: %d x %d WEBP image decoded.\n", + streamData, streamSize, width, height); + + FreeAllocation _(out); + + uint32 dataSize = width * 3 * height; + + TranslatorBitmap bitmapHeader; + bitmapHeader.magic = B_TRANSLATOR_BITMAP; + bitmapHeader.bounds.Set(0, 0, width - 1, height - 1); + bitmapHeader.rowBytes = width * 4; + bitmapHeader.colors = B_RGB32; + bitmapHeader.dataSize = width * 4 * height; + + // write out Be's Bitmap header + swap_data(B_UINT32_TYPE, &bitmapHeader, sizeof(TranslatorBitmap), + B_SWAP_HOST_TO_BENDIAN); + ssize_t bytesWritten = target->Write(&bitmapHeader, sizeof(TranslatorBitmap)); + if (bytesWritten < B_OK) + return bytesWritten; + + if ((size_t)bytesWritten != sizeof(TranslatorBitmap)) + return B_IO_ERROR; + + bool headerOnly = false; + if (settings != NULL) + settings->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &headerOnly); + + if (headerOnly) + return B_OK; +/* + bytesWritten = target->Write(out, dataSize); + if (bytesWritten < B_OK) + return bytesWritten; + + if (bytesWritten != (ssize_t)dataSize) + return B_IO_ERROR; +*/ + + uint32 dataLeft = dataSize; + uint8* p = out; + uint8 rgb[4] = { 0, 0, 0, 255}; + while (dataLeft) { + rgb[0] = *(p+2); + rgb[1] = *(p+1); + rgb[2] = *(p); + + bytesWritten = target->Write(rgb, 4); + if (bytesWritten < B_OK) + return bytesWritten; + + if (bytesWritten != 4) + return B_IO_ERROR; + + p += 3; + dataLeft -= 3; + } + + return B_OK; +} + + + +BView * +WEBPTranslator::NewConfigView(TranslatorSettings *settings) +{ + return new ConfigView(); +} + + +// #pragma mark - + + +BTranslator * +make_nth_translator(int32 n, image_id you, uint32 flags, ...) +{ + if (n != 0) + return NULL; + + return new WEBPTranslator(); +} Added: haiku/trunk/src/add-ons/translators/webp/WEBPTranslator.h =================================================================== --- haiku/trunk/src/add-ons/translators/webp/WEBPTranslator.h (rev 0) +++ haiku/trunk/src/add-ons/translators/webp/WEBPTranslator.h 2010-11-19 12:43:27 UTC (rev 39503) @@ -0,0 +1,60 @@ +/* + * Copyright 2010, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Philippe Houdoin + */ +#ifndef WEBP_TRANSLATOR_H +#define WEBP_TRANSLATOR_H + +#include <ByteOrder.h> +#include <DataIO.h> +#include <File.h> +#include <fs_attr.h> +#include <GraphicsDefs.h> +#include <InterfaceDefs.h> +#include <TranslationDefs.h> +#include <Translator.h> +#include <TranslatorFormats.h> + +#include "BaseTranslator.h" + +#define WEBP_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(0,1,0) +#define WEBP_IMAGE_FORMAT 'WEBP' + +#define WEBP_IN_QUALITY 0.90 +#define WEBP_IN_CAPABILITY 0.90 + +#define BITS_OUT_QUALITY 1 +#define BITS_OUT_CAPABILITY 0.9 + +class WEBPTranslator : public BaseTranslator { +public: + WEBPTranslator(); + + virtual status_t DerivedIdentify(BPositionIO *inSource, + const translation_format *inFormat, BMessage *ioExtension, + translator_info *outInfo, uint32 outType); + + virtual status_t DerivedTranslate(BPositionIO *inSource, + const translator_info *inInfo, BMessage *ioExtension, + uint32 outType, BPositionIO *outDestination, int32 baseType); + + virtual BView *NewConfigView(TranslatorSettings *settings); + +protected: + virtual ~WEBPTranslator(); + // this is protected because the object is deleted by the + // Release() function instead of being deleted directly by + // the user + +private: + status_t translate_from_bits(BPositionIO *inSource, uint32 outType, + BPositionIO *outDestination); + + status_t translate_from_tiff(BPositionIO *inSource, BMessage *ioExtension, + uint32 outType, BPositionIO *outDestination); +}; + +#endif // #ifndef WEBP_TRANSLATOR_H Added: haiku/trunk/src/add-ons/translators/webp/bits.c =================================================================== --- haiku/trunk/src/add-ons/translators/webp/bits.c (rev 0) +++ haiku/trunk/src/add-ons/translators/webp/bits.c 2010-11-19 12:43:27 UTC (rev 39503) @@ -0,0 +1,78 @@ +// Copyright 2010 Google Inc. +// +// This code is licensed under the same terms as WebM: +// Software License Agreement: http://www.webmproject.org/license/software/ +// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// ----------------------------------------------------------------------------- +// +// Boolean decoder +// +// Author: Skal (pascal.massimino@xxxxxxxxx) + +#include "bits.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +//----------------------------------------------------------------------------- +// VP8BitReader + +int VP8Init(VP8BitReader* const br, const uint8_t* buf, uint32_t size) { + if (!br || !buf || size < 2) { + return 0; + } + br->buf_ = buf + 2; + br->buf_end_ = buf + size; + br->left_ = -8; + br->value_ = (buf[0] << 8) | buf[1]; + br->range_ = 255 - 1; + return 1; +} + +const uint8_t kVP8Log2Range[128] = { + 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0 +}; + +// range = ((range + 1) << kVP8Log2Range[range]) - 1 +const uint8_t kVP8NewRange[128] = { + 127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239, + 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, + 247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, + 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, + 243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, + 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, + 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, + 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, + 241, 243, 245, 247, 249, 251, 253, 127 +}; + +//----------------------------------------------------------------------------- +// 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 = (bits > 0) ? VP8GetValue(br, bits) : 0; + return VP8Get(br) ? -value : value; +} + +//----------------------------------------------------------------------------- + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif Added: haiku/trunk/src/add-ons/translators/webp/bits.h =================================================================== --- haiku/trunk/src/add-ons/translators/webp/bits.h (rev 0) +++ haiku/trunk/src/add-ons/translators/webp/bits.h 2010-11-19 12:43:27 UTC (rev 39503) @@ -0,0 +1,106 @@ +// Copyright 2010 Google Inc. +// +// This code is licensed under the same terms as WebM: +// Software License Agreement: http://www.webmproject.org/license/software/ +// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// ----------------------------------------------------------------------------- +// +// Boolean decoder +// +// Author: Skal (pascal.massimino@xxxxxxxxx) + +#ifndef WEBP_DECODE_BITS_H_ +#define WEBP_DECODE_BITS_H_ + +#include <assert.h> +#include "webp/decode_vp8.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +//----------------------------------------------------------------------------- +// Bitreader and code-tree reader + +typedef struct { + 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 + + // boolean decoder + uint32_t range_; // current range minus 1. In [127, 254] interval. + uint32_t value_; // current value + int left_; // how many unused bits (negated) +} VP8BitReader; + +// Initialize the bit reader and the boolean decoder. Return true if ok. +int VP8Init(VP8BitReader* const br, const uint8_t* buf, uint32_t size); + +// return the next value made of 'num_bits' bits +uint32_t VP8GetValue(VP8BitReader* const br, int num_bits); +static 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); + +// Read a bit with proba 'prob'. Speed-critical function! +extern const uint8_t kVP8Log2Range[128]; +extern const uint8_t kVP8NewRange[128]; +static inline uint32_t VP8GetByte(VP8BitReader* const br) { + assert(br); + if (br->buf_ < br->buf_end_) { + assert(br->buf_); + return *br->buf_++; + } + br->eof_ = 1; + return 0x80; +} + +static inline void VP8Shift(VP8BitReader* const br) { + // range_ is in [0..127] interval here. + const int shift = kVP8Log2Range[br->range_]; + br->range_ = kVP8NewRange[br->range_]; + br->value_ <<= shift; + br->left_ += shift; + if (br->left_ > 0) { + br->value_ |= VP8GetByte(br) << br->left_; + br->left_ -= 8; + } +} + +static inline uint32_t VP8GetBit(VP8BitReader* const br, int prob) { + const uint32_t split = (br->range_ * prob) >> 8; + const uint32_t bit = ((br->value_ >> 8) > split); + if (bit) { + br->range_ -= split + 1; + br->value_ -= (split + 1) << 8; + } else { + br->range_ = split; + } + if (br->range_ < 0x7f) { + VP8Shift(br); + } + return bit; +} + +static inline int VP8GetSigned(VP8BitReader* const br, int v) { + const uint32_t split = br->range_ >> 1; + const uint32_t bit = ((br->value_ >> 8) > split); + if (bit) { + br->range_ -= split + 1; + br->value_ -= (split + 1) << 8; + v = -v; + } else { + br->range_ = split; + } + VP8Shift(br); + return v; +} + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif + +#endif // WEBP_DECODE_BITS_H_ Added: haiku/trunk/src/add-ons/translators/webp/dsp.c =================================================================== --- haiku/trunk/src/add-ons/translators/webp/dsp.c (rev 0) +++ haiku/trunk/src/add-ons/translators/webp/dsp.c 2010-11-19 12:43:27 UTC (rev 39503) @@ -0,0 +1,696 @@ +// Copyright 2010 Google Inc. +// +// This code is licensed under the same terms as WebM: +// Software License Agreement: http://www.webmproject.org/license/software/ +// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ +// ----------------------------------------------------------------------------- +// +// speed-critical functions. +// +// Author: Skal (pascal.massimino@xxxxxxxxx) + +#include "vp8i.h" + +#if defined(__SSE2__) +#include <emmintrin.h> +#endif + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +//----------------------------------------------------------------------------- +// run-time tables (~4k) + +static uint8_t abs0[255 + 255 + 1]; // abs(i) +static uint8_t abs1[255 + 255 + 1]; // abs(i)>>1 +static int8_t sclip1[1020 + 1020 + 1]; // clips [-1020, 1020] to [-128, 127] +static int8_t sclip2[112 + 112 + 1]; // clips [-112, 112] to [-16, 15] +static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255] + +static int tables_ok = 0; + +void VP8DspInitTables() { + if (!tables_ok) { + int i; + for (i = -255; i <= 255; ++i) { + abs0[255 + i] = (i < 0) ? -i : i; + abs1[255 + i] = abs0[255 + i] >> 1; + } + 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; + } +} + +static inline uint8_t clip_8b(int v) { + assert(v >= -255 && v <= 255 + 255); + return clip1[255 + v]; +} + +//----------------------------------------------------------------------------- +// Transforms (Paragraph 14.4) + +#define STORE(x, y, v) \ + dst[x + y * BPS] = clip_8b(dst[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 void Transform(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, 0, a + d); + STORE(1, 0, b + c); + STORE(2, 0, b - c); + STORE(3, 0, a - d); + tmp++; + dst += BPS; + } +} +#undef MUL + +static void TransformUV(const int16_t* in, uint8_t* dst) { + Transform(in + 0 * 16, dst); + Transform(in + 1 * 16, dst + 4); + Transform(in + 2 * 16, dst + 4 * BPS); + Transform(in + 3 * 16, dst + 4 * BPS + 4); +} + +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]) TransformDC(in + 0 * 16, dst); + if (in[1 * 16]) TransformDC(in + 1 * 16, dst + 4); + if (in[2 * 16]) TransformDC(in + 2 * 16, dst + 4 * BPS); + if (in[3 * 16]) TransformDC(in + 3 * 16, dst + 4 * BPS + 4); +} + +#undef STORE + +// default C implementations: +VP8Idct VP8Transform = Transform; +VP8Idct VP8TransformUV = TransformUV; +VP8Idct VP8TransformDC = TransformDC; +VP8Idct VP8TransformDCUV = TransformDCUV; + +//----------------------------------------------------------------------------- +// 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) = TransformWHT; + +//----------------------------------------------------------------------------- +// Intra predictions + +#define OUT(x, y) dst[(x) + (y) * BPS] + +static inline void TrueMotion(uint8_t *dst, int size) { + const uint8_t* top = dst - BPS; + const int tl = top[-1]; + int x, y; + + for (y = 0; y < size; ++y) { + const uint8_t* const clip = clip1 + 255 + dst[-1] - tl; + 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 V16(uint8_t *dst) { // vertical + int j; + for (j = 0; j < 16; ++j) { + memcpy(dst + j * BPS, dst - BPS, 16); + } +} + +static void H16(uint8_t *dst) { // horizontal + int j; + for (j = 16; j > 0; --j) { + memset(dst, dst[-1], 16); + dst += BPS; + } +} + +static 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 + +static inline void Put4(uint32_t v, uint8_t* dst) { + int i; + for (i = 4; i > 0; --i) { + *(uint32_t*)dst = v; + dst += BPS; + } +} + +#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2) +#define AVG2(a, b) (((a) + (b) + 1) >> 1) + +static void V4(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]) + }; + const uint32_t v = *(uint32_t*)vals; + Put4(v, dst); +} + +static void H4(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]; + } + Put4((dc >> 3) * 0x01010101U, dst); +} + +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]; + OUT(0, 3) = AVG3(J, K, L); + OUT(0, 2) = OUT(1, 3) = AVG3(I, J, K); + OUT(0, 1) = OUT(1, 2) = OUT(2, 3) = AVG3(X, I, J); + OUT(0, 0) = OUT(1, 1) = OUT(2, 2) = OUT(3, 3) = AVG3(A, X, I); + OUT(1, 0) = OUT(2, 1) = OUT(3, 2) = AVG3(B, A, X); + OUT(2, 0) = OUT(3, 1) = AVG3(C, B, A); + OUT(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]; + OUT(0, 0) = AVG3(A, B, C); + OUT(1, 0) = OUT(0, 1) = AVG3(B, C, D); + OUT(2, 0) = OUT(1, 1) = OUT(0, 2) = AVG3(C, D, E); + OUT(3, 0) = OUT(2, 1) = OUT(1, 2) = OUT(0, 3) = AVG3(D, E, F); + OUT(3, 1) = OUT(2, 2) = OUT(1, 3) = AVG3(E, F, G); + OUT(3, 2) = OUT(2, 3) = AVG3(F, G, H); + OUT(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]; [... truncated: 3407 lines follow ...]